Beginners Custom CO Tutorial: Difference between revisions

(Second Part WIP)
(WIP)
Line 176: Line 176:
             break;
             break;
             case GameEnums.PowerMode_Tagpower:
             case GameEnums.PowerMode_Tagpower:
             return [qsTr("("Type here for your own tag power quotes")];
             return [qsTr("Type here for your own tag power quotes")];
             break;  
             break;  
             }
             }
Line 240: Line 240:
             break;
             break;
//Depends on which CO zone you want "Deffensive(defPosX, defPosY), defender)", "Offensive(atkPosX, atkPosY), attacker)", Luck(posX, posY), unit)
//Depends on which CO zone you want "Deffensive(defPosX, defPosY), defender)", "Offensive(atkPosX, atkPosY), attacker)", Luck(posX, posY), unit)
</syntaxhighlight>Global Damage Codes<syntaxhighlight lang="js">
    this.activatePower = function(co, map)
    {
        var dialogAnimation = co.createPowerSentence();
        var powerNameAnimation = co.createPowerScreen(GameEnums.PowerMode_Power);
        dialogAnimation.queueAnimation(powerNameAnimation);
        CO_TEST.nameDamage(co, CO_TEST.powerDamage, powerNameAnimation, map);
    };
    this.powerDamage = 3;
    this.activateSuperpower = function(co, powerMode, map)
    {
        var dialogAnimation = co.createPowerSentence();
        var powerNameAnimation = co.createPowerScreen(powerMode);
        powerNameAnimation.queueAnimationBefore(dialogAnimation);
        CO_TEST.nameDamage(co, CO_TEST.superPowerDamage, powerNameAnimation, map);
    };
    this.superPowerDamage = 7;
    this.nameDamage = function(co, value, animation2, map)
    {
        var player = co.getOwner();
        var counter = 0;
        var playerCounter = map.getPlayerCount();
        var animation = null;
        var animations = [];
        for (var i2 = 0; i2 < playerCounter; i2++)
        {
            var enemyPlayer = map.getPlayer(i2);
            if ((enemyPlayer !== player) &&
                    (player.checkAlliance(enemyPlayer) === GameEnums.Alliance_Enemy))
            {
                var units = enemyPlayer.getUnits();
                units.randomize();
                for (i = 0; i < units.size(); i++)
                {
                    var unit = units.at(i);
                    animation = GameAnimationFactory.createAnimation(map, unit.getX(), unit.getY());
                    var delay = globals.randInt(135, 265);
                    if (animations.length < 5)
                    {
                        delay *= i;
                    }
                    animation.setSound("power4.wav", 1, delay);
                    if (animations.length < 5)
                    {
                        animation.addSprite("power4", -map.getImageSize() * 1.27, -map.getImageSize() * 1.27, 0, 2, delay);
                        animation2.queueAnimation(animation);
                        animations.push(animation);
                    }
                    else
                    {
                        animation.addSprite("power4", -map.getImageSize() * 1.27, -map.getImageSize() * 1.27, 0, 2, delay);
                        animations[counter].queueAnimation(animation);
                        animations[counter] = animation;
                        counter++;
                        if (counter >= animations.length)
                        {
                            counter = 0;
                        }
                    }
                    animation.writeDataInt32(unit.getX());
                    animation.writeDataInt32(unit.getY());
                    animation.writeDataInt32(value);
                    animation.setEndOfAnimationCall("ANIMATION", "postAnimationDamage");
                }
            }
        }
    };
    this.postAnimationDamage = function(postAnimation, map)
    {
        postAnimation.seekBuffer();
        var x = postAnimation.readDataInt32();
        var y = postAnimation.readDataInt32();
        var damage = postAnimation.readDataInt32();
        if (map.onMap(x, y))
        {
            var unit = map.getTerrain(x, y).getUnit();
            if (unit !== null)
            {
                var hp = unit.getHpRounded();
                if (hp - damage <= 0.1)
                {
                    // set hp to very very low
                    unit.setHp(0.1);
                }
                else
                {
                    unit.setHp(hp - damage);
                }
            }
        }
    };   
