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 + -
显示快捷键?