transportcai.cpp
来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 973 行 · 第 1/2 页
CPP
973 行
dropSpots.clear();
startingDropPos = pos;
approachVector = startingDropPos-owner->pos;
approachVector.Normalize();
canUnload = FindEmptyDropSpots(pos, pos + approachVector*max(16.0f,radius), dropSpots);
} else if (!dropSpots.empty() ) {
//make sure we check current spot infront of us each unload
pos = dropSpots.back(); //take last landing pos as new start spot
canUnload = dropSpots.size() > 0;
}
if( canUnload ){
if(SpotIsClear(dropSpots.back(),((CTransportUnit*)owner)->transported.front().unit)) {
float3 pos = dropSpots.back();
Command c2;
c2.id=CMD_UNLOAD_UNIT;
c2.params.push_back(pos.x);
c2.params.push_back(pos.y);
c2.params.push_back(pos.z);
c2.options=c.options | INTERNAL_ORDER;
commandQue.push_front(c2);
SlowUpdate();
isFirstIteration = false;
return;
} else {
dropSpots.pop_back();
}
} else {
startingDropPos = float3(-1,-1,-1);
isFirstIteration=true;
dropSpots.clear();
FinishCommand();
}
}
void CTransportCAI::UnloadUnits_CrashFlood(Command& c, CTransportUnit* transport) {
//TODO - fly into the ground, doing damage to units at landing pos, then unload.
//needs heavy modification of TAAirMoveType
}
void CTransportCAI::UnloadUnits_LandFlood(Command& c, CTransportUnit* transport) {
if(lastCall==gs->frameNum) //avoid infinite loops
return;
lastCall=gs->frameNum;
if(((CTransportUnit*)owner)->transported.empty()){
FinishCommand();
return;
}
float3 pos(c.params[0],c.params[1],c.params[2]);
float radius=c.params[3];
float3 found;
//((CTransportUnit*)owner)->transported
bool canUnload=FindEmptySpot(pos,max(16.0f,radius),((CTransportUnit*)owner)->transported.front().unit->radius * ((CTransportUnit*)owner)->unitDef->unloadSpread,
found,((CTransportUnit*)owner)->transported.front().unit);
if(canUnload){
Command c2;
c2.id=CMD_UNLOAD_UNIT;
c2.params.push_back(found.x);
c2.params.push_back(found.y);
c2.params.push_back(found.z);
c2.options=c.options | INTERNAL_ORDER;
commandQue.push_front(c2);
if (isFirstIteration ) {
Command c1;
c1.id=CMD_MOVE;
c1.params.push_back(pos.x);
c1.params.push_back(pos.y);
c1.params.push_back(pos.z);
c1.options=c.options | INTERNAL_ORDER;
commandQue.push_front(c1);
startingDropPos = pos;
}
SlowUpdate();
return;
} else {
FinishCommand();
}
return;
}
//
void CTransportCAI::UnloadLand(Command& c) {
//default unload
CTransportUnit* transport = (CTransportUnit*)owner;
if (inCommand) {
if (!owner->cob->busy) {
// if(scriptReady)
FinishCommand();
}
} else {
const std::list<CTransportUnit::TransportedUnit>& transList =
transport->transported;
if (transList.empty()) {
FinishCommand();
return;
}
float3 pos(c.params[0], c.params[1], c.params[2]);
if(goalPos.distance2D(pos) > 20){
SetGoal(pos, owner->pos);
}
CUnit* unit = NULL;
if (c.params.size() < 4) {
unit = transList.front().unit;
} else {
const int unitID = (int)c.params[3];
std::list<CTransportUnit::TransportedUnit>::const_iterator it;
for (it = transList.begin(); it != transList.end(); ++it) {
CUnit* carried = it->unit;
if (unitID == carried->id) {
unit = carried;
break;
}
}
if (unit == NULL) {
FinishCommand();
return;
}
}
if (pos.distance2D(owner->pos) < (owner->unitDef->loadingRadius * 0.9f)) {
CTAAirMoveType* am = dynamic_cast<CTAAirMoveType*>(owner->moveType);
if (am != NULL) {
// handle air transports differently
pos.y = ground->GetHeight(pos.x, pos.z);
const float3 wantedPos = pos + UpVector * unit->model->height;
SetGoal(wantedPos, owner->pos);
am->SetWantedAltitude(unit->model->height);
am->maxDrift = 1;
if ((owner->pos.distance(wantedPos) < 8) &&
(owner->updir.dot(UpVector) > 0.99f)) {
transport->DetachUnit(unit);
if (transport->transported.empty()) {
am->dontLand = false;
owner->cob->Call("EndTransport");
}
const float3 fix = owner->pos + owner->frontdir * 20;
SetGoal(fix, owner->pos); //move the transport away slightly
FinishCommand();
}
} else {
inCommand = true;
scriptReady = false;
StopMove();
std::vector<int> args;
args.push_back(transList.front().unit->id);
args.push_back(PACKXZ(pos.x, pos.z));
owner->cob->Call("TransportDrop", args, ScriptCallback, this, 0);
}
}
}
return;
}
void CTransportCAI::UnloadDrop(Command& c) {
//fly over and drop unit
if(inCommand){
if(!owner->cob->busy)
//if(scriptReady)
FinishCommand();
} else {
if(((CTransportUnit*)owner)->transported.empty()){
FinishCommand();
return;
}
float3 pos(c.params[0],c.params[1],c.params[2]); //head towards goal
//note that taairmovetype must be modified to allow non stop movement through goals for this to work well
if(goalPos.distance2D(pos)>20){
SetGoal(pos,owner->pos);
lastDropPos = pos;
}
if(CTAAirMoveType* am=dynamic_cast<CTAAirMoveType*>(owner->moveType)){
pos.y=ground->GetHeight(pos.x,pos.z);
CUnit* unit=((CTransportUnit*)owner)->transported.front().unit;
am->maxDrift=1;
//if near target or have past it accidentally- drop unit
if(owner->pos.distance2D(pos) < 40 || (((pos - owner->pos).Normalize()).distance(owner->frontdir.Normalize()) > 0.5 && owner->pos.distance2D(pos)< 205)) {
am->dontLand=true;
owner->cob->Call("EndTransport"); //test
((CTransportUnit*)owner)->DetachUnitFromAir(unit,pos);
dropSpots.pop_back();
if (dropSpots.empty()) {
float3 fix = owner->pos+owner->frontdir*200;
SetGoal(fix,owner->pos);//move the transport away after last drop
}
FinishCommand();
}
} else {
inCommand=true;
scriptReady=false;
StopMove();
std::vector<int> args;
args.push_back(((CTransportUnit*)owner)->transported.front().unit->id);
args.push_back(PACKXZ(pos.x, pos.z));
owner->cob->Call("TransportDrop",args,ScriptCallback,this,0);
}
}
}
void CTransportCAI::UnloadCrashFlood(Command& c) {
//TODO - will require heavy modification of TAAirMoveType.cpp
}
void CTransportCAI::UnloadLandFlood(Command& c) {
//land, then release all units at once
CTransportUnit* transport = (CTransportUnit*)owner;
if (inCommand) {
if (!owner->cob->busy) {
//if(scriptReady)
FinishCommand();
}
} else {
const std::list<CTransportUnit::TransportedUnit>& transList =
transport->transported;
if (transList.empty()) {
FinishCommand();
return;
}
//check units are all carried
CUnit* unit = NULL;
if (c.params.size() < 4) {
unit = transList.front().unit;
} else {
const int unitID = (int)c.params[3];
std::list<CTransportUnit::TransportedUnit>::const_iterator it;
for (it = transList.begin(); it != transList.end(); ++it) {
CUnit* carried = it->unit;
if (unitID == carried->id) {
unit = carried;
break;
}
}
if (unit == NULL) {
FinishCommand();
return;
}
}
//move to position
float3 pos(c.params[0], c.params[1], c.params[2]);
if (isFirstIteration) {
if(goalPos.distance2D(pos) > 20)
SetGoal(startingDropPos, owner->pos);
}
if (startingDropPos.distance2D(owner->pos) < (owner->unitDef->loadingRadius * 0.9f)) {
//create aircraft movetype instance
CTAAirMoveType* am = dynamic_cast<CTAAirMoveType*>(owner->moveType);
if (am != NULL) {
//lower to ground
startingDropPos.y = ground->GetHeight(startingDropPos.x,startingDropPos.z);
const float3 wantedPos = startingDropPos + UpVector * unit->model->height;
SetGoal(wantedPos, owner->pos);
am->SetWantedAltitude(1);
am->maxDrift = 1;
am->dontLand = false;
//when on our way down start animations for unloading gear
if (isFirstIteration) {
owner->cob->Call("StartUnload");
}
isFirstIteration = false;
//once at ground
if (owner->pos.y - ground->GetHeight(wantedPos.x,wantedPos.z) < 8) {
am->SetState(am->AIRCRAFT_LANDED);//nail it to the ground before it tries jumping up, only to land again...
std::vector<int> args;
args.push_back(transList.front().unit->id);
args.push_back(PACKXZ(pos.x, pos.z));
owner->cob->Call("TransportDrop", args, ScriptCallback, this, 0); //call this so that other animations such as opening doors may be started
transport->DetachUnitFromAir(unit,pos);
FinishCommand();
if (transport->transported.empty()) {
am->dontLand = false;
owner->cob->Call("EndTransport");
am->UpdateLanded();
}
}
} else {
//land transports
inCommand = true;
scriptReady = false;
StopMove();
std::vector<int> args;
args.push_back(transList.front().unit->id);
args.push_back(PACKXZ(pos.x, pos.z));
owner->cob->Call("TransportDrop", args, ScriptCallback, this, 0);
transport->DetachUnitFromAir(unit,pos);
isFirstIteration = false;
FinishCommand();
if (transport->transported.empty())
owner->cob->Call("EndTransport");
}
}
}
return;
}
CUnit* CTransportCAI::FindUnitToTransport(float3 center, float radius)
{
CUnit* best=0;
float bestDist=100000000;
std::vector<CUnit*> units=qf->GetUnitsExact(center,radius);
for(std::vector<CUnit*>::iterator ui=units.begin();ui!=units.end();++ui){
CUnit* unit=(*ui);
float dist=unit->pos.distance2D(owner->pos);
if(CanTransport(unit) && dist<bestDist && !unit->toBeTransported &&
(unit->losStatus[owner->allyteam] & (LOS_INRADAR|LOS_INLOS))){
bestDist=dist;
best=unit;
}
}
return best;
}
int CTransportCAI::GetDefaultCmd(CUnit* pointed, CFeature* feature)
{
if (pointed) {
if (!gs->Ally(gu->myAllyTeam, pointed->allyteam)) {
if (owner->unitDef->canAttack) {
return CMD_ATTACK;
} else if (CanTransport(pointed)) {
return CMD_LOAD_UNITS; // comm napping?
}
} else {
if (CanTransport(pointed)) {
return CMD_LOAD_UNITS;
} else if (owner->unitDef->canGuard) {
return CMD_GUARD;
}
}
}
// if(((CTransportUnit*)owner)->transported.empty())
if (owner->unitDef->canmove) {
return CMD_MOVE;
} else {
return CMD_STOP;
}
// else
// return CMD_UNLOAD_UNITS;
}
void CTransportCAI::DrawCommands(void)
{
lineDrawer.StartPath(owner->midPos, cmdColors.start);
if (owner->selfDCountdown != 0) {
lineDrawer.DrawIconAtLastPos(CMD_SELFD);
}
CCommandQueue::iterator ci;
for(ci=commandQue.begin();ci!=commandQue.end();++ci){
switch(ci->id){
case CMD_MOVE:{
const float3 endPos(ci->params[0],ci->params[1],ci->params[2]);
lineDrawer.DrawLineAndIcon(ci->id, endPos, cmdColors.move);
break;
}
case CMD_FIGHT:{
if (ci->params.size() >= 3) {
const float3 endPos(ci->params[0],ci->params[1],ci->params[2]);
lineDrawer.DrawLineAndIcon(ci->id, endPos, cmdColors.fight);
}
break;
}
case CMD_PATROL:{
const float3 endPos(ci->params[0],ci->params[1],ci->params[2]);
lineDrawer.DrawLineAndIcon(ci->id, endPos, cmdColors.patrol);
break;
}
case CMD_ATTACK:{
if(ci->params.size()==1){
const CUnit* unit = uh->units[int(ci->params[0])];
if((unit != NULL) && isTrackable(unit)) {
const float3 endPos =
helper->GetUnitErrorPos(unit, owner->allyteam);
lineDrawer.DrawLineAndIcon(ci->id, endPos, cmdColors.attack);
}
} else {
const float3 endPos(ci->params[0],ci->params[1],ci->params[2]);
lineDrawer.DrawLineAndIcon(ci->id, endPos, cmdColors.attack);
}
break;
}
case CMD_GUARD:{
const CUnit* unit = uh->units[int(ci->params[0])];
if((unit != NULL) && isTrackable(unit)) {
const float3 endPos =
helper->GetUnitErrorPos(unit, owner->allyteam);
lineDrawer.DrawLineAndIcon(ci->id, endPos, cmdColors.guard);
}
break;
}
case CMD_LOAD_UNITS:{
if(ci->params.size()==4){
const float3 endPos(ci->params[0],ci->params[1],ci->params[2]);
lineDrawer.DrawLineAndIcon(ci->id, endPos, cmdColors.load);
lineDrawer.Break(endPos, cmdColors.load);
glSurfaceCircle(endPos, ci->params[3], 20);
lineDrawer.RestartSameColor();
} else {
const CUnit* unit = uh->units[int(ci->params[0])];
if((unit != NULL) && isTrackable(unit)) {
const float3 endPos =
helper->GetUnitErrorPos(unit, owner->allyteam);
lineDrawer.DrawLineAndIcon(ci->id, endPos, cmdColors.load);
}
}
break;
}
case CMD_UNLOAD_UNITS:{
if(ci->params.size()==4){
const float3 endPos(ci->params[0],ci->params[1],ci->params[2]);
lineDrawer.DrawLineAndIcon(ci->id, endPos, cmdColors.unload);
lineDrawer.Break(endPos, cmdColors.unload);
glSurfaceCircle(endPos, ci->params[3], 20);
lineDrawer.RestartSameColor();
}
break;
}
case CMD_UNLOAD_UNIT:{
const float3 endPos(ci->params[0],ci->params[1],ci->params[2]);
lineDrawer.DrawLineAndIcon(ci->id, endPos, cmdColors.unload);
break;
}
case CMD_WAIT:{
DrawWaitIcon(*ci);
break;
}
case CMD_SELFD:{
lineDrawer.DrawIconAtLastPos(ci->id);
break;
}
default:
DrawDefaultCommand(*ci);
break;
}
}
lineDrawer.FinishPath();
}
void CTransportCAI::FinishCommand(void)
{
if(CTAAirMoveType* am=dynamic_cast<CTAAirMoveType*>(owner->moveType))
am->dontCheckCol=false;
if(toBeTransportedUnitId!=-1){
if(uh->units[toBeTransportedUnitId])
uh->units[toBeTransportedUnitId]->toBeTransported=false;
toBeTransportedUnitId=-1;
}
CMobileCAI::FinishCommand();
}
bool CTransportCAI::LoadStillValid(CUnit* unit){
if(commandQue.size() < 2){
return false;
}
Command cmd = commandQue[1];
return !(cmd.id == CMD_LOAD_UNITS && cmd.params.size() == 4
&& unit->pos.distance2D(
float3(cmd.params[0], cmd.params[1], cmd.params[2])) > cmd.params[3]*2);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?