</syntaxhighlight>Reinforcements codes (since there are two I put them up)<syntaxhighlight lang="js">
//Sensei powers
    this.activatePower = function(co, map)
    {
        var dialogAnimation = co.createPowerSentence();
        var powerNameAnimation = co.createPowerScreen(GameEnums.PowerMode_Power);
        dialogAnimation.queueAnimation(powerNameAnimation);
        CO_TEST.spawnUnits(co, "INFANTRY", CO_TEST.powerSpawnHp, powerNameAnimation, map);
    };
    this.activateSuperpower = function(co, powerMode, map)
    {
        var dialogAnimation = co.createPowerSentence();
        var powerNameAnimation = co.createPowerScreen(powerMode);
        powerNameAnimation.queueAnimationBefore(dialogAnimation);
        CO_TEST.spawnUnits(co, "MECH", CO_TEST.powerSpawnHp, powerNameAnimation, map);
    };
    this.spawnUnits = function(co, unitID, hp, powerNameAnimation, map)
    {
        var buildings = co.getOwner().getBuildings();
        var animations = [];
        var counter = 0;
        buildings.randomize();
        var size = buildings.size();
        for (var i = 0; i < size; i++)
        {
            var building = buildings.at(i);
            if (building.getBuildingID() === "TOWN")
            {
                if (map.getTerrain(building.getX(), building.getY()).getUnit() === null)
                {
                    var animation = GameAnimationFactory.createAnimation(map, building.getX(), building.getY());
                    animation.writeDataInt32(building.getX());
                    animation.writeDataInt32(building.getY());
                    animation.writeDataString(unitID);
                    animation.writeDataInt32(co.getOwner().getPlayerID());
                    animation.writeDataInt32(hp);
                    animation.setStartOfAnimationCall("ANIMATION", "postAnimationSpawnUnit");
                    var delay = globals.randInt(135, 265);
                    if (animations.length < 5)
                    {
                        delay *= i;
                    }
                    if (i % 2 === 0)
                    {
                        animation.setSound("power8_1.wav", 1, delay);
                    }
                    else
                    {
                        animation.setSound("power8_2.wav", 1, delay);
                    }
                    if (animations.length < 5)
                    {
                        animation.addSprite("power8", -map.getImageSize() * 1.27, -map.getImageSize() * 1.27, 0, 2, delay);
                        powerNameAnimation.queueAnimation(animation);
                        animations.push(animation);
                    }
                    else
                    {
                        animation.addSprite("power8", -map.getImageSize() * 1.27, -map.getImageSize() * 1.27, 0, 2, delay);
                        animations[counter].queueAnimation(animation);
                        animations[counter] = animation;
                        counter++;
                        if (counter >= animations.length)
                        {
                            counter = 0;
                        }
                    }
                }
            }
        }
    };
    this.powerSpawnHp = 9;
//Yukio Powers
    this.activatePower = function(co, map)
    {
        var invasion = ["ARTILLERY", "FLAK", "LIGHT_TANK", "FLAK", "LIGHT_TANK"];
        var dialogAnimation = co.createPowerSentence();
        var powerNameAnimation = co.createPowerScreen(GameEnums.PowerMode_Power);
        dialogAnimation.queueAnimation(powerNameAnimation);
        CO_TEST.spawnUnits(co, 0.4, invasion, powerNameAnimation, map);
    };
    this.activateSuperpower = function(co, powerMode, map)
    {
        var invasion = ["HEAVY_TANK", "FLAK", "LIGHT_TANK", "ARTILLERY", "LIGHT_TANK", "K_HELI", "K_HELI"];
        var dialogAnimation = co.createPowerSentence();
        var powerNameAnimation = co.createPowerScreen(powerMode);
        powerNameAnimation.queueAnimationBefore(dialogAnimation);
        CO_TEST.spawnUnits(co, 0.7, invsion, powerNameAnimation, map);
    };
    this.spawnUnits = function(co, count, invasion, powerNameAnimation, map)
    {
        var buildings = co.getOwner().getBuildings();
        var animations = [];
        var counter = 0;
        buildings.randomize();
        var size = buildings.size();
        for (var i = 0; i < size * count; i++)
        {
            var building = buildings.at(i);
            if (building.getBuildingID() === "TOWN")
            {
                if (map.getTerrain(building.getX(), building.getY()).getUnit() === null)
                {
                    var animation = GameAnimationFactory.createAnimation(map, building.getX(), building.getY());
                    animation.writeDataInt32(building.getX());
                    animation.writeDataInt32(building.getY());
                    animation.writeDataString(invasion[i % invasion.length]);
                    animation.writeDataInt32(co.getOwner().getPlayerID());
                    animation.writeDataInt32(10);
                    animation.setStartOfAnimationCall("ANIMATION", "postAnimationSpawnUnit");
                    var delay = globals.randInt(135, 265);
                    if (animations.length < 5)
                    {
                        delay *= i;
                    }
                    if (i % 2 === 0)
                    {
                        animation.setSound("power8_1.wav", 1, delay);
                    }
                    else
                    {
                        animation.setSound("power8_2.wav", 1, delay);
                    }
                    if (animations.length < 5)
                    {
                        animation.addSprite("power8", -map.getImageSize() * 1.27, -map.getImageSize() * 1.27, 0, 2, delay);
                        powerNameAnimation.queueAnimation(animation);
                        animations.push(animation);
                    }
                    else
                    {
                        animation.addSprite("power8", -map.getImageSize() * 1.27, -map.getImageSize() * 1.27, 0, 2, delay);
                        animations[counter].queueAnimation(animation);
                        animations[counter] = animation;
                        counter++;
                        if (counter >= animations.length)
                        {
                            counter = 0;
                        }
                    }
                }
            }
        }
    };
