aircai.cpp

来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 830 行 · 第 1/2 页

CPP
830
字号
#include "StdAfx.h"
#include "AirCAI.h"
#include "LineDrawer.h"
#include "ExternalAI/Group.h"
#include "Game/GameHelper.h"
#include "Game/SelectedUnits.h"
#include "Game/UI/CommandColors.h"
#include "Game/UI/CursorIcons.h"
#include "Map/Ground.h"
#include "Rendering/GL/glExtra.h"
#include "Rendering/GL/myGL.h"
#include "Sim/MoveTypes/AirMoveType.h"
#include "Sim/Units/UnitDef.h"
#include "Sim/Units/UnitHandler.h"
#include "Sim/Weapons/Weapon.h"
#include "Sim/Weapons/WeaponDefHandler.h"
#include "System/myMath.h"
#include "System/LogOutput.h"
#include "mmgr.h"

CR_BIND_DERIVED(CAirCAI,CMobileCAI , );

CR_REG_METADATA(CAirCAI, (
				CR_MEMBER(basePos),
				CR_MEMBER(baseDir),

				CR_MEMBER(activeCommand),
				CR_MEMBER(targetAge),

				CR_MEMBER(lastPC1),
				CR_MEMBER(lastPC2),
				CR_RESERVED(16)
				));

CAirCAI::CAirCAI()
: CMobileCAI(), lastPC1(-1), lastPC2(-1)
{}

CAirCAI::CAirCAI(CUnit* owner)
: CMobileCAI(owner), lastPC1(-1), lastPC2(-1)
{
	cancelDistance = 16000;
	CommandDescription c;

	// aircraft can always move...
	/*c.id=CMD_MOVE;
	c.action="move";
	c.type=CMDTYPE_ICON_MAP;
	c.name="Move";
	c.mouseicon=c.name;
	c.hotkey="m";
	c.tooltip="Move: Commands the aircraft to fly to the location";
	possibleCommands.push_back(c);

	if(owner->unitDef->canPatrol){
		c.id=CMD_PATROL;
		c.action="patrol";
		c.type=CMDTYPE_ICON_MAP;
		c.name="Patrol";
		c.mouseicon=c.name;
		c.hotkey="p";
		c.tooltip="Patrol: Sets the aircraft to patrol a path to one or more waypoints";
		possibleCommands.push_back(c);
	}

	if (owner->unitDef->canFight) {
		c.id = CMD_FIGHT;
		c.action="fight";
		c.type = CMDTYPE_ICON_MAP;
		c.name = "Fight";
		c.mouseicon=c.name;
		c.hotkey = "f";
		c.tooltip = "Fight: Order the aircraft to take action while moving to a position";
		possibleCommands.push_back(c);
	}*/

	if(owner->unitDef->canAttack){
		c.id=CMD_AREA_ATTACK;
		c.action="areaattack";
		c.type=CMDTYPE_ICON_AREA;
		c.name="Area attack";
		c.mouseicon=c.name;
		c.hotkey="a";
		c.tooltip="Sets the aircraft to attack enemy units within a circle";
		possibleCommands.push_back(c);
	}/*

	if(owner->unitDef->canGuard){
		c.id=CMD_GUARD;
		c.action="guard";
		c.type=CMDTYPE_ICON_UNIT;
		c.name="Guard";
		c.mouseicon=c.name;
		c.hotkey="g";
		c.tooltip="Guard: Order a unit to guard another unit and attack units attacking it";
		possibleCommands.push_back(c);
	}*/
/*
	c.params.clear();
	c.id=CMD_AUTOREPAIRLEVEL;
	c.action="autorepairlevel";
	c.type=CMDTYPE_ICON_MODE;
	c.name="Repair level";
	c.mouseicon=c.name;
	c.params.push_back("1");
	c.params.push_back("LandAt 0");
	c.params.push_back("LandAt 30");
	c.params.push_back("LandAt 50");
	c.params.push_back("LandAt 80");
	c.tooltip="Repair level: Sets at which health level an aircraft will try to find a repair pad";
	c.hotkey="";
	possibleCommands.push_back(c);
	nonQueingCommands.insert(CMD_AUTOREPAIRLEVEL);
*/
	if(owner->unitDef->canLoopbackAttack){
		c.params.clear();
		c.id=CMD_LOOPBACKATTACK;
		c.action="loopbackattack";
		c.type=CMDTYPE_ICON_MODE;
		c.name="Loopback";
		c.mouseicon=c.name;
		c.params.push_back("0");
		c.params.push_back("Normal");
		c.params.push_back("Loopback");
		c.tooltip="Loopback attack: Sets if the aircraft should loopback after an attack instead of overflying target";
		c.hotkey="";
		possibleCommands.push_back(c);
		nonQueingCommands.insert(CMD_LOOPBACKATTACK);
	}

	basePos=owner->pos;
	goalPos=owner->pos;
	tempOrder=false;
	targetAge=0;
	commandPos1=ZeroVector;
	commandPos2=ZeroVector;
}

