Missile Silos

The concept of missile silos is similar to pillboxes: If you build the tile improvement "missile silo" the script creates a "missile silo"-unit that is able to carry up to 12 missiles (nukes or cruise missiles). As in Activision’s "Nuclear Detente"-scenario the nukes stored in the silos may be targeted for an automated nuclear counter-strike.

The script is also intended to make the AI move their nukes into those silos.

The advantage of storing missiles in silos instead of cities consists in not weakening the garrisons of your cities.

The Script

//--------------------------------------------------------------------------
// MoT Mod for CTP2 (Apolyton Edition) by BureauBert
// v1.1
// http://motmod.ctp2.info
//--------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////
// Nuclear Warfare features
// by BureauBert
// Makes missile silos functional, and makes the AI store their nukes there
////////////////////////////////////////////////////////////////////////////


/////////////////////////////////
// MISSILE SILOS
/////////////////////////////////

// Creates/removes silo unit

HandleEvent(ImprovementComplete) 'ActivateSilo' post {               
        location_t silTmpLoc;
        int_t silSiloOwner;

        silTmpLoc = location[0];
        silSiloOwner = CellOwner(location[0]);

        // If the tile has a silo ti, create silo unit

        if(TileHasImprovement(silTmpLoc, TerrainImprovementDB(TILEIMP_MISSILE_SILO))) {       
                CreateUnit(silSiloOwner, UnitDB(MISSILE_SILO), silTmpLoc, 0);
        }
}

HandleEvent(CutImprovements) 'DeActivateSilo1' post {               
        location_t silTmpLoc;
        unit_t silTmpUnit;
        int_t silNumUnits;
        int_t silCount;
        int_t silSiloOwner;

        silTmpLoc = location[0];

        // If the tile has a Pillbox, kill the silo unit

        if(!TileHasImprovement(silTmpLoc, TerrainImprovementDB(TILEIMP_MISSILE_SILO))) {
                silSiloOwner = CellOwner(silTmpLoc);
                silNumUnits = GetUnitsAtLocation(silTmpLoc);
                for(silCount = 0; silCount < silNumUnits; silCount = silCount + 1) {
                        GetUnitFromCell(silTmpLoc, silCount, silTmpUnit);
                        if(silTmpUnit.valid && IsSiloUnit(silTmpUnit)) {
                                KillUnit(silTmpUnit);
                        }
                }
        }       
}

HandleEvent(ImprovementComplete) 'DeActivateSilo2' post {
        location_t silTmpLoc;
        unit_t silTmpUnit;
        int_t silNumUnits;
        int_t silCount;
        int_t silSiloOwner;

        silTmpLoc = location[0];        // start location

        // If the tile has no Pillbox, kill the pillbox unit

        if(!TileHasImprovement(silTmpLoc, TerrainImprovementDB(TILEIMP_MISSILE_SILO))) {
                silSiloOwner = CellOwner(silTmpLoc);
                silNumUnits = GetUnitsAtLocation(silTmpLoc);
                for(silCount = 0; silCount < silNumUnits; silCount = silCount + 1) {
                        GetUnitFromCell(silTmpLoc, silCount, silTmpUnit);
                        if(silTmpUnit.valid && IsSiloUnit(silTmpUnit)) {
                                KillUnit(silTmpUnit);
                        }
                }
        }       
}

HandleEvent(KillUnit) 'DeActivateSiloTileimp' pre {
        location_t silTmpLoc;
        unit_t silTmpUnit;

        silTmpUnit = unit[1];
        silTmpLoc = silTmpUnit.location;

        if(silTmpUnit.valid && IsSiloUnit(silTmpUnit)) {
                Event:CutImprovements(silTmpLoc);
        }
}

HandleEvent(BeginTurnUnit) 'SiloChangeOwner' pre {
        location_t silTmpLoc;
        unit_t silTmpUnit;
        int_t silUnitOwner;
        int_t silTileOwner;

        silTmpUnit = unit[0];
        silTmpLoc = silTmpUnit.location;
        silUnitOwner = silTmpUnit.owner;
        silTileOwner = CellOwner(silTmpLoc);

        if(silTmpUnit.valid && IsSiloUnit(silTmpUnit)) {
                if(silUnitOwner != silTileOwner) {
                        if(TileHasImprovement(silTmpLoc, TerrainImprovementDB(TILEIMP_MISSILE_SILO))) {
                                KillUnit(silTmpUnit);
                                CreateUnit(silTileOwner, UnitDB(PILLBOX), silTmpLoc, 0);
                        }
                }
        }
}

// Move our boom-booms to the store

HandleEvent(AddUnitToArmy) 'MoveBoomBoomToStore' post {
        unit_t                nucUnit;
        int_t                nucCountA;
        int_t                nucCountB;
        int_t                nucPlayer;
        location_t        nucLoc;
        location_t        nucLocations[];
        location_t        nucSiloLoc;
        int_t                nucDist;
        int_t                nucCheckDist;
        army_t                nucArmy;

        nucUnit = unit[0];
        nucPlayer = unit[0].owner;
        nucLoc = unit[0].location;
        nucArmy = army[0];
        nucCountB = 0;
        nucDist = 999999;

        if(!IsHumanPlayer(nucPlayer)) {
                if(nucUnit.type == UnitDB(UNIT_NUKE)) {
                        for(nucCountA = 0; nucCountA < MOD_MAPLOCATIONS.#; nucCountA = nucCountA + 1) {
                                if(CellOwner(MOD_MAPLOCATIONS[nucCountA]) == nucPlayer
                                && TileHasImprovement(MOD_MAPLOCATIONS[nucCountA], TerrainImprovementDB(TILEIMP_MISSILE_SILO))) {
                                        nucLocations[nucCountB] = MOD_MAPLOCATIONS[nucCountA];
                                        nucCountB = nucCountB + 1;
                                }
                        }
                        for(nucCountA = 0; nucCountA < nucLocations.#; nucCountA = nucCountA + 1) {
                                nucCheckDist = Distance(nucLoc, nucLocations[nucCountA]);
                                if(nucCheckDist < nucDist
                                && UnitsInCell(nucLocations[nucCountA]) < 13) {
                                        nucDist = nucCheckDist;
                                        nucSiloLoc = nucLocations[nucCountA];
                                }
                        }
                        if(nucDist < 999999) {
                                MoveArmyToTarget(nucArmy, nucSiloLoc);
                        }
                }
        }
}