</syntaxhighlight>Meteor Code<syntaxhighlight lang="js">
    this.activatePower = function(co, map)
    {
        var dialogAnimation = co.createPowerSentence();
        var powerNameAnimation = co.createPowerScreen(GameEnums.PowerMode_Power);
        dialogAnimation.queueAnimation(powerNameAnimation);
        CO_TEST.throwMeteor(co, CO_TEST.powerDamage, powerNameAnimation, map);
    };
    this.powerDamage = 4;
    this.activateSuperpower = function(co, powerMode, map)
    {
        var dialogAnimation = co.createPowerSentence();
        var powerNameAnimation = co.createPowerScreen(powerMode);
        powerNameAnimation.queueAnimationBefore(dialogAnimation);
        CO_TEST.throwMeteor(co, CO_TEST.superPowerDamage, powerNameAnimation, map);
    };
    this.superPowerDamage = 8;
    this.throwMeteor = function(co, damage, powerNameAnimation, map)
    {
        var meteorTarget = co.getOwner().getRockettarget(2, damage);
        // create cool meteor animation :)
        var animation = GameAnimationFactory.createAnimation(map, meteorTarget.x + 2, meteorTarget.y - 4);
        animation.addSprite("meteor", 0, 0, 2500, 4.0);
        animation.addTweenPosition(Qt.point((meteorTarget.x - 2) * map.getImageSize(), (meteorTarget.y - 2) * map.getImageSize()), 1000);
        animation.addTweenScale(0.65, 1000);
        animation.addTweenColor(0, "#FFFFFFFF", "#00FFFFFF", 1000, false, 1200);
        animation.addSound("meteorFall.wav");
        powerNameAnimation.queueAnimation(animation);
        var animation2 = GameAnimationFactory.createAnimation(map, 0, 0);
        animation2.addSprite2("white_pixel", 0, 0, 4200, map.getMapWidth(), map.getMapHeight());
        animation2.addTweenColor(0, "#00FFFFFF", "#FFFFFFFF", 3000, true, 1000);
        animation2.addSound("meteorImpact.wav");
        powerNameAnimation.queueAnimation(animation2);
        animation.setEndOfAnimationCall("CO_TEST", "postAnimationThrowMeteor");
        animation.setStartOfAnimationCall("CO_TEST", "preAnimationThrowMeteor");
        CO_TEST.postAnimationThrowMeteorTarget = meteorTarget;
        CO_TEST.postAnimationThrowMeteorDamage = damage;
    };
    this.preAnimationThrowMeteor = function(animation, map)
    {
        map.centerMap(CO_TEST.postAnimationThrowMeteorTarget.x, CO_STURM.postAnimationThrowMeteorTarget.y);
    };
    this.postAnimationThrowMeteorTarget = null;
    this.postAnimationThrowMeteorDamage = 0;
    this.postAnimationThrowMeteor = function(animation, map)
    {
        var meteorTarget = CO_TEST.postAnimationThrowMeteorTarget;
        var damage = CO_TEST.postAnimationThrowMeteorDamage;
        var fields = globals.getCircle(0, 2);
        // check all target fields
        var size = fields.size();
        for (var i = 0; i < size; i++)
        {
            var x = fields.at(i).x + meteorTarget.x;
            var y = fields.at(i).y + meteorTarget.y;
            // check if the target is on the map
            if (map.onMap(x, y))
            {
                var unit = map.getTerrain(x, y).getUnit();
                if (unit !== null)
                {
                    var hp = unit.getHpRounded();
                    if (hp - damage <= 0.1)
                    {
                        // set hp to very very low
                        unit.setHp(0.1);
                    }
                    else
                    {
                        unit.setHp(hp - damage);
                    }
                }
            }
        }
        CO_TEST.postAnimationThrowMeteorTarget = null;
        CO_TEST.postAnimationThrowMeteorDamage = 0;
    };
