Skip to content
Snippets Groups Projects
travel.rs 2.38 KiB
Newer Older
Louis's avatar
Louis committed
use std::ops::{Deref, DerefMut, SubAssign};

use bevy::math::Vec3Swizzles;
use bevy::prelude::*;
use serde::{Deserialize, Serialize};
use crate::persistance::SaveFileEvent;
Louis's avatar
Louis committed
use crate::states::Player;
use crate::system::utilities::format_distance;
use crate::world::encounters::EncounterState;
use crate::world::towns::{CurrentResidence, TravelPath, TravelTarget};
use crate::world::PathingResult;

#[derive(Component, Serialize, Deserialize, Debug, Copy, Clone, Default)]
pub struct DistanceTravelled(pub f32);
Louis's avatar
Louis committed
impl Deref for DistanceTravelled {
	type Target = f32;
	fn deref(&self) -> &Self::Target {
		&self.0
	}
}
impl DerefMut for DistanceTravelled {
	fn deref_mut(&mut self) -> &mut Self::Target {
		&mut self.0
	}
}
pub fn tick_travelling_merchant(
	mut commands: Commands,
	time: Res<Time>,
	mut merchant_query: Query<(
		Entity,
		&mut Transform,
		&mut TravelPath,
		&mut TravelTarget,
		&mut CurrentResidence,
		&mut DistanceTravelled,
	encounter_state: Res<EncounterState>,
	mut autosave: EventWriter<SaveFileEvent>,
	if encounter_state.is_in_encounter() {
		return;
	}

	let delta = time.delta_seconds();
	for (entity, mut transform, mut path, mut target, mut residence, mut high_score) in
		&mut merchant_query
	{
		let step = path.get_step(transform.translation.xy(), 16.0) * delta;
		high_score.0 += step.length();
		transform.translation.sub_assign(step.extend(0.0));

		match path.check_position(transform.translation.xy()) {
			PathingResult::PathComplete => {
				commands
					.entity(entity)
					.remove::<(TravelPath, TravelTarget)>();
				*residence = CurrentResidence::RestingAt(target.0.clone());
				autosave.send(SaveFileEvent::autosave());
			}
			PathingResult::NextNode => {
				path.increment_indexes();
			}
			PathingResult::TravelTo(new_point) => {
				transform.translation = new_point.extend(transform.translation.z);
			}
			PathingResult::Travelling => {}
		}
	}
}
Louis's avatar
Louis committed

pub struct WorldTickEvent;

pub fn track_travel(
	mut tracked: Local<DistanceTravelled>,
	player_query: Query<&DistanceTravelled, With<Player>>,
	mut events: EventWriter<WorldTickEvent>,
) {
	let before = **tracked.deref();
	let after = {
		if let Ok(player_dist) = player_query.get_single() {
			*tracked = *player_dist;
			*player_dist.deref()
		} else {
			before
		}
	};

	if format_distance(before) % 5.0 > format_distance(after) % 5.0 {
		log::info!("Ticking World Objects");
Louis's avatar
Louis committed
		events.send(WorldTickEvent);
	}
}