////////////////////////////////////////////////////////////////////////////////
// GroundVehicleAI.h
// AI for ground vehicles (biped and quad mechs, wheeled, tracked vehicles, hovercraft)
// Copyright Bjoern Ganster
// Developed since 2019
////////////////////////////////////////////////////////////////////////////////

#ifndef GroundVehicleAI__h
#define GroundVehicleAI__h

#include "VehicleAI.h"

class GroundVehicleAI: public AbstractVehicleAI {
public:
	// Constructor
	GroundVehicleAI(const char* className, Vehicle* vehicle);

	// Destructor
	~GroundVehicleAI() OVERRIDE;

	void setAim(double dx, double dy) OVERRIDE;

	// Check if a weapon is currently active - used by the HUD
	bool weaponActive(int i, bool groupFire) const OVERRIDE;

	int getEffectiveHeatSinks() const;

	virtual void planMovement(DWORD now);

	void addAttackGoal(const BGCPString& target);

	// Add goals for AI
	void addGoals(const std::vector<AIGoal>& goals, bool clearExisting) OVERRIDE;

	// Notify AI of an event, like a destroyed object
	void updateObjectStatus(const BGCPString& id, SubObjectiveType newStatus) OVERRIDE;

	// Set range where AI triggers
	void setTriggerRange(double newVal) OVERRIDE;

	// Set skills (will be reflected by other variables));
	virtual void setPiloting(int newVal);
	virtual void setGunnery(int newVal);

	void setTarget(GameObject* gameObject);
protected:

	// When an enemy enters this range, this mech will attack it
	double mTriggerRange;

	// When was the last weapon fired?
	DWORD mLastFired;

	// Goals for the AI
	size_t mCurrentGoal;
	std::vector<AIGoal> mGoals;

	// Number of milliseconds between AI frames used to aim
	DWORD mMsBetweenAimFrames;

	// Number of milliseconds between AI frames used to move
	DWORD mMsBetweenMoveFrames;

	// Time stamp for the last frame where the AI aimed or moved
	DWORD mLastAimFrame, mLastMoveFrame;

	// How far the AI aim is off
	double mAimError;

	int mGunnery, mPiloting;

	// Collision handlers
	void treatVehicleCollision(Vehicle* collider);
	void treatCollisionWithImmobile(RenderableObject* collider, double moveUp);

	// Choose heading and speed to walk towards a target
	void moveTowards(const Point3D& aimGoal);

	// Aim at target
	void aimAndFire(const Point3D& aimGoal, DWORD now);

	// Fight mTarget
	void fight(DWORD now);

	// Handle goal types
	void checkWakeUp();
	void doAttack();
	void doDefend();
	void doInspect();
	void doVisit();
	void doJoinFormation();
};

#endif