</syntaxhighlight>If you got question about this tutorial, please visit Discord for this kind of question.
== Images ==
The image is the next part of this tutorial.
There is few thing when add some images up.
First you need an res.xml file to be made first<syntaxhighlight lang="xml">
<?xml version="1.0"?>
<resources>
<set path = "mods/testco/images/co/" />
<atlas>
<image file="co_test+nrm.png" />
<image file="co_test+info.png" />
<image file="co_test+face.png" cols = "3" />
</atlas>
</resources>
//Optional is if you planning make a mini please type this in <image file="co_test+mini.png" /> this allow you to see your mini when it CO board a unit in game
</syntaxhighlight>
</syntaxhighlight>
[[Category:Modding Tutorials]]
[[Category:Modding Tutorials]]

Revision as of 04:39, 17 December 2023

This is a beginners Custom CO Tutorial work

This is a simple tutorial for beginners, new or fresh coders to want to make their own custom CO in COW

So first off you need to have this for your beginners setup.

var Constructor = function () {
    this.init = function (co, map) {
        co.setPowerStars(3);
        co.setSuperpowerStars(3);
    };

    this.activatePower = function(co, map)
    {
        var dialogAnimation = co.createPowerSentence();
        var powerNameAnimation = co.createPowerScreen(GameEnums.PowerMode_Power);
        dialogAnimation.queueAnimation(powerNameAnimation);

        var units = co.getOwner().getUnits();
        var animations = [];
        var counter = 0;
        units.randomize();
        for (var i = 0; i < units.size(); i++)
        {
            var unit = units.at(i);

            var animation = GameAnimationFactory.createAnimation(map, unit.getX(), unit.getY());
            animation.writeDataInt32(unit.getX());
            animation.writeDataInt32(unit.getY());
            animation.writeDataInt32(2);
            animation.setEndOfAnimationCall("ANIMATION", "postAnimationHeal");
            var delay = globals.randInt(135, 265);
            if (animations.length < 5)
            {
                delay *= i;
            }
            animation.setSound("power0.wav", 1, delay);
            if (animations.length < 5)
            {
                animation.addSprite("power0", -map.getImageSize() * 1.27, -map.getImageSize() * 1.27, 0, 2, delay);
                powerNameAnimation.queueAnimation(animation);
                animations.push(animation);
            }
            else
            {
                animation.addSprite("power0", -map.getImageSize() * 1.27, -map.getImageSize() * 1.27, 0, 2, delay);
                animations[counter].queueAnimation(animation);
                animations[counter] = animation;
                counter++;
                if (counter >= animations.length)
                {
                    counter = 0;
                }
            }
        }
        units.remove();
    };


    this.activateSuperpower = function(co, powerMode, map)
    {
        var dialogAnimation = co.createPowerSentence();
        var powerNameAnimation = co.createPowerScreen(powerMode);
        powerNameAnimation.queueAnimationBefore(dialogAnimation);

        var units = co.getOwner().getUnits();
        var animations = [];
        var counter = 0;
        units.randomize();
        for (var i = 0; i < units.size(); i++)
        {
            var unit = units.at(i);

            var animation = GameAnimationFactory.createAnimation(map, unit.getX(), unit.getY());
            animation.writeDataInt32(unit.getX());
            animation.writeDataInt32(unit.getY());
            animation.writeDataInt32(8);
            animation.setEndOfAnimationCall("ANIMATION", "postAnimationHeal");
            var delay = globals.randInt(135, 265);
            if (animations.length < 7)
            {
                delay *= i;
            }
            if (i % 2 === 0)
            {
                animation.setSound("power12_1.wav", 1, delay);
            }
            else
            {
                animation.setSound("power12_2.wav", 1, delay);
            }
            if (animations.length < 7)
            {
                animation.addSprite("power12", -map.getImageSize() * 2, -map.getImageSize() * 2, 0, 2, delay);
                powerNameAnimation.queueAnimation(animation);
                animations.push(animation);
            }
            else
            {
                animation.addSprite("power12", -map.getImageSize() * 2, -map.getImageSize() * 2, 0, 2, delay);
                animations[counter].queueAnimation(animation);
                animations[counter] = animation;
                counter++;
                if (counter >= animations.length)
                {
                    counter = 0;
                }
            }
        }
        units.remove();
    };

    this.loadCOMusic = function (co, map) {
        // put the co music in here.
        switch (co.getPowerMode()) {
            case GameEnums.PowerMode_Power:
                audio.addMusic("mods/testco/music/cos/Power.mp3", 0, 0);
                break;
            case GameEnums.PowerMode_Superpower:
                audio.addMusic("mods/testco/music/cos/Super.mp3", 0, 0);
                break;
            case GameEnums.PowerMode_Tagpower:
                audio.addMusic("mods/testco/music/cos/Super.mp3", 0, 0);
                break;
            default:
                audio.addMusic("mods/testco/music/cos/Theme.mp3", 0, 0);
                break;
        }
    };

    this.getCOUnitRange = function (co, map) {
        return Number;
    };
    this.getCOArmy = function () {
        return "Vanilla Base Game or custom";
    };
    // CO - Intel
    this.getBio = function (co) {
        return qsTr("Type for your own description");
    };
    this.getLongBio = function(co, map)
    {
        return qsTr("\n\n\"Special Message Quote\"");
    };
    this.getHits = function (co) {
        return qsTr("");
    };
    this.getMiss = function (co) {
        return qsTr("");
    };
    this.getCODescription = function (co) {
        return qsTr("Type for your own description only affect D2D or CO zone Effect");
    };
    this.getLongCODescription = function() {
    return qsTr("\nD2D Effect: \nType your D2D ability") +
           qsTr("\n\nZone Effect: \nType your CO Zone ability");
    };
    this.getPowerDescription = function (co) {
        return qsTr("Type for your own description for power (COP)");
    };
    this.getPowerName = function (co) {
        return qsTr("Name");
    };
    this.getSuperPowerDescription = function (co) {
        return qsTr("Type for your own description for super power (SCOP)");
    };
    this.getSuperPowerName = function (co) {
        return qsTr("Name");
    };
    this.getPowerSentences = function (co) {
        switch (co.getPowerMode()) {
            case GameEnums.PowerMode_Power:
            return [qsTr("Type here for your own power quotes")];
            break;
            case GameEnums.PowerMode_Superpower:
            return [qsTr("Type here for your own super power quotes")];
            break;
            case GameEnums.PowerMode_Tagpower:
            return [qsTr("Type here for your own tag power quotes")];
            break; 
            }
    };
    this.getVictorySentences = function (co) {
        return [qsTr("Type here for your own victory quotes")];
    };
    this.getDefeatSentences = function (co) {
        return [qsTr("Type here for your own defeat quotes")];
    };
    this.getName = function () {
        return qsTr("Name");
    };
}

