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); }