rlane / oort3

A space fleet programming game
https://oort.rs
GNU General Public License v3.0
296 stars 23 forks source link

Compiler: Unknown Language #153

Closed Perodactyl closed 4 months ago

Perodactyl commented 4 months ago

I have been coding in an external editor, using a rust bundler. After making some changes to my code and increasing it's length, the compiler refuses to compile and just says "Unknown Language." I've verified that the right code is being input, so I'm not sure what the issue is.

Here is my bundled source (exactly as the compiler receives it)

pub mod oort_ai_v2 {
use oort_api::prelude::*;
#[cfg(test)]
pub mod test {
use oort_api::prelude::*;
use byteorder::{ByteOrder, ReadBytesExt, BE, LE};
use std::io::{Cursor, Read};
use super::api::comms::*;
#[test]
fn test_serde_vec4() {
let vec = vec2(16.0 * 500.0, 16.0 * 811.0);
let bytes = serialize_vec_i16(vec);
println!("bytes: {:0>8b} {:0>8b}, {:0>8b} {:0>8b}", bytes[0], bytes[1], bytes[2], bytes[3]);
let new_vec = deserialize_vec_i16(&bytes);
assert_eq!(vec, new_vec, "Data preserved by serde_vec4");
}
#[test]
fn test_serde_vec8() {
let vec = vec2(500.0, 811.0);
let bytes = serialize_vec_f32(vec);
let new_vec = deserialize_vec_f32(&bytes);
assert_eq!(vec, new_vec, "Data preserved by serde_vec8");
}
}
pub mod api {
pub mod comms {
use std::io::Cursor;
use oort_api::prelude::*;
use byteorder::{ReadBytesExt, WriteBytesExt, ByteOrder, BE};
pub fn serialize_vec_i16(vec: Vec2) -> [u8; 4]{
let x = vec.x.round_ties_even() as i16;
let y = vec.y.round_ties_even() as i16;
[
(y >> 8) as u8,
y as u8,
(x >> 8) as u8,
x as u8,
]
}
pub fn deserialize_vec_i16(data: &[u8; 4]) -> Vec2{
vec2(
((data[2] as i16) << 8 | (data[3] as i16)) as f64,
((data[0] as i16) << 8 | (data[1] as i16)) as f64,
)
}
pub fn serialize_vec_f32(vec: Vec2) -> [u8; 8]{
let mut writer = Cursor::new([0; 8]);
writer.write_f32::<BE>(vec.x as f32).unwrap();
writer.write_f32::<BE>(vec.y as f32).unwrap();
writer.into_inner()
}
pub fn deserialize_vec_f32(data: &[u8; 8]) -> Vec2 {
let mut reader = Cursor::new(data);
let x = reader.read_f32::<BE>().unwrap();
let y = reader.read_f32::<BE>().unwrap();
vec2(x as f64, y as f64)
}
pub enum MessageData {
EnemyArea(Vec2)
} impl MessageData {
pub fn serialize(self) {
match self {
MessageData::EnemyArea(pos) => todo!(),
}
}
}
pub struct Message {
data: MessageData,
sender: u16,
}
}
pub mod targeting {
use oort_api::prelude::*;
#[derive(Clone, Copy, PartialEq)]
pub struct Target {
pub class: Class,
pub position: Vec2,
pub velocity: Vec2,
pub last_seen: f64,
} impl From<ScanResult> for Target {
fn from(value: ScanResult) -> Self {
Target {
class: value.class,
position: value.position,
velocity: value.velocity,
last_seen: current_time(),
}
}
} impl Target {
pub fn vec_to(&self) -> Vec2 {
self.position - position()
}
pub fn angle_to(&self) -> f64 {
self.vec_to().angle()
}
}
#[derive(Clone, Copy, PartialEq)]
pub enum RadarOperation {
Search(f64), //dist
Look(f64), //angle
Track(Target),
}
#[derive(Clone, Copy, PartialEq)]
pub struct RadarStatus {
heading: f64,
width: f64,
min: f64,
max: f64,
ecm: EcmMode,
} impl RadarStatus {
pub fn save() -> Self {
RadarStatus {
heading: radar_heading(),
width: radar_width(),
min: radar_min_distance(),
max: radar_max_distance(),
ecm: radar_ecm_mode(),
}
}
pub fn restore(self) {
set_radar_heading(self.heading);
set_radar_width(self.width);
set_radar_min_distance(self.min);
set_radar_max_distance(self.max);
set_radar_ecm_mode(self.ecm);
}
}
pub struct RadarBeamSearcher {
pub width: f64,
pub min: f64,
pub max: f64,
} impl RadarBeamSearcher {
pub fn new() -> Self {
RadarBeamSearcher {
width: TAU / 10.0,
min: 2.0,
max: 20000.0,
}
}
pub fn tick(&self) {
set_radar_heading(heading());
set_radar_min_distance(self.min);
set_radar_max_distance(self.max);
set_radar_width(self.width);
}
pub fn get_target(&self) -> Option<Target> {
scan().map(|v| v.into())
}
}
pub struct RadarBeamSweeper {
pub width: f64,
pub min: f64,
pub max: f64,
look_angle: f64,
target: Option<Target>,
} impl RadarBeamSweeper {
pub fn new() -> Self {
RadarBeamSweeper {
width: TAU / 10.0,
min: 2.0,
max: 20000.0,
look_angle: 0.0,
target: None,
}
}
pub fn tick(&mut self) {
if let Some(result) = scan() {
let result = Target::from(result);
self.target = Some(result);
self.look_angle = result.angle_to();
debug!("Sweeper: Active");
} else if let Some(target) = self.target {
let age = current_time() - target.last_seen;
debug!("Sweeper: Last-Seen {age} ago");
if age > 2.5 {
self.target.take();
}
} else {
debug!("Sweeper: Scanning");
self.look_angle += self.width / 5.0;
}
set_radar_heading(self.look_angle);
set_radar_min_distance(self.min);
set_radar_max_distance(self.max);
set_radar_width(self.width);
}
pub fn get_target(&self) -> Option<Target> {
self.target
}
}
pub struct RadarTracker {
operations: Vec<(RadarStatus, RadarOperation)>
}
}
pub mod control {
pub mod movement {
use oort_api::prelude::*;
#[allow(dead_code)]
pub fn lerp(a: f64, b: f64, d: f64) -> f64 {
(1.0 - d) * a + d * b
}
pub fn max_accel(current_heading: f64, target_heading: f64) -> f64 {
let offset = angle_diff(target_heading, current_heading+PI/2.0) + PI;
let quarter = (offset / (TAU / 4.0)) as u32;
let mut quarter_offset = offset;
while quarter_offset > TAU / 4.0 {
quarter_offset -= TAU / 4.0;
}
quarter_offset = quarter_offset * 4.0 / TAU;
match quarter {
0 => lerp(max_lateral_acceleration(), max_backward_acceleration(), quarter_offset),
1 => lerp(max_backward_acceleration(), max_lateral_acceleration(), quarter_offset),
2 => lerp(max_lateral_acceleration(), max_forward_acceleration(), quarter_offset),
3 => lerp(max_forward_acceleration(), max_lateral_acceleration(), quarter_offset),
_ => unreachable!(),
}
}
pub enum ActionControl<T> {
NoControl,
Auto,
Manual(T),
}
pub type AngleControl = ActionControl<f64>;
}
pub mod pid {
#[allow(dead_code)]
pub struct PID {
pub gain_p: f64,
pub gain_i: f64,
pub gain_d: f64,
prev_error: Option<f64>,
idle_time: u32,
} impl PID {
pub fn solve(&mut self, error: f64, dt: f64) -> f64 {
let p = error;
let i = 0.0;
let d;
if let Some(prev_error) = self.prev_error.replace(error) {
d = (error - prev_error) / dt;
self.prev_error.replace(error);
} else {
d = 0.0;
}
let out = p * self.gain_p
+ i * self.gain_i
+ d * self.gain_d;
out
}
pub fn new(gain_p: f64, gain_i: f64, gain_d: f64, output_rate: f64) -> Self {
PID {
gain_p: gain_p * output_rate,
gain_i: gain_i * output_rate,
gain_d: gain_d * output_rate,
prev_error: None,
idle_time: 0,
}
}
pub fn reset(&mut self) {
self.prev_error = None;
}
pub fn idle(&mut self) {
if self.prev_error.is_some() {
self.idle_time += 1;
if self.idle_time > 15 {
self.prev_error.take();
self.idle_time = 0;
}
}
}
}
}
pub mod point {
use oort_api::prelude::*;
use super::super::super::api::{control::{movement::max_accel, pid::PID}, targeting::Target};
#[allow(dead_code)]
pub struct PointAutopilot {
angle_pid: PID,
position_pid: PID,
auto_angle: bool,
infinite_accel: bool,
pub allow_boost: bool,
orbit_distance: f64,
target_angle: Option<f64>,
target_location: Option<Vec2>,
angle_error: Option<f64>,
} impl PointAutopilot {
pub fn new() -> Self {
PointAutopilot {
angle_pid: PID::new(1.0, 0.0, 1.0, max_angular_acceleration()),
position_pid: PID::new(0.5, 0.0, 1.5, 1.0),
auto_angle: true,
infinite_accel: false,
allow_boost: false,
orbit_distance: 0.0,
target_angle: None,
target_location: None,
angle_error: None,
}
}
pub fn tick(&mut self) {
let mut is_at_target = false;
if let Some(target) = self.target_location {
if (target - position()).length() < self.orbit_distance + 3.0 {
is_at_target = true;
}
}
debug!("Point @{} >{} ('{}')", match (self.target_location, self.infinite_accel, is_at_target) {
(Some(_), _, true) => "++",
(Some(_), false, _) => "To",
(Some(_), true, _) => "Cross",
(None, _, _) => "OVERRIDE",
}, match (self.target_angle, self.auto_angle) {
(_, true) => "Auto",
(Some(_), false) => "Specific",
(None, false) => "OVERRIDE",
}, match (self.target_location, self.infinite_accel, self.target_angle, self.auto_angle) {
(Some(location), false, None, true) => {
draw_line(position(), location, 0xFFFF00);
"goto"
},
(Some(location), true, None, true) => {
draw_line(position(), location, 0xFFFF00);
draw_diamond(location, 10.0, 0xFFFF00);
"flyby"
},
(Some(location), _, None, false) => {
draw_line(position(), location, 0xFF0000);
"strafe"
},
(Some(location), _, Some(angle), false) => {
draw_line(position(), location, 0xFF0000);
draw_line(position(), position() + vec2(100.0, 0.0).rotate(angle), 0x00FF00);
"target-strafe"
},
(None, _, Some(angle), _) => {
draw_line(position(), position() + vec2(100.0, 0.0).rotate(angle), 0x00FF00);
"point-at"
},
(None, _, None, _) => "idle",
_ => "?",
});
let mut target_angle = self.target_angle.clone();
if let Some(target) = self.target_location {
let vec_between = target - position();
if self.auto_angle {
target_angle = Some(vec_between.angle());
}
if self.orbit_distance > 0.0 {
draw_polygon(target, self.orbit_distance, 10, current_time(), 0xFF00FF);
}
if !is_at_target && fuel() > 0.0 {
if self.allow_boost {
if self.angle_error.is_some_and(|v| v.abs() < TAU/32.0) && vec_between.length() - self.orbit_distance > 100.0 {
activate_ability(Ability::Boost);
} else if self.angle_error.is_some_and(|v| v.abs() > TAU / 16.0) {
deactivate_ability(Ability::Boost);
}
}
if self.infinite_accel {
accelerate(vec_between.normalize() * max_forward_acceleration());
} else {
let impulse = self.position_pid.solve(vec_between.length() - self.orbit_distance, TICK_LENGTH) * max_accel(heading(), -vec_between.angle());
accelerate(vec_between.normalize() * impulse);
}
} else if is_at_target {
accelerate(-velocity());
deactivate_ability(Ability::Boost);
} else {
debug!("Point ⚠️Not at target, but no fuel!⚠️");
}
}
if self.target_location.is_none() || is_at_target {
self.position_pid.idle();
}
if let Some(angle) = target_angle {
let error = angle_diff(heading(), angle);
self.angle_error = Some(error);
let force = self.angle_pid.solve(error, TICK_LENGTH);
torque(force);
}
if target_angle.is_none() {
self.angle_pid.idle();
}
}
pub fn orbit_distance(&mut self, distance: f64) {
self.orbit_distance = distance;
}
pub fn go_to(&mut self, location: Vec2) {
self.auto_angle = true;
self.infinite_accel = false;
self.target_angle = None;
self.target_location = Some(location);
}
pub fn fly_by(&mut self, location: Vec2) {
self.auto_angle = true;
self.infinite_accel = true;
self.target_angle = None;
self.target_location = Some(location);
}
pub fn point_at(&mut self, location: Vec2) {
self.auto_angle = false;
let vec_between = location - position();
self.target_angle = Some(vec_between.angle());
}
pub fn point_at_angle(&mut self, angle: f64) {
let indicator = position() + vec2(100.0, 0.0).rotate(angle);
self.auto_angle = false;
self.target_angle = Some(angle);
}
pub fn strafe_to(&mut self, location: Vec2) {
self.auto_angle = false;
self.target_location = Some(location);
}
pub fn target_ship(&mut self, ship: Option<Target>) {
}
pub fn angle_error(&self) -> Option<f64> {
self.angle_error
}
pub fn eta(&self) -> Option<f64> {
let target = self.target_location?;
let rel_target = target - position();
let approach = rel_target / velocity();
Some(approach.length())
}
pub fn distance(&self) -> Option<f64> {
Some((self.target_location? - position()).length())
}
pub fn builder() -> PointAutopilotBuilder {
PointAutopilotBuilder::new()
}
}
pub struct PointAutopilotBuilder {
allow_boost: bool,
} impl PointAutopilotBuilder {
pub fn new() -> Self {
PointAutopilotBuilder {
allow_boost: false,
}
}
pub fn build(self) -> PointAutopilot {
let mut out = PointAutopilot::new();
out.allow_boost = self.allow_boost;
out
}
pub fn allow_boost(mut self) -> Self {
self.allow_boost = true;
self
}
pub fn disallow_boost(mut self) -> Self {
self.allow_boost = false;
self
}
}
}
Perodactyl commented 4 months ago

Removing a file from my module tree fixed, which may hint that it's a bundler issue. After further testing, rust will compile the code with or without the removed module, only giving an error that I lack a main function.

Updated (shortened) source:

pub mod oort_ai_v2 {
use oort_api::prelude::*;
#[cfg(test)]
pub mod test {
use oort_api::prelude::*;
use byteorder::{ByteOrder, ReadBytesExt, BE, LE};
use std::io::{Cursor, Read};
use super::api::comms::*;
#[test]
fn test_serde_vec4() {
let vec = vec2(16.0 * 500.0, 16.0 * 811.0);
let bytes = serialize_vec_i16(vec);
println!("bytes: {:0>8b} {:0>8b}, {:0>8b} {:0>8b}", bytes[0], bytes[1], bytes[2], bytes[3]);
let new_vec = deserialize_vec_i16(&bytes);
assert_eq!(vec, new_vec, "Data preserved by serde_vec4");
}
#[test]
fn test_serde_vec8() {
let vec = vec2(500.0, 811.0);
let bytes = serialize_vec_f32(vec);
let new_vec = deserialize_vec_f32(&bytes);
assert_eq!(vec, new_vec, "Data preserved by serde_vec8");
}
}
pub mod api {
pub mod comms {
use std::io::Cursor;
use oort_api::prelude::*;
use byteorder::{ReadBytesExt, WriteBytesExt, ByteOrder, BE};
pub fn serialize_vec_i16(vec: Vec2) -> [u8; 4]{
let x = vec.x.round_ties_even() as i16;
let y = vec.y.round_ties_even() as i16;
[
(y >> 8) as u8,
y as u8,
(x >> 8) as u8,
x as u8,
]
}
pub fn deserialize_vec_i16(data: &[u8; 4]) -> Vec2{
vec2(
((data[2] as i16) << 8 | (data[3] as i16)) as f64,
((data[0] as i16) << 8 | (data[1] as i16)) as f64,
)
}
pub fn serialize_vec_f32(vec: Vec2) -> [u8; 8]{
let mut writer = Cursor::new([0; 8]);
writer.write_f32::<BE>(vec.x as f32).unwrap();
writer.write_f32::<BE>(vec.y as f32).unwrap();
writer.into_inner()
}
pub fn deserialize_vec_f32(data: &[u8; 8]) -> Vec2 {
let mut reader = Cursor::new(data);
let x = reader.read_f32::<BE>().unwrap();
let y = reader.read_f32::<BE>().unwrap();
vec2(x as f64, y as f64)
}
pub enum MessageData {
EnemyArea(Vec2)
} impl MessageData {
pub fn serialize(self) {
match self {
MessageData::EnemyArea(pos) => todo!(),
}
}
}
pub struct Message {
data: MessageData,
sender: u16,
}
}
pub mod targeting {
use oort_api::prelude::*;
#[derive(Clone, Copy, PartialEq)]
pub struct Target {
pub class: Class,
pub position: Vec2,
pub velocity: Vec2,
pub last_seen: f64,
} impl From<ScanResult> for Target {
fn from(value: ScanResult) -> Self {
Target {
class: value.class,
position: value.position,
velocity: value.velocity,
last_seen: current_time(),
}
}
} impl Target {
pub fn vec_to(&self) -> Vec2 {
self.position - position()
}
pub fn angle_to(&self) -> f64 {
self.vec_to().angle()
}
}
#[derive(Clone, Copy, PartialEq)]
pub enum RadarOperation {
Search(f64), //dist
Look(f64), //angle
Track(Target),
}
#[derive(Clone, Copy, PartialEq)]
pub struct RadarStatus {
heading: f64,
width: f64,
min: f64,
max: f64,
ecm: EcmMode,
} impl RadarStatus {
pub fn save() -> Self {
RadarStatus {
heading: radar_heading(),
width: radar_width(),
min: radar_min_distance(),
max: radar_max_distance(),
ecm: radar_ecm_mode(),
}
}
pub fn restore(self) {
set_radar_heading(self.heading);
set_radar_width(self.width);
set_radar_min_distance(self.min);
set_radar_max_distance(self.max);
set_radar_ecm_mode(self.ecm);
}
}
pub struct RadarBeamSearcher {
pub width: f64,
pub min: f64,
pub max: f64,
} impl RadarBeamSearcher {
pub fn new() -> Self {
RadarBeamSearcher {
width: TAU / 10.0,
min: 2.0,
max: 20000.0,
}
}
pub fn tick(&self) {
set_radar_heading(heading());
set_radar_min_distance(self.min);
set_radar_max_distance(self.max);
set_radar_width(self.width);
}
pub fn get_target(&self) -> Option<Target> {
scan().map(|v| v.into())
}
}
pub struct RadarBeamSweeper {
pub width: f64,
pub min: f64,
pub max: f64,
look_angle: f64,
target: Option<Target>,
} impl RadarBeamSweeper {
pub fn new() -> Self {
RadarBeamSweeper {
width: TAU / 10.0,
min: 2.0,
max: 20000.0,
look_angle: 0.0,
target: None,
}
}
pub fn tick(&mut self) {
if let Some(result) = scan() {
let result = Target::from(result);
self.target = Some(result);
self.look_angle = result.angle_to();
debug!("Sweeper: Active");
} else if let Some(target) = self.target {
let age = current_time() - target.last_seen;
debug!("Sweeper: Last-Seen {age} ago");
if age > 2.5 {
self.target.take();
}
} else {
debug!("Sweeper: Scanning");
self.look_angle += self.width / 5.0;
}
set_radar_heading(self.look_angle);
set_radar_min_distance(self.min);
set_radar_max_distance(self.max);
set_radar_width(self.width);
}
pub fn get_target(&self) -> Option<Target> {
self.target
}
}
pub struct RadarTracker {
operations: Vec<(RadarStatus, RadarOperation)>
}
}
pub mod control {
pub mod movement {
use oort_api::prelude::*;
#[allow(dead_code)]
pub fn lerp(a: f64, b: f64, d: f64) -> f64 {
(1.0 - d) * a + d * b
}
pub fn max_accel(current_heading: f64, target_heading: f64) -> f64 {
let offset = angle_diff(target_heading, current_heading+PI/2.0) + PI;
let quarter = (offset / (TAU / 4.0)) as u32;
let mut quarter_offset = offset;
while quarter_offset > TAU / 4.0 {
quarter_offset -= TAU / 4.0;
}
quarter_offset = quarter_offset * 4.0 / TAU;
match quarter {
0 => lerp(max_lateral_acceleration(), max_backward_acceleration(), quarter_offset),
1 => lerp(max_backward_acceleration(), max_lateral_acceleration(), quarter_offset),
2 => lerp(max_lateral_acceleration(), max_forward_acceleration(), quarter_offset),
3 => lerp(max_forward_acceleration(), max_lateral_acceleration(), quarter_offset),
_ => unreachable!(),
}
}
pub enum ActionControl<T> {
NoControl,
Auto,
Manual(T),
}
pub type AngleControl = ActionControl<f64>;
}
pub mod pid {
#[allow(dead_code)]
pub struct PID {
pub gain_p: f64,
pub gain_i: f64,
pub gain_d: f64,
prev_error: Option<f64>,
idle_time: u32,
} impl PID {
pub fn solve(&mut self, error: f64, dt: f64) -> f64 {
let p = error;
let i = 0.0;
let d;
if let Some(prev_error) = self.prev_error.replace(error) {
d = (error - prev_error) / dt;
self.prev_error.replace(error);
} else {
d = 0.0;
}
let out = p * self.gain_p
+ i * self.gain_i
+ d * self.gain_d;
out
}
pub fn new(gain_p: f64, gain_i: f64, gain_d: f64, output_rate: f64) -> Self {
PID {
gain_p: gain_p * output_rate,
gain_i: gain_i * output_rate,
gain_d: gain_d * output_rate,
prev_error: None,
idle_time: 0,
}
}
pub fn reset(&mut self) {
self.prev_error = None;
}
pub fn idle(&mut self) {
if self.prev_error.is_some() {
self.idle_time += 1;
if self.idle_time > 15 {
self.prev_error.take();
self.idle_time = 0;
}
}
}
}
}
pub mod ship {
use oort_api::prelude::*;
use super::super::super::api::{control::{movement::max_accel, pid::PID}, targeting::Target};
use super::movement::AngleControl;
#[allow(dead_code)]
pub struct ShipAutopilot {
angle_pid: PID,
position_pid: PID,
allow_boost: bool,
approach_distance: f64,
angle: AngleControl,
target: Option<Target>,
} impl ShipAutopilot {
pub fn new() -> Self {
ShipAutopilot {
angle_pid: PID::new(1.0, 0.0, 1.0, max_angular_acceleration()),
position_pid: PID::new(0.5, 0.0, 1.5, 1.0),
allow_boost: false,
approach_distance: 0.0,
angle: AngleControl::Auto,
target: None,
}
}
pub fn tick(&mut self) {
debug!("Ship");
let mut target_angle = if let AngleControl::Manual(angle) = self.angle {
Some(angle)
} else { None };
if let Some(target) = self.target {
let vec_between = target.position - position();
if let AngleControl::Auto = self.angle {
target_angle = Some(vec_between.angle());
}
if self.approach_distance > 0.0 {
draw_polygon(target.position, self.approach_distance, 10, current_time(), 0xFF00FF);
}
}
if let Some(angle) = target_angle {
let error = angle_diff(heading(), angle);
let force = self.angle_pid.solve(error, TICK_LENGTH);
torque(force);
} else {
self.angle_pid.idle();
}
}
pub fn assign(&mut self, task: ShipAutopilotTask) {
match task {
ShipAutopilotTask::Stop => {
self.target = None;
self.angle = AngleControl::NoControl;
self.allow_boost = false;
},
ShipAutopilotTask::Go { target, angle, allow_boost } => {
self.target = Some(target);
self.angle = angle;
self.allow_boost = allow_boost;
}
}
}
}
pub enum ShipAutopilotTask {
Stop,
Go {
target: Target,
angle: AngleControl,
allow_boost: bool,
},
}
}
}
}
pub mod ship {
pub mod cruiser {
pub struct Cruiser {
} impl Cruiser {
pub fn new() -> Self {
Cruiser {}
}
pub fn tick(&mut self) {
}
}
}
pub mod fighter {
use oort_api::prelude::*;
use super::super::api::{control::{movement::AngleControl, ship::{ShipAutopilotTask, ShipAutopilot}}, targeting::RadarBeamSweeper};
pub struct Fighter {
auto: ShipAutopilot,
searcher: RadarBeamSweeper,
} impl Fighter {
pub fn new() -> Self {
Fighter {
auto: ShipAutopilot::new(),
searcher: RadarBeamSweeper::new(),
}
}
pub fn tick(&mut self) {
self.searcher.tick();
self.auto.assign(self.searcher.get_target()
.map_or(ShipAutopilotTask::Stop, |t| ShipAutopilotTask::Go {
target: t,
angle: AngleControl::Auto,
allow_boost: true,
}));
fire(1);
}
}
}
pub mod frigate {
pub struct Frigate {
} impl Frigate {
pub fn new() -> Self {
Frigate {}
}
pub fn tick(&mut self) {
}
}
}
pub mod missile {
use oort_api::prelude::*;
use super::super::api::{targeting::{RadarBeamSearcher, RadarBeamSweeper, Target}};
pub struct Missile {
searcher: RadarBeamSweeper,
} impl Missile {
pub fn new() -> Self {
Missile {
searcher: RadarBeamSweeper::new(),
}
}
pub fn tick(&mut self) {
self.searcher.tick();
let target = self.searcher.get_target();
if fuel() <= 0.0 {
explode();
}
}
}
}
pub mod torpedo {
use oort_api::prelude::*;
use super::super::api::targeting::Target;
pub struct Torpedo {
scan_angle: f64,
should_turn: bool,
} impl Torpedo {
pub fn new() -> Self {
Torpedo {
scan_angle: 0.0,
should_turn: false,
}
}
pub fn tick(&mut self) {
let dir_vec = vec2(1.0, 0.0).rotate(heading());
if fuel() > velocity().length() / 4.0 || self.should_turn { //Should be able to flip directions.
accelerate(max_forward_acceleration() * dir_vec);
}
set_radar_min_distance(10.0);
set_radar_max_distance(10000.0);
set_radar_width(TAU / 64.0);
set_radar_heading(self.scan_angle);
self.scan_angle += TAU / 32.0;
if let Some(result) = scan() {
let target: Target = result.into();
let vec_to = target.position - position();
let angle_to = vec_to.angle();
self.scan_angle = angle_to - TAU / 64.0;
self.should_turn = true;
turn(angle_diff(heading(), angle_to));
}
}
}
}
pub use cruiser::Cruiser;
pub use fighter::Fighter;
pub use frigate::Frigate;
pub use missile::Missile;
pub use torpedo::Torpedo;
}
use ship::*;
pub enum Ship {
Fighter(Fighter),
Frigate(Frigate),
Cruiser(Cruiser),
Missile(Missile),
Torpedo(Torpedo),
Unknown,
} impl Ship {
pub fn new() -> Ship {
match class() {
Class::Fighter => Ship::Fighter(Fighter::new()),
Class::Frigate => Ship::Frigate(Frigate::new()),
Class::Cruiser => Ship::Cruiser(Cruiser::new()),
Class::Missile => Ship::Missile(Missile::new()),
Class::Torpedo => Ship::Torpedo(Torpedo::new()),
_ => Ship::Unknown,
}
}
pub fn tick(&mut self) {
match self {
Ship::Fighter(s) => s.tick(),
Ship::Frigate(s) => s.tick(),
Ship::Cruiser(s) => s.tick(),
Ship::Missile(s) => s.tick(),
Ship::Torpedo(s) => s.tick(),
Ship::Unknown => {
debug!("Unknown ???")
},
}
}
}
} //This has to be here for it to work.
pub use oort_ai_v2::*;
Perodactyl commented 4 months ago

A discord user notes that the first code has no impl Ship block, which seems like a reasonable cause. Maybe the error code be more helpful in the future though?