Constructor.prototype = CO;
var CO_TEST = new Constructor();
//Make sure put that CO_NAME (CO_TEST) in full caps lock in order to getting working

Feel free to copy that code block to get started!

If you got your very first setup (if you got copy it from the code block above) you good to go follow this next step!

Stats, Co zone & abilities

This is the second part of the tutorial is all about stats, CO zone & abilities

Now you need some stats, just mainly your Custom Co D2D, Power & Super Power

Stats Code Library (D2D, other abilities & ects)

Terrain Codes (Modified terrain itself)

Weather Codes (Weather manipulations)

Building (Props for income bonus)

Units also affect on stats as well

Naval

Air

Infantry

Ground

Hover

Or you could visit Github for some COs coding Resource work https://github.com/Robosturm/Commander_Wars/tree/master/resources/scripts/cos

As for abilities there is quite lots cos have unique abilities

  • Global Damage
  • Reinforcements
  • Meteor Strike
  • Healing
  • ects

For the CO zone effects you need to be like this

            if (co.inCORange(Qt.point(defPosX, defPosY), defender))
            {
                return 50;
            }
            break;
//Depends on which CO zone you want "Deffensive(defPosX, defPosY), defender)", "Offensive(atkPosX, atkPosY), attacker)", Luck(posX, posY), unit)

