class MyTest extends AIController {
oil = false;
oilFleet = [];
myRigs = AIList();
function Start();
}
function MyTest::Start() {
local cargoes = AICargoList();
foreach (cargo, value in cargoes) {
if( AICargo.GetCargoLabel(cargo) == "OIL_") {
oil = cargo;
break;
}
}
local oilrigs = AIIndustryList_CargoProducing(oil);
oilrigs.Valuate(AIIndustry.HasDock);
oilrigs.KeepValue(1);
oilrigs.Valuate(AIIndustry.GetLastMonthProduction, oil);
local myRig = oilrigs.Begin();
AISign.BuildSign(AIIndustry.GetLocation(myRig), "origin");
myRigs.AddItem(myRig, 0);
local refineries = AIIndustryList_CargoAccepting(oil);
refineries.Valuate(AIIndustry.GetDistanceManhattanToTile, AIIndustry.GetLocation(myRig));
refineries.Sort(AIList.SORT_BY_VALUE, true);
local myRef = refineries.Begin();
AISign.BuildSign(AIIndustry.GetLocation(myRef), "destination");
local myDock = this.BuildDock(myRef);
local stations = AIStationList(AIStation.STATION_DOCK);
local buoys = this.BuildBuoys(myDock, myRig);
local depot = this.BuildDepot(AIIndustry.GetLocation(myRig));
local ship = this.BuildShip(depot, myDock, myRig, buoys);
while (true) {
this.ManageFleet();
this.Sleep(72);
}
}
function MyTest::BuildDock(industry) {
local dockLocation = false;
// Depending on the Realistic Catchment Area setting, the catchment area radius
// for a dock can be either 4 or 5.
local accepting = AITileList_IndustryAccepting(industry, 4);
accepting.Valuate(AITile.IsCoastTile);
accepting.KeepValue(1);
foreach(myTile, value in accepting) {
local slope = AITile.GetSlope(myTile);
// Keep trying to build a dock until it succeeds
if (AIMarine.BuildDock(myTile, AIStation.STATION_NEW)) {
dockLocation = myTile;
break;
}
}
return dockLocation;
}
function MyTest::BuildBuoys(dock, rig) {
local rigStation = AIIndustry.GetDockLocation(rig);
local distance = AIMap.DistanceMax(dock, rigStation);
local xDistance = AIMap.GetTileX(rigStation) - AIMap.GetTileX(dock);
local yDistance = AIMap.GetTileY(rigStation) - AIMap.GetTileY(dock);
// This part is built on assumption that it's a good idea to place a buoy
// about every 20 tiles, par https://wiki.openttd.org/Building_buoys#Finding_a_suitable_location
local numSegments = distance / 20;
local buoys = AIList();
if (numSegments > 0) {
local xSegSize = xDistance / numSegments;
local ySegSize = yDistance / numSegments;
local xLoc = AIMap.GetTileX(dock);
local yLoc = AIMap.GetTileY(dock);
for (local i = 0; i < numSegments; i++) {
xLoc = xLoc + xSegSize;
yLoc = yLoc + ySegSize;
local buoy = this.BuildBuoy(xLoc, yLoc);
if (buoy) {
buoys.AddItem(buoy, 0);
}
}
}
return buoys;
}
function MyTest::BuildBuoy(x, y) {
local tile = AIMap.GetTileIndex(x, y);
if (AIMarine.BuildBuoy(tile)) {
return AIWaypoint.GetWaypointID(tile);
}
else {
return false;
}
}
function MyTest::BuildDepot(tile) {
local xLoc = AIMap.GetTileX(tile);
local yLoc = AIMap.GetTileY(tile);
local myDock = false;
xLoc = xLoc - 5;
yLoc = yLoc - 5;
if (xLoc < 0) xLoc = 0;
if (yLoc < 0) yLoc = 0;
for (local x = 0; x < 12; x++) {
for (local y = 0; y < 12; y++) {
local tile1 = AIMap.GetTileIndex(xLoc+x, yLoc+y);
local tile2 = AIMap.GetTileIndex(xLoc+x+1, yLoc+y);
if (AIMarine.BuildWaterDepot(tile1, tile2)) {
myDock = tile1;
break;
}
}
if (myDock) {
break;
}
}
return myDock;
}
function MyTest::BuildShip(depot, dock, rig, buoys) {
local engines = AIEngineList(AIVehicle.VT_WATER);
engines.Valuate(AIEngine.CanRefitCargo, oil);
engines.KeepValue(1);
engines.Valuate(AIEngine.GetCapacity);
local engine = engines.Begin();
local ship = AIVehicle.BuildVehicle(depot, engine);
AIVehicle.RefitVehicle(ship, oil);
local rigStation = AIIndustry.GetDockLocation(rig);
AIOrder.InsertOrder(ship, 0, rigStation, AIOrder.OF_FULL_LOAD_ANY);
local counter = 1;
foreach (buoy, value in buoys) {
local location = AIWaypoint.GetLocation(buoy);
AIOrder.InsertOrder(ship, counter, location, AIOrder.OF_NONE);
counter++;
}
AIOrder.InsertOrder(ship, counter, dock, (AIOrder.OF_NO_LOAD + AIOrder.OF_UNLOAD));
counter++;
buoys.Sort(AIList.SORT_BY_ITEM, true);
foreach (buoy, value in buoys) {
local location = AIWaypoint.GetLocation(buoy);
AIOrder.InsertOrder(ship, counter, location, AIOrder.OF_NONE);
counter++;
}
AIVehicle.StartStopVehicle(ship);
Sleep(500);
return ship;
}
function MyTest::ManageFleet() {
foreach (rig, value in myRigs) {
local dockLocation = AIIndustry.GetDockLocation(rig);
local dock = AIStation.GetStationID(dockLocation);
if (AIStation.HasCargoRating(dock, oil)) {
// If a station rating falls below 57%, clone a ship
if (AIStation.GetCargoRating(dock, oil) < 57) {
this.CloneFleet(dock);
}
}
}
}
function MyTest::CloneFleet(station) {
local vehicles = AIVehicleList_Station(station);
local vehicle = vehicles.Begin();
local stationLocation = AIStation.GetLocation(station);
local depots = AIDepotList(AITile.TRANSPORT_WATER);
depots.Valuate(AITile.GetDistanceSquareToTile, stationLocation);
depots.Sort(AIList.SORT_BY_VALUE, true);
local depot = depots.Begin();
local newShip = AIVehicle.CloneVehicle(depot, vehicle, true);
AIVehicle.StartStopVehicle(newShip);
Sleep(500);
}