{"FileModelVersion":{"Major":1,"Minor":0},"Name":"MQ 201","Version":15,"SavedTotalBlockCount":345,"SavedMaterialCost":10498.4,"ContainedMaterialCost":272.0,"ItemDictionary":{"1515":"b9d21957-633f-4926-9562-4cfab38badee","1518":"2ddec223-13c2-4bf9-ba05-66338c51bd45","1534":"40659614-1b34-497a-b745-78497e4b2025","1538":"369eefd9-0c39-412e-a294-d0bb2251c509","1461":"8ae14459-075e-4384-bd95-1fef61b4021f","1460":"4035532b-9d7b-4570-8ede-68ebfe42418d","1533":"bcaf33a4-98c3-41d7-b416-438670e97d53","1537":"ee18a848-1319-4ff9-b5e5-3f3710635dbf","1514":"442f3ea3-c7cd-4759-84ee-a0d2fac5a711","1513":"de50f4f6-3d7e-4d6b-ae34-e6a34b24b104","1509":"5548037e-8428-43f8-bcb6-d730dbcd0a79","1510":"8477bbec-974c-45bf-a1ce-49a48d5b5307","877":"ab699540-efc8-4592-bc97-204f6a874b3a","264":"26a604f0-071c-49ca-8a0e-e1d9c959b1c5","263":"f29b1372-f4f3-4305-aa85-5fe214361fb7","283":"3ed4d2a4-62ce-4807-b516-6da685804e1e","286":"f003eae6-6818-4da9-a1d0-6e4f1677d49f","260":"edd65760-896f-4f6a-ba8c-eb2b072635f4","267":"57cd27b4-7876-41a7-8030-d5099d86bc0a","306":"2c557c38-4136-436a-bae2-c5cd1102690c","795":"9413049d-a4f7-4c1c-8b8a-d2f1f4c18e53","763":"38e9a85a-ac7d-4cb0-bd43-a5ae2099640c","770":"c8fe583a-357b-4fa6-86f1-fc2de639c909","290":"ef545d00-c22d-4eed-bd76-74d6432e2974","279":"ddee4f0c-e9de-4a73-b87f-c34d674450cb","295":"42033da8-485e-43be-99db-ffe2492767b4","751":"d4e23d98-fbde-449e-823f-872004cadc7a","749":"4934fff3-aca3-4fb3-b242-60afbe8d4439","664":"75a78e48-0848-45ee-9df2-e2b328c1933d","752":"478efa9f-5743-4238-ad2e-750770d7da11","199":"d3924bae-be5a-43a0-be19-64fc7c8d6059","319":"310a7a9a-8d4e-4365-a877-1a8e2bac2a81","318":"154e5001-729c-4a9f-983b-342d3092a0f3","327":"4aa8cfcb-7aeb-430b-9726-f8bb8d8f4124","364":"d30acc39-3742-47bd-82de-f5e1b9af565d","360":"a7aaf947-f16c-489b-a10e-b48d03e0d209","358":"8cfd4184-ee25-4431-8c83-b9f0bf214625","359":"f0bc9808-c1d6-49c4-967e-3ff2de9379cf","311":"a56e0dcf-94e4-48a0-b8b9-5e33e0ab69cf","309":"e6bb2b09-daee-432d-9aff-45fc63d24fca","296":"10a165d1-1333-4c57-a942-b857542c4b45","976":"84dce5de-cacc-4ce5-b3fe-498f926c7ea4","122":"ae37018a-2b07-422c-b281-87f10fb95d3c","900":"ec96c0cd-ceb8-4d66-8002-c3914947ee9b","901":"e1d0c17b-9877-47a2-b5aa-d88db60781ca","821":"8746f5b3-e2a6-4067-95bc-9da3900690f8","760":"82b2446e-c12e-436a-8340-76d38372ead1","692":"7475c363-fa60-4348-a2e9-f3e2329fc20a","403":"8d948200-242c-47c3-b46a-ecdf40f7b39b","302":"d3cc2b19-daee-432d-9aff-45fc63d24fca","186":"0706d2b0-c244-4e0f-8577-79338cb073cf","107":"e63040c9-0027-4fd3-be30-67fe3e950140","95":"cdca5dec-eeee-4849-9b2e-73b23e216465","738":"b093f1e8-7129-4f1b-83ab-737363aceb52","739":"fcffecd8-0550-4ff6-b85e-36f45cf04be1","744":"08101f92-442f-41c8-913e-e5c264463b58","740":"7489ebd4-92d2-4641-9db4-139bb592fc34","736":"2b2d4fdc-8ffa-4399-985a-f9f5ec1263d0","727":"26a852c0-da52-4232-8e04-69913c8edc13","734":"c7d3ffb8-3ceb-40ae-a2b0-69c1f4d59462","729":"cacc9c8b-9149-4adf-a86c-5cf5f4b035b8","743":"95e34566-9234-4559-b601-9a0b9b7c11e5","94":"788700be-1e74-46d7-9e34-1a5ec2747548","357":"1b9aa074-9b04-4b5c-b30e-35bdfa0e0835","182":"a3d914e9-697d-425f-abda-a6b21b4de952","105":"c5cec892-2e43-4905-9d28-44fc8ecb5cc7","35":"5cf2b4da-c1b8-4005-930b-73cc39ac9d28","272":"0d1d97b5-3c99-45bf-8a5d-e7a624b3ddb6","106":"213026bc-fd7a-44e6-b543-a31c219aaef0"},"Blueprint":{"ContainedMaterialCost":264.0,"CSI":[0.0,0.0,-1.0,0.0,-1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,13980.127,3.73394966,1.0,1.0,0.0,1.0,100.947121,446.359436,-1.0,0.0,14000.0,1.0,1.0,120000.0,0.0,0.0,0.0,64.1170044,0.0,0.1,0.1,1.0,1.0,3.0,-1.0,0.0,-1.0,0.0,-1.0,1.0,3.48394966,-1.0,0.0,0.0,-1.0,63297.46,120000.0,0.0,150.0,-1.0,321.480042,133.538437,0.625,0.0,0.0,500.0,-1.0,12.0,0.0,0.0,0.0,5.0790906,0.0,0.0,0.25,0.0,0.0298379548,0.0,0.0,0.0,0.0,1.0,1.0,-1.0,-1.0,-1.0,-1.0],"COL":["0.011764,0,0,0","1,0,0,0.5","0,1,0,0.5","0,0,1,0.5","0.1,0.1,0.1,0.5","0.3,0.3,0.3,0.5","0.5,0.5,0.5,0.5","1,1,1,0.1","1,1,1,0.5","1,1,1,0.99","1,0.921568,0.015686,0.99","0,1,1,0.99","1,0,1,0.99","0.100635,0.153869,0.198678,0.753213","0.058455,0.895634,0.141254,0.259447","0.75955,0.13648,0.81718,0.586141","0.956279,0.651906,0.28633,0.733341","0.216387,0.785903,0.789481,0.50299","0.582391,0.419156,0.537576,0.387514","0.624492,0.104434,0.789525,0.668813","0.249608,0.843415,0.400674,0.666851","0.18131,0.805797,0.692405,0.912307","0.137329,0.968983,0.130173,0.555318","0.035005,0.004021,0.359432,0.067034","0.320352,0.209019,0.529055,0.791607","0.450276,0.288072,0.575069,0.080955","0.368467,0.787826,0.65394,0.673982","0,0,0,0","0.349019,0.35,0.35,0.99","0.25,0.25,0.25,0.99","0.349019,0.35,0.35,0.99","0.282353,0.3,0.3,1"],"SCs":[{"ContainedMaterialCost":0.0,"CSI":[-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0],"COL":null,"SCs":[],"BLP":["0,0,0","-1,11,0","-1,10,0","-1,9,0","-1,8,0","-1,7,0","-1,5,0","-1,4,0","-1,3,0","-1,2,0","-1,1,0","0,11,-1","0,10,-1","0,9,-1","0,8,-1","0,7,-1","0,5,-1","0,4,-1","0,3,-1","0,2,-1","0,12,0","0,11,0","0,10,0","0,9,0","0,8,0","0,7,0","0,6,0","0,5,0","0,4,0","0,3,0","0,2,0","0,1,0","0,11,1","0,10,1","0,9,1","0,8,1","0,7,1","0,5,1","0,4,1","0,3,1","0,2,1","0,1,1","1,11,0","1,10,0","1,9,0","1,8,0","1,7,0","1,5,0","1,4,0","1,3,0","1,2,0","1,1,0"],"BLR":[0,7,7,7,7,7,7,7,7,7,7,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5],"BP1":null,"BP2":null,"BCI":[31,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"BEI":null,"BlockData":"AAAAKgAAAAsAAQAAAAAAAAIAAAAABAADAAAAAAQAJIgAAAAEAF0AAAAABABdGwEAAAQABwABAQAABAIAAAAaAAAjAAAAFQCJAAAAAAAA7GIAAAAAAIZ7AAAAAABdAAAAAA4AXRsBAAAOAAQABAAAgD8HAAQAAIA/AAAEBAAAAA==","VehicleData":"Vy4AAAAAAAAHAAAAAAAAAAAAAAAA8FsKAQAAAAAOAAAAAAAPJwAAAAAA0AcAAAAAAJ9xBAAAAAAADgAAAAAADycAAAAAAKCGAQAAAABHKQEAAAAAAAcAAAAAAAAAAAAAAAA=","designChanged":false,"blueprintVersion":0,"blueprintName":"ADFX-11 engine","SerialisedInfo":{"JsonDictionary":{},"IsEmpty":true},"Name":null,"ItemNumber":94,"LocalPosition":"-1,0,-1","LocalRotation":"0.707106,0,0,-0.707106","ForceId":0,"TotalBlockCount":52,"MaxCords":"1,12,1","MinCords":"-1,0,-1","BlockIds":[95,738,738,738,738,738,739,739,739,739,744,740,740,740,740,740,739,739,739,739,736,727,727,727,727,727,734,729,729,729,729,743,738,738,738,738,738,739,739,739,739,744,738,738,738,738,738,739,739,739,739,744],"BlockState":"=0,52","AliveCount":52,"BlockStringData":[],"BlockStringDataIds":[],"GameVersion":"3.2.3.1","PersistentSubObjectIndex":2,"PersistentBlockIndex":-1,"AuthorDetails":{"Valid":true,"ForeignBlocks":0,"CreatorId":"14f9a105-cbc6-47fb-a4bb-58fc6188ecff","ObjectId":"4acf0f23-955a-4ee0-bc84-fc26e3dc293b","CreatorReadableName":"Iorn Wolves","HashV1":"dd4a0d3bdf5fd950635d878a17eb42a0"},"BlockCount":52},{"ContainedMaterialCost":4.0,"CSI":[-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0],"COL":null,"SCs":[],"BLP":["0,0,0","1,0,0","1,0,-1","1,0,-2","2,0,0"],"BLR":[0,2,2,2,17],"BP1":null,"BP2":null,"BCI":[31,31,31,31,31],"BEI":null,"BlockData":"AAAAKgAAAAsAAQAAAAAAAAIAAAAABAADAAAAAAQAJIgAAAAEAF0AAAAABABdGwEAAAQABwABAQAABAYAAAABAAAqAAAAFQAFAAAAAAAAAQAAAAAAAAIAAAAAAAB2JgAAAAcAQhgAAAAHAF0bAQAADgABAAQAADRCAQAEAADIQgAABAEAAAADAAAVAAAAHABaAAAAAAAAEwAAAAAcAF0bAQAAHADGBAQyAAAAHQkEawAAAHQNBEMAAADLEQREAAAABAAAIwAAACcAAQAAAAAAAAIAAAAAEgADAAAAABkAXQAAAAAgAF0bAQAAIAClAAgAAAAAAECPQJgABBMAAACYAAQoAAAAAwAEAgAAAAAABAcAAAA=","VehicleData":"Vy4AAAAAAAAHAAAAAAAAAAAAAAAA8FsKAQAAAAAOAAAAAAAPJwAAAAAA0AcAAAAAAJ9xBAAAAAAADgAAAAAADycAAAAAAKCGAQAAAABHKQEAAAAAAAcAAAAAAAAAAAAAAAA=","designChanged":false,"blueprintVersion":0,"blueprintName":"micro flares","SerialisedInfo":{"JsonDictionary":{},"IsEmpty":true},"Name":null,"ItemNumber":94,"LocalPosition":"6,0,-15","LocalRotation":"0,0,0,0.999999","ForceId":0,"TotalBlockCount":5,"MaxCords":"2,0,0","MinCords":"0,0,-2","BlockIds":[95,319,318,357,182],"BlockState":"=0,5","AliveCount":5,"BlockStringData":[],"BlockStringDataIds":[],"GameVersion":"3.2.3.1","PersistentSubObjectIndex":5,"PersistentBlockIndex":-1,"AuthorDetails":{"Valid":true,"ForeignBlocks":0,"CreatorId":"14f9a105-cbc6-47fb-a4bb-58fc6188ecff","ObjectId":"32817288-a13a-4bfc-9be9-db1a1bf6b875","CreatorReadableName":"Iorn Wolves","HashV1":"8fb70db148e5a6e5ca275ae1b5e75081"},"BlockCount":5},{"ContainedMaterialCost":4.0,"CSI":[-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0],"COL":null,"SCs":[],"BLP":["0,0,0","-1,0,0","-1,0,-1","-1,0,-2","-2,0,0"],"BLR":[0,2,2,2,19],"BP1":null,"BP2":null,"BCI":[31,31,31,31,31],"BEI":null,"BlockData":"AAAAKgAAAAcAAQAAAAAAAAIAAAAAAAADAAAAAAAAJIgAAAAAAF0AAAAAAABdGwEAAAAAAAAECAAAAAEAACoAAAAVAAUAAAAAAAABAAAAAAAAAgAAAAAAAHYmAAAABwBCGAAAAAcAXRsBAAAOAAEABAAANEIBAAQAAK5CAAAEAgAAAAMAABUAAAAcAFoAAAAAAAATAAAAABwAXRsBAAAcAMYEBDIAAAAdCQRrAAAAdA0EQwAAAMsRBEQAAAAEAAAjAAAAJwABAAAAAAAAAgAAAAASAAMAAAAAGQBdAAAAACAAXRsBAAAgAKUACAAAAAAAQI9AmAAEEwAAAJgABCgAAAADAAQCAAAAAAAECQAAAA==","VehicleData":"Vy4AAAAAAAAHAAAAAAAAAAAAAAAA8FsKAQAAAAAOAAAAAAAPJwAAAAAA0AcAAAAAAJ9xBAAAAAAADgAAAAAADycAAAAAAKCGAQAAAABHKQEAAAAAAAcAAAAAAAAAAAAAAAA=","designChanged":false,"blueprintVersion":0,"blueprintName":"Spin / Turn block","SerialisedInfo":{"JsonDictionary":{},"IsEmpty":true},"Name":null,"ItemNumber":94,"LocalPosition":"-8,0,-15","LocalRotation":"0,0,0,0.999999","ForceId":0,"TotalBlockCount":5,"MaxCords":"0,0,0","MinCords":"-2,0,-2","BlockIds":[95,319,318,357,182],"BlockState":"=0,5","AliveCount":5,"BlockStringData":[],"BlockStringDataIds":[],"GameVersion":"3.2.3.1","PersistentSubObjectIndex":7,"PersistentBlockIndex":-1,"AuthorDetails":{"Valid":true,"ForeignBlocks":0,"CreatorId":"14f9a105-cbc6-47fb-a4bb-58fc6188ecff","ObjectId":"32817288-a13a-4bfc-9be9-db1a1bf6b875","CreatorReadableName":"Iorn Wolves","HashV1":"8fb70db148e5a6e5ca275ae1b5e75081"},"BlockCount":5},{"ContainedMaterialCost":0.0,"CSI":[-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0],"COL":null,"SCs":[{"ContainedMaterialCost":0.0,"CSI":[-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0],"COL":null,"SCs":[],"BLP":["0,0,0","0,1,0","0,1,-1","0,2,-1","1,1,-1","-1,1,-1","1,1,0","-1,1,0","1,1,1","-1,1,1","0,1,-2","0,0,-1"],"BLR":[0,0,0,0,19,17,19,17,19,17,21,12],"BP1":null,"BP2":null,"BCI":[0,0,0,0,0,0,0,0,0,0,0,0],"BEI":null,"BlockData":"AAAAKgAAABkAAwAAAAAAAAEAAAAAAAACAAAAAAsAdiYAAAASAEIYAAAAEgBdGwEAABIAAgAEAAAAAAYAAQEBAATNzMw9AAAENwAAAAEAACoAAAAjAAUAAAAAAAABAAAAAAcAAgAAAAAHAHYmAAAADgBCGAAAAA4AXRsBAAAcAAAABP8AIf8BAAQAADRCAAAEAMBARAEABGNmRkEAAAQDAAAAAwAADgAAAAcAAAAAAAAAAF0bAQAAAAAAAAQ4AAAACwAADgAAAAcAaQEAAAAAAF0bAQAAAAAAAAQ6AAAA","VehicleData":"Vy4AAAAAAAAHAAAAAAAAAAAAAAAA8FsKAQAAAAAOAAAAAAAPJwAAAAAA0AcAAAAAAJ9xBAAAAAAADgAAAAAADycAAAAAAKCGAQAAAABHKQEAAAAAAAcAAAAAAAAAAAAAAAA=","designChanged":false,"blueprintVersion":0,"blueprintName":"Two Axis Turret","SerialisedInfo":{"JsonDictionary":{},"IsEmpty":true},"Name":null,"ItemNumber":106,"LocalPosition":"0,0,2","LocalRotation":"0,0,0.999999,0","ForceId":0,"TotalBlockCount":12,"MaxCords":"1,2,3","MinCords":"-1,0,-2","BlockIds":[105,35,263,272,122,122,122,122,122,122,122,309],"BlockState":"=0,12","AliveCount":12,"BlockStringData":[],"BlockStringDataIds":[],"GameVersion":"3.2.3.1","PersistentSubObjectIndex":13,"PersistentBlockIndex":-1,"AuthorDetails":{"Valid":true,"ForeignBlocks":0,"CreatorId":"14f9a105-cbc6-47fb-a4bb-58fc6188ecff","ObjectId":"32817288-a13a-4bfc-9be9-db1a1bf6b875","CreatorReadableName":"Iorn Wolves","HashV1":"8fb70db148e5a6e5ca275ae1b5e75081"},"BlockCount":12}],"BLP":["0,0,0","0,0,1","1,0,1","-1,0,1"],"BLR":[0,12,15,11],"BP1":null,"BP2":null,"BCI":[0,0,0,0],"BEI":null,"BlockData":"AAAAKgAAAAcAAQAAAAAAAAIAAAAAAAADAAAAAAAAJIgAAAAAAF0AAAAAAABdGwEAAAAAAAAENAAAAAEAABwAAAAOAAIAAAAAAAABAAAAAAAAjhwAAAAAAF0bAQAADgAAAAQAgOJDAQAEzsyMQAIAAA4AAAAHAAEAAAAAAABdGwEAAAcAAQAEAACAPwMAAA4AAAAHAGkBAAAAAABdGwEAAAAAAAAENgAAAA==","VehicleData":"Vy4AAAAAAAAHAAAAAAAAAAAAAAAA8FsKAQAAAAAOAAAAAAAPJwAAAAAA0AcAAAAAAJ9xBAAAAAAADgAAAAAADycAAAAAAKCGAQAAAABHKQEAAAAAAAcAAAAAAAAAAAAAAAA=","designChanged":false,"blueprintVersion":0,"blueprintName":"Spin / Turn block","SerialisedInfo":{"JsonDictionary":{},"IsEmpty":true},"Name":null,"ItemNumber":94,"LocalPosition":"-1,0,-9","LocalRotation":"0,0,0,-0.999999","ForceId":0,"TotalBlockCount":16,"MaxCords":"1,0,2","MinCords":"-1,0,0","BlockIds":[95,290,279,309],"BlockState":"0000","AliveCount":4,"BlockStringData":[],"BlockStringDataIds":[],"GameVersion":"3.2.3.1","PersistentSubObjectIndex":12,"PersistentBlockIndex":-1,"AuthorDetails":{"Valid":true,"ForeignBlocks":0,"CreatorId":"14f9a105-cbc6-47fb-a4bb-58fc6188ecff","ObjectId":"32817288-a13a-4bfc-9be9-db1a1bf6b875","CreatorReadableName":"Iorn Wolves","HashV1":"8fb70db148e5a6e5ca275ae1b5e75081"},"BlockCount":4}],"BLP":["0,0,-1","-2,0,-1","1,0,-1","-3,0,-1","1,0,-3","-3,0,-3","2,0,-3","-4,0,-3","2,0,-5","-4,0,-5","3,0,-5","-5,0,-5","3,0,-7","-5,0,-7","4,0,-7","-6,0,-7","4,0,-9","-6,0,-9","5,0,-9","-7,0,-9","6,0,-9","-8,0,-9","6,0,-10","-8,0,-10","7,0,-10","-9,0,-10","7,0,-11","-9,0,-11","8,0,-11","-10,0,-11","8,0,-12","-10,0,-12","9,0,-12","-11,0,-12","9,0,-13","-11,0,-13","10,0,-13","-12,0,-13","10,0,-14","-12,0,-14","11,0,-14","-13,0,-14","11,0,-15","-13,0,-15","12,0,-15","-14,0,-15","12,0,-16","-14,0,-16","13,0,-16","-15,0,-16","13,0,-17","-15,0,-17","13,0,-18","-15,0,-18","13,0,-19","-15,0,-19","12,0,-19","-14,0,-19","9,0,-19","-11,0,-19","8,0,-19","-10,0,-19","8,0,-18","-10,0,-18","7,0,-18","-9,0,-18","7,0,-17","-9,0,-17","6,0,-17","-8,0,-17","6,0,-16","-8,0,-16","5,0,-16","-7,0,-16","5,0,-15","-7,0,-15","4,0,-15","-6,0,-15","4,0,-14","-6,0,-14","3,0,-14","-5,0,-14","2,0,-14","-4,0,-14","1,0,-14","-3,0,-14","0,0,-14","-2,0,-14","-1,0,1","0,0,1","-2,0,1","0,0,-2","-2,0,-2","-1,0,-2","-1,0,-3","-1,0,-4","-1,0,-5","-1,0,-6","0,0,-4","-2,0,-4","0,0,-5","-2,0,-5","0,0,-6","-1,1,-2","-1,0,-7","0,0,-7","-2,0,-7","0,0,-13","-2,0,-13","1,0,-13","-3,0,-13","2,0,-13","-4,0,-13","-5,0,-13","3,0,-13","3,0,-9","-5,0,-9","-1,0,-8","-2,0,-8","-2,0,-3","0,0,-3","9,0,-18","-11,0,-18","10,0,-18","-12,0,-18","11,0,-18","-13,0,-18","12,0,-18","-14,0,-18","6,0,-14","-8,0,-14","6,0,-13","-8,0,-13","6,0,-12","-8,0,-12","6,0,-11","-8,0,-11","-3,0,-5","1,0,-5","-3,0,-6","1,0,-6","-4,0,-6","2,0,-6","-3,0,-7","-4,0,-7","-4,0,-8","-2,0,-9","-5,0,-8","0,0,-9","0,0,-8","1,0,-7","2,0,-8","2,0,-7","3,0,-8","12,0,-20","-14,0,-20","9,0,-20","-11,0,-20","10,0,-20","-12,0,-20","11,0,-20","-13,0,-20","11,0,-19","-13,0,-19","10,0,-19","-12,0,-19","-1,0,0","4,0,-10","-6,0,-10","4,0,-11","-6,0,-11","4,0,-12","-6,0,-12","4,0,-13","-6,0,-13","5,0,-13","-7,0,-13","5,0,-12","-7,0,-12","4,-1,-13","-6,-1,-13","4,-1,-12","-6,-1,-12","4,-1,-11","-6,-1,-11","-2,0,-6","-7,0,-10","-7,0,-11","5,0,-10","5,0,-11","-1,1,-7","12,0,-17","-14,0,-17","-3,0,-4","1,0,-4","-1,0,-11","-1,0,-12","-14,1,-17","12,1,-17","-13,1,-17","11,1,-17","-13,1,-16","11,1,-16","-12,1,-17","10,1,-17","-12,1,-18","10,1,-18","-11,1,-18","9,1,-18","-12,1,-19","10,1,-19","-13,1,-19","11,1,-19","-13,1,-18","11,1,-18","-14,1,-18","12,1,-18","-14,1,-19","12,1,-19","-11,1,-19","9,1,-19","-11,1,-17","9,1,-17","-12,1,-16","10,1,-16","-14,1,-16","12,1,-16","-12,-1,-16","10,-1,-16","-13,-1,-16","11,-1,-16","-14,-1,-16","12,-1,-16","-11,-1,-17","9,-1,-17","-12,-1,-17","10,-1,-17","-13,-1,-17","11,-1,-17","-14,-1,-17","12,-1,-17","-11,-1,-18","9,-1,-18","-12,-1,-18","10,-1,-18","-13,-1,-18","11,-1,-18","-14,-1,-18","12,-1,-18","-11,-1,-19","9,-1,-19","-12,-1,-19","10,-1,-19","-13,-1,-19","11,-1,-19","-14,-1,-19","12,-1,-19","-4,0,-9","2,0,-9","-3,0,-9","1,0,-9","1,0,-8","-3,0,-8","-12,0,-17","5,0,-14","-7,0,-14","-1,0,-10"],"BLR":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,1,3,1,3,1,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,21,20,21,20,21,0,14,0,0,12,12,12,12,12,12,0,0,2,2,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,2,2,2,2,2,2,0,0,0,0,1,2,2,2,2,2,2,2,2,2,2,2,2,12,12,12,12,12,12,7,0,10,0,10,2,0,0,0,0,0,0,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,15,13,14,14,13,15,13,15,12,12,0,0,1,3,3,1,0,0,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,2,2,3,1,3,1,22,22,10,4,4,0],"BP1":null,"BP2":null,"BCI":[31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,0,0,0,0],"BEI":null,"BlockData":"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","VehicleData":"Vy4AAAAAAAAHAAAAAAAAAAAAAAAA8FsKAQAAAAAOAAAAAAAPJwAAAAAA0AcAAAAAAJ9xBAAAAAAADgAAAAAADycAAAAAAKCGAQAAAABHKQEAAAAAAAcAAAAAAAAAAAAAAADBfVafAAAAAAcAAAAHAAAAAAAAAAAAAAQBAAAAOe0HAAAAAAAHAAAAAAABAAAAAAAAPjUUAAAAAAAHAAAAHAABAAAAAAAACgAEzcwMPwsABM3MzD0MAATNzMw9DQAEzczMPVJDAAAAAAAABwAAAAcAAQAAAAAAAAIABB8AAADESgAAAAAAAAcAAAAcAAAAAAAAAAAAAATyYcZHAQAEW2bsQwIABKeXzEMDAARoJYtGK94KAAAAAAAHAAAACAABAAAAAAAAAAABAQEAAQEyjlAAAAAAAAcAAAAAAAAAAAAAAADQq2UAAAAAAAcAAAAAAAAAAAAAAADCJ2EAAAAAAAcAAABGAAAAAAAAAAAAAAQAAEhCCgAEAADIwQ8ABAAAXEIUAAQAAPpDGQAEAIA7RTIABABAHEY3AAQAQBxGHgAEAACAPyMABAAAgD8oAAQAAKBB","designChanged":false,"blueprintVersion":15,"blueprintName":"MQ 201","SerialisedInfo":{"JsonDictionary":{},"IsEmpty":true},"Name":null,"ItemNumber":107,"LocalPosition":"9690.829,372.2162,10244.92","LocalRotation":"-0.2727363,-0.3940567,-0.4370401,-0.7611374","ForceId":1709452683,"TotalBlockCount":345,"MaxCords":"13,1,2","MinCords":"-15,-1,-20","BlockIds":[1515,1518,1534,1538,1515,1518,1534,1538,1515,1518,1534,1538,1515,1518,1534,1538,1515,1518,1461,1460,1533,1537,1514,1513,1533,1537,1514,1513,1533,1537,1514,1513,1533,1537,1514,1513,1533,1537,1514,1513,1533,1537,1514,1513,1533,1537,1514,1513,1533,1537,1509,1509,1509,1509,1533,1537,1514,1513,1514,1513,1533,1537,1514,1513,1533,1537,1514,1513,1533,1537,1514,1513,1533,1537,1514,1513,1533,1537,1514,1513,1509,1509,1509,1509,1509,1509,1509,1509,1510,1534,1538,877,877,264,263,263,263,263,283,283,283,283,283,286,260,267,306,795,795,795,795,795,795,763,763,770,770,290,279,295,295,751,751,751,751,751,751,751,751,749,749,749,749,749,749,749,749,664,664,664,664,664,664,752,752,752,752,752,752,752,752,752,752,752,1533,1537,1533,1537,1509,1509,1509,1509,751,751,751,751,199,319,319,318,318,318,318,318,318,327,327,364,364,360,360,358,358,359,359,311,290,309,290,309,296,976,976,976,976,976,976,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,900,901,900,901,900,901,900,901,900,901,900,901,122,122,900,901,900,901,122,122,122,122,122,122,122,122,122,122,122,122,122,122,900,901,122,122,122,122,900,901,821,821,760,760,692,692,403,302,302,186],"BlockState":"=0,267","AliveCount":267,"BlockStringData":["--[[\r\nAdvanced aerial AI, version 5.4\r\nCreated by Madwand 7/3/2020\r\nUse and modify this code however you like, however please credit me\r\nif you use this AI or a derivative of it in a tournament, or you publish a blueprint\r\nusing it. Also let me know if you make any significant improvements,\r\nso I can add them back into the code. \r\nLatest version and documentation is available at:\r\nhttps://github.com/Madwand99/From-the-Depths/tree/master/Advanced%20Aerial%20AI\r\nForum thread to go for help:\r\nhttp://www.fromthedepthsgame.com/forum/showthread.php?tid=9108\r\n--]]\r\n\r\n-- BASIC OPTIONS\r\nAngleBeforeTurn = 0\r\nAngleBeforeRoll = 70\r\nAttackRunDistance = 1000\r\nAbortRunDistance = 300\r\nClosingDistance = 1500\r\nForceAttackTime = 15\r\nCruiseAltitude = 150\r\nMaxDistance = 5000\r\nMaxPitch = 30\r\nMinPitch = -15\r\n\r\n-- SPEED CONTROL\r\nMinimumSpeed = 0\r\nMaximumSpeed = 999\r\nCruiseThrottle = 1\r\nAttackRunThrottle = 1\r\nEscapeThrottle = 1\r\nRollingThrottle = 1\r\nClosingThrottle = 1\r\n\r\n-- PID SETTINGS\r\n--                   P,        D,       I,    OutMax,   OutMin,    IMax,    IMin\r\nyawPIDData      = {0.2,     0.05,     0.0,         1,       -1,       1,      -1}\r\nrollPIDData     = {0.2,     0.05,     0.0,         1,       -1,       1,      -1}\r\npitchPIDData    = {0.2,     0.02,     0.0,         1,       -1,       1,      -1}\r\n\r\n-- HELICOPTER OPTIONS\r\nHeliSpinners = {}\r\nHeliDediblades = {}\r\nMinHelicopterBladeSpeed = 10\r\nMaxHelicopterBladeSpeed = 30\r\n\r\n-- TERRAIN AVOIDANCE OPTIONS\r\nAvoidTerrain = true\r\nMinAltitude = 100\r\nMaxAltitude = 800\r\nTerrainLookahead = {0,1,2,4}\r\nMaxTerrainThrottle = 1\r\nTerrainAvoidanceWeight = 1\r\n\r\n-- WATER START OPTIONS\r\nDeployAlt = 5\r\nReleaseAlt = 15\r\nEnableEnginesAlt = 0\r\n\r\n-- COLLISION AVOIDANCE OPTIONS\r\nCollisionTThreshold = 5\r\nCraftRadius = 25\nBufferSize = 50\r\nEnemyRadius = 50\r\nAvoidFriendlies = true\r\nAvoidTarget = true\r\nAvoidOtherEnemies = true\r\nAvoidanceWeight = 10\r\n\r\n-- STEERING OPTIONS\r\nNeighborRadius = 0\r\nIgnoreBelowSpeed = 40\r\nFlockWithBlueprintNames = {'Cutlass'}\r\nAlignmentWeight = 0\r\nCohesionWeight = 0\r\nSeparationWeight = 0\r\nInjuredWeight = 0\r\nLongRangeWeight = 0\r\nTargetWeight = 1\r\n\r\n-- \"DOGFIGHTING\" OPTIONS\r\nMatchTargetAltitude = true\nMatchAltitudeRange = 1000\r\nMatchAltitudeOffset = 100\r\nMinMatchingAltitude = 50\r\nMaxMatchingAltitude = 800\r\nBroadsideWithin=0\r\nBroadsideAngle=0\r\n\r\n-- MISSILE AVOIDANCE OPTIONS\r\nWarningMainframe = -1\r\nRunAwayTTT = 4\r\nDodgeTTT = 2\r\nDangerRadius = 20\r\nNormalSpeed = 75\r\nRunAwayWeight = 2\r\nDodgingWeight = 5\r\n\r\n-- VECTOR THRUST/LARGE RUDDER OPTIONS\r\nVTSpinners = nil\r\nMaxVTAngle = {40,40,40,90} -- yaw, roll, pitch, VTOL\r\nVTResponseAngleMax = {20,20,20}\r\nVTResponseAngleMin = {5,5,5}\r\nVTSpeed = 30\r\n\r\n--VTOL/HOVER OPTIONS\r\nUseAltitudeJets = false\r\nUseVTOLBeneathSpeed = 0\r\nVTOLEngines = nil\r\nVTOLSpinners = 'all'\r\n\r\n-- ADVANCED OPTIONS\r\nDriveMode = 2\r\nHydrofoilMode = 0\r\nUpdateRate = 1\r\nAltitudeClamp = .2\r\nMainDriveControlType = 0\r\nMaxRollAngle = 90\r\nRollTolerance = 30\r\nDebugMode = false\r\nUsePreferredSide = false\r\nUsePredictiveGuidance = false\r\nAltitudeOffset = 0\r\nAngleOfEscape = 0\r\nExcludeSpinners = nil\r\nOrbitSpawn = true\r\n\r\n--Static variables. Do not change these.\r\nYAWDRIVE = 1\r\nROLLDRIVE = 2\r\nPITCHDRIVE = 3\r\nDRIVEMAIN = 8\r\nDriveTypeDesc = {'Left','Right','RLeft','RRight','PUp','PDown','','','Main'}\r\n\r\nfirstpass = true\r\nstate = \"cruise\"\r\nonattackrun = false\r\nWaterStarted = false\r\nNextAttackTime = 0\r\nPitchCorrection = 0\r\nRollSpinners = {}\r\nPitchSpinners = {}\r\nYawSpinners = {}\r\nHoverSpinners = {}\r\nAllSpinners = {}\r\nExcludedSpinners = {}\r\nRollEngines = {}\r\nPitchEngines = {}\r\nHydrofoils=0\r\nImpulseType = {}\r\nEngineDF = {}\r\nSpinnerStartRotations={}\r\nNumEngines = 0\r\nDesiredAltitude = 0\r\nDesiredAzimuth = 0\r\nOverTerrain = false\r\nRolling = false\r\nThrottle=CruiseThrottle\r\nTicks = 0\r\nVTPower = {0,0,0,0} -- yaw, roll, pitch, VTOL\r\nDodgeDir=0\r\n\r\nfunction InitPID(pidData)\r\n    PID = {}\r\n    PID.Kp            = pidData[1]\r\n    PID.Kd            = pidData[2]\r\n    PID.Ki            = pidData[3]\r\n    PID.OutMax        = pidData[4]\r\n    PID.OutMin        = pidData[5]\r\n    PID.IMax          = pidData[6]\r\n    PID.IMin          = pidData[7]\r\n    PID.integral      = 0\r\n    PID.previousError = 0\r\n\r\n    return PID\r\nend\r\n\r\nfunction InitPIDs()\r\n    rollPID     = InitPID(rollPIDData)\r\n    pitchPID    = InitPID(pitchPIDData)\r\n    yawPID      = InitPID(yawPIDData)\r\nend\r\n\r\nfunction GetPIDOutput(SetPoint, ProcessVariable, PID)\r\n    local error     = SetPoint - ProcessVariable\r\n    local timeDelta = 0.025\r\n    local derivative\r\n    local output\r\n\r\n    PID.integral = PID.integral + (error*timeDelta) * PID.Ki\r\n    if (PID.integral > PID.IMax) then PID.integral = PID.IMax end\r\n    if (PID.integral < PID.IMin) then PID.integral = PID.IMin end\r\n\r\n    derivative = (error - PID.previousError)/timeDelta\r\n\r\n    output = PID.Kp*error + PID.Kd*derivative + PID.integral\r\n    if (output > PID.OutMax) then output = PID.OutMax end\r\n    if (output < PID.OutMin) then output = PID.OutMin end\r\n\r\n    PID.previousError = error\r\n    return output,PID\r\nend\r\n\r\n--Try to pitch (or yaw, if necessary) to a given angle of elevation\r\nfunction AdjustPitchTo(I,DesiredPitch)\r\n  pitchInput,pitchPID = GetPIDOutput(DesiredPitch, Pitch, pitchPID)\r\n\r\n  PitchDiff = Pitch - DesiredPitch\r\n  if (Pitch > DesiredPitch) then\r\n    if (math.abs(Roll)>135) then\r\n      Control(I, PITCHDRIVE, pitchInput, PitchDiff)\r\n    elseif (Roll<-45) then\r\n      Control(I, YAWDRIVE, pitchInput, -PitchDiff)\r\n    elseif (Roll>45) then\r\n      Control(I, YAWDRIVE, -pitchInput, -PitchDiff)\r\n    elseif (math.abs(Roll)<45 and state~=\"rolling\") then\r\n      Control(I, PITCHDRIVE, pitchInput, PitchDiff)\r\n    end\r\n  elseif (Pitch < DesiredPitch) then\r\n    if (math.abs(Roll)>135 and state~=\"rolling\") then\r\n      Control(I, PITCHDRIVE, pitchInput, PitchDiff)\r\n    elseif (Roll<-45) then\r\n      Control(I, YAWDRIVE, pitchInput, -PitchDiff)\r\n    elseif (Roll>45) then\r\n      Control(I, YAWDRIVE, -pitchInput, -PitchDiff)\r\n    elseif (math.abs(Roll)<45) then\r\n      Control(I, PITCHDRIVE, pitchInput, PitchDiff)\r\n    end\r\n  end\r\nend\r\n\r\nfunction GetDesiredAltitude(I, Engaged, Pos)\r\n  local NewAltitude = CruiseAltitude\r\n\r\n  if Engaged and MatchTargetAltitude and Pos.GroundDistance < MatchAltitudeRange then\r\n    NewAltitude = math.max(math.min(Pos.AltitudeAboveSeaLevel+MatchAltitudeOffset,MaxAltitude,MaxMatchingAltitude),MinMatchingAltitude)\r\n  end\r\n\r\n  if AvoidTerrain then\r\n    local VelocityV = I:GetVelocityVector()\r\n    local TerrainAltitude = GetTerrainAltitude(I, VelocityV, {-30,0,30})\r\n    local OverTerrain = Alt < TerrainAltitude + MinAltitude\r\n    return OverTerrain, math.max(NewAltitude, TerrainAltitude + MinAltitude)\r\n  end\r\n\r\n  return false, NewAltitude\r\nend\r\n\r\n--Calculate desired altitude and go there\r\nfunction AdjustAltitude(I, NewAltitude, OverTerrain)\r\n  local AltPower = limiter((NewAltitude-Alt)*AltitudeClamp,1)\r\n  if ((Alt < NewAltitude or VTOLEngines) and Speed<UseVTOLBeneathSpeed) then\r\n    VTPower[4]=math.max(.2,AltPower)\r\n    AdjustPitchTo(I, 0)\r\n  else\r\n    local Angle = math.max(MinPitch,math.min(MaxPitch,(NewAltitude-Alt)*AltitudeClamp))\r\n-- pull up/down with full strength if we are below/above min/max altitudes\r\n    if Alt>MaxAltitude and Pitch>0 then Angle = MinPitch end\r\n    if OverTerrain then Angle = MaxPitch end\r\n    AdjustPitchTo(I, Angle)\r\n  end\r\n\r\n  AdjustAltitudeJets(I,AltPower)\r\n  AdjustHelicopterBlades(I,AltPower)\r\nend\r\n\r\nfunction AdjustAltitudeJets(I,AltPower)\r\n  if not UseAltitudeJets then return end\r\n  if (AltPower>0) then\r\n    I:RequestThrustControl(4,AltPower)\r\n    vertical = \"up\"\r\n  else\r\n    I:RequestThrustControl(5,-AltPower)\r\n    vertical = \"down\"\r\n  end\r\nend\r\n\r\nfunction ControlVTOLPower(I)\r\n  local DriveFraction = {}\r\n  if VTPower[4]~=0 then\r\n    for k,v in pairs(PitchEngines) do DriveFraction[k] = VTPower[4]*EngineDF[k] end\r\n    ComputeEngines(DriveFraction, RollEngines, 2)\r\n    ComputeEngines(DriveFraction, PitchEngines, 3)\r\n  else\r\n    for k,v in pairs(PitchEngines) do DriveFraction[k] = EngineDF[k] end\r\n  end\r\n  for k, v in pairs(PitchEngines) do I:Component_SetFloatLogic(9,k,DriveFraction[k]) end\r\nend\r\n\r\nfunction AdjustHelicopterBlades(I,AltPower)\r\n  if table.getn(HeliSpinners)+table.getn(HeliDediblades)==0 then return end\r\n  local MidSpeed = (MaxHelicopterBladeSpeed-MinHelicopterBladeSpeed)/2\r\n  local SpinSpeed = MinHelicopterBladeSpeed+MidSpeed+AltPower*MidSpeed\r\n  for k,v in pairs(HeliSpinners) do I:SetSpinBlockContinuousSpeed(v, SpinSpeed) end\r\n  for k,v in pairs(HeliDediblades) do I:SetDedibladeContinuousSpeed(v, SpinSpeed) end\r\nend\r\n\r\n-- Get the current stats about angles of the vehicle\r\nfunction GetAngleStats(I)\r\n  Roll = I:GetConstructRoll()\r\n-- transform roll into roll we are familiar with from the game\r\n  if (Roll > 180) then Roll = Roll-360 end\r\n  \r\n  Pitch = -I:GetConstructPitch()\r\n  Yaw = I:GetConstructYaw()\r\n  \r\n-- Many vehicles need to keep their nose pitched upwards relative to velocity.\r\n-- This uses basic machine learning to calculate the upwards pitch correction.\r\n  if not VTPower or VTPower[4]==0 then -- if we haven't been in VTOL mode\r\n    VPitch = math.deg(math.asin(I:GetVelocityVectorNormalized().y)) -- observed pitch from velocity\r\n    PitchCorrection = math.max(MinPitch,math.min(MaxPitch,PitchCorrection + .01*(Pitch-VPitch-PitchCorrection)))\r\n    Pitch = Pitch - PitchCorrection\r\n  end\r\n\r\n  CoM = I:GetConstructCenterOfMass()\r\n  Alt = CoM.y\r\n  ForwardV = I:GetConstructForwardVector()\r\n  Speed=I:GetVelocityMagnitude()\r\nend\r\n\r\nfunction sign(x)\r\n  return x>0 and 1 or x<0 and -1 or 0\r\nend\r\n\r\n-- returns azimuth modified by an offset angle, and whether rolling will be needed\r\nfunction GetModifiedAzimuth(I, Azimuth, Offset, Flock)\r\n  Azimuth = Azimuth-(UsePreferredSide and 1 or sign(Azimuth))*Offset\r\n  if math.abs(Azimuth)>180 then Azimuth=Azimuth-sign(Azimuth)*360 end\r\n  if Flock>0 then Azimuth=Flocking(I,Azimuth,Flock>1) end\r\n  return Azimuth, VTPower[4]==0 and math.abs(Azimuth) > AngleBeforeRoll-Offset\r\nend\r\n\r\n--Finds roll angle needed to broadside target\r\nfunction GetTargetElevation(Pos)\r\n  local DAlt=Alt-Pos.AltitudeAboveSeaLevel\r\n  local d=Pos.GroundDistance*math.cos(math.rad(90-math.abs(Pos.Azimuth)))\r\n  return math.deg(math.atan(DAlt/d))\r\nend\r\n\r\nfunction TurnTowardsAzimuth(I, Azimuth, NewAltitude, Rolling)\r\n  if Rolling then -- roll to turn\r\n    RollTowardsAzimuth(I,Azimuth,NewAltitude)\r\n    YawTowardsAzimuth(I,Azimuth)\r\n    state = \"rolling\"\r\n  else -- yaw to turn\r\n    local RollAngle=0\r\n    if TargetPos.Valid and TargetPos.GroundDistance<BroadsideWithin then\r\n      RollAngle=math.min(MaxRollAngle,(GetTargetElevation(TargetPos)+BroadsideAngle))*(TargetPos.Azimuth>0 and 1 or -1)\r\n    end\r\n\r\n    AdjustRollToAngle(I,RollAngle)\r\n    state = \"yawing\"\r\n    YawTowardsAzimuth(I,Azimuth)\r\n  end\r\nend\r\n\r\n-- Try to roll the craft and pull up on pitch controls to face a given azimuth (relative to the vehicles facing)\r\n-- Will try to set roll angle at one that will maintain a given altitude\r\nfunction RollTowardsAzimuth(I,Azimuth,NewAltitude)\r\n-- depending on our altitude, RollAngle will be set to 90 +/- 40 degrees to climb or descend as appropriate\r\n  RollAngle = sign(Azimuth)*math.min(MaxRollAngle, 90+limiter((Alt-NewAltitude)*.66, 30))\r\n  \r\n  AdjustRollToAngle(I,RollAngle)\r\n\r\n  if (sign(Roll)==sign(Azimuth) and Roll >= RollAngle-RollTolerance and Roll <= RollAngle+RollTolerance) then -- start pitching\r\n    Control(I, PITCHDRIVE, 1, Azimuth)\r\n  end\r\nend\r\n\r\n-- Roll the vehicle to a specified roll angle\r\nfunction AdjustRollToAngle(I,Angle)\r\n  rollInput,rollPID = GetPIDOutput(Angle, Roll, rollPID)\r\n  Control(I, ROLLDRIVE, rollInput, Roll-Angle)\r\nend\r\n\r\n-- transform an absolute azimuth into one relative to the nose of the vehicle\r\nfunction GetRelativeAzimuth(AbsAzimuth)\r\n  local Azimuth = Yaw-AbsAzimuth\r\n  if math.abs(Azimuth)>180 then return Azimuth-sign(Azimuth)*360 end\r\n  return Azimuth\r\nend\r\n      \r\n-- Yaw the vehicle towards a given aziumth (relative to the vehicle's facing)\r\nfunction YawTowardsAzimuth(I,Azimuth)\r\n  if (math.abs(Roll)<30) then\r\n    yawInput,yawPID = GetPIDOutput(0, Azimuth, yawPID)\r\n    Control(I, YAWDRIVE, -yawInput, -Azimuth)\r\n    return true\r\n  end\r\n  return false\r\nend\r\n\r\n-- No enemies, just cruise along\r\nfunction Cruise(I)\r\n  if OrbitSpawn and I:GetNumberOfMainframes()>0 then\r\n    SpawnInfo = I:GetTargetPositionInfoForPosition(0, SpawnPos.x, 0, SpawnPos.z)\r\n    NavigateToPoint(I, false, SpawnInfo)\r\n  else\r\n    if I:GetNumberOfMainframes()==0 then\r\n      I:LogToHud(\"No AI mainframe found; please add one!\")\r\n    end\r\n    state = \"cruise\"\r\n    OverTerrain, DesiredAltitude = GetDesiredAltitude(I,false,nil)\r\n    AdjustAltitude(I, DesiredAltitude, OverTerrain)\r\n    AdjustRollToAngle(I, 0)\r\n    SetSpeed(I, CruiseThrottle)\r\n    NextAttackTime = I:GetTime()+ForceAttackTime\r\n  end\r\nend\r\n\r\n-- Given the current velocity vector and an azimuth, get the expected terrain height in that direction\r\nfunction GetTerrainAltitude(I, VelocityV, Angles)\r\n  local TerrainAltitude = -999\r\n  for j,Angle in ipairs(Angles) do\r\n    for i,Lookahead in ipairs(TerrainLookahead) do\r\n      local Position = CoM + Quaternion.Euler(0,Angle,0) * VelocityV * Lookahead\r\n      TerrainAltitude = math.max(TerrainAltitude,I:GetTerrainAltitudeForPosition(Position))\r\n    end\r\n  end\r\n  return TerrainAltitude\r\nend\r\n\r\nfunction GetIntercept(I, Pos)\r\n  local TTT = FindConvergence(I, Pos.Position, Pos.Velocity, CoM, Speed, Speed*.75)\r\n  local Prediction = Pos.Position + Pos.Velocity * TTT\r\n  return TTT, I:GetTargetPositionInfoForPosition(0, Prediction.x, 0, Prediction.z).Azimuth, Prediction.y\r\nend\r\n\r\n-- Perform a water start check. Returns true if movement is permitted.\r\nfunction WaterStartCheck(I)\r\n  if (Alt < DeployAlt) then \r\n    I:Component_SetBoolLogicAll(0, true)\r\n    WaterStarted = true\r\n  elseif (WaterStarted and Alt > ReleaseAlt) then\r\n    I:Component_SetBoolLogicAll(0, false)\r\n    WaterStarted = false\r\n  end\r\n  \r\n  if (not WaterStarted or Alt>=EnableEnginesAlt) then\r\n    return true\r\n  end\r\n  return false\r\nend\r\n\r\nfunction SetSpeed(I, Throttle)\r\n  if (Speed>MaximumSpeed) then Throttle=.1\r\n  elseif (Speed<MinimumSpeed) then Throttle=1 end\r\n  if MainDriveControlType==1 then\r\n    I:RequestThrustControl(0)\r\n  elseif MainDriveControlType==2 then\r\n    I:RequestControl(DriveMode,DRIVEMAIN,1)\r\n    for k, v in pairs(Main) do I:Component_SetFloatLogic(9,v,Throttle) end\r\n  else\r\n    I:RequestControl(DriveMode,DRIVEMAIN,Throttle)\r\n  end\r\nend\r\n\r\nfunction limiter(p,l)\r\n  return math.min(l,math.max(-l,p))\r\nend\r\n\r\nfunction Control(I, DoFType, Impulse, Angle)\r\n  local Type = DoFType*2 - (Impulse<0 and 1 or 2)\r\n  I:RequestControl(DriveMode, Type, math.abs(Impulse))\r\n  DriveDesc[DoFType] = DriveTypeDesc[Type+1]\r\n  ImpulseType[DoFType] = Impulse\r\n  if math.abs(Angle)>VTResponseAngleMin[DoFType] then\r\n    local Max=VTResponseAngleMax[DoFType]-VTResponseAngleMin[DoFType]+.01\r\n    VTPower[DoFType] = limiter(Angle-sign(Angle)*VTResponseAngleMin[DoFType],Max)/Max\r\n  else VTPower[DoFType]=0 end\r\nend\r\n\r\nfunction ComputeSpinners(Rotation, Spinners, Axis)\r\n  for Spinner,Dir in pairs(Spinners) do\r\n    Rotation[Spinner] = Rotation[Spinner] + Dir*VTPower[Axis]*MaxVTAngle[Axis]\r\n  end\r\nend\r\n\r\nfunction ComputeEngines(DriveFraction, Engines, Axis)\r\n  for Engine,Dir in pairs(Engines) do\r\n    if Dir==sign(VTPower[Axis]) then\r\n      DriveFraction[Engine] = DriveFraction[Engine]*(1-math.abs(VTPower[Axis]))\r\n    end\r\n  end\r\nend\r\n\r\nfunction VectorEngines(I)\r\n  local RL,RR,RY = 0,0,0\r\n  \r\n  local Rotation = {}\r\n  for k,v in pairs(AllSpinners) do Rotation[v] = 0 end\r\n  \r\n  if (state==\"rolling\" and VTPower[3]>0) then\r\n    VTPower[3]=0\r\n  end\r\n  ComputeSpinners(Rotation, YawSpinners, 1)\r\n  ComputeSpinners(Rotation, RollSpinners, 2)\r\n  ComputeSpinners(Rotation, PitchSpinners, 3)\r\n  if (VTOLEngines and VTPower[4]~=0) then -- VTOL Mode\r\n    for Spinner,Dir in pairs(HoverSpinners) do Rotation[Spinner] = Dir*MaxVTAngle[4] end\r\n  else\r\n    ComputeSpinners(Rotation, HoverSpinners, 4)\r\n  end \r\n\r\n  RotateSpinnersTo(I,Rotation)\r\n  \r\n  --I:LogToHud(string.format(\"Y: %.02f R: %.02f P: %.02f\", VTPower[1], VTPower[2], VTPower[3]))\r\nend\r\n\r\nfunction ClassifySpinner(I,p)\r\n  if VTSpinners=='all' and ExcludedSpinners[p] then return end\r\n  local info = I:GetSubConstructInfo(p)\r\n  local h,a,b = EulerAngles(info.LocalRotation)\r\n  local pos = info.LocalPositionRelativeToCom\r\n  SpinnerStartRotations[p]=I:GetSubConstructIdleRotation(p)\r\n  a=math.floor(a+.5)\r\n  b=math.floor(b+.5)\r\n  if (a==0 and b==0) then\r\n    tinsert(pos.z,YawSpinners,1,-1,p)\r\n    AddSpinner(pos.y,-1,p)\r\n  elseif (a==0 and math.abs(b)>170) then\r\n    tinsert(pos.z,YawSpinners,-1,1,p)\r\n    AddSpinner(pos.y,1,p)\r\n  else\r\n    local h,a,b = EulerAngles(info.LocalRotation*Quaternion.Euler(0, 0, 90))\r\n    h=math.floor(h+.5)\r\n    a=math.floor(a+.5)\r\n    if (h==0 and a==0) then -- pointed right\r\n      tinsert(pos.z,PitchSpinners,1,-1,p)\r\n      if VTOLSpinners=='all' and ExcludedSpinners[p] then tinsert(pos.z,HoverSpinners,-1,-1,p) end\r\n      AddSpinner(pos.x,-1,p)\r\n    elseif (a==0 and math.abs(h)>170) then -- pointed left\r\n      tinsert(pos.z,PitchSpinners,-1,1,p)\r\n      if VTOLSpinners=='all' and ExcludedSpinners[p] then tinsert(pos.z,HoverSpinners,1,1,p) end\r\n      AddSpinner(pos.x,1,p)\r\n    end\r\n  end\r\nend\r\n\r\nfunction ClassifyVTOLSpinner(I,p)\r\n  local info = I:GetSubConstructInfo(p)\r\n  local h,a,b = EulerAngles(info.LocalRotation*Quaternion.Euler(0, 0, 90))\r\n  local pos = info.LocalPositionRelativeToCom\r\n  h=math.floor(h+.5)\r\n  a=math.floor(a+.5)\r\n  --I:Log(string.format(\"Spinner: %d Orientation: (%.2f, %.2f, %.2f) Position: (%.2f, %.2f, %.2f)\", p, h, a, b, pos.x, pos.y, pos.z))\r\n  if (h==0 and a==0) then\r\n    tinsert(pos.z,HoverSpinners,-1,-1,p)\r\n  elseif (a==0 and math.abs(h)>170) then\r\n    tinsert(pos.z,HoverSpinners,1,1,p)\r\n  end\r\nend\r\n\r\nfunction GetPosRelativeToCoM(pos)\r\n  local rot = Quaternion.Inverse(Quaternion.LookRotation(ForwardV))\r\n  local rpos = rot*(pos-CoM)\r\n  for i, p in ipairs(rpos) do rpos[i]=math.floor(p*10+.5)/10 end\r\n  return rpos\r\nend\r\n\r\nfunction ClassifyEngine(I,p,force)\r\n  local info = I:Component_GetBlockInfo(9,p)\r\n  if (force or info.LocalForwards.y==1) then\r\n    pos = GetPosRelativeToCoM(info.Position)\r\n    EngineDF[p] = I:Component_GetFloatLogic(9,p)\r\n    tinsert(pos.z,PitchEngines,1,-1,p)\r\n    if pos.x<-1.1 then  -- on left\r\n      tinsert(pos.z,RollEngines,-1,-1,p)\r\n    elseif pos.x>1.1 then -- on right\r\n      tinsert(pos.z,RollEngines,1,1,p)\r\n    end\r\n  end\r\nend\r\n\r\nfunction AddSpinner(comp,dir,p)\r\n  if comp<-1 then  -- on left\r\n    RollSpinners[p] = dir\r\n  elseif comp>1 then -- on right\r\n    RollSpinners[p] = -dir\r\n  end\r\n  table.insert(AllSpinners,p)\r\nend\r\n      \r\nfunction tinsert(z,s,x,y,p)\r\n  s[p] = z>0 and x or y\r\nend\r\n\r\nfunction ClassifyHydrofoil(I,p)\r\n  local info = I:Component_GetBlockInfo(8,p)\r\n  local pos = info.LocalPositionRelativeToCom\r\n  local h,a,b = EulerAngles(info.LocalRotation)\r\n  h=math.floor(h+.5)\r\n  a=math.floor(a+.5)\r\n\r\n  if h/180~=math.floor(h/180) then\r\n    return -- not properly placed\r\n  elseif a==0 then\r\n    PitchHydros[p],RollHydros[p]=HydroTurnRoll(h==0,pos.z,pos.x)\r\n  else\r\n    YawHydros[p],  RollHydros[p]=HydroTurnRoll(a>=0,pos.z,pos.y)\r\n  end\r\nend\r\n\r\nfunction HydroTurnRoll(test,pos1,pos2)\r\n  local forwards=test and 1 or -1\r\n  local HTurn,HRoll = nil,nil\r\n  if pos1>Length/6 then\r\n    HTurn=forwards\r\n  elseif pos1<-Length/6 then\r\n    HTurn=-forwards\r\n  end\r\n\r\n  if HydrofoilMode==2 or not HTurn then\r\n    if pos2<0 then\r\n      HRoll=forwards\r\n    elseif pos2>0 then\r\n      HRoll=-forwards\r\n    end\r\n  end\r\n  return HTurn,HRoll\r\nend\r\n\r\nfunction ClassifyHydrofoils(I)\r\n  if HydrofoilMode>0 and Hydrofoils~=I:Component_GetCount(8) then\r\n    Hydrofoils=I:Component_GetCount(8)\r\n    YawHydros,RollHydros,PitchHydros={},{},{}\r\n    for p = 0, Hydrofoils - 1 do ClassifyHydrofoil(I,p) end\r\n  end\r\nend\r\n\r\nfunction AdjustHydrofoils(I)\r\n  local Hydros={}\r\n  local ToYaw=ImpulseType[1]*45\r\n  local ToRoll=-ImpulseType[2]*45\r\n  local ToPitch=ImpulseType[3]*45\r\n  for p = 0, Hydrofoils - 1 do Hydros[p]=0 end\r\n  for p, k in pairs(YawHydros) do Hydros[p]=ToYaw*k end\r\n  for p, k in pairs(PitchHydros) do Hydros[p]=ToPitch*k end\r\n  for p, k in pairs(RollHydros) do Hydros[p]=Hydros[p]+ToRoll*k end\r\n  for p, k in pairs(Hydros) do I:Component_SetFloatLogic(8,p,k) end\r\nend\r\n\r\nfunction EulerAngles(q1)\r\n  local sqw = q1.w*q1.w\r\n  local sqx = q1.x*q1.x\r\n  local sqy = q1.y*q1.y\r\n  local sqz = q1.z*q1.z\r\n  local unit = sqx + sqy + sqz + sqw --if normalised is one, otherwise is correction factor\r\n  local test = q1.x*q1.y + q1.z*q1.w\r\n  local heading, attitude, bank\r\n  if (test > 0.499*unit) then --singularity at north pole\r\n    heading = 2 * math.atan2(q1.x,q1.w)\r\n    attitude = math.pi/2;\r\n    bank = 0\r\n  elseif (test < -0.499*unit) then --singularity at south pole\r\n    heading = -2 * math.atan2(q1.x,q1.w)\r\n    attitude = -math.pi/2\r\n    bank = 0\r\n  else\r\n    heading = math.atan2(2*q1.y*q1.w-2*q1.x*q1.z , sqx - sqy - sqz + sqw)\r\n    attitude = math.asin(2*test/unit)\r\n    bank = math.atan2(2*q1.x*q1.w-2*q1.y*q1.z , -sqx + sqy - sqz + sqw)\r\n  end\r\n  return math.deg(heading), math.deg(attitude), math.deg(bank)\r\nend\r\n\r\nfunction RotateSpinnersTo(I, Spinners)\r\n  for Spinner, NewAngle in pairs(Spinners) do\r\n    local Angle = EulerAngles(Quaternion.Inverse(SpinnerStartRotations[Spinner]) * I:GetSubConstructInfo(Spinner).LocalRotation)\r\n    local DeflectAngle = limiter(limiter(NewAngle,90)-Angle,VTSpeed*43/30)\r\n    if math.abs(DeflectAngle)<1 then DeflectAngle=0 end\r\n    I:SetSpinBlockContinuousSpeed(Spinner,DeflectAngle*30/43)\r\n  end\r\nend\r\n\r\nfunction FindConvergence(I, tPos, tVel, wPos, wSpeed, minConv)\r\n   local relativePosition = wPos - tPos\r\n   local distance = Vector3.Magnitude(relativePosition)\r\n   local targetAngle = I:Maths_AngleBetweenVectors(relativePosition, tVel)\r\n   local tSpeed = Vector3.Magnitude(tVel)\r\n\r\n   local a = tSpeed^2 - wSpeed^2\r\n   local b = -2 * tSpeed * distance * math.cos(math.rad(targetAngle))\r\n   local c = distance^2\r\n   local det = math.sqrt(b^2-4*a*c)\r\n   local ttt = distance / (minConv+.01)\r\n\r\n   if det > 0 then\r\n      local root1 = math.min((-b + det)/(2*a), (-b - det)/(2*a))\r\n      local root2 = math.max((-b + det)/(2*a), (-b - det)/(2*a))\r\n      ttt = (root1 > 0 and root1) or (root2 > 0 and root2) or ttt\r\n   end\r\n   return ttt\r\nend\r\n\r\nfunction GetMissileWarnings(I)\r\n  local NumWarnings = I:GetNumberOfWarnings(WarningMainframe)\r\n  local OwnVelocity = ForwardV * math.max(NormalSpeed, Speed)\r\n  local TTTs={}\r\n  local Warnings={}\r\n  \r\n  for w = 0, NumWarnings - 1 do\r\n    local Warning = I:GetMissileWarning(WarningMainframe, w)\r\n    if Warning.Valid and I:Maths_AngleBetweenVectors(Warning.Velocity, CoM - Warning.Position) < 90 then\r\n      local mSpeed = Vector3.Magnitude(Warning.Velocity)\r\n      local TTT = FindConvergence(I, CoM, OwnVelocity, Warning.Position, mSpeed, mSpeed*.75)\r\n      local PredictedPosition = CoM + OwnVelocity * TTT\r\n      local Orthogonal = (Warning.Position + Vector3.Normalize(Warning.Velocity)\r\n                         * Vector3.Distance(Warning.Position, PredictedPosition)\r\n                         * math.cos(math.rad(I:Maths_AngleBetweenVectors(Warning.Velocity, PredictedPosition - Warning.Position))))\r\n                         - PredictedPosition\r\n      local AdjustedPosition = PredictedPosition + Vector3.ClampMagnitude(Orthogonal, CraftRadius)\r\n      local Radius = (Vector3.Distance(Warning.Position, AdjustedPosition) / 2)\r\n                     / math.cos(math.rad(I:Maths_AngleBetweenVectors(Warning.Velocity, AdjustedPosition - Warning.Position) - 90))\r\n      if TTT < math.max(RunAwayTTT,DodgeTTT) and Radius > DangerRadius then\r\n        table.insert(TTTs, TTT)\r\n        table.insert(Warnings, Warning)\r\n      end\r\n    end\r\n  end\r\n  return TTTs, Warnings\r\nend\r\n\r\nfunction PrintList(I, name, list)\r\n  str = name..': '\r\n  for i,v in pairs(list) do\r\n    str = str..string.format(\"%d \", i)\r\n  end\r\n  I:Log(str)\r\nend\r\n\r\nfunction ClassifyEngines(I)\r\n  if NumEngines==I:Component_GetCount(9) then return end\r\n  NumEngines=I:Component_GetCount(9)\r\n\r\n  Main={} -- try to figure out which drives are pointed backwards\r\n  for p = 0, NumEngines - 1 do\r\n    local info=I:Component_GetBlockInfo(9,p)\r\n    if (info.LocalForwards.z==1 and GetPosRelativeToCoM(info.Position)==info.LocalPositionRelativeToCom) then\r\n      table.insert(Main,p)\r\n    end\r\n  end\r\n\r\n  if VTOLEngines=='all' then\r\n    for p = 0, NumEngines - 1 do ClassifyEngine(I,p,false) end\r\n  end\r\n  PrintList(I,\"RollEngines\",RollEngines)\r\n  PrintList(I,\"PitchEngines\",PitchEngines)\r\n  PrintList(I,\"Main\",Main)\r\nend\r\n\r\nfunction NameMatches(Name)\r\n  if FlockWithBlueprintNames=='all' then return true end\r\n  if type(FlockWithBlueprintNames) == \"table\" then\r\n    for k,v in pairs(FlockWithBlueprintNames) do\r\n      if v==string.sub(Name,1,string.len(v)) then return true end\r\n    end\r\n  elseif FlockWithBlueprintNames==string.sub(Name,1,string.len(FlockWithBlueprintNames)) then return true\r\n  end\r\n  return false\r\nend\r\n\r\nfunction SteerToAvoidCollisions(I)\r\n  local ThreatCoM, ThreatVel\r\n  local minTime = CollisionTThreshold\r\n  local OwnVelocity = ForwardV * Speed\r\n\r\n  if AvoidFriendlies then\r\n    local FCount = I:GetFriendlyCount()\r\n    for f = 0, FCount-1 do\r\n      local FInfo = I:GetFriendlyInfo(f)\r\n      if FInfo.Valid then\r\n        local time, dist = GetApproach(OwnVelocity, FInfo.Velocity, FInfo.CenterOfMass)\r\n        if time>=0 and time<minTime then\r\n          fsize = math.max(unpack(FInfo.PositiveSize-FInfo.NegativeSize))\r\n          if dist < CraftRadius+fsize/2+BufferSize then\r\n            minTime=time\r\n            ThreatCoM, ThreatVel = FInfo.CenterOfMass, FInfo.Velocity\r\n          end\r\n        end\r\n      end\r\n    end\r\n  end\r\n\r\n  if (AvoidTarget or AvoidOtherEnemies) and I:GetNumberOfMainframes() > 0 then\r\n    local ECount = I:GetNumberOfTargets(0)\r\n    for e = (AvoidTarget and 0 or 1), (AvoidOtherEnemies and ECount-1 or 0) do\r\n      local EInfo = I:GetTargetPositionInfo(0,e)\r\n      if EInfo.Valid then\r\n        local time, dist, tpos = GetApproach(OwnVelocity, EInfo.Velocity, EInfo.Position)\r\n        if time>=0 and time<minTime and dist < CraftRadius+EnemyRadius+BufferSize then\r\n          minTime=time\r\n          ThreatPos, ThreatCoM, ThreatVel = tpos, EInfo.Position, EInfo.Velocity\r\n        end\r\n      end\r\n    end\r\n  end\r\n\r\n  return I:GetConstructRightVector()*Dodge(I, minTime, CollisionTThreshold, ThreatVel, ThreatCoM)\r\nend\r\n\r\n-- Given a time-to-target, threat velocity,\r\n-- and threat CoM, returns a dodge vector\r\nfunction Dodge(I, TTT, TThreshold, TVel, TCoM)\r\n  local side = I:GetConstructRightVector()\r\n  local steer = 0\r\n\r\n  if TTT<TThreshold then\r\n    local parallelness = Vector3.Dot(ForwardV, TVel.normalized)\r\n    \r\n    if parallelness<-0.707 then  -- head-on collision\r\n      local TFPos=TCoM+TVel*TTT\r\n      local offset=TFPos-CoM\r\n      local sideDot=Vector3.Dot(offset,side)\r\n      steer = sideDot>0 and -1 or 1\r\n    else--if parallelness>0.707 then  -- parallel paths\r\n      local offset=TCoM-CoM\r\n      local sideDot=Vector3.Dot(offset,side)\r\n      steer = sideDot>0 and -1 or 1      \r\n--    else  --perpendicular paths\r\n--      if TVel.magnitude<=Speed then\r\n--        local sideDot=Vector3.Dot(side,TVel)\r\n--        steer = sideDot>0 and -1 or 1\r\n--      end\r\n    end    \r\n  end\r\n\r\n  return steer\r\nend\r\n\r\nfunction GetApproach(OwnVelocity, TVelocity, TPos)\r\n  local relVelocity = TVelocity - OwnVelocity\r\n  local relSpeed = relVelocity.magnitude+.01\r\n\r\n  if relSpeed==0 then return 0 end\r\n\r\n  local relTangent = relVelocity / relSpeed\r\n  local relPos = CoM - TPos\r\n  local projection = Vector3.Dot(relTangent,relPos)\r\n\r\n  local time = projection/relSpeed\r\n\r\n  local myFinal = CoM + ForwardV*Speed*time\r\n  local oFinal = TPos + TVelocity*time\r\n\r\n  return time, (myFinal-oFinal).magnitude\r\nend\r\n\r\nfunction Flocking(I, Azimuth, Escaping)\r\n  local A = Vector3(0,0,0)\r\n  local C,S,J,L,E,D,M = A,A,A,A,A,A,A\r\n  local Near,Aligning,Injured,Far,Terrain=0,0,0,0,0\r\n\r\n  local V=SteerToAvoidCollisions(I)*AvoidanceWeight\r\n\r\n  if NeighborRadius>0 then\r\n    local FCount = I:GetFriendlyCount()\r\n    for f = 0, FCount-1 do\r\n      local FInfo = I:GetFriendlyInfo(f)\r\n      if FInfo.Valid then\r\n        local Dist=FInfo.CenterOfMass-CoM\r\n        if Dist.magnitude<NeighborRadius then\r\n          if FInfo.Velocity.magnitude>=IgnoreBelowSpeed and NameMatches(FInfo.BlueprintName) then\r\n            A=A+FInfo.Velocity  -- Alignment\r\n            C=C+FInfo.CenterOfMass -- Cohesion\r\n            J=J+FInfo.CenterOfMass*(1-FInfo.HealthFraction) -- Injured cohesion\r\n            Aligning=Aligning+1\r\n            Injured=Injured+(1-FInfo.HealthFraction)\r\n          end\r\n          S=S+Dist -- Separation\r\n          Near=Near+1\r\n        elseif FInfo.Velocity.magnitude>=IgnoreBelowSpeed and NameMatches(FInfo.BlueprintName) then\r\n          L=L+FInfo.CenterOfMass -- Long-range cohesion\r\n          Far=Far+1\r\n        end\r\n      end\r\n    end\r\n\r\n    if Aligning>0 then\r\n      A=(A/Aligning).normalized*AlignmentWeight\r\n      C=(C/Aligning-CoM).normalized*CohesionWeight\r\n    end\r\n    if Injured>0 then J=(J/Injured-CoM).normalized*InjuredWeight end\r\n    if Far>0 then L=(L/Far-CoM).normalized*LongRangeWeight end\r\n    if Near>0 then S=(-S/Near).normalized*SeparationWeight end\r\n  end\r\n\r\n  if TerrainAvoidanceWeight~=0 then\r\n    local VelocityV = I:GetVelocityVector()\r\n    local Angles = {0,45,90,135,180,225,270,315}\r\n    for k, a in pairs(Angles) do\r\n      local Position = CoM + Quaternion.Euler(0,a,0) * VelocityV\r\n      local TerrainAltitude = GetTerrainAltitude(I, VelocityV, {a})\r\n      if (TerrainAltitude + MinAltitude > CruiseAltitude) then\r\n        local Dist=Position-CoM\r\n        E=E+Dist*(TerrainAltitude + MinAltitude - CruiseAltitude)\r\n        Terrain=Terrain+1\r\n      end\r\n    end\r\n    if Terrain>0 then E=(-E/Terrain).normalized*TerrainAvoidanceWeight end\r\n  end\r\n\r\n  if WarningMainframe>=0 and I:GetNumberOfMainframes() > 0 and RunAwayWeight+DodgingWeight~=0 then \r\n    local TTTs, Warnings = GetMissileWarnings(I)\r\n    local DodgingTTT=RunAwayTTT\r\n    local DodgeCount=0\r\n    for w,t in ipairs(TTTs) do\r\n      if t<DodgeTTT then DodgeCount=DodgeCount+1 end\r\n      if not Dodging then DodgeDir=DodgeDir+Dodge(I, t, DodgeTTT, Warnings[w].Velocity, Warnings[w].Position)*(1-t/RunAwayTTT) end\r\n      D=D+(CoM-Warnings[w].Position).normalized*(1-t/RunAwayTTT)*RunAwayWeight\r\n    end\r\n    Dodging = DodgeCount~=0\r\n    if Dodging then D=(I:GetConstructRightVector()*DodgeDir).normalized*DodgingWeight\r\n    else DodgeDir=0 end\r\n  end \r\n\r\n  local T=Quaternion.Euler(0,Yaw-Azimuth,0)*Vector3.forward*TargetWeight*(Escaping and 0.1 or 1)\r\n  if TargetPos.Valid and MaxDistance>0 then\r\n    local ToTarget=TargetPos.Position-CoM\r\n    M=ToTarget.normalized*math.max(0,ToTarget.magnitude-MaxDistance)-E\r\n  end\r\n\r\n  local AllVectors=A+C+S+J+L+E+T+V+D+M\r\n  local Objective = CoM+AllVectors\r\n  return I:GetTargetPositionInfoForPosition(0, Objective.x, 0, Objective.z).Azimuth\r\nend\r\n\r\nfunction GetNavigationInfo(I,Engaged,Pos)\r\n  Throttle = EscapeThrottle\r\n  local CollisionTTT, CollisionAzimuth, CollisionAlt = GetIntercept(I, Pos)\r\n  local OverTerrain, NewAltitude = GetDesiredAltitude(I,Engaged,Pos)\r\n  local NewAzimuth, Rolling\r\n\r\n  if (Pos.GroundDistance > ClosingDistance) then\r\n    NewAzimuth, Rolling=GetModifiedAzimuth(I, CollisionAzimuth, 0, 1)\r\n    Throttle = ClosingThrottle\r\n    state = \"closing\"\r\n    onattackrun = true\r\n  elseif onattackrun then\r\n    NewAzimuth, Rolling = GetModifiedAzimuth(I, UsePredictiveGuidance and CollisionAzimuth or Pos.Azimuth, AngleBeforeTurn, 1)\r\n    Throttle = AttackRunThrottle\r\n    if (Pos.GroundDistance < AbortRunDistance) then\r\n      onattackrun = false\r\n      NextAttackTime = I:GetTime()+ForceAttackTime\r\n      EscapeAngle = Yaw+(UsePreferredSide and 1 or sign(NewAzimuth))*AngleOfEscape\r\n    end\r\n  else -- not on attack run, just go forwards until we're out of range\r\n    NewAzimuth, Rolling=GetModifiedAzimuth(I, GetRelativeAzimuth(EscapeAngle), 0, 2)\r\n    state = \"escaping\"\r\n    onattackrun = Pos.GroundDistance > AttackRunDistance or I:GetTime()>NextAttackTime\r\n  end\r\n  \r\n  if Rolling then Throttle=RollingThrottle end\r\n  if OverTerrain then\r\n    Throttle = math.min(Throttle,MaxTerrainThrottle)\r\n  end\r\n  if not Engaged then\r\n    Throttle = math.min(Throttle,CruiseThrottle)\r\n  end\r\n\r\n  return OverTerrain, NewAltitude, NewAzimuth, Rolling\r\nend\r\n\r\n-- given information about a target, navigates to it\r\nfunction NavigateToPoint(I, Engaged, Pos)\r\n  if Ticks==0 then\r\n    OverTerrain, DesiredAltitude, DesiredAzimuth, Rolling = GetNavigationInfo(I,Engaged,Pos)\r\n  end\r\n  Ticks = Ticks+1\r\n  if Ticks>=UpdateRate then Ticks=0 end\r\n\r\n  AdjustAltitude(I, DesiredAltitude, OverTerrain)\r\n  TurnTowardsAzimuth(I, DesiredAzimuth, DesiredAltitude, Rolling)\r\n  SetSpeed(I, Throttle)\r\nend\r\n\r\nfunction Initialize(I)\r\n  if not firstpass then return end\r\n  firstpass = false\r\n\r\n  SpawnPos = CoM\r\n  EscapeAngle = Yaw\r\n  if type(AltitudeOffset) == \"table\" then\r\n    math.randomseed(I:GetTime()+CoM.x+CoM.y+CoM.z)\r\n    AltitudeOffset=math.floor(math.random()*(AltitudeOffset[2]-AltitudeOffset[1])+AltitudeOffset[1])\r\n    I:Log(\"AltitudeOffset: \"..AltitudeOffset)\r\n  end\r\n  CruiseAltitude = CruiseAltitude+AltitudeOffset\r\n  MaxAltitude = MaxAltitude+AltitudeOffset\r\n  MatchAltitudeOffset = MatchAltitudeOffset+AltitudeOffset\r\n  MinMatchingAltitude = MinMatchingAltitude+AltitudeOffset\r\n  MaxMatchingAltitude = MaxMatchingAltitude+AltitudeOffset\r\n  Length = (I:GetConstructMaxDimensions() - I:GetConstructMinDimensions()).z\r\n\r\n  Ticks=math.floor(math.random()*UpdateRate)\r\n\r\n  InitPIDs()\r\n\r\n  if type(VTOLEngines) == \"table\" then\r\n    for k, p in pairs(VTOLEngines) do ClassifyEngine(I,p,true) end\r\n  end\r\n\r\n  if ExcludeSpinners then\r\n    for k, p in pairs(ExcludeSpinners) do ExcludedSpinners[p]=true end\r\n  end\r\n\r\n  if HeliSpinners=='all' then\r\n    HeliSpinners={}\r\n    for k,p in pairs(I:GetAllSubConstructs()) do\r\n      if I:IsSpinBlock(p) then\r\n        table.insert(HeliSpinners, p)\r\n      end\r\n    end\r\n  elseif HeliSpinners then\r\n    for k, p in pairs(HeliSpinners) do ExcludedSpinners[p]=true end\r\n  end\r\n\r\n  if HeliDediblades=='all' then\r\n    HeliDediblades={}\r\n    for p = 0, I:GetDedibladeCount() - 1 do\r\n       table.insert(HeliDediblades, p)\r\n    end\r\n  end\r\n\r\n  if VTSpinners=='all' then\r\n    local subs = I:GetAllSubConstructs();\r\n    for i = 1, #subs do\r\n      p = subs[i]\r\n      if I:IsSpinBlock(p) and not ExcludedSpinners[p] then\r\n        ClassifySpinner(I,p)\r\n      end\r\n    end\r\n  elseif type(VTSpinners) == \"table\" then\r\n    for k, p in pairs(VTSpinners) do\r\n      ClassifySpinner(I,p)\r\n    end\r\n  end\r\n\r\n  if type(VTOLSpinners) == \"table\" then\r\n    for k, p in pairs(VTOLSpinners) do ClassifyVTOLSpinner(I,p) end\r\n  end\r\n  PrintList(I,\"RollSpinners\",RollSpinners)\r\n  PrintList(I,\"PitchSpinners\",PitchSpinners)\r\n  PrintList(I,\"YawSpinners\",YawSpinners)\r\n  PrintList(I,\"HoverSpinners\",HoverSpinners)\r\n\r\n  I:Log(\"AI successfully initialized.\")\r\nend\r\n\r\n-- Calculate all movement for the vehicle\r\nfunction Movement(I)\r\n  Initialize(I)\r\n  ClassifyEngines(I)\r\n  ClassifyHydrofoils(I)\r\n\r\n  DriveDesc = {'','','',''}\r\n    \r\n  TargetPos = I:GetTargetPositionInfo(0,0)\r\n  if TargetPos.Valid then\r\n      NavigateToPoint(I, true, TargetPos)\r\n  else\r\n    Cruise(I)\r\n  end\r\n  \r\n  if VTSpinners then VectorEngines(I) end\r\n  if VTOLEngines then ControlVTOLPower(I) end\r\n  if HydrofoilMode>0 then AdjustHydrofoils(I) end\r\n  \r\n  if DebugMode then\r\n    --I:LogToHud(string.format(\"%.2f %.2f\", DPitch, math.abs(Roll)))\r\n    I:LogToHud(string.format(\"%s %s %s %s %f\", state, DriveDesc[1], DriveDesc[2], DriveDesc[3], Throttle))\r\n    --I:LogToHud(string.format(\"Y:%.2f R:%.2f P:%.2f\", Yaw, Roll, Pitch))\r\n  end\r\nend\r\n\r\n-- Main update function. Everything starts here.\r\nfunction Update(I)\r\n  GetAngleStats(I)\r\n  if not I:IsDocked() and WaterStartCheck(I) then\r\n    Movement(I)\r\n  else\r\n    for k,p in pairs(AllSpinners) do I:SetSpinBlockRotationAngle(p,0) end\r\n  end\r\nend\r\n--\r\n"],"BlockStringDataIds":[16],"GameVersion":"3.2.3.1","PersistentSubObjectIndex":13,"PersistentBlockIndex":61,"AuthorDetails":{"Valid":true,"ForeignBlocks":0,"CreatorId":"14f9a105-cbc6-47fb-a4bb-58fc6188ecff","ObjectId":"32817288-a13a-4bfc-9be9-db1a1bf6b875","CreatorReadableName":"Iorn Wolves","HashV1":"8fb70db148e5a6e5ca275ae1b5e75081"},"BlockCount":267}}