Global Damage Codes

    this.activatePower = function(co, map)
    {
        var dialogAnimation = co.createPowerSentence();
        var powerNameAnimation = co.createPowerScreen(GameEnums.PowerMode_Power);
        dialogAnimation.queueAnimation(powerNameAnimation);

        CO_TEST.nameDamage(co, CO_TEST.powerDamage, powerNameAnimation, map);
    };
    this.powerDamage = 3;
    this.activateSuperpower = function(co, powerMode, map)
    {
        var dialogAnimation = co.createPowerSentence();
        var powerNameAnimation = co.createPowerScreen(powerMode);
        powerNameAnimation.queueAnimationBefore(dialogAnimation);

        CO_TEST.nameDamage(co, CO_TEST.superPowerDamage, powerNameAnimation, map);
    };
    this.superPowerDamage = 7;

    this.nameDamage = function(co, value, animation2, map)
    {
        var player = co.getOwner();
        var counter = 0;
        var playerCounter = map.getPlayerCount();
        var animation = null;
        var animations = [];

        for (var i2 = 0; i2 < playerCounter; i2++)
        {
            var enemyPlayer = map.getPlayer(i2);
            if ((enemyPlayer !== player) &&
                    (player.checkAlliance(enemyPlayer) === GameEnums.Alliance_Enemy))
            {

                var units = enemyPlayer.getUnits();
                units.randomize();
                for (i = 0; i < units.size(); i++)
                {
                    var unit = units.at(i);

                    animation = GameAnimationFactory.createAnimation(map, unit.getX(), unit.getY());
                    var delay = globals.randInt(135, 265);
                    if (animations.length < 5)
                    {
                        delay *= i;
                    }
                    animation.setSound("power4.wav", 1, delay);
                    if (animations.length < 5)
                    {
                        animation.addSprite("power4", -map.getImageSize() * 1.27, -map.getImageSize() * 1.27, 0, 2, delay);
                        animation2.queueAnimation(animation);
                        animations.push(animation);
                    }
                    else
                    {
                        animation.addSprite("power4", -map.getImageSize() * 1.27, -map.getImageSize() * 1.27, 0, 2, delay);
                        animations[counter].queueAnimation(animation);
                        animations[counter] = animation;
                        counter++;
                        if (counter >= animations.length)
                        {
                            counter = 0;
                        }
                    }
                    animation.writeDataInt32(unit.getX());
                    animation.writeDataInt32(unit.getY());
                    animation.writeDataInt32(value);
                    animation.setEndOfAnimationCall("ANIMATION", "postAnimationDamage");
                }
            }
        }
    };
    this.postAnimationDamage = function(postAnimation, map)
    {
        postAnimation.seekBuffer();
        var x = postAnimation.readDataInt32();
        var y = postAnimation.readDataInt32();
        var damage = postAnimation.readDataInt32();
        if (map.onMap(x, y))
        {
            var unit = map.getTerrain(x, y).getUnit();
            if (unit !== null)
            {
                var hp = unit.getHpRounded();
                if (hp - damage <= 0.1)
                {
                    // set hp to very very low
                    unit.setHp(0.1);
                }
                else
                {
                    unit.setHp(hp - damage);
                }
            }

        }
    };

Reinforcements codes (since there are two I put them up)