CAirCAI::~CAirCAI(void)
{
}

void CAirCAI::GiveCommandReal(const Command &c)
{
	// take care not to allow aircraft to be ordered to move out of the map
	if (c.id != CMD_MOVE && !AllowedCommand(c))
		return;

	else if (c.id == CMD_MOVE && c.params.size() >= 3 &&
			(c.params[0] < 0.f || c.params[2] < 0.f
			 || c.params[0] > gs->mapx*SQUARE_SIZE
			 || c.params[2] > gs->mapy*SQUARE_SIZE))
		return;

	if (c.id == CMD_SET_WANTED_MAX_SPEED) {
	  return;
	}

	if (c.id == CMD_AUTOREPAIRLEVEL) {
		if (c.params.empty()) {
			return;
		}
		CAirMoveType* airMT;
		if (owner->usingScriptMoveType) {
			airMT = (CAirMoveType*)owner->prevMoveType;
		} else {
			airMT = (CAirMoveType*)owner->moveType;
		}
		switch((int)c.params[0]){
			case 0: { airMT->repairBelowHealth = 0.0f; break; }
			case 1: { airMT->repairBelowHealth = 0.3f; break; }
			case 2: { airMT->repairBelowHealth = 0.5f; break; }
			case 3: { airMT->repairBelowHealth = 0.8f; break; }
		}
		for(vector<CommandDescription>::iterator cdi = possibleCommands.begin();
				cdi != possibleCommands.end(); ++cdi){
			if(cdi->id==CMD_AUTOREPAIRLEVEL){
				char t[10];
				SNPRINTF(t,10,"%d", (int)c.params[0]);
				cdi->params[0]=t;
				break;
			}
		}
		selectedUnits.PossibleCommandChange(owner);
		return;
	}

	if (c.id == CMD_IDLEMODE) {
		if (c.params.empty()) {
			return;
		}
		CAirMoveType* airMT;
		if (owner->usingScriptMoveType) {
			airMT = (CAirMoveType*)owner->prevMoveType;
		} else {
			airMT = (CAirMoveType*)owner->moveType;
		}
		switch((int)c.params[0]){
			case 0: { airMT->autoLand = false; break; }
			case 1: { airMT->autoLand = true;  break; }
		}
		for(vector<CommandDescription>::iterator cdi = possibleCommands.begin();
				cdi != possibleCommands.end(); ++cdi){
			if(cdi->id == CMD_IDLEMODE){
				char t[10];
				SNPRINTF(t, 10, "%d", (int)c.params[0]);
				cdi->params[0] = t;
				break;
			}
		}
		selectedUnits.PossibleCommandChange(owner);
		return;
	}

	if (c.id == CMD_LOOPBACKATTACK) {
		if (c.params.empty()) {
			return;
		}
		CAirMoveType* airMT;
		if (owner->usingScriptMoveType) {
			airMT = (CAirMoveType*)owner->prevMoveType;
		} else {
			airMT = (CAirMoveType*)owner->moveType;
		}
		switch((int)c.params[0]){
			case 0: { airMT->loopbackAttack = false; break; }
			case 1: { airMT->loopbackAttack = true;  break; }
		}
		for(vector<CommandDescription>::iterator cdi = possibleCommands.begin();
				cdi != possibleCommands.end(); ++cdi){
			if(cdi->id == CMD_LOOPBACKATTACK){
				char t[10];
				SNPRINTF(t, 10, "%d", (int)c.params[0]);
				cdi->params[0] = t;
				break;
			}
		}
		selectedUnits.PossibleCommandChange(owner);
		return;
	}

	if (!(c.options & SHIFT_KEY)
			&& nonQueingCommands.find(c.id) == nonQueingCommands.end()) {
		activeCommand=0;
		tempOrder=false;
	}

	if (c.id == CMD_AREA_ATTACK && c.params.size() < 4){
		Command c2 = c;
		c2.id = CMD_ATTACK;
		CCommandAI::GiveAllowedCommand(c2);
		return;
	}

	CCommandAI::GiveAllowedCommand(c);
}

