Attached Files |
-
ArcWeapon&Fight.patch (39,579 bytes) 2006-06-28 00:48
Index: rts/build/vstudio7/rts.vcproj
===================================================================
--- rts/build/vstudio7/rts.vcproj (revision 1536)
+++ rts/build/vstudio7/rts.vcproj (working copy)
@@ -2246,6 +2246,12 @@
RelativePath="..\..\System\FileSystem\ArchiveBuffered.h">
</File>
<File
+ RelativePath="..\..\System\FileSystem\ArchiveDir.cpp">
+ </File>
+ <File
+ RelativePath="..\..\System\FileSystem\ArchiveDir.h">
+ </File>
+ <File
RelativePath="..\..\System\FileSystem\ArchiveFactory.cpp">
</File>
<File
@@ -3026,6 +3032,12 @@
</Filter>
</Filter>
<File
+ RelativePath="..\..\System\IconHandler.cpp">
+ </File>
+ <File
+ RelativePath="..\..\System\IconHandler.h">
+ </File>
+ <File
RelativePath=".\resource.h">
</File>
<File
Index: rts/Game/command.h
===================================================================
--- rts/Game/command.h (revision 1536)
+++ rts/Game/command.h (working copy)
@@ -15,6 +15,7 @@
#define CMD_WAIT 5
#define CMD_MOVE 10
#define CMD_PATROL 15
+#define CMD_FIGHT 16
#define CMD_ATTACK 20
#define CMD_AREA_ATTACK 21
#define CMD_GUARD 25
Index: rts/Game/UI/MouseHandler.cpp
===================================================================
--- rts/Game/UI/MouseHandler.cpp (revision 1536)
+++ rts/Game/UI/MouseHandler.cpp (working copy)
@@ -76,6 +76,7 @@
cursors["Attack"] = new CMouseCursor("cursorattack", CMouseCursor::Center);
cursors["DGun"] = new CMouseCursor("cursorattack", CMouseCursor::Center);
cursors["Patrol"] = new CMouseCursor("cursorpatrol", CMouseCursor::Center);
+ cursors["Fight"] = new CMouseCursor("cursorattack", CMouseCursor::Center);
cursors["Repair"] = new CMouseCursor("cursorrepair", CMouseCursor::Center);
cursors["Load units"] = new CMouseCursor("cursorpickup", CMouseCursor::Center);
cursors["Unload units"] = new CMouseCursor("cursorunload", CMouseCursor::Center);
Index: rts/Sim/MoveTypes/groundmovetype.cpp
===================================================================
--- rts/Sim/MoveTypes/groundmovetype.cpp (revision 1536)
+++ rts/Sim/MoveTypes/groundmovetype.cpp (working copy)
@@ -24,6 +24,7 @@
#include "Mobility.h"
#include "MoveMath/MoveMath.h"
#include "Sim/Misc/GeometricObjects.h"
+#include "Sim/Weapons/Weapon.h"
#include "Game/SelectedUnits.h"
#include "Rendering/GroundDecalHandler.h"
#include "ExternalAI/GlobalAIHandler.h"
@@ -90,7 +91,9 @@
nextDeltaSpeedUpdate(0),
nextObstacleAvoidanceUpdate(0),
oldPhysState(CSolidObject::OnGround),
- lastTrackUpdate(0)
+ lastTrackUpdate(0),
+ mainHeadingPos(0,0,0),
+ useMainHeading(false)
{
moveSquareX=(int)owner->pos.x/(SQUARE_SIZE*2);
moveSquareY=(int)owner->pos.z/(SQUARE_SIZE*2);
@@ -155,7 +158,6 @@
ChangeHeading(owner->heading+deltaHeading);
} else
#endif
- {
if(pathId || currentSpeed > 0.0) { //TODO: Stop the unit from moving as a reaction on collision/explosion physics.
//Initial calculations.
currentDistanceToWaypoint = owner->pos.distance2D(waypoint);
@@ -191,8 +193,11 @@
//Apply obstacle avoidance.
float3 desiredVelocity = /*waypointDir/*/ObstacleAvoidance(waypointDir)/**/;
- if(desiredVelocity != ZeroVector)
+ if(desiredVelocity != ZeroVector){
ChangeHeading(GetHeadingFromVector(desiredVelocity.x, desiredVelocity.z));
+ } else {
+ this->SetMainHeading();
+ }
if(nextDeltaSpeedUpdate<=gs->frameNum){
wantedSpeed = pathId ? requestedSpeed : 0;
@@ -203,8 +208,9 @@
wantedSpeed*=max(0.,std::min(1.,desiredVelocity.dot(owner->frontdir)+0.1));
SetDeltaSpeed();
}
+ } else {
+ this->SetMainHeading();
}
- }
if(wantedSpeed>0 || currentSpeed>0) {
@@ -343,6 +349,7 @@
requestedSpeed = min(speed, maxSpeed*2);
requestedTurnRate = owner->mobility->maxTurnRate;
atGoal = false;
+ useMainHeading = false;
progressState = Active;
@@ -368,6 +375,7 @@
StopEngine();
+ this->useMainHeading = false;
if(progressState != Done)
progressState = Done;
}
@@ -1411,3 +1419,52 @@
{
oldPos=owner->pos+UpVector*0.001;
}
+
+void CGroundMoveType::KeepPointingTo(float3 pos, float distance, bool aggressive){
+ this->mainHeadingPos = pos;
+ this->useMainHeading = aggressive;
+ if(this->useMainHeading && !this->owner->weapons.empty()){
+ float3 dir1 = this->owner->weapons.front()->mainDir;
+ dir1.y = 0;
+ dir1.Normalize();
+ float3 dir2 = this->mainHeadingPos-this->owner->pos;
+ dir2.y = 0;
+ dir2.Normalize();
+ if(dir2 != ZeroVector){
+ short heading = GetHeadingFromVector(dir2.x,dir2.z) - GetHeadingFromVector(dir1.x,dir1.z);
+ if(this->owner->heading != heading
+ && !this->owner->weapons.front()->TryTarget(this->mainHeadingPos, true,0)){
+ this->progressState = Active;
+ }
+ }
+ }
+}
+
+/**
+* @breif Orients owner so that weapon[0]'s arc includes mainHeadingPos
+*/
+void CGroundMoveType::SetMainHeading(){
+ if(this->useMainHeading && !this->owner->weapons.empty()){
+ float3 dir1 = this->owner->weapons.front()->mainDir;
+ dir1.y = 0;
+ dir1.Normalize();
+ float3 dir2 = this->mainHeadingPos-this->owner->pos;
+ dir2.y = 0;
+ dir2.Normalize();
+ if(dir2 != ZeroVector){
+ short heading = GetHeadingFromVector(dir2.x,dir2.z) - GetHeadingFromVector(dir1.x,dir1.z);
+ if(this->progressState == Active && this->owner->heading == heading){
+ this->owner->cob->Call(COBFN_StopMoving);
+ this->progressState = Done;
+ } else if(this->progressState == Active){
+ this->ChangeHeading(heading);
+ } else if(this->progressState != Active
+ && this->owner->heading != heading
+ && !this->owner->weapons.front()->TryTarget(this->mainHeadingPos, true,0)){
+ this->progressState = Active;
+ this->owner->cob->Call(COBFN_StartMoving);
+ this->ChangeHeading(heading);
+ }
+ }
+ }
+}
Index: rts/Sim/MoveTypes/groundmovetype.h
===================================================================
--- rts/Sim/MoveTypes/groundmovetype.h (revision 1536)
+++ rts/Sim/MoveTypes/groundmovetype.h (working copy)
@@ -27,6 +27,8 @@
void StopMoving();
void ImpulseAdded(void);
+
+ void KeepPointingTo(float3 pos, float distance, bool aggressive);
//float baseSpeed; //Not used
//float maxSpeed; //Moved to CMoveType, by Lars 04-08-23
@@ -120,6 +122,11 @@
bool CheckColV(int y, int x1, int x2, float zmove, int squareTestY);
static std::vector<int2> lineTable[11][11];
+
+ float3 mainHeadingPos;
+ bool useMainHeading;
+ void SetMainHeading();
+
public:
static void CreateLineTable(void);
void TestNewTerrainSquare(void);
Index: rts/Sim/Units/CommandAI/AirCAI.cpp
===================================================================
--- rts/Sim/Units/CommandAI/AirCAI.cpp (revision 1536)
+++ rts/Sim/Units/CommandAI/AirCAI.cpp (working copy)
@@ -12,7 +12,7 @@
#include "mmgr.h"
CAirCAI::CAirCAI(CUnit* owner)
-: CCommandAI(owner)
+: CCommandAI(owner), lastPC1(-1), lastPC2(-1)
{
CommandDescription c;
c.id=CMD_MOVE;
@@ -29,6 +29,13 @@
c.tooltip="Patrol: Sets the aircraft to patrol a path to one or more waypoints";
possibleCommands.push_back(c);
+ c.id = CMD_FIGHT;
+ c.type = CMDTYPE_ICON_MAP;
+ c.name = "Fight";
+ c.key = 'F';
+ c.tooltip = "Fight: Order the aircraft to take action while moving to a position";
+ possibleCommands.push_back(c);
+
c.id=CMD_AREA_ATTACK;
c.type=CMDTYPE_ICON_AREA;
c.name="Area attack";
@@ -254,63 +261,99 @@
}
break;}
case CMD_PATROL:{
+ float3 curPos=owner->pos;
+ if(c.params.size()<3){ //this shouldnt happen but anyway ...
+ info->AddLine("Error: got patrol cmd with less than 3 params on %s in aircai",
+ owner->unitDef->humanName.c_str());
+ return;
+ }
+ Command temp;
+ temp.id = CMD_FIGHT;
+ temp.params.push_back(c.params[0]);
+ temp.params.push_back(c.params[1]);
+ temp.params.push_back(c.params[2]);
+ temp.options = c.options|INTERNAL_ORDER;
+ commandQue.push_back(c);
+ commandQue.pop_front();
+ commandQue.push_front(temp);
+ if(owner->group){
+ owner->group->CommandFinished(owner->id,CMD_PATROL);
+ }
+ SlowUpdate();
+ break;}
+ case CMD_FIGHT:{
if(tempOrder){
tempOrder=false;
inCommand=true;
}
+ goalPos=float3(c.params[0],c.params[1],c.params[2]);
if(!inCommand){
- float3 pos(c.params[0],c.params[1],c.params[2]);
+ commandPos2=goalPos;
inCommand=true;
- Command co;
- co.id=CMD_PATROL;
- co.params.push_back(curPos.x);
- co.params.push_back(curPos.y);
- co.params.push_back(curPos.z);
- commandQue.push_front(co);
- commandPos1=curPos;
- activeCommand=1;
- patrolTime=3;
}
- Command& c=commandQue[activeCommand];
- if(c.params.size()<3){
- info->AddLine("Patrol command with insufficient parameters ?");
+ commandPos1=curPos;
+ if(c.params.size()<3){ //this shouldnt happen but anyway ...
+ info->AddLine("Error: got fight cmd with less than 3 params on %s in aircai",
+ owner->unitDef->humanName.c_str());
return;
}
- goalPos=float3(c.params[0],c.params[1],c.params[2]);
- commandPos2=goalPos;
- patrolTime++;
+ float testRad=1000*owner->moveState;
+ CUnit* enemy = helper->GetClosestEnemyAircraft(owner->pos+owner->speed*10,testRad,owner->allyteam);
if(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){
- if(owner->moveState!=1 || LinePointDist(commandPos1,commandPos2,enemy->pos) < 1000){
- Command nc;
- nc.id=CMD_ATTACK;
- nc.params.push_back(enemy->id);
- nc.options=c.options;
- commandQue.push_front(nc);
- tempOrder=true;
- inCommand=false;
- SlowUpdate();
- return;
- }
+ if(myPlane->isFighter
+ && enemy && !enemy->crashing
+ && (owner->moveState!=1 || LinePointDist(commandPos1,commandPos2,enemy->pos) < 1000))
+ {
+ Command nc,c3;
+ c3.id = CMD_MOVE; //keep it from being pulled too far off the path
+ float3 dir = goalPos-curPos;
+ dir.Normalize();
+ dir*=sqrtf(1024+owner->xsize*owner->xsize+owner->ysize*owner->ysize);
+ dir+=curPos;
+ c3.params.push_back(dir.x);
+ c3.params.push_back(dir.y);
+ c3.params.push_back(dir.z);
+ c3.options = c.options|INTERNAL_ORDER;
+ nc.id=CMD_ATTACK;
+ nc.params.push_back(enemy->id);
+ nc.options=c.options|INTERNAL_ORDER;
+ commandQue.push_front(nc);
+ tempOrder=true;
+ inCommand=false;
+ if(lastPC1!=gs->frameNum){ //avoid infinite loops
+ lastPC1=gs->frameNum;
+ SlowUpdate();
}
- }
- if((!myPlane->isFighter || owner->moveState==2) && owner->maxRange>0){
+ return;
+ } else if(owner->maxRange>0){
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)){
+ enemy=helper->GetClosestEnemyUnit(owner->pos+owner->speed*20,testRad,owner->allyteam);
+ if(enemy && (owner->hasUWWeapons || !enemy->isUnderWater) && !enemy->crashing
+ && (myPlane->isFighter || !enemy->unitDef->canfly))
+ {
if(owner->moveState!=1 || LinePointDist(commandPos1,commandPos2,enemy->pos) < 1000){
- Command nc;
+ Command nc,c3;
+ c3.id = CMD_MOVE; //keep it from being pulled too far off the path
+ float3 dir = goalPos-curPos;
+ dir.Normalize();
+ dir*=sqrtf(1024+owner->xsize*owner->xsize+owner->ysize*owner->ysize);
+ dir+=curPos;
+ c3.params.push_back(dir.x);
+ c3.params.push_back(dir.y);
+ c3.params.push_back(dir.z);
+ c3.options = c.options|INTERNAL_ORDER;
nc.id=CMD_ATTACK;
nc.params.push_back(enemy->id);
- nc.options=c.options;
+ nc.options=c.options|INTERNAL_ORDER;
+ commandQue.push_front(c3);
commandQue.push_front(nc);
tempOrder=true;
inCommand=false;
- SlowUpdate();
+ if(lastPC2!=gs->frameNum){ //avoid infinite loops
+ lastPC2=gs->frameNum;
+ SlowUpdate();
+ }
return;
}
}
@@ -319,18 +362,7 @@
myPlane->goalPos=goalPos;
if((owner->pos-goalPos).SqLength2D()<16000 || (owner->pos+owner->speed*8-goalPos).SqLength2D()<16000){
- if(owner->group)
- owner->group->CommandFinished(owner->id,CMD_PATROL);
-
- commandPos1=commandPos2;
- if((int)commandQue.size()<=activeCommand+1)
- activeCommand=0;
- else {
- if(commandQue[activeCommand+1].id!=CMD_PATROL)
- activeCommand=0;
- else
- activeCommand++;
- }
+ FinishCommand();
}
return;}
case CMD_ATTACK:
@@ -481,10 +513,11 @@
glColor4f(0.5,1,0.5,0.4);
glVertexf3(pos);
break;
+ case CMD_FIGHT:
case CMD_PATROL:
pos=float3(ci->params[0],ci->params[1]+curHeight,ci->params[2]);
glColor4f(0.5,0.5,1,0.4);
- glVertexf3(pos);
+ glVertexf3(pos);
break;
case CMD_ATTACK:
if(ci->params.size()==1){
Index: rts/Sim/Units/CommandAI/AirCAI.h
===================================================================
--- rts/Sim/Units/CommandAI/AirCAI.h (revision 1536)
+++ rts/Sim/Units/CommandAI/AirCAI.h (working copy)
@@ -31,8 +31,11 @@
int activeCommand;
int targetAge;
- unsigned int patrolTime;
+// unsigned int patrolTime;
+ int lastPC1;
+ int lastPC2;
+
float3 commandPos1; //used to limit how far away stuff can fly from path
float3 commandPos2;
};
Index: rts/Sim/Units/CommandAI/BuilderCAI.cpp
===================================================================
--- rts/Sim/Units/CommandAI/BuilderCAI.cpp (revision 1536)
+++ rts/Sim/Units/CommandAI/BuilderCAI.cpp (working copy)
@@ -26,11 +26,12 @@
CBuilderCAI::CBuilderCAI(CUnit* owner)
: CMobileCAI(owner),
building(false),
- commandFromPatrol(false),
buildPos(0,0,0),
cachedRadius(0),
cachedRadiusId(0),
- buildRetries(0)
+ buildRetries(0),
+ lastPC1(-1),
+ lastPC2(-1)
{
CommandDescription c;
c.id=CMD_REPAIR;
@@ -107,6 +108,7 @@
Command& c=commandQue.front();
CBuilder* fac=(CBuilder*)owner;
+ float3 curPos=owner->pos;
map<int,string>::iterator boi;
if((boi=buildOptions.find(c.id))!=buildOptions.end()){
@@ -114,7 +116,8 @@
if(cachedRadiusId==c.id){
radius=cachedRadius;
} else {
- radius=modelParser->Load3DO(unitDefHandler->GetUnitByName(boi->second)->model.modelpath,1,owner->team)->radius;
+ radius=modelParser->Load3DO(
+ unitDefHandler->GetUnitByName(boi->second)->model.modelpath,1,owner->team)->radius;
cachedRadiusId=c.id;
cachedRadius=radius;
}
@@ -192,7 +195,7 @@
case CMD_REPAIR:{
if(c.params.size()==1){ //repair unit
CUnit* unit=uh->units[(int)c.params[0]];
- if(commandFromPatrol && owner->moveState==1){ //limit how far away we go
+ if(tempOrder && owner->moveState==1){ //limit how far away we go
if(unit && LinePointDist(commandPos1,commandPos2,unit->pos) > 500){
StopMove();
FinishCommand();
@@ -360,7 +363,7 @@
} else if(c.params.size()==4){//area reclaim
float3 pos(c.params[0],c.params[1],c.params[2]);
float radius=c.params[3];
- if(FindReclaimableFeatureAndReclaim(pos,radius,c.options)){
+ if(FindReclaimableFeatureAndReclaim(pos,radius,c.options,true)){
inCommand=false;
SlowUpdate();
return;
@@ -426,75 +429,81 @@
return;}
case CMD_PATROL:{
float3 curPos=owner->pos;
- if(commandFromPatrol){
- commandFromPatrol=false;
- inCommand=true;
- --patrolTime; //prevent searching reclaimtargets etc directly if one of those call returned directly (infinite loop)
+ if(c.params.size()<3){ //this shouldnt happen but anyway ...
+ info->AddLine("Error: got patrol cmd with less than 3 params on %s in buildercai",
+ owner->unitDef->humanName.c_str());
+ return;
}
- if(!inCommand){
- float3 pos(c.params[0],c.params[1],c.params[2]);
+ Command temp;
+ temp.id = CMD_FIGHT;
+ temp.params.push_back(c.params[0]);
+ temp.params.push_back(c.params[1]);
+ temp.params.push_back(c.params[2]);
+ temp.options = c.options|INTERNAL_ORDER;
+ commandQue.push_back(c);
+ commandQue.pop_front();
+ commandQue.push_front(temp);
+ if(owner->group){
+ owner->group->CommandFinished(owner->id,CMD_PATROL);
+ }
+ SlowUpdate();
+ return;}
+ case CMD_FIGHT:{
+ if(tempOrder){
+ tempOrder=false;
inCommand=true;
- Command co;
- co.id=CMD_PATROL;
- co.params.push_back(curPos.x);
- co.params.push_back(curPos.y);
- co.params.push_back(curPos.z);
- commandQue.push_front(co);
- activeCommand=1;
- commandPos1=curPos;
- patrolTime=0;
}
- Command& c=commandQue[activeCommand];
-
if(c.params.size()<3){ //this shouldnt happen but anyway ...
info->AddLine("Error: got patrol cmd with less than 3 params on %s in BuilderCAI",owner->unitDef->humanName.c_str());
return;
}
+ if(c.params.size() >= 6){
+ if(!inCommand){
+ commandPos1 = float3(c.params[3],c.params[4],c.params[5]);
+ }
+ } else {
+ commandPos1 = curPos;
+ }
patrolGoal=float3(c.params[0],c.params[1],c.params[2]);
- commandPos2=patrolGoal;
-
- if(!(patrolTime&3) && owner->fireState==2){
- if(FindRepairTargetAndRepair(owner->pos,300*owner->moveState,c.options,true)){
- CUnit* target=uh->units[(int)commandQue.front().params[0]];
- if(owner->moveState!=1 || LinePointDist(commandPos1,commandPos2,target->pos) < 300){
- commandFromPatrol=true;
- inCommand=false;
+ if(!inCommand){
+ inCommand = true;
+ commandPos2=patrolGoal;
+ }
+ if(!(patrolGoal==goalPos)){
+ SetGoal(patrolGoal,curPos);
+ }
+ if(FindRepairTargetAndRepair(curPos,300*owner->moveState+fac->buildDistance-8,c.options,true)){
+ CUnit* target=uh->units[(int)commandQue.front().params[0]];
+ if(owner->moveState==2 || LinePointDist(commandPos1,commandPos2,target->pos) < 300){
+ tempOrder=true;
+ inCommand=false;
+ if(lastPC1!=gs->frameNum){ //avoid infinite loops
+ lastPC1=gs->frameNum;
SlowUpdate();
- return;
- } else {
- commandQue.pop_front();
}
+ return;
+ } else {
+ commandQue.pop_front();
}
- if(FindReclaimableFeatureAndReclaim(owner->pos,300*owner->moveState,c.options)){
- commandFromPatrol=true;
- inCommand=false;
+ }
+ if(FindReclaimableFeatureAndReclaim(owner->pos,300,c.options,false)){
+ tempOrder=true;
+ inCommand=false;
+ if(lastPC2!=gs->frameNum){ //avoid infinite loops
+ lastPC2=gs->frameNum;
SlowUpdate();
- return;
}
+ return;
}
- patrolTime++;
- if(!(patrolGoal==goalPos)){
- SetGoal(patrolGoal,curPos);
- }
if((curPos-patrolGoal).SqLength2D()<4096){
- if(owner->group)
- owner->group->CommandFinished(owner->id,CMD_PATROL);
-
- if((int)commandQue.size()<=activeCommand+1)
- activeCommand=0;
- else {
- if(commandQue[activeCommand+1].id!=CMD_PATROL)
- activeCommand=0;
- else
- activeCommand++;
- }
- commandPos1=commandPos2;
+ FinishCommand();
+ return;
}
- if(owner->haveTarget && owner->moveType->progressState!=CMoveType::Done)
+ if(owner->haveTarget && owner->moveType->progressState!=CMoveType::Done){
StopMove();
- else if(owner->moveType->progressState!=CMoveType::Active)
+ } else if(owner->moveType->progressState!=CMoveType::Active){
owner->moveType->StartMoving(goalPos, 8);
-
+ }
return;}
case CMD_RESTORE:{
if(inCommand){
@@ -605,6 +614,7 @@
}
draw=true;
break;
+ case CMD_FIGHT:
case CMD_PATROL:
pos=float3(ci->params[0],ci->params[1],ci->params[2]);
glColor4f(0.5,0.5,1,0.4);
@@ -763,7 +773,7 @@
}
}
-bool CBuilderCAI::FindReclaimableFeatureAndReclaim(float3 pos, float radius,unsigned char options)
+bool CBuilderCAI::FindReclaimableFeatureAndReclaim(float3 pos, float radius,unsigned char options, bool recAny)
{
CFeature* best=0;
float bestDist=10000000;
@@ -771,7 +781,9 @@
for(std::vector<CFeature*>::iterator fi=features.begin();fi!=features.end();++fi){
if((*fi)->def->destructable && (*fi)->allyteam!=owner->allyteam){
float dist=(*fi)->pos.distance2D(owner->pos);
- if(dist<bestDist){
+ if(dist<bestDist && (recAny
+ ||((*fi)->def->energy > 0 && gs->Team(owner->team)->energy < gs->Team(owner->team)->energyStorage)
+ ||((*fi)->def->metal > 0 && gs->Team(owner->team)->metal < gs->Team(owner->team)->metalStorage))){
bestDist=dist;
best=*fi;
}
@@ -779,6 +791,9 @@
}
if(best){
Command c2;
+ if(!recAny){
+ commandQue.push_front(this->GetReturnFight(commandQue.front()));
+ }
c2.options=options | INTERNAL_ORDER;
c2.id=CMD_RECLAIM;
c2.params.push_back(MAX_UNITS+best->id);
@@ -796,7 +811,8 @@
for(std::vector<CFeature*>::iterator fi=features.begin();fi!=features.end();++fi){
if((*fi)->def->destructable && (*fi)->createdFromUnit!=""){
float dist=(*fi)->pos.distance2D(owner->pos);
- if(dist<bestDist){
+ if(dist<bestDist)
+ {
bestDist=dist;
best=*fi;
}
@@ -820,7 +836,7 @@
CMobileCAI::FinishCommand();
}
-bool CBuilderCAI::FindRepairTargetAndRepair(float3 pos, float radius,unsigned char options,bool attackEnemy)
+bool CBuilderCAI::FindRepairTargetAndRepair(float3 pos, float radius,unsigned char options, bool attackEnemy)
{
std::vector<CUnit*> cu=qf->GetUnits(pos,radius);
int myAllyteam=owner->allyteam;
@@ -829,6 +845,9 @@
if((*ui)->mobility && (*ui)->beingBuilt && owner->moveState<2) //dont help factories produce units unless set on roam
continue;
Command nc;
+ if(attackEnemy){
+ commandQue.push_front(this->GetReturnFight(this->commandQue.front()));
+ }
nc.id=CMD_REPAIR;
nc.options=options | INTERNAL_ORDER;
nc.params.push_back((*ui)->id);
@@ -836,6 +855,7 @@
return true;
} else if(attackEnemy && owner->maxRange>0 && !gs->Ally(owner->allyteam,(*ui)->allyteam)){
Command nc;
+ commandQue.push_front(this->GetReturnFight(this->commandQue.front()));
nc.id=CMD_ATTACK;
nc.options=options | INTERNAL_ORDER;
nc.params.push_back((*ui)->id);
Index: rts/Sim/Units/CommandAI/BuilderCAI.h
===================================================================
--- rts/Sim/Units/CommandAI/BuilderCAI.h (revision 1536)
+++ rts/Sim/Units/CommandAI/BuilderCAI.h (working copy)
@@ -17,13 +17,12 @@
void GiveCommand(Command& c);
void DrawQuedBuildingSquares(void);
- bool FindReclaimableFeatureAndReclaim(float3 pos, float radius,unsigned char options);
+ bool FindReclaimableFeatureAndReclaim(float3 pos, float radius,unsigned char options, bool recAny);
bool FindResurrectableFeatureAndResurrect(float3 pos, float radius,unsigned char options);
void FinishCommand(void);
bool FindRepairTargetAndRepair(float3 pos, float radius,unsigned char options,bool attackEnemy);
bool FindCaptureTargetAndCapture(float3 pos, float radius,unsigned char options);
- bool commandFromPatrol;
map<int,string> buildOptions;
bool building;
float3 buildPos;
@@ -32,6 +31,9 @@
int cachedRadiusId;
int buildRetries;
+
+ int lastPC1; //helps avoid infinite loops
+ int lastPC2;
};
#endif // __BUILDER_CAI_H__
Index: rts/Sim/Units/CommandAI/CommandAI.cpp
===================================================================
--- rts/Sim/Units/CommandAI/CommandAI.cpp (revision 1536)
+++ rts/Sim/Units/CommandAI/CommandAI.cpp (working copy)
@@ -295,18 +295,20 @@
stockpileWeapon->numStockpileQued=0;
UpdateStockpileIcon();
return; }
- case CMD_SELFD:
+ case CMD_SELFD:{
if(owner->selfDCountdown){
owner->selfDCountdown=0;
} else {
owner->selfDCountdown = owner->unitDef->selfDCountdown*2+1;
}
- return;
+ return;}
}
-
+
if(!(c.options & SHIFT_KEY)){
if(!commandQue.empty()){
- if(commandQue.front().id==CMD_ATTACK || commandQue.front().id==CMD_AREA_ATTACK || commandQue.front().id==CMD_DGUN){
+ if(commandQue.front().id==CMD_ATTACK || commandQue.front().id==CMD_AREA_ATTACK
+ || commandQue.front().id==CMD_DGUN)
+ {
owner->AttackUnit(0,true);
}
@@ -321,30 +323,65 @@
orderTarget=0;
}
}
+ if(c.id == CMD_PATROL){
+ std::deque<Command>::iterator ci = commandQue.begin();
+ for(; ci != commandQue.end() && ci->id!=CMD_PATROL; ci++);
+ if(ci==commandQue.end()){
+ if(commandQue.empty()){
+ Command c2;
+ c2.id = CMD_PATROL;
+ c2.params.push_back(owner->pos.x);
+ c2.params.push_back(owner->pos.y);
+ c2.params.push_back(owner->pos.z);
+ c2.options = c.options;
+ commandQue.push_back(c2);
+ } else {
+ do{
+ ci--;
+ if(ci->params.size() >=3){
+ Command c2;
+ c2.id = CMD_PATROL;
+ c2.params = ci->params;
+ c2.options = c.options;
+ commandQue.push_back(c2);
+ ci=commandQue.begin();
+ } else if(ci==commandQue.begin()){
+ Command c2;
+ c2.id = CMD_PATROL;
+ c2.params.push_back(owner->pos.x);
+ c2.params.push_back(owner->pos.y);
+ c2.params.push_back(owner->pos.z);
+ c2.options = c.options;
+ commandQue.push_back(c2);
+ }
+ }while(ci!=commandQue.begin());
+ }
+ }
+ }
std::deque<Command>::iterator ci = CCommandAI::GetCancelQueued(c);
- if(c.id<0 && ci != this->commandQue.end()){
+ if(c.id<0 && ci != commandQue.end()){
do{
- if(ci == this->commandQue.begin()){
- this->commandQue.erase(ci);
+ if(ci == commandQue.begin()){
+ commandQue.erase(ci);
Command c2;
c2.id = CMD_STOP;
- this->commandQue.push_front(c2);
- this->SlowUpdate();
+ commandQue.push_front(c2);
+ SlowUpdate();
} else {
- this->commandQue.erase(ci);
+ commandQue.erase(ci);
}
ci = CCommandAI::GetCancelQueued(c);
- }while(ci != this->commandQue.end());
+ }while(ci != commandQue.end());
return;
- } else if(ci != this->commandQue.end()){
- if(ci == this->commandQue.begin()){
- this->commandQue.erase(ci);
+ } else if(ci != commandQue.end()){
+ if(ci == commandQue.begin()){
+ commandQue.erase(ci);
Command c2;
c2.id = CMD_STOP;
- this->commandQue.push_front(c2);
- this->SlowUpdate();
+ commandQue.push_front(c2);
+ SlowUpdate();
} else {
- this->commandQue.erase(ci);
+ commandQue.erase(ci);
}
ci = CCommandAI::GetCancelQueued(c);
return;
@@ -547,7 +584,7 @@
void CCommandAI::FinishCommand(void)
{
int type=commandQue.front().id;
- if(repeatOrders && type!=CMD_STOP && !(commandQue.front().options & INTERNAL_ORDER))
+ if(repeatOrders && type!=CMD_STOP && type != CMD_PATROL && !(commandQue.front().options & INTERNAL_ORDER))
commandQue.push_back(commandQue.front());
commandQue.pop_front();
inCommand=false;
@@ -589,7 +626,8 @@
for(pci=possibleCommands.begin();pci!=possibleCommands.end();++pci){
if(pci->id==CMD_STOCKPILE){
char name[50];
- sprintf(name,"%i/%i",stockpileWeapon->numStockpiled,stockpileWeapon->numStockpiled+stockpileWeapon->numStockpileQued);
+ sprintf(name,"%i/%i",stockpileWeapon->numStockpiled,
+ stockpileWeapon->numStockpiled+stockpileWeapon->numStockpileQued);
pci->name=name;
selectedUnits.PossibleCommandChange(owner);
}
@@ -598,7 +636,9 @@
void CCommandAI::WeaponFired(CWeapon* weapon)
{
- if(weapon->weaponDef->manualfire && !weapon->weaponDef->dropped && !commandQue.empty() && (commandQue.front().id==CMD_ATTACK || commandQue.front().id==CMD_DGUN) && inCommand){
+ if(weapon->weaponDef->manualfire && !weapon->weaponDef->dropped && !commandQue.empty()
+ && (commandQue.front().id==CMD_ATTACK || commandQue.front().id==CMD_DGUN) && inCommand)
+ {
owner->AttackUnit(0,true);
globalAI->WeaponFired(owner,weapon->weaponDef);
FinishCommand();
Index: rts/Sim/Units/CommandAI/FactoryCAI.cpp
===================================================================
--- rts/Sim/Units/CommandAI/FactoryCAI.cpp (revision 1536)
+++ rts/Sim/Units/CommandAI/FactoryCAI.cpp (working copy)
@@ -21,12 +21,21 @@
c.key='M';
c.tooltip="Move: Order ready built units to move to a position";
possibleCommands.push_back(c);
+
c.id=CMD_PATROL;
c.type=CMDTYPE_ICON_MAP;
c.name="Patrol";
c.key='P';
c.tooltip="Patrol: Order ready built units to patrol to one or more waypoints";
possibleCommands.push_back(c);
+
+ c.id = CMD_FIGHT;
+ c.type = CMDTYPE_ICON_MAP;
+ c.name = "Fight";
+ c.key = 'F';
+ c.tooltip = "Fight: Order ready built units to take action while moving to a position";
+ possibleCommands.push_back(c);
+
c.id=CMD_GUARD;
c.type=CMDTYPE_ICON_UNIT;
c.name="Guard";
@@ -220,6 +229,7 @@
glColor4f(0.5,1,0.5,0.4);
draw=true;
break;
+ case CMD_FIGHT:
case CMD_PATROL:
pos=float3(ci->params[0],ci->params[1]+3,ci->params[2]);
glColor4f(0.5,0.5,1,0.4);
Index: rts/Sim/Units/CommandAI/MobileCAI.cpp
===================================================================
--- rts/Sim/Units/CommandAI/MobileCAI.cpp (revision 1536)
+++ rts/Sim/Units/CommandAI/MobileCAI.cpp (working copy)
@@ -17,8 +17,7 @@
CMobileCAI::CMobileCAI(CUnit* owner)
: CCommandAI(owner),
- activeCommand(0),
- patrolTime(0),
+// patrolTime(0),
goalPos(-1,-1,-1),
tempOrder(false),
patrolGoal(1,1,1),
@@ -28,7 +27,8 @@
maxWantedSpeed(0),
lastIdleCheck(0),
commandPos1(ZeroVector),
- commandPos2(ZeroVector)
+ commandPos2(ZeroVector),
+ lastPC(-1)
{
lastUserGoal=owner->pos;
@@ -48,6 +48,15 @@
c.tooltip="Patrol: Order the unit to patrol to one or more waypoints";
possibleCommands.push_back(c);
+ c.params.clear();
+ c.id = CMD_FIGHT;
+ c.type = CMDTYPE_ICON_MAP;
+ c.name = "Fight";
+ c.key = 'F';
+ c.tooltip = "Fight: Order the unit to take action while moving to a position";
+ possibleCommands.push_back(c);
+
+
c.id=CMD_GUARD;
c.type=CMDTYPE_ICON_UNIT;
c.name="Guard";
@@ -114,7 +123,6 @@
}
if(!(c.options & SHIFT_KEY) && nonQueingCommands.find(c.id)==nonQueingCommands.end()){
- activeCommand=0;
tempOrder=false;
}
CCommandAI::GiveCommand(c);
@@ -154,72 +162,83 @@
}
break;}
case CMD_PATROL:{
+ if(c.params.size()<3){ //this shouldnt happen but anyway ...
+ info->AddLine("Error: got patrol cmd with less than 3 params on %s in mobilecai",
+ owner->unitDef->humanName.c_str());
+ return;
+ }
+ Command temp;
+ temp.id = CMD_FIGHT;
+ temp.params.push_back(c.params[0]);
+ temp.params.push_back(c.params[1]);
+ temp.params.push_back(c.params[2]);
+ temp.options = c.options|INTERNAL_ORDER;
+ commandQue.push_back(c);
+ commandQue.pop_front();
+ commandQue.push_front(temp);
+ if(owner->group){
+ owner->group->CommandFinished(owner->id,CMD_PATROL);
+ }
+ SlowUpdate();
+ return;}
+ case CMD_FIGHT:{
if(tempOrder){
- tempOrder=false;
- inCommand=true;
- patrolTime=1;
+ inCommand = true;
+ tempOrder = false;
}
- if(!inCommand){
- float3 pos(c.params[0],c.params[1],c.params[2]);
- inCommand=true;
- Command co;
- co.id=CMD_PATROL;
- co.params.push_back(curPos.x);
- co.params.push_back(curPos.y);
- co.params.push_back(curPos.z);
- commandQue.push_front(co);
- activeCommand=1;
- commandPos1=curPos;
- patrolTime=1;
- }
- Command& c=commandQue[activeCommand];
if(c.params.size()<3){ //this shouldnt happen but anyway ...
- info->AddLine("Error: got patrol cmd with less than 3 params on %s in mobilecai",owner->unitDef->humanName.c_str());
+ info->AddLine("Error: got fight cmd with less than 3 params on %s in mobilecai",
+ owner->unitDef->humanName.c_str());
return;
}
- patrolGoal=float3(c.params[0],c.params[1],c.params[2]);
- commandPos2=patrolGoal;
- patrolTime++;
+ if(c.params.size() >= 6){
+ if(!inCommand){
+ commandPos1 = float3(c.params[3],c.params[4],c.params[5]);
+ }
+ } else {
+ commandPos1 = curPos;
+ }
+ float3 pos(c.params[0],c.params[1],c.params[2]);
+ if(!inCommand){
+ inCommand = true;
+ commandPos2 = pos;
+ }
+ if(pos!=goalPos){
+ SetGoal(pos,curPos);
+ }
- if(!(patrolTime&1) && owner->fireState==2){
- CUnit* enemy=helper->GetClosestEnemyUnit(curPos,owner->maxRange+100*owner->moveState*owner->moveState,owner->allyteam);
- if(enemy && (owner->hasUWWeapons || !enemy->isUnderWater) && !(owner->unitDef->noChaseCategory & enemy->category) && !owner->weapons.empty()){ //todo: make sure they dont stray to far from path
- if(owner->moveState!=1 || LinePointDist(commandPos1,commandPos2,enemy->pos) < 300+owner->maxRange){
- Command c2;
+ if(owner->fireState==2){
+ CUnit* enemy=helper->GetClosestEnemyUnit(
+ curPos, owner->maxRange+100*owner->moveState*owner->moveState, owner->allyteam);
+ if(enemy && (owner->hasUWWeapons || !enemy->isUnderWater)
+ && !(owner->unitDef->noChaseCategory & enemy->category) && !owner->weapons.empty()){ //todo: make sure they dont stray to far from path
+ if(owner->moveState!=1
+ || LinePointDist(commandPos1,commandPos2,enemy->pos)
+ < 300+max(owner->maxRange, (float)owner->losRadius)){
+ Command c2,c3;
+ c3 = this->GetReturnFight(c);
c2.id=CMD_ATTACK;
- c2.options=c.options;
+ c2.options=c.options|INTERNAL_ORDER;
c2.params.push_back(enemy->id);
+ commandQue.push_front(c3);
commandQue.push_front(c2);
inCommand=false;
tempOrder=true;
- SlowUpdate(); //if attack can finish immidiatly this could lead to an infinite loop so make sure it doesnt
+ if(lastPC!=gs->frameNum){ //avoid infinite loops
+ lastPC=gs->frameNum;
+ SlowUpdate();
+ }
return;
}
}
}
- if((curPos-patrolGoal).SqLength2D()<4096 || owner->moveType->progressState==CMoveType::Failed){
- if(owner->group)
- owner->group->CommandFinished(owner->id,CMD_PATROL);
-
- if((int)commandQue.size()<=activeCommand+1)
- activeCommand=0;
- else {
- if(commandQue[activeCommand+1].id!=CMD_PATROL)
- activeCommand=0;
- else
- activeCommand++;
- }
- Command& c=commandQue[activeCommand];
- patrolGoal=float3(c.params[0],c.params[1],c.params[2]);
- commandPos1=commandPos2;
- commandPos2=patrolGoal;
+ if((curPos-goalPos).SqLength2D()<4096 || owner->moveType->progressState==CMoveType::Failed){
+ FinishCommand();
}
- if((patrolGoal!=goalPos)){
- SetGoal(patrolGoal,curPos);
- }
return;}
case CMD_DGUN:
- if(uh->limitDgun && owner->unitDef->isCommander && owner->pos.distance(gs->Team(owner->team)->startPos)>uh->dgunRadius){
+ if(uh->limitDgun && owner->unitDef->isCommander
+ && owner->pos.distance(gs->Team(owner->team)->startPos)>uh->dgunRadius){
StopMove();
FinishCommand();
return;
@@ -259,33 +278,35 @@
}
if(orderTarget){
//note that we handle aircrafts slightly differently
- if(((owner->AttackUnit(orderTarget, c.id==CMD_DGUN) || dynamic_cast<CTAAirMoveType*>(owner->moveType)) && (owner->pos-orderTarget->pos).Length2D()<owner->maxRange*0.9) || (owner->pos-orderTarget->pos).SqLength2D()<1024){
- // if(owner->isMoving) {
+ if((((owner->AttackUnit(orderTarget, c.id==CMD_DGUN) && owner->weapons.size() > 0
+ && owner->weapons.front()->range > orderTarget->pos.distance(owner->pos))
+ || dynamic_cast<CTAAirMoveType*>(owner->moveType))
+ && (owner->pos-orderTarget->pos).Length2D()<owner->maxRange*0.9)
+ || (owner->pos-orderTarget->pos).SqLength2D()<1024){
StopMove();
- owner->moveType->KeepPointingTo(orderTarget->pos, min((double)(owner->losRadius*SQUARE_SIZE*2),owner->maxRange*0.9), true);
- // }
- } else {
- if((orderTarget->pos+owner->posErrorVector*128).distance2D(goalPos)>10+orderTarget->pos.distance2D(owner->pos)*0.2)
- {
- float3 fix=orderTarget->pos+owner->posErrorVector*128;
- SetGoal(fix,curPos);
- }
+ owner->moveType->KeepPointingTo(orderTarget->pos, min((double)(owner->losRadius*SQUARE_SIZE*2),
+ owner->maxRange*0.9), true);
+ } else if((orderTarget->pos+owner->posErrorVector*128).distance2D(goalPos)
+ > 10+orderTarget->pos.distance2D(owner->pos)*0.2){
+ float3 fix=orderTarget->pos+owner->posErrorVector*128;
+ SetGoal(fix,curPos);
}
} else {
float3 pos(c.params[0],c.params[1],c.params[2]);
- if(owner->AttackGround(pos,c.id==CMD_DGUN) || (owner->pos-pos).SqLength2D()<1024) {
+ if((owner->AttackGround(pos,c.id==CMD_DGUN) && owner->weapons.size() > 0
+ && (owner->pos-pos).Length()< owner->weapons.front()->range) || (owner->pos-pos).SqLength2D()<1024){
StopMove();
owner->moveType->KeepPointingTo(pos, owner->maxRange*0.9, true);
- } else {
- if(pos.distance2D(goalPos)>10)
- SetGoal(pos,curPos);
+ } else if(pos.distance2D(goalPos)>10){
+ SetGoal(pos,curPos);
}
}
break;
case CMD_GUARD:
if(uh->units[int(c.params[0])]!=0){
CUnit* guarded=uh->units[int(c.params[0])];
- if(guarded->lastAttacker && guarded->lastAttack+40<gs->frameNum && (owner->hasUWWeapons || !guarded->lastAttacker->isUnderWater)){
+ if(guarded->lastAttacker && guarded->lastAttack+40<gs->frameNum
+ && (owner->hasUWWeapons || !guarded->lastAttacker->isUnderWater)){
Command nc;
nc.id=CMD_ATTACK;
nc.params.push_back(guarded->lastAttacker->id);
@@ -357,6 +378,7 @@
draw=true;
break;
case CMD_PATROL:
+ case CMD_FIGHT:
pos=float3(ci->params[0],ci->params[1],ci->params[2]);
glColor4f(0.5,0.5,1,0.4);
draw=true;
@@ -424,7 +446,6 @@
lastUserGoal=owner->pos;
// info->AddLine("Reseting user goal");
}
-
CCommandAI::FinishCommand();
}
@@ -471,3 +492,34 @@
NonMoving();
}
}
+
+/**
+* @brief gets the command that keeps the unit close to the path
+* @return a Fight Command with 6 arguments, the first three being where to return to (the current position of the
+* unit), and the second being the location of the origional command.
+* @param c the command to return to
+**/
+Command CMobileCAI::GetReturnFight(Command c){
+ Command c3;
+ c3.id = CMD_FIGHT; //keep it from being pulled too far off the path
+ float3 pos = float3(c.params[0],c.params[1],c.params[2]);
+ const float3 &curPos = this->owner->pos;
+ float3 dir = pos-curPos;
+ dir.Normalize();
+ dir*=sqrtf(abs(1024+owner->xsize*owner->xsize+owner->ysize*owner->ysize));
+ dir+=curPos;
+ c3.params.push_back(dir.x);
+ c3.params.push_back(dir.y);
+ c3.params.push_back(dir.z);
+ if(c.params.size() >= 6){
+ c3.params.push_back(c.params[3]);
+ c3.params.push_back(c.params[4]);
+ c3.params.push_back(c.params[5]);
+ } else {
+ c3.params.push_back(c.params[0]);
+ c3.params.push_back(c.params[1]);
+ c3.params.push_back(c.params[2]);
+ }
+ c3.options = c.options|INTERNAL_ORDER;
+ return c3;
+}
\ No newline at end of file
Index: rts/Sim/Units/CommandAI/MobileCAI.h
===================================================================
--- rts/Sim/Units/CommandAI/MobileCAI.h (revision 1536)
+++ rts/Sim/Units/CommandAI/MobileCAI.h (working copy)
@@ -20,17 +20,19 @@
void NonMoving(void);
void FinishCommand(void);
void IdleCheck(void);
+ Command GetReturnFight(Command c);
float3 goalPos;
float3 patrolGoal;
float3 lastUserGoal;
- int activeCommand;
int lastIdleCheck;
bool tempOrder;
- unsigned int patrolTime;
+ int lastPC; //helps avoid infinate loops
+// unsigned int patrolTime;
+
float maxWantedSpeed;
int lastBuggerOffTime;
Index: rts/Sim/Units/CommandAI/TransportCAI.cpp
===================================================================
--- rts/Sim/Units/CommandAI/TransportCAI.cpp (revision 1536)
+++ rts/Sim/Units/CommandAI/TransportCAI.cpp (working copy)
@@ -334,6 +334,7 @@
glColor4f(0.5,1,0.5,0.4);
draw=true;
break;
+ case CMD_FIGHT:
case CMD_PATROL:
pos=float3(ci->params[0],ci->params[1],ci->params[2]);
glColor4f(0.5,0.5,1,0.4);
-
ArcWeapon&Fight(1).patch (39,820 bytes) 2006-07-01 10:35
Index: rts/Game/command.h
===================================================================
--- rts/Game/command.h (revision 1536)
+++ rts/Game/command.h (working copy)
@@ -15,6 +15,7 @@
#define CMD_WAIT 5
#define CMD_MOVE 10
#define CMD_PATROL 15
+#define CMD_FIGHT 16
#define CMD_ATTACK 20
#define CMD_AREA_ATTACK 21
#define CMD_GUARD 25
Index: rts/Game/UI/MouseHandler.cpp
===================================================================
--- rts/Game/UI/MouseHandler.cpp (revision 1536)
+++ rts/Game/UI/MouseHandler.cpp (working copy)
@@ -76,6 +76,7 @@
cursors["Attack"] = new CMouseCursor("cursorattack", CMouseCursor::Center);
cursors["DGun"] = new CMouseCursor("cursorattack", CMouseCursor::Center);
cursors["Patrol"] = new CMouseCursor("cursorpatrol", CMouseCursor::Center);
+ cursors["Fight"] = new CMouseCursor("cursorattack", CMouseCursor::Center);
cursors["Repair"] = new CMouseCursor("cursorrepair", CMouseCursor::Center);
cursors["Load units"] = new CMouseCursor("cursorpickup", CMouseCursor::Center);
cursors["Unload units"] = new CMouseCursor("cursorunload", CMouseCursor::Center);
Index: rts/Sim/MoveTypes/groundmovetype.cpp
===================================================================
--- rts/Sim/MoveTypes/groundmovetype.cpp (revision 1536)
+++ rts/Sim/MoveTypes/groundmovetype.cpp (working copy)
@@ -24,6 +24,7 @@
#include "Mobility.h"
#include "MoveMath/MoveMath.h"
#include "Sim/Misc/GeometricObjects.h"
+#include "Sim/Weapons/Weapon.h"
#include "Game/SelectedUnits.h"
#include "Rendering/GroundDecalHandler.h"
#include "ExternalAI/GlobalAIHandler.h"
@@ -90,7 +91,9 @@
nextDeltaSpeedUpdate(0),
nextObstacleAvoidanceUpdate(0),
oldPhysState(CSolidObject::OnGround),
- lastTrackUpdate(0)
+ lastTrackUpdate(0),
+ mainHeadingPos(0,0,0),
+ useMainHeading(false)
{
moveSquareX=(int)owner->pos.x/(SQUARE_SIZE*2);
moveSquareY=(int)owner->pos.z/(SQUARE_SIZE*2);
@@ -155,7 +158,6 @@
ChangeHeading(owner->heading+deltaHeading);
} else
#endif
- {
if(pathId || currentSpeed > 0.0) { //TODO: Stop the unit from moving as a reaction on collision/explosion physics.
//Initial calculations.
currentDistanceToWaypoint = owner->pos.distance2D(waypoint);
@@ -191,8 +193,11 @@
//Apply obstacle avoidance.
float3 desiredVelocity = /*waypointDir/*/ObstacleAvoidance(waypointDir)/**/;
- if(desiredVelocity != ZeroVector)
+ if(desiredVelocity != ZeroVector){
ChangeHeading(GetHeadingFromVector(desiredVelocity.x, desiredVelocity.z));
+ } else {
+ this->SetMainHeading();
+ }
if(nextDeltaSpeedUpdate<=gs->frameNum){
wantedSpeed = pathId ? requestedSpeed : 0;
@@ -203,8 +208,9 @@
wantedSpeed*=max(0.,std::min(1.,desiredVelocity.dot(owner->frontdir)+0.1));
SetDeltaSpeed();
}
+ } else {
+ this->SetMainHeading();
}
- }
if(wantedSpeed>0 || currentSpeed>0) {
@@ -343,6 +349,7 @@
requestedSpeed = min(speed, maxSpeed*2);
requestedTurnRate = owner->mobility->maxTurnRate;
atGoal = false;
+ useMainHeading = false;
progressState = Active;
@@ -368,6 +375,7 @@
StopEngine();
+ this->useMainHeading = false;
if(progressState != Done)
progressState = Done;
}
@@ -1411,3 +1419,52 @@
{
oldPos=owner->pos+UpVector*0.001;
}
+
+void CGroundMoveType::KeepPointingTo(float3 pos, float distance, bool aggressive){
+ this->mainHeadingPos = pos;
+ this->useMainHeading = aggressive;
+ if(this->useMainHeading && !this->owner->weapons.empty()){
+ float3 dir1 = this->owner->weapons.front()->mainDir;
+ dir1.y = 0;
+ dir1.Normalize();
+ float3 dir2 = this->mainHeadingPos-this->owner->pos;
+ dir2.y = 0;
+ dir2.Normalize();
+ if(dir2 != ZeroVector){
+ short heading = GetHeadingFromVector(dir2.x,dir2.z) - GetHeadingFromVector(dir1.x,dir1.z);
+ if(this->owner->heading != heading
+ && !this->owner->weapons.front()->TryTarget(this->mainHeadingPos, true,0)){
+ this->progressState = Active;
+ }
+ }
+ }
+}
+
+/**
+* @breif Orients owner so that weapon[0]'s arc includes mainHeadingPos
+*/
+void CGroundMoveType::SetMainHeading(){
+ if(this->useMainHeading && !this->owner->weapons.empty()){
+ float3 dir1 = this->owner->weapons.front()->mainDir;
+ dir1.y = 0;
+ dir1.Normalize();
+ float3 dir2 = this->mainHeadingPos-this->owner->pos;
+ dir2.y = 0;
+ dir2.Normalize();
+ if(dir2 != ZeroVector){
+ short heading = GetHeadingFromVector(dir2.x,dir2.z) - GetHeadingFromVector(dir1.x,dir1.z);
+ if(this->progressState == Active && this->owner->heading == heading){
+ this->owner->cob->Call(COBFN_StopMoving);
+ this->progressState = Done;
+ } else if(this->progressState == Active){
+ this->ChangeHeading(heading);
+ } else if(this->progressState != Active
+ && this->owner->heading != heading
+ && !this->owner->weapons.front()->TryTarget(this->mainHeadingPos, true,0)){
+ this->progressState = Active;
+ this->owner->cob->Call(COBFN_StartMoving);
+ this->ChangeHeading(heading);
+ }
+ }
+ }
+}
Index: rts/Sim/MoveTypes/groundmovetype.h
===================================================================
--- rts/Sim/MoveTypes/groundmovetype.h (revision 1536)
+++ rts/Sim/MoveTypes/groundmovetype.h (working copy)
@@ -27,6 +27,8 @@
void StopMoving();
void ImpulseAdded(void);
+
+ void KeepPointingTo(float3 pos, float distance, bool aggressive);
//float baseSpeed; //Not used
//float maxSpeed; //Moved to CMoveType, by Lars 04-08-23
@@ -120,6 +122,11 @@
bool CheckColV(int y, int x1, int x2, float zmove, int squareTestY);
static std::vector<int2> lineTable[11][11];
+
+ float3 mainHeadingPos;
+ bool useMainHeading;
+ void SetMainHeading();
+
public:
static void CreateLineTable(void);
void TestNewTerrainSquare(void);
Index: rts/Sim/Units/CommandAI/AirCAI.cpp
===================================================================
--- rts/Sim/Units/CommandAI/AirCAI.cpp (revision 1536)
+++ rts/Sim/Units/CommandAI/AirCAI.cpp (working copy)
@@ -12,7 +12,7 @@
#include "mmgr.h"
CAirCAI::CAirCAI(CUnit* owner)
-: CCommandAI(owner)
+: CCommandAI(owner), lastPC1(-1), lastPC2(-1)
{
CommandDescription c;
c.id=CMD_MOVE;
@@ -29,6 +29,13 @@
c.tooltip="Patrol: Sets the aircraft to patrol a path to one or more waypoints";
possibleCommands.push_back(c);
+ c.id = CMD_FIGHT;
+ c.type = CMDTYPE_ICON_MAP;
+ c.name = "Fight";
+ c.key = 'F';
+ c.tooltip = "Fight: Order the aircraft to take action while moving to a position";
+ possibleCommands.push_back(c);
+
c.id=CMD_AREA_ATTACK;
c.type=CMDTYPE_ICON_AREA;
c.name="Area attack";
@@ -254,63 +261,99 @@
}
break;}
case CMD_PATROL:{
+ float3 curPos=owner->pos;
+ if(c.params.size()<3){ //this shouldnt happen but anyway ...
+ info->AddLine("Error: got patrol cmd with less than 3 params on %s in aircai",
+ owner->unitDef->humanName.c_str());
+ return;
+ }
+ Command temp;
+ temp.id = CMD_FIGHT;
+ temp.params.push_back(c.params[0]);
+ temp.params.push_back(c.params[1]);
+ temp.params.push_back(c.params[2]);
+ temp.options = c.options|INTERNAL_ORDER;
+ commandQue.push_back(c);
+ commandQue.pop_front();
+ commandQue.push_front(temp);
+ if(owner->group){
+ owner->group->CommandFinished(owner->id,CMD_PATROL);
+ }
+ SlowUpdate();
+ break;}
+ case CMD_FIGHT:{
if(tempOrder){
tempOrder=false;
inCommand=true;
}
+ goalPos=float3(c.params[0],c.params[1],c.params[2]);
if(!inCommand){
- float3 pos(c.params[0],c.params[1],c.params[2]);
+ commandPos2=goalPos;
inCommand=true;
- Command co;
- co.id=CMD_PATROL;
- co.params.push_back(curPos.x);
- co.params.push_back(curPos.y);
- co.params.push_back(curPos.z);
- commandQue.push_front(co);
- commandPos1=curPos;
- activeCommand=1;
- patrolTime=3;
}
- Command& c=commandQue[activeCommand];
- if(c.params.size()<3){
- info->AddLine("Patrol command with insufficient parameters ?");
+ commandPos1=curPos;
+ if(c.params.size()<3){ //this shouldnt happen but anyway ...
+ info->AddLine("Error: got fight cmd with less than 3 params on %s in aircai",
+ owner->unitDef->humanName.c_str());
return;
}
- goalPos=float3(c.params[0],c.params[1],c.params[2]);
- commandPos2=goalPos;
- patrolTime++;
+ float testRad=1000*owner->moveState;
+ CUnit* enemy = helper->GetClosestEnemyAircraft(owner->pos+owner->speed*10,testRad,owner->allyteam);
if(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){
- if(owner->moveState!=1 || LinePointDist(commandPos1,commandPos2,enemy->pos) < 1000){
- Command nc;
- nc.id=CMD_ATTACK;
- nc.params.push_back(enemy->id);
- nc.options=c.options;
- commandQue.push_front(nc);
- tempOrder=true;
- inCommand=false;
- SlowUpdate();
- return;
- }
+ if(myPlane->isFighter
+ && enemy && !enemy->crashing
+ && (owner->moveState!=1 || LinePointDist(commandPos1,commandPos2,enemy->pos) < 1000))
+ {
+ Command nc,c3;
+ c3.id = CMD_MOVE; //keep it from being pulled too far off the path
+ float3 dir = goalPos-curPos;
+ dir.Normalize();
+ dir*=sqrtf(1024+owner->xsize*owner->xsize+owner->ysize*owner->ysize);
+ dir+=curPos;
+ c3.params.push_back(dir.x);
+ c3.params.push_back(dir.y);
+ c3.params.push_back(dir.z);
+ c3.options = c.options|INTERNAL_ORDER;
+ nc.id=CMD_ATTACK;
+ nc.params.push_back(enemy->id);
+ nc.options=c.options|INTERNAL_ORDER;
+ commandQue.push_front(nc);
+ tempOrder=true;
+ inCommand=false;
+ if(lastPC1!=gs->frameNum){ //avoid infinite loops
+ lastPC1=gs->frameNum;
+ SlowUpdate();
}
- }
- if((!myPlane->isFighter || owner->moveState==2) && owner->maxRange>0){
+ return;
+ } else if(owner->maxRange>0){
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)){
+ enemy=helper->GetClosestEnemyUnit(owner->pos+owner->speed*20,testRad,owner->allyteam);
+ if(enemy && (owner->hasUWWeapons || !enemy->isUnderWater) && !enemy->crashing
+ && (myPlane->isFighter || !enemy->unitDef->canfly))
+ {
if(owner->moveState!=1 || LinePointDist(commandPos1,commandPos2,enemy->pos) < 1000){
- Command nc;
+ Command nc,c3;
+ c3.id = CMD_MOVE; //keep it from being pulled too far off the path
+ float3 dir = goalPos-curPos;
+ dir.Normalize();
+ dir*=sqrtf(1024+owner->xsize*owner->xsize+owner->ysize*owner->ysize);
+ dir+=curPos;
+ c3.params.push_back(dir.x);
+ c3.params.push_back(dir.y);
+ c3.params.push_back(dir.z);
+ c3.options = c.options|INTERNAL_ORDER;
nc.id=CMD_ATTACK;
nc.params.push_back(enemy->id);
- nc.options=c.options;
+ nc.options=c.options|INTERNAL_ORDER;
+ commandQue.push_front(c3);
commandQue.push_front(nc);
tempOrder=true;
inCommand=false;
- SlowUpdate();
+ if(lastPC2!=gs->frameNum){ //avoid infinite loops
+ lastPC2=gs->frameNum;
+ SlowUpdate();
+ }
return;
}
}
@@ -319,18 +362,7 @@
myPlane->goalPos=goalPos;
if((owner->pos-goalPos).SqLength2D()<16000 || (owner->pos+owner->speed*8-goalPos).SqLength2D()<16000){
- if(owner->group)
- owner->group->CommandFinished(owner->id,CMD_PATROL);
-
- commandPos1=commandPos2;
- if((int)commandQue.size()<=activeCommand+1)
- activeCommand=0;
- else {
- if(commandQue[activeCommand+1].id!=CMD_PATROL)
- activeCommand=0;
- else
- activeCommand++;
- }
+ FinishCommand();
}
return;}
case CMD_ATTACK:
@@ -481,10 +513,11 @@
glColor4f(0.5,1,0.5,0.4);
glVertexf3(pos);
break;
+ case CMD_FIGHT:
case CMD_PATROL:
pos=float3(ci->params[0],ci->params[1]+curHeight,ci->params[2]);
glColor4f(0.5,0.5,1,0.4);
- glVertexf3(pos);
+ glVertexf3(pos);
break;
case CMD_ATTACK:
if(ci->params.size()==1){
Index: rts/Sim/Units/CommandAI/AirCAI.h
===================================================================
--- rts/Sim/Units/CommandAI/AirCAI.h (revision 1536)
+++ rts/Sim/Units/CommandAI/AirCAI.h (working copy)
@@ -31,8 +31,11 @@
int activeCommand;
int targetAge;
- unsigned int patrolTime;
+// unsigned int patrolTime;
+ int lastPC1;
+ int lastPC2;
+
float3 commandPos1; //used to limit how far away stuff can fly from path
float3 commandPos2;
};
Index: rts/Sim/Units/CommandAI/BuilderCAI.cpp
===================================================================
--- rts/Sim/Units/CommandAI/BuilderCAI.cpp (revision 1536)
+++ rts/Sim/Units/CommandAI/BuilderCAI.cpp (working copy)
@@ -26,11 +26,12 @@
CBuilderCAI::CBuilderCAI(CUnit* owner)
: CMobileCAI(owner),
building(false),
- commandFromPatrol(false),
buildPos(0,0,0),
cachedRadius(0),
cachedRadiusId(0),
- buildRetries(0)
+ buildRetries(0),
+ lastPC1(-1),
+ lastPC2(-1)
{
CommandDescription c;
c.id=CMD_REPAIR;
@@ -107,6 +108,7 @@
Command& c=commandQue.front();
CBuilder* fac=(CBuilder*)owner;
+ float3 curPos=owner->pos;
map<int,string>::iterator boi;
if((boi=buildOptions.find(c.id))!=buildOptions.end()){
@@ -114,7 +116,8 @@
if(cachedRadiusId==c.id){
radius=cachedRadius;
} else {
- radius=modelParser->Load3DO(unitDefHandler->GetUnitByName(boi->second)->model.modelpath,1,owner->team)->radius;
+ radius=modelParser->Load3DO(
+ unitDefHandler->GetUnitByName(boi->second)->model.modelpath,1,owner->team)->radius;
cachedRadiusId=c.id;
cachedRadius=radius;
}
@@ -192,7 +195,7 @@
case CMD_REPAIR:{
if(c.params.size()==1){ //repair unit
CUnit* unit=uh->units[(int)c.params[0]];
- if(commandFromPatrol && owner->moveState==1){ //limit how far away we go
+ if(tempOrder && owner->moveState==1){ //limit how far away we go
if(unit && LinePointDist(commandPos1,commandPos2,unit->pos) > 500){
StopMove();
FinishCommand();
@@ -360,7 +363,7 @@
} else if(c.params.size()==4){//area reclaim
float3 pos(c.params[0],c.params[1],c.params[2]);
float radius=c.params[3];
- if(FindReclaimableFeatureAndReclaim(pos,radius,c.options)){
+ if(FindReclaimableFeatureAndReclaim(pos,radius,c.options,true)){
inCommand=false;
SlowUpdate();
return;
@@ -426,75 +429,81 @@
return;}
case CMD_PATROL:{
float3 curPos=owner->pos;
- if(commandFromPatrol){
- commandFromPatrol=false;
- inCommand=true;
- --patrolTime; //prevent searching reclaimtargets etc directly if one of those call returned directly (infinite loop)
+ if(c.params.size()<3){ //this shouldnt happen but anyway ...
+ info->AddLine("Error: got patrol cmd with less than 3 params on %s in buildercai",
+ owner->unitDef->humanName.c_str());
+ return;
}
- if(!inCommand){
- float3 pos(c.params[0],c.params[1],c.params[2]);
+ Command temp;
+ temp.id = CMD_FIGHT;
+ temp.params.push_back(c.params[0]);
+ temp.params.push_back(c.params[1]);
+ temp.params.push_back(c.params[2]);
+ temp.options = c.options|INTERNAL_ORDER;
+ commandQue.push_back(c);
+ commandQue.pop_front();
+ commandQue.push_front(temp);
+ if(owner->group){
+ owner->group->CommandFinished(owner->id,CMD_PATROL);
+ }
+ SlowUpdate();
+ return;}
+ case CMD_FIGHT:{
+ if(tempOrder){
+ tempOrder=false;
inCommand=true;
- Command co;
- co.id=CMD_PATROL;
- co.params.push_back(curPos.x);
- co.params.push_back(curPos.y);
- co.params.push_back(curPos.z);
- commandQue.push_front(co);
- activeCommand=1;
- commandPos1=curPos;
- patrolTime=0;
}
- Command& c=commandQue[activeCommand];
-
if(c.params.size()<3){ //this shouldnt happen but anyway ...
info->AddLine("Error: got patrol cmd with less than 3 params on %s in BuilderCAI",owner->unitDef->humanName.c_str());
return;
}
+ if(c.params.size() >= 6){
+ if(!inCommand){
+ commandPos1 = float3(c.params[3],c.params[4],c.params[5]);
+ }
+ } else {
+ commandPos1 = curPos;
+ }
patrolGoal=float3(c.params[0],c.params[1],c.params[2]);
- commandPos2=patrolGoal;
-
- if(!(patrolTime&3) && owner->fireState==2){
- if(FindRepairTargetAndRepair(owner->pos,300*owner->moveState,c.options,true)){
- CUnit* target=uh->units[(int)commandQue.front().params[0]];
- if(owner->moveState!=1 || LinePointDist(commandPos1,commandPos2,target->pos) < 300){
- commandFromPatrol=true;
- inCommand=false;
+ if(!inCommand){
+ inCommand = true;
+ commandPos2=patrolGoal;
+ }
+ if(!(patrolGoal==goalPos)){
+ SetGoal(patrolGoal,curPos);
+ }
+ if(FindRepairTargetAndRepair(curPos,300*owner->moveState+fac->buildDistance-8,c.options,true)){
+ CUnit* target=uh->units[(int)commandQue.front().params[0]];
+ if(owner->moveState==2 || LinePointDist(commandPos1,commandPos2,target->pos) < 300){
+ tempOrder=true;
+ inCommand=false;
+ if(lastPC1!=gs->frameNum){ //avoid infinite loops
+ lastPC1=gs->frameNum;
SlowUpdate();
- return;
- } else {
- commandQue.pop_front();
}
+ return;
+ } else {
+ commandQue.pop_front();
}
- if(FindReclaimableFeatureAndReclaim(owner->pos,300*owner->moveState,c.options)){
- commandFromPatrol=true;
- inCommand=false;
+ }
+ if(FindReclaimableFeatureAndReclaim(owner->pos,300,c.options,false)){
+ tempOrder=true;
+ inCommand=false;
+ if(lastPC2!=gs->frameNum){ //avoid infinite loops
+ lastPC2=gs->frameNum;
SlowUpdate();
- return;
}
+ return;
}
- patrolTime++;
- if(!(patrolGoal==goalPos)){
- SetGoal(patrolGoal,curPos);
- }
if((curPos-patrolGoal).SqLength2D()<4096){
- if(owner->group)
- owner->group->CommandFinished(owner->id,CMD_PATROL);
-
- if((int)commandQue.size()<=activeCommand+1)
- activeCommand=0;
- else {
- if(commandQue[activeCommand+1].id!=CMD_PATROL)
- activeCommand=0;
- else
- activeCommand++;
- }
- commandPos1=commandPos2;
+ FinishCommand();
+ return;
}
- if(owner->haveTarget && owner->moveType->progressState!=CMoveType::Done)
+ if(owner->haveTarget && owner->moveType->progressState!=CMoveType::Done){
StopMove();
- else if(owner->moveType->progressState!=CMoveType::Active)
+ } else if(owner->moveType->progressState!=CMoveType::Active){
owner->moveType->StartMoving(goalPos, 8);
-
+ }
return;}
case CMD_RESTORE:{
if(inCommand){
@@ -605,6 +614,7 @@
}
draw=true;
break;
+ case CMD_FIGHT:
case CMD_PATROL:
pos=float3(ci->params[0],ci->params[1],ci->params[2]);
glColor4f(0.5,0.5,1,0.4);
@@ -763,7 +773,7 @@
}
}
-bool CBuilderCAI::FindReclaimableFeatureAndReclaim(float3 pos, float radius,unsigned char options)
+bool CBuilderCAI::FindReclaimableFeatureAndReclaim(float3 pos, float radius,unsigned char options, bool recAny)
{
CFeature* best=0;
float bestDist=10000000;
@@ -771,7 +781,9 @@
for(std::vector<CFeature*>::iterator fi=features.begin();fi!=features.end();++fi){
if((*fi)->def->destructable && (*fi)->allyteam!=owner->allyteam){
float dist=(*fi)->pos.distance2D(owner->pos);
- if(dist<bestDist){
+ if(dist<bestDist && (recAny
+ ||((*fi)->def->energy > 0 && gs->Team(owner->team)->energy < gs->Team(owner->team)->energyStorage)
+ ||((*fi)->def->metal > 0 && gs->Team(owner->team)->metal < gs->Team(owner->team)->metalStorage))){
bestDist=dist;
best=*fi;
}
@@ -779,6 +791,9 @@
}
if(best){
Command c2;
+ if(!recAny){
+ commandQue.push_front(this->GetReturnFight(commandQue.front()));
+ }
c2.options=options | INTERNAL_ORDER;
c2.id=CMD_RECLAIM;
c2.params.push_back(MAX_UNITS+best->id);
@@ -796,7 +811,8 @@
for(std::vector<CFeature*>::iterator fi=features.begin();fi!=features.end();++fi){
if((*fi)->def->destructable && (*fi)->createdFromUnit!=""){
float dist=(*fi)->pos.distance2D(owner->pos);
- if(dist<bestDist){
+ if(dist<bestDist)
+ {
bestDist=dist;
best=*fi;
}
@@ -820,7 +836,7 @@
CMobileCAI::FinishCommand();
}
-bool CBuilderCAI::FindRepairTargetAndRepair(float3 pos, float radius,unsigned char options,bool attackEnemy)
+bool CBuilderCAI::FindRepairTargetAndRepair(float3 pos, float radius,unsigned char options, bool attackEnemy)
{
std::vector<CUnit*> cu=qf->GetUnits(pos,radius);
int myAllyteam=owner->allyteam;
@@ -829,6 +845,9 @@
if((*ui)->mobility && (*ui)->beingBuilt && owner->moveState<2) //dont help factories produce units unless set on roam
continue;
Command nc;
+ if(attackEnemy){
+ commandQue.push_front(this->GetReturnFight(this->commandQue.front()));
+ }
nc.id=CMD_REPAIR;
nc.options=options | INTERNAL_ORDER;
nc.params.push_back((*ui)->id);
@@ -836,6 +855,7 @@
return true;
} else if(attackEnemy && owner->maxRange>0 && !gs->Ally(owner->allyteam,(*ui)->allyteam)){
Command nc;
+ commandQue.push_front(this->GetReturnFight(this->commandQue.front()));
nc.id=CMD_ATTACK;
nc.options=options | INTERNAL_ORDER;
nc.params.push_back((*ui)->id);
Index: rts/Sim/Units/CommandAI/BuilderCAI.h
===================================================================
--- rts/Sim/Units/CommandAI/BuilderCAI.h (revision 1536)
+++ rts/Sim/Units/CommandAI/BuilderCAI.h (working copy)
@@ -17,13 +17,12 @@
void GiveCommand(Command& c);
void DrawQuedBuildingSquares(void);
- bool FindReclaimableFeatureAndReclaim(float3 pos, float radius,unsigned char options);
+ bool FindReclaimableFeatureAndReclaim(float3 pos, float radius,unsigned char options, bool recAny);
bool FindResurrectableFeatureAndResurrect(float3 pos, float radius,unsigned char options);
void FinishCommand(void);
bool FindRepairTargetAndRepair(float3 pos, float radius,unsigned char options,bool attackEnemy);
bool FindCaptureTargetAndCapture(float3 pos, float radius,unsigned char options);
- bool commandFromPatrol;
map<int,string> buildOptions;
bool building;
float3 buildPos;
@@ -32,6 +31,9 @@
int cachedRadiusId;
int buildRetries;
+
+ int lastPC1; //helps avoid infinite loops
+ int lastPC2;
};
#endif // __BUILDER_CAI_H__
Index: rts/Sim/Units/CommandAI/CommandAI.cpp
===================================================================
--- rts/Sim/Units/CommandAI/CommandAI.cpp (revision 1536)
+++ rts/Sim/Units/CommandAI/CommandAI.cpp (working copy)
@@ -295,18 +295,20 @@
stockpileWeapon->numStockpileQued=0;
UpdateStockpileIcon();
return; }
- case CMD_SELFD:
+ case CMD_SELFD:{
if(owner->selfDCountdown){
owner->selfDCountdown=0;
} else {
owner->selfDCountdown = owner->unitDef->selfDCountdown*2+1;
}
- return;
+ return;}
}
-
+
if(!(c.options & SHIFT_KEY)){
if(!commandQue.empty()){
- if(commandQue.front().id==CMD_ATTACK || commandQue.front().id==CMD_AREA_ATTACK || commandQue.front().id==CMD_DGUN){
+ if(commandQue.front().id==CMD_ATTACK || commandQue.front().id==CMD_AREA_ATTACK
+ || commandQue.front().id==CMD_DGUN)
+ {
owner->AttackUnit(0,true);
}
@@ -321,30 +323,65 @@
orderTarget=0;
}
}
+ if(c.id == CMD_PATROL){
+ std::deque<Command>::iterator ci = commandQue.begin();
+ for(; ci != commandQue.end() && ci->id!=CMD_PATROL; ci++);
+ if(ci==commandQue.end()){
+ if(commandQue.empty()){
+ Command c2;
+ c2.id = CMD_PATROL;
+ c2.params.push_back(owner->pos.x);
+ c2.params.push_back(owner->pos.y);
+ c2.params.push_back(owner->pos.z);
+ c2.options = c.options;
+ commandQue.push_back(c2);
+ } else {
+ do{
+ ci--;
+ if(ci->params.size() >=3){
+ Command c2;
+ c2.id = CMD_PATROL;
+ c2.params = ci->params;
+ c2.options = c.options;
+ commandQue.push_back(c2);
+ ci=commandQue.begin();
+ } else if(ci==commandQue.begin()){
+ Command c2;
+ c2.id = CMD_PATROL;
+ c2.params.push_back(owner->pos.x);
+ c2.params.push_back(owner->pos.y);
+ c2.params.push_back(owner->pos.z);
+ c2.options = c.options;
+ commandQue.push_back(c2);
+ }
+ }while(ci!=commandQue.begin());
+ }
+ }
+ }
std::deque<Command>::iterator ci = CCommandAI::GetCancelQueued(c);
- if(c.id<0 && ci != this->commandQue.end()){
+ if(c.id<0 && ci != commandQue.end()){
do{
- if(ci == this->commandQue.begin()){
- this->commandQue.erase(ci);
+ if(ci == commandQue.begin()){
+ commandQue.erase(ci);
Command c2;
c2.id = CMD_STOP;
- this->commandQue.push_front(c2);
- this->SlowUpdate();
+ commandQue.push_front(c2);
+ SlowUpdate();
} else {
- this->commandQue.erase(ci);
+ commandQue.erase(ci);
}
ci = CCommandAI::GetCancelQueued(c);
- }while(ci != this->commandQue.end());
+ }while(ci != commandQue.end());
return;
- } else if(ci != this->commandQue.end()){
- if(ci == this->commandQue.begin()){
- this->commandQue.erase(ci);
+ } else if(ci != commandQue.end()){
+ if(ci == commandQue.begin()){
+ commandQue.erase(ci);
Command c2;
c2.id = CMD_STOP;
- this->commandQue.push_front(c2);
- this->SlowUpdate();
+ commandQue.push_front(c2);
+ SlowUpdate();
} else {
- this->commandQue.erase(ci);
+ commandQue.erase(ci);
}
ci = CCommandAI::GetCancelQueued(c);
return;
@@ -547,7 +584,7 @@
void CCommandAI::FinishCommand(void)
{
int type=commandQue.front().id;
- if(repeatOrders && type!=CMD_STOP && !(commandQue.front().options & INTERNAL_ORDER))
+ if(repeatOrders && type!=CMD_STOP && type != CMD_PATROL && !(commandQue.front().options & INTERNAL_ORDER))
commandQue.push_back(commandQue.front());
commandQue.pop_front();
inCommand=false;
@@ -589,7 +626,8 @@
for(pci=possibleCommands.begin();pci!=possibleCommands.end();++pci){
if(pci->id==CMD_STOCKPILE){
char name[50];
- sprintf(name,"%i/%i",stockpileWeapon->numStockpiled,stockpileWeapon->numStockpiled+stockpileWeapon->numStockpileQued);
+ sprintf(name,"%i/%i",stockpileWeapon->numStockpiled,
+ stockpileWeapon->numStockpiled+stockpileWeapon->numStockpileQued);
pci->name=name;
selectedUnits.PossibleCommandChange(owner);
}
@@ -598,7 +636,9 @@
void CCommandAI::WeaponFired(CWeapon* weapon)
{
- if(weapon->weaponDef->manualfire && !weapon->weaponDef->dropped && !commandQue.empty() && (commandQue.front().id==CMD_ATTACK || commandQue.front().id==CMD_DGUN) && inCommand){
+ if(weapon->weaponDef->manualfire && !weapon->weaponDef->dropped && !commandQue.empty()
+ && (commandQue.front().id==CMD_ATTACK || commandQue.front().id==CMD_DGUN) && inCommand)
+ {
owner->AttackUnit(0,true);
globalAI->WeaponFired(owner,weapon->weaponDef);
FinishCommand();
Index: rts/Sim/Units/CommandAI/FactoryCAI.cpp
===================================================================
--- rts/Sim/Units/CommandAI/FactoryCAI.cpp (revision 1536)
+++ rts/Sim/Units/CommandAI/FactoryCAI.cpp (working copy)
@@ -21,12 +21,21 @@
c.key='M';
c.tooltip="Move: Order ready built units to move to a position";
possibleCommands.push_back(c);
+
c.id=CMD_PATROL;
c.type=CMDTYPE_ICON_MAP;
c.name="Patrol";
c.key='P';
c.tooltip="Patrol: Order ready built units to patrol to one or more waypoints";
possibleCommands.push_back(c);
+
+ c.id = CMD_FIGHT;
+ c.type = CMDTYPE_ICON_MAP;
+ c.name = "Fight";
+ c.key = 'F';
+ c.tooltip = "Fight: Order ready built units to take action while moving to a position";
+ possibleCommands.push_back(c);
+
c.id=CMD_GUARD;
c.type=CMDTYPE_ICON_UNIT;
c.name="Guard";
@@ -220,6 +229,7 @@
glColor4f(0.5,1,0.5,0.4);
draw=true;
break;
+ case CMD_FIGHT:
case CMD_PATROL:
pos=float3(ci->params[0],ci->params[1]+3,ci->params[2]);
glColor4f(0.5,0.5,1,0.4);
Index: rts/Sim/Units/CommandAI/MobileCAI.cpp
===================================================================
--- rts/Sim/Units/CommandAI/MobileCAI.cpp (revision 1536)
+++ rts/Sim/Units/CommandAI/MobileCAI.cpp (working copy)
@@ -17,8 +17,7 @@
CMobileCAI::CMobileCAI(CUnit* owner)
: CCommandAI(owner),
- activeCommand(0),
- patrolTime(0),
+// patrolTime(0),
goalPos(-1,-1,-1),
tempOrder(false),
patrolGoal(1,1,1),
@@ -28,7 +27,8 @@
maxWantedSpeed(0),
lastIdleCheck(0),
commandPos1(ZeroVector),
- commandPos2(ZeroVector)
+ commandPos2(ZeroVector),
+ lastPC(-1)
{
lastUserGoal=owner->pos;
@@ -48,6 +48,15 @@
c.tooltip="Patrol: Order the unit to patrol to one or more waypoints";
possibleCommands.push_back(c);
+ c.params.clear();
+ c.id = CMD_FIGHT;
+ c.type = CMDTYPE_ICON_MAP;
+ c.name = "Fight";
+ c.key = 'F';
+ c.tooltip = "Fight: Order the unit to take action while moving to a position";
+ possibleCommands.push_back(c);
+
+
c.id=CMD_GUARD;
c.type=CMDTYPE_ICON_UNIT;
c.name="Guard";
@@ -114,7 +123,6 @@
}
if(!(c.options & SHIFT_KEY) && nonQueingCommands.find(c.id)==nonQueingCommands.end()){
- activeCommand=0;
tempOrder=false;
}
CCommandAI::GiveCommand(c);
@@ -154,72 +162,83 @@
}
break;}
case CMD_PATROL:{
+ if(c.params.size()<3){ //this shouldnt happen but anyway ...
+ info->AddLine("Error: got patrol cmd with less than 3 params on %s in mobilecai",
+ owner->unitDef->humanName.c_str());
+ return;
+ }
+ Command temp;
+ temp.id = CMD_FIGHT;
+ temp.params.push_back(c.params[0]);
+ temp.params.push_back(c.params[1]);
+ temp.params.push_back(c.params[2]);
+ temp.options = c.options|INTERNAL_ORDER;
+ commandQue.push_back(c);
+ commandQue.pop_front();
+ commandQue.push_front(temp);
+ if(owner->group){
+ owner->group->CommandFinished(owner->id,CMD_PATROL);
+ }
+ SlowUpdate();
+ return;}
+ case CMD_FIGHT:{
if(tempOrder){
- tempOrder=false;
- inCommand=true;
- patrolTime=1;
+ inCommand = true;
+ tempOrder = false;
}
- if(!inCommand){
- float3 pos(c.params[0],c.params[1],c.params[2]);
- inCommand=true;
- Command co;
- co.id=CMD_PATROL;
- co.params.push_back(curPos.x);
- co.params.push_back(curPos.y);
- co.params.push_back(curPos.z);
- commandQue.push_front(co);
- activeCommand=1;
- commandPos1=curPos;
- patrolTime=1;
- }
- Command& c=commandQue[activeCommand];
if(c.params.size()<3){ //this shouldnt happen but anyway ...
- info->AddLine("Error: got patrol cmd with less than 3 params on %s in mobilecai",owner->unitDef->humanName.c_str());
+ info->AddLine("Error: got fight cmd with less than 3 params on %s in mobilecai",
+ owner->unitDef->humanName.c_str());
return;
}
- patrolGoal=float3(c.params[0],c.params[1],c.params[2]);
- commandPos2=patrolGoal;
- patrolTime++;
+ if(c.params.size() >= 6){
+ if(!inCommand){
+ commandPos1 = float3(c.params[3],c.params[4],c.params[5]);
+ }
+ } else {
+ commandPos1 = curPos;
+ }
+ float3 pos(c.params[0],c.params[1],c.params[2]);
+ if(!inCommand){
+ inCommand = true;
+ commandPos2 = pos;
+ }
+ if(pos!=goalPos){
+ SetGoal(pos,curPos);
+ }
- if(!(patrolTime&1) && owner->fireState==2){
- CUnit* enemy=helper->GetClosestEnemyUnit(curPos,owner->maxRange+100*owner->moveState*owner->moveState,owner->allyteam);
- if(enemy && (owner->hasUWWeapons || !enemy->isUnderWater) && !(owner->unitDef->noChaseCategory & enemy->category) && !owner->weapons.empty()){ //todo: make sure they dont stray to far from path
- if(owner->moveState!=1 || LinePointDist(commandPos1,commandPos2,enemy->pos) < 300+owner->maxRange){
- Command c2;
+ if(owner->fireState==2){
+ CUnit* enemy=helper->GetClosestEnemyUnit(
+ curPos, owner->maxRange+100*owner->moveState*owner->moveState, owner->allyteam);
+ if(enemy && (owner->hasUWWeapons || !enemy->isUnderWater)
+ && !(owner->unitDef->noChaseCategory & enemy->category) && !owner->weapons.empty()){ //todo: make sure they dont stray to far from path
+ if(owner->moveState!=1
+ || LinePointDist(commandPos1,commandPos2,enemy->pos)
+ < 300+max(owner->maxRange, (float)owner->losRadius)){
+ Command c2,c3;
+ c3 = this->GetReturnFight(c);
c2.id=CMD_ATTACK;
- c2.options=c.options;
+ c2.options=c.options|INTERNAL_ORDER;
c2.params.push_back(enemy->id);
+ commandQue.push_front(c3);
commandQue.push_front(c2);
inCommand=false;
tempOrder=true;
- SlowUpdate(); //if attack can finish immidiatly this could lead to an infinite loop so make sure it doesnt
+ if(lastPC!=gs->frameNum){ //avoid infinite loops
+ lastPC=gs->frameNum;
+ SlowUpdate();
+ }
return;
}
}
}
- if((curPos-patrolGoal).SqLength2D()<4096 || owner->moveType->progressState==CMoveType::Failed){
- if(owner->group)
- owner->group->CommandFinished(owner->id,CMD_PATROL);
-
- if((int)commandQue.size()<=activeCommand+1)
- activeCommand=0;
- else {
- if(commandQue[activeCommand+1].id!=CMD_PATROL)
- activeCommand=0;
- else
- activeCommand++;
- }
- Command& c=commandQue[activeCommand];
- patrolGoal=float3(c.params[0],c.params[1],c.params[2]);
- commandPos1=commandPos2;
- commandPos2=patrolGoal;
+ if((curPos-goalPos).SqLength2D()<4096 || owner->moveType->progressState==CMoveType::Failed){
+ FinishCommand();
}
- if((patrolGoal!=goalPos)){
- SetGoal(patrolGoal,curPos);
- }
return;}
case CMD_DGUN:
- if(uh->limitDgun && owner->unitDef->isCommander && owner->pos.distance(gs->Team(owner->team)->startPos)>uh->dgunRadius){
+ if(uh->limitDgun && owner->unitDef->isCommander
+ && owner->pos.distance(gs->Team(owner->team)->startPos)>uh->dgunRadius){
StopMove();
FinishCommand();
return;
@@ -259,33 +278,35 @@
}
if(orderTarget){
//note that we handle aircrafts slightly differently
- if(((owner->AttackUnit(orderTarget, c.id==CMD_DGUN) || dynamic_cast<CTAAirMoveType*>(owner->moveType)) && (owner->pos-orderTarget->pos).Length2D()<owner->maxRange*0.9) || (owner->pos-orderTarget->pos).SqLength2D()<1024){
- // if(owner->isMoving) {
+ if((((owner->AttackUnit(orderTarget, c.id==CMD_DGUN) && owner->weapons.size() > 0
+ && owner->weapons.front()->range > orderTarget->pos.distance(owner->pos))
+ || dynamic_cast<CTAAirMoveType*>(owner->moveType))
+ && (owner->pos-orderTarget->pos).Length2D()<owner->maxRange*0.9)
+ || (owner->pos-orderTarget->pos).SqLength2D()<1024){
StopMove();
- owner->moveType->KeepPointingTo(orderTarget->pos, min((double)(owner->losRadius*SQUARE_SIZE*2),owner->maxRange*0.9), true);
- // }
- } else {
- if((orderTarget->pos+owner->posErrorVector*128).distance2D(goalPos)>10+orderTarget->pos.distance2D(owner->pos)*0.2)
- {
- float3 fix=orderTarget->pos+owner->posErrorVector*128;
- SetGoal(fix,curPos);
- }
+ owner->moveType->KeepPointingTo(orderTarget->pos, min((double)(owner->losRadius*SQUARE_SIZE*2),
+ owner->maxRange*0.9), true);
+ } else if((orderTarget->pos+owner->posErrorVector*128).distance2D(goalPos)
+ > 10+orderTarget->pos.distance2D(owner->pos)*0.2){
+ float3 fix=orderTarget->pos+owner->posErrorVector*128;
+ SetGoal(fix,curPos);
}
} else {
float3 pos(c.params[0],c.params[1],c.params[2]);
- if(owner->AttackGround(pos,c.id==CMD_DGUN) || (owner->pos-pos).SqLength2D()<1024) {
+ if((owner->AttackGround(pos,c.id==CMD_DGUN) && owner->weapons.size() > 0
+ && (owner->pos-pos).Length()< owner->weapons.front()->range) || (owner->pos-pos).SqLength2D()<1024){
StopMove();
owner->moveType->KeepPointingTo(pos, owner->maxRange*0.9, true);
- } else {
- if(pos.distance2D(goalPos)>10)
- SetGoal(pos,curPos);
+ } else if(pos.distance2D(goalPos)>10){
+ SetGoal(pos,curPos);
}
}
break;
case CMD_GUARD:
if(uh->units[int(c.params[0])]!=0){
CUnit* guarded=uh->units[int(c.params[0])];
- if(guarded->lastAttacker && guarded->lastAttack+40<gs->frameNum && (owner->hasUWWeapons || !guarded->lastAttacker->isUnderWater)){
+ if(guarded->lastAttacker && guarded->lastAttack+40<gs->frameNum
+ && (owner->hasUWWeapons || !guarded->lastAttacker->isUnderWater)){
Command nc;
nc.id=CMD_ATTACK;
nc.params.push_back(guarded->lastAttacker->id);
@@ -357,6 +378,7 @@
draw=true;
break;
case CMD_PATROL:
+ case CMD_FIGHT:
pos=float3(ci->params[0],ci->params[1],ci->params[2]);
glColor4f(0.5,0.5,1,0.4);
draw=true;
@@ -424,7 +446,6 @@
lastUserGoal=owner->pos;
// info->AddLine("Reseting user goal");
}
-
CCommandAI::FinishCommand();
}
@@ -471,3 +492,34 @@
NonMoving();
}
}
+
+/**
+* @brief gets the command that keeps the unit close to the path
+* @return a Fight Command with 6 arguments, the first three being where to return to (the current position of the
+* unit), and the second being the location of the origional command.
+* @param c the command to return to
+**/
+Command CMobileCAI::GetReturnFight(Command c){
+ Command c3;
+ c3.id = CMD_FIGHT; //keep it from being pulled too far off the path
+ float3 pos = float3(c.params[0],c.params[1],c.params[2]);
+ const float3 &curPos = this->owner->pos;
+ float3 dir = pos-curPos;
+ dir.Normalize();
+ dir*=sqrtf(abs(1024+owner->xsize*owner->xsize+owner->ysize*owner->ysize));
+ dir+=curPos;
+ c3.params.push_back(dir.x);
+ c3.params.push_back(dir.y);
+ c3.params.push_back(dir.z);
+ if(c.params.size() >= 6){
+ c3.params.push_back(c.params[3]);
+ c3.params.push_back(c.params[4]);
+ c3.params.push_back(c.params[5]);
+ } else {
+ c3.params.push_back(c.params[0]);
+ c3.params.push_back(c.params[1]);
+ c3.params.push_back(c.params[2]);
+ }
+ c3.options = c.options|INTERNAL_ORDER;
+ return c3;
+}
\ No newline at end of file
Index: rts/Sim/Units/CommandAI/MobileCAI.h
===================================================================
--- rts/Sim/Units/CommandAI/MobileCAI.h (revision 1536)
+++ rts/Sim/Units/CommandAI/MobileCAI.h (working copy)
@@ -20,17 +20,19 @@
void NonMoving(void);
void FinishCommand(void);
void IdleCheck(void);
+ Command GetReturnFight(Command c);
float3 goalPos;
float3 patrolGoal;
float3 lastUserGoal;
- int activeCommand;
int lastIdleCheck;
bool tempOrder;
- unsigned int patrolTime;
+ int lastPC; //helps avoid infinate loops
+// unsigned int patrolTime;
+
float maxWantedSpeed;
int lastBuggerOffTime;
Index: rts/Sim/Units/CommandAI/TransportCAI.cpp
===================================================================
--- rts/Sim/Units/CommandAI/TransportCAI.cpp (revision 1536)
+++ rts/Sim/Units/CommandAI/TransportCAI.cpp (working copy)
@@ -334,6 +334,7 @@
glColor4f(0.5,1,0.5,0.4);
draw=true;
break;
+ case CMD_FIGHT:
case CMD_PATROL:
pos=float3(ci->params[0],ci->params[1],ci->params[2]);
glColor4f(0.5,0.5,1,0.4);
|
---|