//Sensei powers
    this.activatePower = function(co, map)
    {
        var dialogAnimation = co.createPowerSentence();
        var powerNameAnimation = co.createPowerScreen(GameEnums.PowerMode_Power);
        dialogAnimation.queueAnimation(powerNameAnimation);

        CO_TEST.spawnUnits(co, "INFANTRY", CO_TEST.powerSpawnHp, powerNameAnimation, map);
    };

    this.activateSuperpower = function(co, powerMode, map)
    {
        var dialogAnimation = co.createPowerSentence();
        var powerNameAnimation = co.createPowerScreen(powerMode);
        powerNameAnimation.queueAnimationBefore(dialogAnimation);

        CO_TEST.spawnUnits(co, "MECH", CO_TEST.powerSpawnHp, powerNameAnimation, map);
    };

    this.spawnUnits = function(co, unitID, hp, powerNameAnimation, map)
    {
        var buildings = co.getOwner().getBuildings();
        var animations = [];
        var counter = 0;
        buildings.randomize();
        var size = buildings.size();
        for (var i = 0; i < size; i++)
        {
            var building = buildings.at(i);
            if (building.getBuildingID() === "TOWN")
            {
                if (map.getTerrain(building.getX(), building.getY()).getUnit() === null)
                {
                    var animation = GameAnimationFactory.createAnimation(map, building.getX(), building.getY());
                    animation.writeDataInt32(building.getX());
                    animation.writeDataInt32(building.getY());
                    animation.writeDataString(unitID);
                    animation.writeDataInt32(co.getOwner().getPlayerID());
                    animation.writeDataInt32(hp);
                    animation.setStartOfAnimationCall("ANIMATION", "postAnimationSpawnUnit");
                    var delay = globals.randInt(135, 265);
                    if (animations.length < 5)
                    {
                        delay *= i;
                    }
                    if (i % 2 === 0)
                    {
                        animation.setSound("power8_1.wav", 1, delay);
                    }
                    else
                    {
                        animation.setSound("power8_2.wav", 1, delay);
                    }
                    if (animations.length < 5)
                    {
                        animation.addSprite("power8", -map.getImageSize() * 1.27, -map.getImageSize() * 1.27, 0, 2, delay);
                        powerNameAnimation.queueAnimation(animation);
                        animations.push(animation);
                    }
                    else
                    {
                        animation.addSprite("power8", -map.getImageSize() * 1.27, -map.getImageSize() * 1.27, 0, 2, delay);
                        animations[counter].queueAnimation(animation);
                        animations[counter] = animation;
                        counter++;
                        if (counter >= animations.length)
                        {
                            counter = 0;
                        }
                    }
                }
            }
        }
    };
    this.powerSpawnHp = 9;

//Yukio Powers
    this.activatePower = function(co, map)
    {
        var invasion = ["ARTILLERY", "FLAK", "LIGHT_TANK", "FLAK", "LIGHT_TANK"];
        var dialogAnimation = co.createPowerSentence();
        var powerNameAnimation = co.createPowerScreen(GameEnums.PowerMode_Power);
        dialogAnimation.queueAnimation(powerNameAnimation);
        CO_TEST.spawnUnits(co, 0.4, invasion, powerNameAnimation, map);
    };

    this.activateSuperpower = function(co, powerMode, map)
    {
        var invasion = ["HEAVY_TANK", "FLAK", "LIGHT_TANK", "ARTILLERY", "LIGHT_TANK", "K_HELI", "K_HELI"];
        var dialogAnimation = co.createPowerSentence();
        var powerNameAnimation = co.createPowerScreen(powerMode);
        powerNameAnimation.queueAnimationBefore(dialogAnimation);

        CO_TEST.spawnUnits(co, 0.7, invsion, powerNameAnimation, map);
    };

    this.spawnUnits = function(co, count, invasion, powerNameAnimation, map)
    {
        var buildings = co.getOwner().getBuildings();
        var animations = [];
        var counter = 0;
        buildings.randomize();
        var size = buildings.size();
        for (var i = 0; i < size * count; i++)
        {
            var building = buildings.at(i);
            if (building.getBuildingID() === "TOWN")
            {
                if (map.getTerrain(building.getX(), building.getY()).getUnit() === null)
                {
                    var animation = GameAnimationFactory.createAnimation(map, building.getX(), building.getY());
                    animation.writeDataInt32(building.getX());
                    animation.writeDataInt32(building.getY());
                    animation.writeDataString(invasion[i % invasion.length]);
                    animation.writeDataInt32(co.getOwner().getPlayerID());
                    animation.writeDataInt32(10);
                    animation.setStartOfAnimationCall("ANIMATION", "postAnimationSpawnUnit");

                    var delay = globals.randInt(135, 265);
                    if (animations.length < 5)
                    {
                        delay *= i;
                    }
                    if (i % 2 === 0)
                    {
                        animation.setSound("power8_1.wav", 1, delay);
                    }
                    else
                    {
                        animation.setSound("power8_2.wav", 1, delay);
                    }
                    if (animations.length < 5)
                    {
                        animation.addSprite("power8", -map.getImageSize() * 1.27, -map.getImageSize() * 1.27, 0, 2, delay);
                        powerNameAnimation.queueAnimation(animation);
                        animations.push(animation);
                    }
                    else
                    {
                        animation.addSprite("power8", -map.getImageSize() * 1.27, -map.getImageSize() * 1.27, 0, 2, delay);
                        animations[counter].queueAnimation(animation);
                        animations[counter] = animation;
                        counter++;
                        if (counter >= animations.length)
                        {
                            counter = 0;
                        }
                    }
                }
            }
        }
    };