void CAirCAI::SlowUpdate()
{
	if (!commandQue.empty() && commandQue.front().timeOut < gs->frameNum) {
		FinishCommand();
		return;
	}

	if (owner->usingScriptMoveType) {
		return; // avoid the invalid (CAirMoveType*) cast
	}

	CAirMoveType* myPlane=(CAirMoveType*) owner->moveType;

	if(owner->unitDef->maxFuel > 0){
		if(myPlane->reservedPad){
			return;
		}else{
			if(owner->currentFuel <= 0){
				owner->userAttackGround=false;
				owner->userTarget=0;
				inCommand=false;

				CAirBaseHandler::LandingPad* lp = airBaseHandler->FindAirBase(
					owner, owner->unitDef->minAirBasePower);
				if(lp){
					myPlane->AddDeathDependence(lp);
					myPlane->reservedPad = lp;
					myPlane->padStatus = 0;
					myPlane->oldGoalPos = myPlane->goalPos;
					return;
				}
				float3 landingPos = airBaseHandler->FindClosestAirBasePos(
					owner, owner->unitDef->minAirBasePower);
				if(landingPos != ZeroVector && owner->pos.distance2D(landingPos) > 300){
					if(myPlane->aircraftState == CAirMoveType::AIRCRAFT_LANDED
							&& owner->pos.distance2D(landingPos) > 800) {
						myPlane->SetState(CAirMoveType::AIRCRAFT_TAKEOFF);
					}
					myPlane->goalPos = landingPos;
				} else {
					if(myPlane->aircraftState == CAirMoveType::AIRCRAFT_FLYING)
						myPlane->SetState(CAirMoveType::AIRCRAFT_LANDING);
				}
				return;
			}
			if(owner->currentFuel < myPlane->repairBelowHealth * owner->unitDef->maxFuel){
				if(commandQue.empty() || commandQue.front().id == CMD_PATROL){
					CAirBaseHandler::LandingPad* lp =
						airBaseHandler->FindAirBase(owner, owner->unitDef->minAirBasePower);
					if(lp){
						owner->userAttackGround=false;
						owner->userTarget=0;
						inCommand=false;
						myPlane->AddDeathDependence(lp);
						myPlane->reservedPad=lp;
						myPlane->padStatus=0;
						myPlane->oldGoalPos=myPlane->goalPos;
						if(myPlane->aircraftState == CAirMoveType::AIRCRAFT_LANDED){
							myPlane->SetState(CAirMoveType::AIRCRAFT_TAKEOFF);
						}
						return;
					}
				}
			}
		}
	}

	if(commandQue.empty()){
		if(myPlane->aircraftState == CAirMoveType::AIRCRAFT_FLYING
			&& !owner->unitDef->DontLand() && myPlane->autoLand){
			myPlane->SetState(CAirMoveType::AIRCRAFT_LANDING);
		}

		if(owner->unitDef->canAttack && owner->fireState>=2
				&& owner->moveState != 0 && owner->maxRange > 0){
			if(myPlane->isFighter){
				float testRad=1000 * owner->moveState;
				CUnit* enemy=helper->GetClosestEnemyAircraft(
					owner->pos + (owner->speed * 10), testRad, owner->allyteam);
				if(enemy && !enemy->crashing){
					Command nc;
					nc.id = CMD_ATTACK;
					nc.params.push_back(enemy->id);
					nc.options = 0;
					commandQue.push_front(nc);
					inCommand = false;
					return;
				}
			}
			float testRad = 500 * owner->moveState;
			CUnit* enemy = helper->GetClosestEnemyUnit(
				owner->pos + (owner->speed * 20), testRad, owner->allyteam);
			if(enemy && (owner->hasUWWeapons || !enemy->isUnderWater)
					&& !enemy->crashing
					&& (myPlane->isFighter || !enemy->unitDef->canfly)){
				Command nc;
				nc.id = CMD_ATTACK;
				nc.params.push_back(enemy->id);
				nc.options = 0;
				commandQue.push_front(nc);
				inCommand = false;
				return;
			}
		}
		return;
	}

	Command& c = commandQue.front();

	if (c.id == CMD_WAIT) {
		if ((myPlane->aircraftState == CAirMoveType::AIRCRAFT_FLYING)
		    && !owner->unitDef->DontLand() && myPlane->autoLand) {
			myPlane->SetState(CAirMoveType::AIRCRAFT_LANDING);
		}
		return;
	}

	if (c.id != CMD_STOP) {
		if (myPlane->aircraftState == CAirMoveType::AIRCRAFT_LANDED) {
			myPlane->SetState(CAirMoveType::AIRCRAFT_TAKEOFF);
		}
		if (myPlane->aircraftState == CAirMoveType::AIRCRAFT_LANDING) {
			myPlane->SetState(CAirMoveType::AIRCRAFT_FLYING);
		}
	}

	float3 curPos=owner->pos;

	switch(c.id){
		case CMD_AREA_ATTACK:{
			ExecuteAreaAttack(c);
			return;
		}
		default:{
			CMobileCAI::Execute();
			return;
		}
	}
}

/*
void CAirCAI::ExecuteMove(Command &c){
	if(tempOrder){
		tempOrder = false;
		inCommand = true;
	}
	if(!inCommand){
		inCommand=true;
		commandPos1=myPlane->owner->pos;
	}
	float3 pos(c.params[0], c.params[1], c.params[2]);
	commandPos2 = pos;
	myPlane->goalPos = pos;// This is not what we want move to do
	if(owner->unitDef->canAttack && !(c.options & CONTROL_KEY)){
		if(owner->fireState >= 2 && owner->moveState != 0 && owner->maxRange > 0){
			if(myPlane->isFighter){
				float testRad = 500 * owner->moveState;
				CUnit* enemy = helper->GetClosestEnemyAircraft(

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?