Meteor Code

    this.activatePower = function(co, map)
    {
        var dialogAnimation = co.createPowerSentence();
        var powerNameAnimation = co.createPowerScreen(GameEnums.PowerMode_Power);
        dialogAnimation.queueAnimation(powerNameAnimation);

        CO_TEST.throwMeteor(co, CO_TEST.powerDamage, powerNameAnimation, map);
    };
    this.powerDamage = 4;

    this.activateSuperpower = function(co, powerMode, map)
    {
        var dialogAnimation = co.createPowerSentence();
        var powerNameAnimation = co.createPowerScreen(powerMode);
        powerNameAnimation.queueAnimationBefore(dialogAnimation);

        CO_TEST.throwMeteor(co, CO_TEST.superPowerDamage, powerNameAnimation, map);
    };
    this.superPowerDamage = 8;

    this.throwMeteor = function(co, damage, powerNameAnimation, map)
    {
        var meteorTarget = co.getOwner().getRockettarget(2, damage);
        // create cool meteor animation :)
        var animation = GameAnimationFactory.createAnimation(map, meteorTarget.x + 2, meteorTarget.y - 4);
        animation.addSprite("meteor", 0, 0, 2500, 4.0);
        animation.addTweenPosition(Qt.point((meteorTarget.x - 2) * map.getImageSize(), (meteorTarget.y - 2) * map.getImageSize()), 1000);
        animation.addTweenScale(0.65, 1000);
        animation.addTweenColor(0, "#FFFFFFFF", "#00FFFFFF", 1000, false, 1200);
        animation.addSound("meteorFall.wav");
        powerNameAnimation.queueAnimation(animation);
        var animation2 = GameAnimationFactory.createAnimation(map, 0, 0);
        animation2.addSprite2("white_pixel", 0, 0, 4200, map.getMapWidth(), map.getMapHeight());
        animation2.addTweenColor(0, "#00FFFFFF", "#FFFFFFFF", 3000, true, 1000);
        animation2.addSound("meteorImpact.wav");
        powerNameAnimation.queueAnimation(animation2);
        animation.setEndOfAnimationCall("CO_TEST", "postAnimationThrowMeteor");
        animation.setStartOfAnimationCall("CO_TEST", "preAnimationThrowMeteor");
        CO_TEST.postAnimationThrowMeteorTarget = meteorTarget;
        CO_TEST.postAnimationThrowMeteorDamage = damage;
    };
    this.preAnimationThrowMeteor = function(animation, map)
    {
        map.centerMap(CO_TEST.postAnimationThrowMeteorTarget.x, CO_STURM.postAnimationThrowMeteorTarget.y);
    };
    this.postAnimationThrowMeteorTarget = null;
    this.postAnimationThrowMeteorDamage = 0;
    this.postAnimationThrowMeteor = function(animation, map)
    {
        var meteorTarget = CO_TEST.postAnimationThrowMeteorTarget;
        var damage = CO_TEST.postAnimationThrowMeteorDamage;
        var fields = globals.getCircle(0, 2);
        // check all target fields
        var size = fields.size();
        for (var i = 0; i < size; i++)
        {
            var x = fields.at(i).x + meteorTarget.x;
            var y = fields.at(i).y + meteorTarget.y;
            // check if the target is on the map
            if (map.onMap(x, y))
            {
                var unit = map.getTerrain(x, y).getUnit();
                if (unit !== null)
                {
                    var hp = unit.getHpRounded();
                    if (hp - damage <= 0.1)
                    {
                        // set hp to very very low
                        unit.setHp(0.1);
                    }
                    else
                    {
                        unit.setHp(hp - damage);
                    }
                }
            }
        }
        CO_TEST.postAnimationThrowMeteorTarget = null;
        CO_TEST.postAnimationThrowMeteorDamage = 0;
    };

If you got question about this tutorial, please visit Discord for this kind of question.

Images

The image is the next part of this tutorial.

There is few thing when add some images up.

First you need an res.xml file to be made first

<?xml version="1.0"?>
<resources>
	<set path = "mods/testco/images/co/" />
	<atlas>
		<image file="co_test+nrm.png" />
		<image file="co_test+info.png" />
		<image file="co_test+face.png" cols = "3" />
	</atlas>
</resources>

//Optional is if you planning make a mini please type this in <image file="co_test+mini.png" /> this allow you to see your mini when it CO board a unit in game