2019-12-10 09:49 CET

View Issue Details Jump to Notes ]
IDProjectCategoryView StatusLast Update
0000326Spring engineGeneralpublic2006-12-11 20:21
ReporterILMTitan 
Assigned Totvo 
PrioritynormalSeverityfeatureReproducibilityalways
StatusresolvedResolutionfixed 
Product Version 
Target VersionFixed in Version 
Summary0000326: [Patch] A few things
Description1. Removes the Fight-like behavior of move in airplanes. Fight can now be used to do this.
2. Restructured CCommandAI and its subclasses. CAirCAI now inherits from CMobileCAI. Functions for each command are included in their own "Execute[Command](Command &c)" virtual functions.
3. Units guarding slower units will now slow down and no longer make repeated "Arrived" sounds.
4. Removed the 2 SetDeltaSpeed() calls in StopEngine() and StartEngine(). Added a call to CommandAI::SlowUpdate() in Arrived(). This was an attempt to make movement between multiple waypoints smother, but was only partially sucessful. Units are still slowing down to hit the waypoint. Need to add some logic to disable that if there are more movement commands in the queue.
TagsNo tags attached.
Checked infolog.txt for Errors
Attached Files
  • patch file icon CommandAIReformat.patch (91,461 bytes) 2006-11-13 06:45 -
    Index: rts/Sim/Units/CommandAI/AirCAI.cpp
    ===================================================================
    --- rts/Sim/Units/CommandAI/AirCAI.cpp	(revision 2593)
    +++ rts/Sim/Units/CommandAI/AirCAI.cpp	(working copy)
    @@ -17,12 +17,13 @@
     #include "mmgr.h"
     
     CAirCAI::CAirCAI(CUnit* owner)
    -: CCommandAI(owner), lastPC1(-1), lastPC2(-1)
    +: CMobileCAI(owner), lastPC1(-1), lastPC2(-1)
     {
    +	cancelDistance = 16000;
     	CommandDescription c;
     
     	// aircraft can always move...
    -	c.id=CMD_MOVE;
    +	/*c.id=CMD_MOVE;
     	c.action="move";
     	c.type=CMDTYPE_ICON_MAP;
     	c.name="Move";
    @@ -48,7 +49,7 @@
     		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;
    @@ -58,7 +59,7 @@
     		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;
    @@ -68,7 +69,7 @@
     		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;
    @@ -117,11 +118,11 @@
     	if (c.id != CMD_MOVE && !AllowedCommand(c))
     		return;
     
    -	if (c.id==CMD_SET_WANTED_MAX_SPEED) {
    +	if (c.id == CMD_SET_WANTED_MAX_SPEED) {
     	  return;
     	}
     	
    -	if(c.id==CMD_AUTOREPAIRLEVEL){
    +	if(c.id == CMD_AUTOREPAIRLEVEL){
     		if(c.params.empty())
     			return;
     		switch((int)c.params[0]){
    @@ -135,7 +136,8 @@
     			((CAirMoveType*)owner->moveType)->repairBelowHealth=0.5f;
     			break;
     		}
    -		for(vector<CommandDescription>::iterator cdi=possibleCommands.begin();cdi!=possibleCommands.end();++cdi){
    +		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]);
    @@ -146,35 +148,37 @@
     		selectedUnits.PossibleCommandChange(owner);
     		return;
     	}
    -	if(c.id==CMD_LOOPBACKATTACK){
    +	if(c.id == CMD_LOOPBACKATTACK){
     		if(c.params.empty())
     			return;
     		switch((int)c.params[0]){
     		case 0:
    -			((CAirMoveType*)owner->moveType)->loopbackAttack=false;
    +			((CAirMoveType*)owner->moveType)->loopbackAttack = false;
     			break;
     		case 1:
    -			((CAirMoveType*)owner->moveType)->loopbackAttack=true;
    +			((CAirMoveType*)owner->moveType)->loopbackAttack = true;
     			break;
     		}
    -		for(vector<CommandDescription>::iterator cdi=possibleCommands.begin();cdi!=possibleCommands.end();++cdi){
    -			if(cdi->id==CMD_LOOPBACKATTACK){
    +		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;
    +				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()){
    +	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){
    +	if(c.id == CMD_AREA_ATTACK && c.params.size() < 4){
     		Command c2 = c;
    -		c2.id=CMD_ATTACK;
    +		c2.id = CMD_ATTACK;
     		CCommandAI::GiveAllowedCommand(c2);
     		return;
     	}
    @@ -184,14 +188,14 @@
     
     void CAirCAI::SlowUpdate()
     {
    -	if(!commandQue.empty() && commandQue.front().timeOut<gs->frameNum){
    +	if(!commandQue.empty() && commandQue.front().timeOut < gs->frameNum){
     		FinishCommand();
     		return;
     	}
     
    -	CAirMoveType* myPlane=(CAirMoveType*)owner->moveType;
    +	CAirMoveType* myPlane=(CAirMoveType*) owner->moveType;
     
    -	if(owner->unitDef->maxFuel>0){
    +	if(owner->unitDef->maxFuel > 0){
     		if(myPlane->reservedPad){
     			return;
     		}else{
    @@ -200,28 +204,33 @@
     				owner->userTarget=0;
     				inCommand=false;
     
    -				CAirBaseHandler::LandingPad* lp=airBaseHandler->FindAirBase(owner,8000,owner->unitDef->minAirBasePower);
    +				CAirBaseHandler::LandingPad* lp = airBaseHandler->FindAirBase(
    +					owner, 8000, owner->unitDef->minAirBasePower);
     				if(lp){
     					myPlane->AddDeathDependence(lp);
    -					myPlane->reservedPad=lp;
    -					myPlane->padStatus=0;
    -					myPlane->oldGoalPos=myPlane->goalPos;
    +					myPlane->reservedPad = lp;
    +					myPlane->padStatus = 0;
    +					myPlane->oldGoalPos = myPlane->goalPos;
     					return;
     				}
    -				float3 landingPos = airBaseHandler->FindClosestAirBasePos(owner,8000,owner->unitDef->minAirBasePower);
    +				float3 landingPos = airBaseHandler->FindClosestAirBasePos(
    +					owner, 8000, 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;		
    +					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,8000,owner->unitDef->minAirBasePower);
    +			if(owner->currentFuel < myPlane->repairBelowHealth * owner->unitDef->maxFuel){
    +				if(commandQue.empty() || commandQue.front().id == CMD_PATROL){
    +					CAirBaseHandler::LandingPad* lp =
    +						airBaseHandler->FindAirBase(owner, 8000, owner->unitDef->minAirBasePower);
     					if(lp){
     						owner->userAttackGround=false;
     						owner->userTarget=0;
    @@ -230,7 +239,7 @@
     						myPlane->reservedPad=lp;
     						myPlane->padStatus=0;
     						myPlane->oldGoalPos=myPlane->goalPos;
    -						if(myPlane->aircraftState==CAirMoveType::AIRCRAFT_LANDED){
    +						if(myPlane->aircraftState == CAirMoveType::AIRCRAFT_LANDED){
     							myPlane->SetState(CAirMoveType::AIRCRAFT_TAKEOFF);
     						}
     						return;
    @@ -241,32 +250,39 @@
     	}
     	
     	if(commandQue.empty()){
    -		if(myPlane->aircraftState==CAirMoveType::AIRCRAFT_FLYING && !owner->unitDef->DontLand ())
    +		if(myPlane->aircraftState == CAirMoveType::AIRCRAFT_FLYING
    +				&& !owner->unitDef->DontLand()){
     			myPlane->SetState(CAirMoveType::AIRCRAFT_LANDING);
    +		}
     
    -		if(owner->unitDef->canAttack && owner->fireState==2 && owner->moveState!=0 && owner->maxRange>0){
    +		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);
    +				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.id = CMD_ATTACK;
     					nc.params.push_back(enemy->id);
    -					nc.options=0;
    +					nc.options = 0;
     					commandQue.push_front(nc);
    -					inCommand=false;
    +					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)){
    +			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.id = CMD_ATTACK;
     				nc.params.push_back(enemy->id);
    -				nc.options=0;
    +				nc.options = 0;
     				commandQue.push_front(nc);
    -				inCommand=false;
    +				inCommand = false;
     				return;
     			}
     		}
    @@ -295,295 +311,302 @@
     	float3 curPos=owner->pos;
     
     	switch(c.id){
    -	case CMD_STOP:{
    -		CCommandAI::SlowUpdate();
    -		break;
    +	case CMD_AREA_ATTACK:
    +		return ExecuteAreaAttack(c);
    +	default:
    +		return CMobileCAI::Execute();
     	}
    -	case CMD_MOVE:{
    -		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;
    -		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(owner->pos+owner->speed*20,testRad,owner->allyteam);
    -					if(enemy && ((enemy->unitDef->canfly && !enemy->crashing && myPlane->isFighter) || (!enemy->unitDef->canfly && (!myPlane->isFighter || owner->moveState==2)))){
    -						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;
    -						}
    +}
    +
    +/*
    +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(
    +					owner->pos+owner->speed * 20, testRad, owner->allyteam);
    +				if(enemy && ((enemy->unitDef->canfly && !enemy->crashing
    +						&& myPlane->isFighter) || (!enemy->unitDef->canfly
    +						&& (!myPlane->isFighter || owner->moveState == 2)))){
    +					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 || owner->moveState==2) && owner->maxRange>0){
    -					float testRad=325*owner->moveState;
    -					CUnit* enemy=helper->GetClosestEnemyUnit(owner->pos+owner->speed*30,testRad,owner->allyteam);
    -					if(enemy && (owner->hasUWWeapons || !enemy->isUnderWater) && ((enemy->unitDef->canfly && !enemy->crashing && myPlane->isFighter) || (!enemy->unitDef->canfly && (!myPlane->isFighter || owner->moveState==2)))){
    -						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 || owner->moveState == 2) && owner->maxRange > 0){
    +				float testRad = 325 * owner->moveState;
    +				CUnit* enemy = helper->GetClosestEnemyUnit(
    +					owner->pos + owner->speed * 30, testRad, owner->allyteam);
    +				if(enemy && (owner->hasUWWeapons || !enemy->isUnderWater)
    +						&& ((enemy->unitDef->canfly && !enemy->crashing
    +						&& myPlane->isFighter) || (!enemy->unitDef->canfly
    +						&& (!myPlane->isFighter || owner->moveState==2)))){
    +					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((curPos-pos).SqLength2D()<16000){
    -			FinishCommand();
    +	}
    +	if((curPos - pos).SqLength2D() < 16000){
    +		FinishCommand();
    +	}
    +	return;
    +}*/
    +
    +void CAirCAI::ExecuteFight(Command &c){
    +	assert((c.options & INTERNAL_ORDER) || owner->unitDef->canFight);
    +	CAirMoveType* myPlane = (CAirMoveType*) owner->moveType;
    +	if(tempOrder){
    +		tempOrder=false;
    +		inCommand=true;
    +	}
    +	if(c.params.size()<3){		//this shouldnt happen but anyway ...
    +		logOutput.Print("Error: got fight cmd with less than 3 params on %s in AirCAI",
    +			owner->unitDef->humanName.c_str());
    +		return;
    +	}
    +	if(c.params.size() >= 6){
    +		if(!inCommand){
    +			commandPos1 = float3(c.params[3],c.params[4],c.params[5]);
     		}
    -		break;}
    -	case CMD_PATROL:{
    -		assert(owner->unitDef->canPatrol);
    -		float3 curPos=owner->pos;
    -		if(c.params.size()<3){		//this shouldnt happen but anyway ...
    -			logOutput.Print("Error: got patrol cmd with less than 3 params on %s in aircai",
    -				owner->unitDef->humanName.c_str());
    -			return;
    +	} else {
    +		// Some hackery to make sure the line (commandPos1,commandPos2) is NOT
    +		// rotated (only shortened) if we reach this because the previous return
    +		// fight command finished by the 'if((curPos-pos).SqLength2D()<(127*127)){'
    +		// condition, but is actually updated correctly if you click somewhere
    +		// outside the area close to the line (for a new command).
    +		commandPos1 = ClosestPointOnLine(commandPos1, commandPos2, owner->pos);
    +		if ((owner->pos - commandPos1).SqLength2D() > (150 * 150)) {
    +			commandPos1 = owner->pos;
     		}
    -		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:{
    -		assert((c.options & INTERNAL_ORDER) || owner->unitDef->canFight);
    -		if(tempOrder){
    -			tempOrder=false;
    -			inCommand=true;
    -		}
    -		if(c.params.size()<3){		//this shouldnt happen but anyway ...
    -			logOutput.Print("Error: got fight cmd with less than 3 params on %s in AirCAI", owner->unitDef->humanName.c_str());
    +	}
    +	goalPos = float3(c.params[0], c.params[1], c.params[2]);
    +	if(!inCommand){
    +		inCommand = true;
    +		commandPos2=goalPos;
    +	}
    +
    +	// CMD_FIGHT is pretty useless if !canAttack but we try to honour the modders wishes anyway...
    +	if (owner->unitDef->canAttack && owner->fireState == 2 && owner->moveState != 0 && owner->maxRange > 0) {
    +		float3 curPosOnLine = ClosestPointOnLine(commandPos1, commandPos2, owner->pos+owner->speed*10);
    +		float testRad=1000*owner->moveState;
    +		CUnit* enemy = helper->GetClosestEnemyAircraft(curPosOnLine,testRad,owner->allyteam);
    +		if(myPlane->isFighter
    +			&& enemy && !enemy->crashing
    +			&& (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|INTERNAL_ORDER;
    +			commandQue.push_front(nc);
    +			tempOrder=true;
    +			inCommand=false;
    +			if(lastPC1!=gs->frameNum){	//avoid infinite loops
    +				lastPC1=gs->frameNum;
    +				SlowUpdate();
    +			}
     			return;
    -		}
    -		if(c.params.size() >= 6){
    -			if(!inCommand){
    -				commandPos1 = float3(c.params[3],c.params[4],c.params[5]);
    -			}
     		} else {
    -			// Some hackery to make sure the line (commandPos1,commandPos2) is NOT
    -			// rotated (only shortened) if we reach this because the previous return
    -			// fight command finished by the 'if((curPos-pos).SqLength2D()<(127*127)){'
    -			// condition, but is actually updated correctly if you click somewhere
    -			// outside the area close to the line (for a new command).
    -			commandPos1 = ClosestPointOnLine(commandPos1, commandPos2, curPos);
    -			if ((curPos-commandPos1).SqLength2D()>(150*150)) {
    -				commandPos1 = curPos;
    -			}
    -		}
    -		goalPos=float3(c.params[0],c.params[1],c.params[2]);
    -		if(!inCommand){
    -			inCommand = true;
    -			commandPos2=goalPos;
    -		}
    -
    -		// CMD_FIGHT is pretty useless if !canAttack but we try to honour the modders wishes anyway...
    -		if (owner->unitDef->canAttack && owner->fireState == 2 && owner->moveState != 0 && owner->maxRange > 0) {
    -			float3 curPosOnLine = ClosestPointOnLine(commandPos1, commandPos2, owner->pos+owner->speed*10);
    -			float testRad=1000*owner->moveState;
    -			CUnit* enemy = helper->GetClosestEnemyAircraft(curPosOnLine,testRad,owner->allyteam);
    -			if(myPlane->isFighter
    -				&& enemy && !enemy->crashing
    -				&& (owner->moveState!=1 || LinePointDist(commandPos1,commandPos2,enemy->pos) < 1000))
    +			float3 curPosOnLine = ClosestPointOnLine(
    +				commandPos1, commandPos2, owner->pos + owner->speed * 20);
    +			float testRad = 500 * owner->moveState;
    +			enemy = helper->GetClosestEnemyUnit(curPosOnLine, testRad, owner->allyteam);
    +			if(enemy && (owner->hasUWWeapons || !enemy->isUnderWater)
    +				&& !enemy->crashing
    +				&& (myPlane->isFighter || !enemy->unitDef->canfly))
     			{
     				Command nc;
    -				nc.id=CMD_ATTACK;
    +				nc.id = CMD_ATTACK;
     				nc.params.push_back(enemy->id);
    -				nc.options=c.options|INTERNAL_ORDER;
    +				nc.options = c.options | INTERNAL_ORDER;
    +				PushOrUpdateReturnFight();
     				commandQue.push_front(nc);
    -				tempOrder=true;
    -				inCommand=false;
    -				if(lastPC1!=gs->frameNum){	//avoid infinite loops
    -					lastPC1=gs->frameNum;
    +				tempOrder = true;
    +				inCommand = false;
    +				if(lastPC2 != gs->frameNum){	//avoid infinite loops
    +					lastPC2 = gs->frameNum;
     					SlowUpdate();
     				}
     				return;
    -			} else {
    -				float3 curPosOnLine = ClosestPointOnLine(commandPos1, commandPos2, owner->pos+owner->speed*20);
    -				float testRad=500*owner->moveState;
    -				enemy=helper->GetClosestEnemyUnit(curPosOnLine,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=c.options|INTERNAL_ORDER;
    -					PushOrUpdateReturnFight();
    -					commandQue.push_front(nc);
    -					tempOrder=true;
    -					inCommand=false;
    -					if(lastPC2!=gs->frameNum){	//avoid infinite loops
    -						lastPC2=gs->frameNum;
    -						SlowUpdate();
    -					}
    -					return;
    -				}
     			}
     		}
    -		myPlane->goalPos=goalPos;
    +	}
    +	myPlane->goalPos=goalPos;
     
    -		if((owner->pos-goalPos).SqLength2D()<(127*127) || (owner->pos+owner->speed*8-goalPos).SqLength2D()<(127*127)){
    +	if((owner->pos-goalPos).SqLength2D()<(127*127) || (owner->pos+owner->speed*8-goalPos).SqLength2D()<(127*127)){
    +		FinishCommand();
    +	}
    +	return;
    +}
    +
    +void CAirCAI::ExecuteAttack(Command &c){
    +	assert(owner->unitDef->canAttack);
    +	CAirMoveType* myPlane = (CAirMoveType*) owner->moveType;
    +	targetAge++;
    +	if(tempOrder && owner->moveState == 1){		//limit how far away we fly
    +		if(orderTarget && LinePointDist(commandPos1, commandPos2, orderTarget->pos) > 1500){
    +			owner->SetUserTarget(0);
     			FinishCommand();
    +			return;
     		}
    -		return;}
    -	case CMD_ATTACK:
    -		assert(owner->unitDef->canAttack);
    -		targetAge++;
    -		if(tempOrder && owner->moveState==1){		//limit how far away we fly
    -			if(orderTarget && LinePointDist(commandPos1,commandPos2,orderTarget->pos) > 1500){
    -				owner->SetUserTarget(0);
    -				FinishCommand();
    -				break;
    +	}/* why was this block here? - ILMTitan
    +	if(tempOrder && myPlane->isFighter && orderTarget){
    +		if(owner->fireState == 2 && owner->moveState != 0){
    +			CUnit* enemy = helper->GetClosestEnemyAircraft(
    +				owner->pos + (owner->speed * 50), 800, owner->allyteam);
    +			if(enemy && (!orderTarget->unitDef->canfly
    +					|| (orderTarget->pos-owner->pos + owner->speed * 50).
    +					Length() + (100 * gs->randFloat() * 40) - targetAge
    +					< (enemy->pos-owner->pos + owner->speed * 50).Length())){
    +				c.params.clear();
    +				c.params.push_back(enemy->id);
    +				inCommand=false;
     			}
     		}
    -		if(tempOrder && myPlane->isFighter && orderTarget){
    -			if(owner->fireState==2 && owner->moveState!=0){
    -				CUnit* enemy=helper->GetClosestEnemyAircraft(owner->pos+owner->speed*50,800,owner->allyteam);
    -				if(enemy && (!orderTarget->unitDef->canfly || (orderTarget->pos-owner->pos+owner->speed*50).Length()+100*gs->randFloat()*40-targetAge < (enemy->pos-owner->pos+owner->speed*50).Length())){
    -					c.params.clear();
    -					c.params.push_back(enemy->id);
    -					inCommand=false;
    -				}
    -			}
    +	}*/
    +	if(inCommand){
    +		if(targetDied || (c.params.size() == 1 && UpdateTargetLostTimer(int(c.params[0])) == 0)){
    +			FinishCommand();
    +			return;
     		}
    -		if(inCommand){
    -			if(targetDied || (c.params.size() == 1 && UpdateTargetLostTimer(int(c.params[0])) == 0)){
    -				FinishCommand();
    -				break;
    -			}
    -			if ((c.params.size() == 3) && (owner->commandShotCount > 0) && (commandQue.size() > 1)) {
    -				owner->AttackUnit(0,true); 
    -				FinishCommand();
    -			  break;
    -			}
    -			if(orderTarget && orderTarget->unitDef->canfly && orderTarget->crashing){
    -				owner->SetUserTarget(0);
    -				FinishCommand();
    -				break;
    -			}
    -			if(orderTarget){
    +		if ((c.params.size() == 3) && (owner->commandShotCount > 0) && (commandQue.size() > 1)) {
    +			owner->AttackUnit(0,true); 
    +			FinishCommand();
    +			return;
    +		}
    +		if(orderTarget && orderTarget->unitDef->canfly && orderTarget->crashing){
    +			owner->SetUserTarget(0);
    +			FinishCommand();
    +			return;
    +		}
    +		if(orderTarget){
     //				myPlane->goalPos=orderTarget->pos;
    -			} else {
    +		} else {
     //				float3 pos(c.params[0],c.params[1],c.params[2]);
     //				myPlane->goalPos=pos;
    -			}
    -		} else {
    -			targetAge=0;
    -			if(c.params.size()==1){
    -				if(uh->units[int(c.params[0])]!=0 && uh->units[int(c.params[0])]!=owner){
    -					orderTarget=uh->units[int(c.params[0])];
    -					owner->AttackUnit(orderTarget,false);
    -					AddDeathDependence(orderTarget);
    -					inCommand=true;
    -				} else {
    -					FinishCommand();
    -					break;
    -				}
    +		}
    +	} else {
    +		targetAge=0;
    +		if(c.params.size() == 1){
    +			if(uh->units[int(c.params[0])] != 0 && uh->units[int(c.params[0])] != owner){
    +				orderTarget = uh->units[int(c.params[0])];
    +				owner->AttackUnit(orderTarget, false);
    +				AddDeathDependence(orderTarget);
    +				inCommand = true;
     			} else {
    -				float3 pos(c.params[0],c.params[1],c.params[2]);
    -				owner->AttackGround(pos,false);
    -				inCommand=true;
    -			}
    -		}
    -		break;
    -	case CMD_AREA_ATTACK:{
    -		assert(owner->unitDef->canAttack);
    -		if(targetDied){
    -			targetDied=false;
    -			inCommand=false;
    -		}
    -		float3 pos(c.params[0],c.params[1],c.params[2]);
    -		float radius=c.params[3];
    -		if(inCommand){
    -			if(myPlane->aircraftState==CAirMoveType::AIRCRAFT_LANDED)
    -				inCommand=false;
    -			if(orderTarget && orderTarget->pos.distance2D(pos)>radius){
    -				inCommand=false;
    -				DeleteDeathDependence(orderTarget);
    -				orderTarget=0;
    -			}
    -			if ((c.params.size() == 4) && (owner->commandShotCount > 0) && (commandQue.size() > 1)) {
    -				owner->AttackUnit(0,true); 
     				FinishCommand();
    +				return;
     			}
     		} else {
    -			if(myPlane->aircraftState!=CAirMoveType::AIRCRAFT_LANDED){
    -				inCommand=true;
    -				std::vector<int> eu;
    -				helper->GetEnemyUnits(pos,radius,owner->allyteam,eu);
    -				if(eu.empty()){
    -					float3 attackPos=pos+gs->randVector()*radius;
    -					attackPos.y=ground->GetHeight(attackPos.x,attackPos.z);
    -					owner->AttackGround(attackPos,false);
    -				} else {
    -					int num=(int) (gs->randFloat()*eu.size());
    -					orderTarget=uh->units[eu[num]];
    -					owner->AttackUnit(orderTarget,false);
    -					AddDeathDependence(orderTarget);
    -				}
    -			}
    +			float3 pos(c.params[0],c.params[1],c.params[2]);
    +			owner->AttackGround(pos,false);
    +			inCommand=true;
     		}
    -		break;}
    -	case CMD_GUARD:
    -		assert(owner->unitDef->canGuard);
    -		if (int(c.params[0]) >= 0 && uh->units[int(c.params[0])] != NULL && UpdateTargetLostTimer(int(c.params[0]))) {
    -			CUnit* guarded=uh->units[int(c.params[0])];
    -			if(owner->unitDef->canAttack && guarded->lastAttacker && guarded->lastAttack+40<gs->frameNum && owner->maxRange>0 && (owner->hasUWWeapons || !guarded->lastAttacker->isUnderWater)){
    -				Command nc;
    -				nc.id=CMD_ATTACK;
    -				nc.params.push_back(guarded->lastAttacker->id);
    -				nc.options=c.options;
    -				commandQue.push_front(nc);
    -				SlowUpdate();
    -				return;
    +	}
    +	return;
    +}
    +
    +void CAirCAI::ExecuteAreaAttack(Command &c){
    +	assert(owner->unitDef->canAttack);
    +	CAirMoveType* myPlane = (CAirMoveType*) owner->moveType;
    +	if(targetDied){
    +		targetDied = false;
    +		inCommand = false;
    +	}
    +	float3 pos(c.params[0], c.params[1], c.params[2]);
    +	float radius = c.params[3];
    +	if(inCommand){
    +		if(myPlane->aircraftState == CAirMoveType::AIRCRAFT_LANDED)
    +			inCommand = false;
    +		if(orderTarget && orderTarget->pos.distance2D(pos) > radius){
    +			inCommand = false;
    +			DeleteDeathDependence(orderTarget);
    +			orderTarget = 0;
    +		}
    +		if ((c.params.size() == 4) && (owner->commandShotCount > 0)
    +				&& (commandQue.size() > 1)) {
    +			owner->AttackUnit(0, true); 
    +			FinishCommand();
    +		}
    +	} else {
    +		if(myPlane->aircraftState != CAirMoveType::AIRCRAFT_LANDED){
    +			inCommand = true;
    +			std::vector<int> eu;
    +			helper->GetEnemyUnits(pos, radius, owner->allyteam, eu);
    +			if(eu.empty()){
    +				float3 attackPos = pos + gs->randVector() * radius;
    +				attackPos.y = ground->GetHeight(attackPos.x, attackPos.z);
    +				owner->AttackGround(attackPos, false);
     			} else {
    -				Command c2;
    -				c2.id=CMD_MOVE;
    -				c2.options=c.options;
    -				c2.params.push_back(guarded->pos.x);
    -				c2.params.push_back(guarded->pos.y);
    -				c2.params.push_back(guarded->pos.z);
    -				c2.timeOut=gs->frameNum+60;
    -				commandQue.push_front(c2);
    -				return;
    +				int num = (int) (gs->randFloat() * eu.size());
    +				orderTarget = uh->units[eu[num]];
    +				owner->AttackUnit(orderTarget, false);
    +				AddDeathDependence(orderTarget);
     			}
    +		}
    +	}
    +}
    +
    +void CAirCAI::ExecuteGuard(Command &c){
    +	assert(owner->unitDef->canGuard);
    +	if (int(c.params[0]) >= 0 && uh->units[int(c.params[0])] != NULL
    +			&& UpdateTargetLostTimer(int(c.params[0]))) {
    +		CUnit* guarded = uh->units[int(c.params[0])];
    +		if(owner->unitDef->canAttack && guarded->lastAttacker
    +				&& guarded->lastAttack + 40 < gs->frameNum && owner->maxRange > 0
    +				&& (owner->hasUWWeapons || !guarded->lastAttacker->isUnderWater)){
    +			Command nc;
    +			nc.id = CMD_ATTACK;
    +			nc.params.push_back(guarded->lastAttacker->id);
    +			nc.options = c.options | INTERNAL_ORDER;
    +			commandQue.push_front(nc);
    +			SlowUpdate();
    +			return;
     		} else {
    -			FinishCommand();
    +			Command c2;
    +			c2.id = CMD_MOVE;
    +			c2.options = c.options | INTERNAL_ORDER;
    +			c2.params.push_back(guarded->pos.x);
    +			c2.params.push_back(guarded->pos.y);
    +			c2.params.push_back(guarded->pos.z);
    +			c2.timeOut = gs->frameNum + 60;
    +			commandQue.push_front(c2);
    +			return;
     		}
    -		break;
    -	default:
    -		CCommandAI::SlowUpdate();
    -		break;
    +	} else {
    +		FinishCommand();
     	}
     }
     
    @@ -695,3 +718,8 @@
     		myPlane->SetState(CAirMoveType::AIRCRAFT_TAKEOFF);
     	}
     }
    +
    +void CAirCAI::SetGoal(const float3 &pos, const float3 &curPos, float goalRadius){
    +	((CAirMoveType*) owner->moveType)->goalPos = pos;
    +	CMobileCAI::SetGoal(pos, curPos, goalRadius);
    +}
    Index: rts/Sim/Units/CommandAI/AirCAI.h
    ===================================================================
    --- rts/Sim/Units/CommandAI/AirCAI.h	(revision 2593)
    +++ rts/Sim/Units/CommandAI/AirCAI.h	(working copy)
    @@ -4,10 +4,10 @@
     #ifndef __AIR_CAI_H__
     #define __AIR_CAI_H__
     
    -#include "CommandAI.h"
    +#include "MobileCAI.h"
     
     class CAirCAI :
    -	public CCommandAI
    +	public CMobileCAI
     {
     public:
     	CAirCAI(CUnit* owner);
    @@ -21,14 +21,18 @@
     	void FinishCommand(void);
     	void BuggerOff(float3 pos, float radius);
     	void StopMove();
    +	
    +	void SetGoal(const float3& pos, const float3& curPos, float goalRadius = SQUARE_SIZE);
    +	
    +	void ExecuteGuard(Command &c);
    +	void ExecuteAreaAttack(Command &c);
    +	void ExecuteAttack(Command &c);
    +	void ExecuteFight(Command &c);
    +//	void ExecuteMove(Command &c);
     
    -	float3 goalPos;
    -
     	float3 basePos;
     	float3 baseDir;
     
    -	bool tempOrder;
    -
     	int activeCommand;
     	int targetAge;
     //	unsigned int patrolTime;
    @@ -36,9 +40,6 @@
     	int lastPC1;
     	int lastPC2;
     
    -	float3 commandPos1;		//used to limit how far away stuff can fly from path
    -	float3 commandPos2;
    -
     protected:
     	void PushOrUpdateReturnFight() {
     		CCommandAI::PushOrUpdateReturnFight(commandPos1, commandPos2);
    Index: rts/Sim/Units/CommandAI/BuilderCAI.cpp
    ===================================================================
    --- rts/Sim/Units/CommandAI/BuilderCAI.cpp	(revision 2593)
    +++ rts/Sim/Units/CommandAI/BuilderCAI.cpp	(working copy)
    @@ -218,357 +218,418 @@
     	}
     	switch(c.id){
     	case CMD_STOP:
    -		building=false;
    -		fac->StopBuild();
    +		return ExecuteStop(c);
    +	case CMD_REPAIR:
    +		return ExecuteRepair(c);
    +	case CMD_CAPTURE:
    +		return ExecuteCapture(c);
    +	case CMD_GUARD:
    +		return ExecuteGuard(c);
    +	case CMD_RECLAIM:
    +		return ExecuteReclaim(c);
    +	case CMD_RESURRECT:
    +		return ExecuteResurrect(c);
    +	case CMD_PATROL:
    +		return ExecutePatrol(c);
    +	case CMD_FIGHT:
    +		return ExecuteFight(c);
    +	case CMD_RESTORE:
    +		return ExecuteRestore(c);
    +	default:
     		break;
    -	case CMD_REPAIR:{
    -		assert(owner->unitDef->canRepair || owner->unitDef->canAssist);
    -		if(c.params.size()==1){		//repair unit
    -			CUnit* unit=uh->units[(int)c.params[0]];
    -			if(tempOrder && owner->moveState==1){		//limit how far away we go
    -				if(unit && LinePointDist(commandPos1,commandPos2,unit->pos) > 500){
    -					StopMove();
    -					FinishCommand();
    -					break;
    -				}
    -			}
    -			if(unit && unit->health<unit->maxHealth && unit!=owner && UpdateTargetLostTimer((int)c.params[0])){
    -				if(unit->pos.distance2D(fac->pos)<fac->buildDistance+unit->radius-8){
    -					StopMove();
    -					fac->SetRepairTarget(unit);
    -					owner->moveType->KeepPointingTo(unit->pos, fac->buildDistance*0.9f+unit->radius, false);
    -				} else {
    -					if (goalPos.distance2D(unit->pos)>1) {
    -						SetGoal(unit->pos,owner->pos, fac->buildDistance*0.9f+unit->radius);
    -					}
    -				}
    -			} else {
    +	}
    +	CMobileCAI::SlowUpdate();
    +}
    +
    +void CBuilderCAI::ExecuteStop(Command &c){
    +	CBuilder* fac=(CBuilder*)owner;
    +	building=false;
    +	fac->StopBuild();
    +	CMobileCAI::ExecuteStop(c);
    +}
    +
    +void CBuilderCAI::ExecuteRepair(Command &c){
    +	CBuilder* fac=(CBuilder*)owner;
    +	assert(owner->unitDef->canRepair || owner->unitDef->canAssist);
    +	if(c.params.size()==1){		//repair unit
    +		CUnit* unit=uh->units[(int)c.params[0]];
    +		if(tempOrder && owner->moveState==1){		//limit how far away we go
    +			if(unit && LinePointDist(commandPos1,commandPos2,unit->pos) > 500){
     				StopMove();
     				FinishCommand();
    -			}
    -		} else {			//repair area
    -			float3 pos(c.params[0],c.params[1],c.params[2]);
    -			float radius=c.params[3];
    -			if(FindRepairTargetAndRepair(pos,radius,c.options,false)){
    -				inCommand=false;
    -				SlowUpdate();
     				return;
     			}
    -			if(!(c.options & ALT_KEY)){
    -				FinishCommand();
    +		}
    +		if(unit && unit->health<unit->maxHealth && unit!=owner && UpdateTargetLostTimer((int)c.params[0])){
    +			if(unit->pos.distance2D(fac->pos)<fac->buildDistance+unit->radius-8){
    +				StopMove();
    +				fac->SetRepairTarget(unit);
    +				owner->moveType->KeepPointingTo(unit->pos, fac->buildDistance*0.9f+unit->radius, false);
    +			} else {
    +				if (goalPos.distance2D(unit->pos)>1) {
    +					SetGoal(unit->pos,owner->pos, fac->buildDistance*0.9f+unit->radius);
    +				}
     			}
    +		} else {
    +			StopMove();
    +			FinishCommand();
     		}
    -		return;}
    -	case CMD_CAPTURE:{
    -		assert(owner->unitDef->canCapture);
    -		if(c.params.size()==1){		//capture unit
    -			CUnit* unit=uh->units[(int)c.params[0]];
    -			if(unit && unit->team!=owner->team && UpdateTargetLostTimer((int)c.params[0])){
    -				if(unit->pos.distance2D(fac->pos)<fac->buildDistance+unit->radius-8){
    +	} else {			//repair area
    +		float3 pos(c.params[0],c.params[1],c.params[2]);
    +		float radius=c.params[3];
    +		if(FindRepairTargetAndRepair(pos,radius,c.options,false)){
    +			inCommand=false;
    +			SlowUpdate();
    +			return;
    +		}
    +		if(!(c.options & ALT_KEY)){
    +			FinishCommand();
    +		}
    +	}
    +	return;
    +}
    +
    +void CBuilderCAI::ExecuteCapture(Command &c){
    +	assert(owner->unitDef->canCapture);
    +	CBuilder* fac=(CBuilder*)owner;
    +	if(c.params.size()==1){		//capture unit
    +		CUnit* unit=uh->units[(int)c.params[0]];
    +		if(unit && unit->team!=owner->team && UpdateTargetLostTimer((int)c.params[0])){
    +			if(unit->pos.distance2D(fac->pos)<fac->buildDistance+unit->radius-8){
    +				StopMove();
    +				fac->SetCaptureTarget(unit);
    +				owner->moveType->KeepPointingTo(unit->pos, fac->buildDistance*0.9f+unit->radius, false);
    +			} else {
    +				if(goalPos.distance2D(unit->pos)>1)
    +					SetGoal(unit->pos,owner->pos, fac->buildDistance*0.9f+unit->radius);
    +			}
    +		} else {
    +			StopMove();
    +			FinishCommand();
    +		}
    +	} else {			//capture area
    +		float3 pos(c.params[0],c.params[1],c.params[2]);
    +		float radius=c.params[3];
    +		if(FindCaptureTargetAndCapture(pos,radius,c.options)){
    +			inCommand=false;
    +			SlowUpdate();
    +			return;
    +		}
    +		if(!(c.options & ALT_KEY)){
    +			FinishCommand();
    +		}
    +	}
    +	return;
    +}
    +
    +void CBuilderCAI::ExecuteGuard(Command &c){
    +	assert(owner->unitDef->canGuard);
    +	CBuilder* fac=(CBuilder*)owner;
    +	CUnit* guarded=uh->units[(int)c.params[0]];
    +	if(guarded && guarded!=owner && UpdateTargetLostTimer((int)c.params[0])){
    +		if(CBuilder* b=dynamic_cast<CBuilder*>(guarded)){
    +			if(b->terraforming){
    +				if(fac->pos.distance2D(b->terraformCenter)<fac->buildDistance*0.8f+b->terraformRadius*0.7f){
     					StopMove();
    -					fac->SetCaptureTarget(unit);
    -					owner->moveType->KeepPointingTo(unit->pos, fac->buildDistance*0.9f+unit->radius, false);
    +					owner->moveType->KeepPointingTo(b->terraformCenter, fac->buildDistance*0.9f, false);
    +					fac->HelpTerraform(b);
     				} else {
    -					if(goalPos.distance2D(unit->pos)>1)
    -						SetGoal(unit->pos,owner->pos, fac->buildDistance*0.9f+unit->radius);
    +					SetGoal(b->terraformCenter,fac->pos,fac->buildDistance*0.7f+b->terraformRadius*0.6f);
     				}
    -			} else {
    -				StopMove();
    -				FinishCommand();
    +				return;
     			}
    -		} else {			//capture area
    -			float3 pos(c.params[0],c.params[1],c.params[2]);
    -			float radius=c.params[3];
    -			if(FindCaptureTargetAndCapture(pos,radius,c.options)){
    +			if (b->curBuild && ((b->curBuild->beingBuilt && owner->unitDef->canAssist) || (!b->curBuild->beingBuilt && owner->unitDef->canRepair))) {
    +				Command nc;
    +				nc.id=CMD_REPAIR;
    +				nc.options=c.options;
    +				nc.params.push_back(b->curBuild->id);
    +				commandQue.push_front(nc);
     				inCommand=false;
    -				SlowUpdate();
    +//					SlowUpdate();
     				return;
     			}
    -			if(!(c.options & ALT_KEY)){
    -				FinishCommand();
    -			}
     		}
    -		return;}
    -	case CMD_GUARD:{
    -		assert(owner->unitDef->canGuard);
    -		CUnit* guarded=uh->units[(int)c.params[0]];
    -		if(guarded && guarded!=owner && UpdateTargetLostTimer((int)c.params[0])){
    -			if(CBuilder* b=dynamic_cast<CBuilder*>(guarded)){
    -				if(b->terraforming){
    -					if(fac->pos.distance2D(b->terraformCenter)<fac->buildDistance*0.8f+b->terraformRadius*0.7f){
    -						StopMove();
    -						owner->moveType->KeepPointingTo(b->terraformCenter, fac->buildDistance*0.9f, false);
    -						fac->HelpTerraform(b);
    -					} else {
    -						SetGoal(b->terraformCenter,fac->pos,fac->buildDistance*0.7f+b->terraformRadius*0.6f);
    -					}
    -					return;
    -				}
    -				if (b->curBuild && ((b->curBuild->beingBuilt && owner->unitDef->canAssist) || (!b->curBuild->beingBuilt && owner->unitDef->canRepair))) {
    -					Command nc;
    -					nc.id=CMD_REPAIR;
    -					nc.options=c.options;
    -					nc.params.push_back(b->curBuild->id);
    -					commandQue.push_front(nc);
    -					inCommand=false;
    +		if(CFactory* f=dynamic_cast<CFactory*>(guarded)){
    +			if (f->curBuild
    +					&& ((f->curBuild->beingBuilt && owner->unitDef->canAssist)
    +					|| (!f->curBuild->beingBuilt && owner->unitDef->canRepair))) {
    +				Command nc;
    +				nc.id=CMD_REPAIR;
    +				nc.options=c.options;
    +				nc.params.push_back(f->curBuild->id);
    +				commandQue.push_front(nc);
    +				inCommand=false;
     //					SlowUpdate();
    -					return;
    -				}
    +				return;
     			}
    -			if(CFactory* f=dynamic_cast<CFactory*>(guarded)){
    -				if (f->curBuild && ((f->curBuild->beingBuilt && owner->unitDef->canAssist) || (!f->curBuild->beingBuilt && owner->unitDef->canRepair))) {
    -					Command nc;
    -					nc.id=CMD_REPAIR;
    -					nc.options=c.options;
    -					nc.params.push_back(f->curBuild->id);
    -					commandQue.push_front(nc);
    -					inCommand=false;
    -//					SlowUpdate();
    -					return;
    -				}
    -			}
    -			float3 curPos=owner->pos;
    -			float3 dif=guarded->pos-curPos;
    -			dif.Normalize();
    -			float3 goal=guarded->pos-dif*(fac->buildDistance-5);
    -			if((guarded->pos-curPos).SqLength2D()<(fac->buildDistance*0.9f+guarded->radius)*(fac->buildDistance*0.9f+guarded->radius)){
    -				StopMove();
    +		}
    +		float3 curPos=owner->pos;
    +		float3 dif=guarded->pos-curPos;
    +		dif.Normalize();
    +		float3 goal=guarded->pos-dif*(fac->buildDistance*.5);
    +		if((guarded->pos-curPos).SqLength2D()<
    +				(fac->buildDistance*1.9f + guarded->radius)
    +				*(fac->buildDistance*1.9f + guarded->radius)){
    +			StartSlowGuard(guarded->maxSpeed);
    +		} else {
    +			StopSlowGuard();
    +		}
    +		if((guarded->pos-curPos).SqLength2D()<
    +				(fac->buildDistance*0.9f + guarded->radius)
    +				*(fac->buildDistance*0.9f + guarded->radius)){
    +			StopMove();
     //				logOutput.Print("should point with type 3?");
    -				owner->moveType->KeepPointingTo(guarded->pos, fac->buildDistance*0.9f+guarded->radius, false);
    -				if(guarded->health<guarded->maxHealth && ((guarded->beingBuilt && owner->unitDef->canAssist) || (!guarded->beingBuilt && owner->unitDef->canRepair)))
    -					fac->SetRepairTarget(guarded);
    -				else
    -					NonMoving();
    -			}else{
    -				if((goalPos-goal).SqLength2D()>4000)
    -					SetGoal(goal,curPos);
    +			owner->moveType->KeepPointingTo(guarded->pos,
    +				fac->buildDistance*0.9f+guarded->radius, false);
    +			if(guarded->health<guarded->maxHealth
    +					&& ((guarded->beingBuilt && owner->unitDef->canAssist)
    +					|| (!guarded->beingBuilt && owner->unitDef->canRepair)))
    +				fac->SetRepairTarget(guarded);
    +			else
    +				NonMoving();
    +		}else{
    +			if((goalPos-goal).SqLength2D()>4000
    +					|| (goalPos - owner->pos).SqLength2D() <
    +						(owner->maxSpeed*30 + 1 + SQUARE_SIZE*2)
    +						* (owner->maxSpeed*30 + 1 + SQUARE_SIZE*2)){
    +				SetGoal(goal,curPos);
     			}
    -		} else {
    -			FinishCommand();
     		}
    -		return;}
    -	case CMD_RECLAIM:{
    -		assert(owner->unitDef->canReclaim);
    -		if(c.params.size()==1){
    -			int id=(int) c.params[0];
    -			if(id>=MAX_UNITS){		//reclaim feature
    -				CFeature* feature=featureHandler->features[id-MAX_UNITS];
    -				if(feature){
    -					if(feature->pos.distance2D(fac->pos)<fac->buildDistance*0.9f+feature->radius){
    -						StopMove();
    -						owner->moveType->KeepPointingTo(feature->pos, fac->buildDistance*0.9f+feature->radius, false);
    -						fac->SetReclaimTarget(feature);
    +	} else {
    +		FinishCommand();
    +	}
    +	return;
    +}
    +
    +void CBuilderCAI::ExecuteReclaim(Command &c){
    +	assert(owner->unitDef->canReclaim);
    +	CBuilder* fac=(CBuilder*)owner;
    +	if(c.params.size()==1){
    +		int id=(int) c.params[0];
    +		if(id>=MAX_UNITS){		//reclaim feature
    +			CFeature* feature=featureHandler->features[id-MAX_UNITS];
    +			if(feature){
    +				if(feature->pos.distance2D(fac->pos)<fac->buildDistance*0.9f+feature->radius){
    +					StopMove();
    +					owner->moveType->KeepPointingTo(feature->pos, fac->buildDistance*0.9f+feature->radius, false);
    +					fac->SetReclaimTarget(feature);
    +				} else {
    +					if(goalPos.distance2D(feature->pos)>1){
    +						SetGoal(feature->pos,owner->pos, fac->buildDistance*0.8f+feature->radius);
     					} else {
    -						if(goalPos.distance2D(feature->pos)>1){
    -							SetGoal(feature->pos,owner->pos, fac->buildDistance*0.8f+feature->radius);
    -						} else {
    -							if(owner->moveType->progressState==CMoveType::Failed){
    -								StopMove();
    -								FinishCommand();
    -							}
    +						if(owner->moveType->progressState==CMoveType::Failed){
    +							StopMove();
    +							FinishCommand();
     						}
     					}
    -				} else {
    -					StopMove();
    -					FinishCommand();
     				}
    +			} else {
    +				StopMove();
    +				FinishCommand();
    +			}
     
    -			} else {							//reclaim unit
    -				CUnit* unit=uh->units[id];
    -				if(unit && unit!=owner && unit->unitDef->reclaimable && UpdateTargetLostTimer(id)){
    -					if(unit->pos.distance2D(fac->pos)<fac->buildDistance-1+unit->radius){
    -						StopMove();
    -						owner->moveType->KeepPointingTo(unit->pos, fac->buildDistance*0.9f+unit->radius, false);
    -						fac->SetReclaimTarget(unit);
    -					} else {
    -						if(goalPos.distance2D(unit->pos)>1){
    -							SetGoal(unit->pos,owner->pos);
    -						}else{
    -							if(owner->moveType->progressState==CMoveType::Failed){
    -								StopMove();
    -								FinishCommand();
    -							}
    +		} else {							//reclaim unit
    +			CUnit* unit=uh->units[id];
    +			if(unit && unit!=owner && unit->unitDef->reclaimable && UpdateTargetLostTimer(id)){
    +				if(unit->pos.distance2D(fac->pos)<fac->buildDistance-1+unit->radius){
    +					StopMove();
    +					owner->moveType->KeepPointingTo(unit->pos, fac->buildDistance*0.9f+unit->radius, false);
    +					fac->SetReclaimTarget(unit);
    +				} else {
    +					if(goalPos.distance2D(unit->pos)>1){
    +						SetGoal(unit->pos,owner->pos);
    +					}else{
    +						if(owner->moveType->progressState==CMoveType::Failed){
    +							StopMove();
    +							FinishCommand();
     						}
     					}
    -				} else {
    -					FinishCommand();
     				}
    -			}
    -		} 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,true)){
    -				inCommand=false;
    -				SlowUpdate();
    -				return;
    -			}
    -			if(!(c.options & ALT_KEY)){
    +			} else {
     				FinishCommand();
     			}
    -		} else {	//wrong number of parameters
    +		}
    +	} 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,true)){
    +			inCommand=false;
    +			SlowUpdate();
    +			return;
    +		}
    +		if(!(c.options & ALT_KEY)){
     			FinishCommand();
     		}
    -		return;}
    -	case CMD_RESURRECT:{
    -		assert(owner->unitDef->canResurrect);
    -		if(c.params.size()==1){
    -			int id=(int)c.params[0];
    -			if(id>=MAX_UNITS){		//resurrect feature
    -				CFeature* feature=featureHandler->features[id-MAX_UNITS];
    -				if(feature && feature->createdFromUnit!=""){
    -					if(feature->pos.distance2D(fac->pos)<fac->buildDistance*0.9f+feature->radius){
    -						StopMove();
    -						owner->moveType->KeepPointingTo(feature->pos, fac->buildDistance*0.9f+feature->radius, false);
    -						fac->SetResurrectTarget(feature);
    +	} else {	//wrong number of parameters
    +		FinishCommand();
    +	}
    +	return;
    +}
    +
    +void CBuilderCAI::ExecuteResurrect(Command &c){
    +	assert(owner->unitDef->canResurrect);
    +	CBuilder* fac=(CBuilder*)owner;
    +	if(c.params.size()==1){
    +		int id=(int)c.params[0];
    +		if(id>=MAX_UNITS){		//resurrect feature
    +			CFeature* feature=featureHandler->features[id-MAX_UNITS];
    +			if(feature && feature->createdFromUnit!=""){
    +				if(feature->pos.distance2D(fac->pos)<fac->buildDistance*0.9f+feature->radius){
    +					StopMove();
    +					owner->moveType->KeepPointingTo(feature->pos, fac->buildDistance*0.9f+feature->radius, false);
    +					fac->SetResurrectTarget(feature);
    +				} else {
    +					if(goalPos.distance2D(feature->pos)>1){
    +						SetGoal(feature->pos,owner->pos, fac->buildDistance*0.8f+feature->radius);
     					} else {
    -						if(goalPos.distance2D(feature->pos)>1){
    -							SetGoal(feature->pos,owner->pos, fac->buildDistance*0.8f+feature->radius);
    -						} else {
    -							if(owner->moveType->progressState==CMoveType::Failed){
    -								StopMove();
    -								FinishCommand();
    -							}
    +						if(owner->moveType->progressState==CMoveType::Failed){
    +							StopMove();
    +							FinishCommand();
     						}
     					}
    -				} else {
    -					if(fac->lastResurrected && uh->units[fac->lastResurrected] && owner->unitDef->canRepair){	//resurrection finished, start repair
    -						c.id=CMD_REPAIR;		//kind of hackery to overwrite the current order i suppose
    -						c.params.clear();
    -						c.params.push_back(fac->lastResurrected);
    -						c.options|=INTERNAL_ORDER;
    -						fac->lastResurrected=0;
    -						inCommand=false;
    -						SlowUpdate();
    -						return;
    -					}
    -					StopMove();
    -					FinishCommand();
     				}
    -			} else {							//resurrect unit
    +			} else {
    +				if(fac->lastResurrected && uh->units[fac->lastResurrected] && owner->unitDef->canRepair){	//resurrection finished, start repair
    +					c.id=CMD_REPAIR;		//kind of hackery to overwrite the current order i suppose
    +					c.params.clear();
    +					c.params.push_back(fac->lastResurrected);
    +					c.options|=INTERNAL_ORDER;
    +					fac->lastResurrected=0;
    +					inCommand=false;
    +					SlowUpdate();
    +					return;
    +				}
    +				StopMove();
     				FinishCommand();
     			}
    -		} else if(c.params.size()==4){//area resurect
    -			float3 pos(c.params[0],c.params[1],c.params[2]);
    -			float radius=c.params[3];
    -			if(FindResurrectableFeatureAndResurrect(pos,radius,c.options)){
    -				inCommand=false;
    -				SlowUpdate();
    -				return;
    -			}
    -			if(!(c.options & ALT_KEY)){
    -				FinishCommand();
    -			}
    -		} else {	//wrong number of parameters
    +		} else {							//resurrect unit
     			FinishCommand();
     		}
    -		return;}
    -	case CMD_PATROL:{
    -		assert(owner->unitDef->canPatrol);
    -		if(c.params.size()<3){		//this shouldnt happen but anyway ...
    -			logOutput.Print("Error: got patrol cmd with less than 3 params on %s in buildercai",
    -				owner->unitDef->humanName.c_str());
    +	} else if(c.params.size()==4){//area resurect
    +		float3 pos(c.params[0],c.params[1],c.params[2]);
    +		float radius=c.params[3];
    +		if(FindResurrectableFeatureAndResurrect(pos,radius,c.options)){
    +			inCommand=false;
    +			SlowUpdate();
     			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);
    +		if(!(c.options & ALT_KEY)){
    +			FinishCommand();
     		}
    -		SlowUpdate();
    -		return;}
    -	case CMD_FIGHT:{
    -		assert((c.options & INTERNAL_ORDER) || owner->unitDef->canFight);
    -		if(tempOrder){
    -			tempOrder=false;
    -			inCommand=true;
    -		}
    -		if(c.params.size()<3){		//this shouldnt happen but anyway ...
    -			logOutput.Print("Error: got fight 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 {
    -			// Some hackery to make sure the line (commandPos1,commandPos2) is NOT
    -			// rotated (only shortened) if we reach this because the previous return
    -			// fight command finished by the 'if((curPos-pos).SqLength2D()<(64*64)){'
    -			// condition, but is actually updated correctly if you click somewhere
    -			// outside the area close to the line (for a new command).
    -			commandPos1 = ClosestPointOnLine(commandPos1, commandPos2, curPos);
    -			if ((curPos-commandPos1).SqLength2D()>(96*96)) {
    -				commandPos1 = curPos;
    -			}
    -		}
    -		float3 pos(c.params[0],c.params[1],c.params[2]);
    +	} else {	//wrong number of parameters
    +		FinishCommand();
    +	}
    +	return;
    +}
    +
    +void CBuilderCAI::ExecutePatrol(Command &c){
    +	assert(owner->unitDef->canPatrol);
    +	if(c.params.size()<3){		//this shouldnt happen but anyway ...
    +		logOutput.Print("Error: got patrol cmd with less than 3 params on %s in buildercai",
    +			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;
    +}
    +
    +void CBuilderCAI::ExecuteFight(Command &c){
    +	assert((c.options & INTERNAL_ORDER) || owner->unitDef->canFight);
    +	CBuilder* fac=(CBuilder*)owner;
    +	if(tempOrder){
    +		tempOrder=false;
    +		inCommand=true;
    +	}
    +	if(c.params.size()<3){		//this shouldnt happen but anyway ...
    +		logOutput.Print("Error: got fight cmd with less than 3 params on %s in BuilderCAI",owner->unitDef->humanName.c_str());
    +		return;
    +	}
    +	if(c.params.size() >= 6){
     		if(!inCommand){
    -			inCommand = true;
    -			commandPos2=pos;
    +			commandPos1 = float3(c.params[3],c.params[4],c.params[5]);
     		}
    -		if(!(pos==goalPos)){
    -			SetGoal(pos,curPos);
    +	} else {
    +		// Some hackery to make sure the line (commandPos1,commandPos2) is NOT
    +		// rotated (only shortened) if we reach this because the previous return
    +		// fight command finished by the 'if((curPos-pos).SqLength2D()<(64*64)){'
    +		// condition, but is actually updated correctly if you click somewhere
    +		// outside the area close to the line (for a new command).
    +		commandPos1 = ClosestPointOnLine(commandPos1, commandPos2, owner->pos);
    +		if ((owner->pos - commandPos1).SqLength2D()>(96*96)) {
    +			commandPos1 = owner->pos;
     		}
    -		float3 curPosOnLine = ClosestPointOnLine(commandPos1, commandPos2, curPos);
    -		if((owner->unitDef->canRepair || owner->unitDef->canAssist) && FindRepairTargetAndRepair(curPosOnLine,300*owner->moveState+fac->buildDistance-8,c.options,true)){
    -			CUnit* target=uh->units[(int)commandQue.front().params[0]];
    -			tempOrder=true;
    -			inCommand=false;
    -			if(lastPC1!=gs->frameNum){	//avoid infinite loops
    -				lastPC1=gs->frameNum;
    -				SlowUpdate();
    -			}
    -			return;
    +	}
    +	float3 pos(c.params[0],c.params[1],c.params[2]);
    +	if(!inCommand){
    +		inCommand = true;
    +		commandPos2=pos;
    +	}
    +	if(!(pos==goalPos)){
    +		SetGoal(pos,owner->pos);
    +	}
    +	float3 curPosOnLine = ClosestPointOnLine(commandPos1, commandPos2, owner->pos);
    +	if((owner->unitDef->canRepair || owner->unitDef->canAssist) && FindRepairTargetAndRepair(curPosOnLine,300*owner->moveState+fac->buildDistance-8,c.options,true)){
    +		CUnit* target=uh->units[(int)commandQue.front().params[0]];
    +		tempOrder=true;
    +		inCommand=false;
    +		if(lastPC1!=gs->frameNum){	//avoid infinite loops
    +			lastPC1=gs->frameNum;
    +			SlowUpdate();
     		}
    -		if(owner->unitDef->canReclaim && FindReclaimableFeatureAndReclaim(curPosOnLine,300,c.options,false)){
    -			tempOrder=true;
    -			inCommand=false;
    -			if(lastPC2!=gs->frameNum){	//avoid infinite loops
    -				lastPC2=gs->frameNum;
    -				SlowUpdate();
    -			}
    -			return;
    +		return;
    +	}
    +	if(owner->unitDef->canReclaim && FindReclaimableFeatureAndReclaim(curPosOnLine,300,c.options,false)){
    +		tempOrder=true;
    +		inCommand=false;
    +		if(lastPC2!=gs->frameNum){	//avoid infinite loops
    +			lastPC2=gs->frameNum;
    +			SlowUpdate();
     		}
    -		if((curPos-pos).SqLength2D()<(64*64)){
    +		return;
    +	}
    +	if((owner->pos - pos).SqLength2D()<(64*64)){
    +		FinishCommand();
    +		return;
    +	}
    +	if(owner->haveTarget && owner->moveType->progressState!=CMoveType::Done){
    +		StopMove();
    +	} else if(owner->moveType->progressState!=CMoveType::Active){
    +		owner->moveType->StartMoving(goalPos, 8);
    +	}
    +	return;
    +}
    +void CBuilderCAI::ExecuteRestore(Command &c){
    +	assert(owner->unitDef->canRestore);
    +	CBuilder* fac=(CBuilder*)owner;
    +	if(inCommand){
    +		if(!fac->terraforming){
     			FinishCommand();
    -			return;
     		}
    -		if(owner->haveTarget && owner->moveType->progressState!=CMoveType::Done){
    +	} else if(owner->unitDef->canRestore){
    +		float3 pos(c.params[0],c.params[1],c.params[2]);
    +		float radius(c.params[3]);
    +		if(fac->pos.distance2D(pos)<fac->buildDistance-1){
     			StopMove();
    -		} else if(owner->moveType->progressState!=CMoveType::Active){
    -			owner->moveType->StartMoving(goalPos, 8);
    +			fac->StartRestore(pos,radius);
    +			owner->moveType->KeepPointingTo(pos, fac->buildDistance*0.9f, false);
    +			inCommand=true;
    +		} else {
    +			SetGoal(pos,owner->pos, fac->buildDistance*0.9f);
     		}
    -		return;}
    -	case CMD_RESTORE:{
    -		assert(owner->unitDef->canRestore);
    -		if(inCommand){
    -			if(!fac->terraforming){
    -				FinishCommand();
    -			}
    -		} else if(owner->unitDef->canRestore){
    -			float3 pos(c.params[0],c.params[1],c.params[2]);
    -			float radius(c.params[3]);
    -			if(fac->pos.distance2D(pos)<fac->buildDistance-1){
    -				StopMove();
    -				fac->StartRestore(pos,radius);
    -				owner->moveType->KeepPointingTo(pos, fac->buildDistance*0.9f, false);
    -				inCommand=true;
    -			} else {
    -				SetGoal(pos,owner->pos, fac->buildDistance*0.9f);
    -			}
    -		}
    -		return;}
    -	default:
    -		break;
     	}
    -	CMobileCAI::SlowUpdate();
    +	return;
     }
     
     int CBuilderCAI::GetDefaultCmd(CUnit* pointed, CFeature* feature)
    Index: rts/Sim/Units/CommandAI/BuilderCAI.h
    ===================================================================
    --- rts/Sim/Units/CommandAI/BuilderCAI.h	(revision 2593)
    +++ rts/Sim/Units/CommandAI/BuilderCAI.h	(working copy)
    @@ -24,6 +24,16 @@
     	bool FindRepairTargetAndRepair(float3 pos, float radius,unsigned char options,bool attackEnemy);
     	bool FindCaptureTargetAndCapture(float3 pos, float radius,unsigned char options);
     
    +	void ExecutePatrol(Command &c);
    +	void ExecuteFight(Command &c);
    +	void ExecuteGuard(Command &c);
    +	void ExecuteStop(Command &c);
    +	virtual void ExecuteRepair(Command &c);
    +	virtual void ExecuteCapture(Command &c);
    +	virtual void ExecuteReclaim(Command &c);
    +	virtual void ExecuteResurrect(Command &c);
    +	virtual void ExecuteRestore(Command &c);
    +
     	map<int,string> buildOptions;
     	bool building;
     	BuildInfo build;
    Index: rts/Sim/Units/CommandAI/CommandAI.cpp
    ===================================================================
    --- rts/Sim/Units/CommandAI/CommandAI.cpp	(revision 2593)
    +++ rts/Sim/Units/CommandAI/CommandAI.cpp	(working copy)
    @@ -759,65 +759,86 @@
     	return targetLostTimer;
     }
     
    +/**
    +* @breif Causes this CommandAI to execute the attack order c
    +*/
    +void CCommandAI::ExecuteAttack(Command &c){
    +	assert(owner->unitDef->canAttack);
    +	if(inCommand){
    +		if(targetDied || (c.params.size()==1 && UpdateTargetLostTimer(int(c.params[0])) == 0)){
    +			return FinishCommand();
    +		}
    +		if ((c.params.size() == 3) && (owner->commandShotCount > 0) && (commandQue.size() > 1)) {
    +			return FinishCommand();
    +		}
    +	} else {
    +		if(c.params.size()==1){
    +			if(uh->units[int(c.params[0])]!=0 && uh->units[int(c.params[0])]!=owner){
    +				owner->AttackUnit(uh->units[int(c.params[0])], c.id==CMD_DGUN);
    +				if(orderTarget)
    +					DeleteDeathDependence(orderTarget);
    +				orderTarget=uh->units[int(c.params[0])];
    +				AddDeathDependence(orderTarget);
    +				inCommand=true;
    +			} else {
    +				return FinishCommand();
    +			}
    +		} else {
    +			float3 pos(c.params[0],c.params[1],c.params[2]);
    +			owner->AttackGround(pos, c.id==CMD_DGUN);
    +			inCommand=true;
    +		}
    +	}
    +}
    +
    +/**
    +* @breif executes the stop command c
    +*/
    +void CCommandAI::ExecuteStop(Command &c){
    +	owner->AttackUnit(0,true);
    +	std::vector<CWeapon*>::iterator wi;
    +	for(wi=owner->weapons.begin();wi!=owner->weapons.end();++wi){
    +		(*wi)->HoldFire();
    +	}
    +	return FinishCommand();
    +}
    +
    +/**
    +* @breif executes the DGun command c
    +*/
    +void CCommandAI::ExecuteDGun(Command &c){
    +	return ExecuteAttack(c);
    +}
    +
     void CCommandAI::SlowUpdate()
     {
    -	if(commandQue.empty())
    +	if(commandQue.empty()){
     		return;
    +	}
     
     	Command& c=commandQue.front();
     
     	switch(c.id){
    -	case CMD_WAIT:
    -		break;
    -	case CMD_SELFD:{
    -		if(owner->selfDCountdown != 0){
    -			owner->selfDCountdown=0;
    -		} else {
    -			owner->selfDCountdown = owner->unitDef->selfDCountdown*2+1;
    -		}
    -		FinishCommand();
    -		break;}
    -	case CMD_STOP:{
    -		owner->AttackUnit(0,true);
    -		std::vector<CWeapon*>::iterator wi;
    -		for(wi=owner->weapons.begin();wi!=owner->weapons.end();++wi)
    -			(*wi)->HoldFire();
    -		FinishCommand();
    -		break;};
    -	case CMD_ATTACK:
    -	case CMD_DGUN:
    -		assert(owner->unitDef->canAttack);
    -		if(inCommand){
    -			if(targetDied || (c.params.size()==1 && UpdateTargetLostTimer(int(c.params[0])) == 0)){
    -				FinishCommand();
    -				break;
    -			}
    -			if ((c.params.size() == 3) && (owner->commandShotCount > 0) && (commandQue.size() > 1)) {
    -				FinishCommand();
    -				break;
    -			}
    -		} else {
    -			if(c.params.size()==1){
    -				if(uh->units[int(c.params[0])]!=0 && uh->units[int(c.params[0])]!=owner){
    -					owner->AttackUnit(uh->units[int(c.params[0])], c.id==CMD_DGUN);
    -					if(orderTarget)
    -						DeleteDeathDependence(orderTarget);
    -					orderTarget=uh->units[int(c.params[0])];
    -					AddDeathDependence(orderTarget);
    -					inCommand=true;
    -				} else {
    -					FinishCommand();
    -				}
    +		case CMD_WAIT:
    +			return;
    +	case CMD_SELFD:
    +		{
    +			if(owner->selfDCountdown != 0){
    +				owner->selfDCountdown=0;
     			} else {
    -				float3 pos(c.params[0],c.params[1],c.params[2]);
    -				owner->AttackGround(pos, c.id==CMD_DGUN);
    -				inCommand=true;
    +				owner->selfDCountdown = owner->unitDef->selfDCountdown*2+1;
     			}
    +			FinishCommand();
    +			return;
     		}
    -		break;
    -	default:
    -		FinishCommand();
    -		break;
    +		case CMD_STOP:
    +			return ExecuteStop(c);
    +		case CMD_ATTACK:
    +			return ExecuteAttack(c);
    +		case CMD_DGUN:
    +			return ExecuteDGun(c);
    +		default:
    +			return FinishCommand();
     	}
     }
     
    @@ -901,8 +922,10 @@
     void CCommandAI::FinishCommand(void)
     {
     	int type=commandQue.front().id;
    -	if(repeatOrders && type!=CMD_STOP && type != CMD_PATROL && !(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;
     	targetDied=false;
    Index: rts/Sim/Units/CommandAI/CommandAI.h
    ===================================================================
    --- rts/Sim/Units/CommandAI/CommandAI.h	(revision 2593)
    +++ rts/Sim/Units/CommandAI/CommandAI.h	(working copy)
    @@ -40,6 +40,9 @@
     	std::vector<Command> GetOverlapQueued(const Command &c);
     	std::vector<Command> GetOverlapQueued(const Command &c,
     	                                      std::deque<Command>& queue);
    +	virtual void ExecuteAttack(Command &c);
    +	virtual void ExecuteDGun(Command &c);
    +	virtual void ExecuteStop(Command &c);
     
     	void AddStockpileWeapon(CWeapon* weapon);
     	void StockpileChanged(CWeapon* weapon);
    Index: rts/Sim/Units/CommandAI/FactoryCAI.cpp
    ===================================================================
    --- rts/Sim/Units/CommandAI/FactoryCAI.cpp	(revision 2593)
    +++ rts/Sim/Units/CommandAI/FactoryCAI.cpp	(working copy)
    @@ -259,10 +259,6 @@
     		} else {
     			switch(c.id){
     			case CMD_STOP:
    -				building=false;
    -				fac->StopBuild();
    -				commandQue.pop_front();
    -				break;
     			default:
     				CCommandAI::SlowUpdate();
     				return;
    @@ -273,6 +269,14 @@
     	return;
     }
     
    +void CFactoryCAI::ExecuteStop(Command &c){
    +	CFactory* fac=(CFactory*)owner;
    +	building=false;
    +	fac->StopBuild();
    +	commandQue.pop_front();
    +	return;
    +}
    +
     int CFactoryCAI::GetDefaultCmd(CUnit* pointed, CFeature* feature)
     {
     	if (pointed) {
    Index: rts/Sim/Units/CommandAI/FactoryCAI.h
    ===================================================================
    --- rts/Sim/Units/CommandAI/FactoryCAI.h	(revision 2593)
    +++ rts/Sim/Units/CommandAI/FactoryCAI.h	(working copy)
    @@ -24,6 +24,7 @@
     	void GiveCommand(const Command& c);
     	void DrawCommands(void);
     	void UpdateIconName(int id,BuildOption& bo);
    +	void ExecuteStop(Command &c);
     
     	std::deque<Command> newUnitCommands;
     
    Index: rts/Sim/Units/CommandAI/MobileCAI.cpp
    ===================================================================
    --- rts/Sim/Units/CommandAI/MobileCAI.cpp	(revision 2593)
    +++ rts/Sim/Units/CommandAI/MobileCAI.cpp	(working copy)
    @@ -31,7 +31,9 @@
     	lastIdleCheck(0),
     	commandPos1(ZeroVector),
     	commandPos2(ZeroVector),
    -	lastPC(-1)
    +	lastPC(-1),
    +	cancelDistance(1024),
    +	slowGuard(false)
     {
     	lastUserGoal=owner->pos;
     	CommandDescription c;
    @@ -137,6 +139,7 @@
     
     	if(!(c.options & SHIFT_KEY) && nonQueingCommands.find(c.id)==nonQueingCommands.end()){
     		tempOrder=false;
    +		StopSlowGuard();
     	}
     	CCommandAI::GiveAllowedCommand(c);
     }
    @@ -188,13 +191,13 @@
     							myPlane->SetState(CTAAirMoveType::AIRCRAFT_TAKEOFF);
     						}
     						return;
    -					}		
    +					}
     				}
     			}
     		}
     	}
     
    -	if(!commandQue.empty() && commandQue.front().timeOut<gs->frameNum){
    +	if(!commandQue.empty() && commandQue.front().timeOut < gs->frameNum){
     		StopMove();
     		FinishCommand();
     		return;
    @@ -204,15 +207,17 @@
     //		if(!owner->ai || owner->ai->State() != CHasState::Active) {
     			IdleCheck();
     //		}
    -		if(commandQue.empty() || commandQue.front().id==CMD_ATTACK)	//the attack order could terminate directly and thus cause a loop
    +		//the attack order could terminate directly and thus cause a loop
    +		if(commandQue.empty() || commandQue.front().id == CMD_ATTACK) {
     			return;
    +		}
     	}
     
    -	float3 curPos=owner->pos;
    +	const float3& curPos=owner->pos;
     	
     	// treat any following CMD_SET_WANTED_MAX_SPEED commands as options
    -	// to the current command  (and ignore them when it's their turn)
    -	if (commandQue.size() >= 2) {
    +	// to the current command  (and ignore them when it's their turn
    +	if (commandQue.size() >= 2 && !slowGuard) {
     		deque<Command>::iterator it = commandQue.begin();
     		it++;
     		const Command& c = *it;
    @@ -221,235 +226,286 @@
     			const float newMaxSpeed = min(c.params[0], defMaxSpeed);
     			owner->moveType->SetMaxSpeed(newMaxSpeed);
     		}
    -	}	 
    +	}
    +	return Execute();
    +}
     
    +/**
    +* @brief Executes the first command in the commandQue
    +*/
    +void CMobileCAI::Execute(){
     	Command& c=commandQue.front();
     	switch(c.id){
    -	case CMD_WAIT:{
    -		break;
    +	case CMD_SET_WANTED_MAX_SPEED:
    +		return ExecuteSetWantedMaxSpeed(c);
    +	case CMD_MOVE:
    +		return ExecuteMove(c);
    +	case CMD_PATROL:
    +		return ExecutePatrol(c);
    +	case CMD_FIGHT:
    +		return ExecuteFight(c);
    +	case CMD_GUARD:
    +		return ExecuteGuard(c);
    +	default:
    +		return CCommandAI::SlowUpdate();
     	}
    -	case CMD_STOP:{
    -		StopMove();
    -		CCommandAI::SlowUpdate();
    -		break;
    +}
    +
    +/**
    +* @brief executes the set wanted max speed command
    +*/
    +void CMobileCAI::ExecuteSetWantedMaxSpeed(Command &c){
    +	if (repeatOrders && (commandQue.size() >= 2) &&
    +			(commandQue.back().id != CMD_SET_WANTED_MAX_SPEED)) {
    +		commandQue.push_back(commandQue.front());
     	}
    -	case CMD_SET_WANTED_MAX_SPEED:{
    -	  if (repeatOrders && (commandQue.size() >= 2) &&
    -	      (commandQue.back().id != CMD_SET_WANTED_MAX_SPEED)) {
    -	  	commandQue.push_back(commandQue.front());
    -		}
    -		commandQue.pop_front();
    -		SlowUpdate();
    -		break;
    +	commandQue.pop_front();
    +	SlowUpdate();
    +	return;
    +}
    +
    +/**
    +* @brief executes the move command
    +*/
    +void CMobileCAI::ExecuteMove(Command &c){
    +	float3 pos(c.params[0], c.params[1], c.params[2]);
    +	if(!(pos == goalPos)){
    +		SetGoal(pos, owner->pos);
     	}
    -	case CMD_MOVE:{
    -		float3 pos(c.params[0],c.params[1],c.params[2]);
    -		if(!(pos==goalPos)){
    -			SetGoal(pos,curPos);
    -		}
    -		if((curPos-goalPos).SqLength2D()<1024 || owner->moveType->progressState==CMoveType::Failed){
    -			FinishCommand();
    -		}
    -		break;
    +	if((owner->pos - goalPos).SqLength2D() < cancelDistance ||
    +			owner->moveType->progressState == CMoveType::Failed){
    +		FinishCommand();
     	}
    -	case CMD_PATROL:{
    -		assert(owner->unitDef->canPatrol);
    -		if(c.params.size()<3){		//this shouldnt happen but anyway ...
    -			logOutput.Print("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;
    +}
    +
    +/**
    +* @brief Executes the Patrol command c
    +*/
    +void CMobileCAI::ExecutePatrol(Command &c){
    +	assert(owner->unitDef->canPatrol);
    +	assert(c.params.size() >= 3);
    +	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);
    +	}
    +	ExecuteFight(temp);
    +	return;
    +}
    +
    +/**
    +* @brief Executes the Fight command c
    +*/
    +void CMobileCAI::ExecuteFight(Command &c){
    +	assert((c.options & INTERNAL_ORDER) || owner->unitDef->canFight);
    +	if(tempOrder){
    +		inCommand = true;
    +		tempOrder = false;
    +	}
    +	if(c.params.size()<3){		//this shouldnt happen but anyway ...
    +		logOutput.Print("Error: got fight cmd with less than 3 params on %s in mobilecai",
    +			owner->unitDef->humanName.c_str());
     		return;
     	}
    -	case CMD_FIGHT:{
    -		assert((c.options & INTERNAL_ORDER) || owner->unitDef->canFight);
    -		if(tempOrder){
    -			inCommand = true;
    -			tempOrder = false;
    -		}
    -		if(c.params.size()<3){		//this shouldnt happen but anyway ...
    -			logOutput.Print("Error: got fight cmd with less than 3 params on %s in mobilecai",
    -				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 {
    -			// Some hackery to make sure the line (commandPos1,commandPos2) is NOT
    -			// rotated (only shortened) if we reach this because the previous return
    -			// fight command finished by the 'if((curPos-pos).SqLength2D()<(64*64)){'
    -			// condition, but is actually updated correctly if you click somewhere
    -			// outside the area close to the line (for a new command).
    -			commandPos1 = ClosestPointOnLine(commandPos1, commandPos2, curPos);
    -			if ((curPos-commandPos1).SqLength2D()>(96*96)) {
    -				commandPos1 = curPos;
    -			}
    -		}
    -		float3 pos(c.params[0],c.params[1],c.params[2]);
    +	if(c.params.size() >= 6){
     		if(!inCommand){
    -			inCommand = true;
    -			commandPos2 = pos;
    +			commandPos1 = float3(c.params[3],c.params[4],c.params[5]);
     		}
    -		if(pos!=goalPos){
    -			SetGoal(pos,curPos);
    +	} else {
    +		// Some hackery to make sure the line (commandPos1,commandPos2) is NOT
    +		// rotated (only shortened) if we reach this because the previous return
    +		// fight command finished by the 'if((curPos-pos).SqLength2D()<(64*64)){'
    +		// condition, but is actually updated correctly if you click somewhere
    +		// outside the area close to the line (for a new command).
    +		commandPos1 = ClosestPointOnLine(commandPos1, commandPos2, owner->pos);
    +		if ((owner->pos - commandPos1).SqLength2D() > (96 * 96)) {
    +			commandPos1 = owner->pos;
     		}
    +	}
    +	float3 pos(c.params[0],c.params[1],c.params[2]);
    +	if(!inCommand){
    +		inCommand = true;
    +		commandPos2 = pos;
    +	}
    +	if(c.params.size() >= 6){
    +		pos = ClosestPointOnLine(commandPos1, commandPos2, pos);
    +	}
    +	if(pos!=goalPos){
    +		SetGoal(pos, owner->pos);
    +	}
     
    -		if(owner->unitDef->canAttack && owner->fireState==2){
    -			float3 curPosOnLine = ClosestPointOnLine(commandPos1, commandPos2, curPos);
    -			CUnit* enemy=helper->GetClosestEnemyUnit(
    -				curPosOnLine, owner->maxRange+100*owner->moveState*owner->moveState, owner->allyteam);
    -			if(enemy && (owner->hasUWWeapons || !enemy->isUnderWater)
    -						&& !(owner->unitDef->noChaseCategory & enemy->category) && !owner->weapons.empty()){
    -				Command c2;
    -				c2.id=CMD_ATTACK;
    -				c2.options=c.options|INTERNAL_ORDER;
    -				c2.params.push_back(enemy->id);
    -				PushOrUpdateReturnFight();
    -				commandQue.push_front(c2);
    -				inCommand=false;
    -				tempOrder=true;
    -				if(lastPC!=gs->frameNum){	//avoid infinite loops
    -					lastPC=gs->frameNum;
    -					SlowUpdate();
    -				}
    -				return;
    +	if(owner->unitDef->canAttack && owner->fireState==2){
    +		float3 curPosOnLine = ClosestPointOnLine(commandPos1, commandPos2, owner->pos);
    +		CUnit* enemy=helper->GetClosestEnemyUnit(
    +			curPosOnLine, owner->maxRange + 100 * owner->moveState * owner->moveState,
    +			owner->allyteam);
    +		if(enemy && (owner->hasUWWeapons || !enemy->isUnderWater)
    +				&& !(owner->unitDef->noChaseCategory & enemy->category)
    +				&& !owner->weapons.empty()){
    +			Command c2;
    +			c2.id=CMD_ATTACK;
    +			c2.options=c.options|INTERNAL_ORDER;
    +			c2.params.push_back(enemy->id);
    +			PushOrUpdateReturnFight();
    +			commandQue.push_front(c2);
    +			inCommand=false;
    +			tempOrder=true;
    +			if(lastPC!=gs->frameNum){	//avoid infinite loops
    +				lastPC=gs->frameNum;
    +				SlowUpdate();
     			}
    +			return;
     		}
    -		if((curPos-goalPos).SqLength2D()<(64*64) || owner->moveType->progressState==CMoveType::Failed){
    -			FinishCommand();
    -		}
    -		return;
     	}
    -	case CMD_DGUN:
    -		if(uh->limitDgun && owner->unitDef->isCommander
    -		  && owner->pos.distance(gs->Team(owner->team)->startPos)>uh->dgunRadius){
    -			StopMove();
    -			FinishCommand();
    +	if((owner->pos - goalPos).SqLength2D() < (64 * 64)
    +			|| (owner->moveType->progressState == CMoveType::Failed)){
    +		FinishCommand();
    +	}
    +	return;
    +}
    +
    +/**
    +* @breif Executs the guard command c
    +*/
    +void CMobileCAI::ExecuteGuard(Command &c){
    +	assert(owner->unitDef->canGuard);
    +	assert(!c.params.empty());
    +	if(int(c.params[0]) >= 0 && uh->units[int(c.params[0])] != NULL
    +			&& UpdateTargetLostTimer(int(c.params[0]))){
    +		CUnit* guarded = uh->units[int(c.params[0])];
    +		if(owner->unitDef->canAttack && guarded->lastAttacker
    +				&& guarded->lastAttack + 40 < gs->frameNum
    +				&& (owner->hasUWWeapons || !guarded->lastAttacker->isUnderWater)){
    +			StopSlowGuard();
    +			Command nc;
    +			nc.id=CMD_ATTACK;
    +			nc.params.push_back(guarded->lastAttacker->id);
    +			nc.options = c.options;
    +			commandQue.push_front(nc);
    +			SlowUpdate();
     			return;
    -		}
    -		//no break
    -	case CMD_ATTACK:
    -		assert(owner->unitDef->canAttack);
    -		if(tempOrder && owner->moveState<2){		//limit how far away we fly
    -			if(orderTarget && LinePointDist(commandPos1,commandPos2,orderTarget->pos) > 500+owner->maxRange){
    -				StopMove();
    -				FinishCommand();
    -				break;
    +		} else {
    +			//float3 dif = guarded->speed * guarded->frontdir;
    +			float3 dif = guarded->pos - owner->pos;
    +			dif.Normalize();
    +			float3 goal = guarded->pos - dif * (guarded->radius + owner->radius + 64);
    +			if((goalPos - goal).SqLength2D() > 1600
    +					|| (goalPos - owner->pos).SqLength2D()
    +						< (owner->maxSpeed*30 + 1 + SQUARE_SIZE*2)
    +						 * (owner->maxSpeed*30 + 1 + SQUARE_SIZE*2)){
    +				SetGoal(goal, owner->pos);
     			}
    -		}
    -		if(!inCommand){
    -			if(c.params.size()==1){
    -				if(uh->units[int(c.params[0])]!=0 && uh->units[int(c.params[0])]!=owner){
    -					float3 fix=uh->units[int(c.params[0])]->pos+owner->posErrorVector*128;
    -					SetGoal(fix,curPos);
    -					orderTarget=uh->units[int(c.params[0])];
    -					AddDeathDependence(orderTarget);
    -					inCommand=true;
    -				} else {
    -					StopMove();		//cancel keeppointingto
    -					FinishCommand();
    -					break;
    +			if((goal - owner->pos).SqLength2D() < 6400) {
    +				StartSlowGuard(guarded->maxSpeed);
    +				if((goal-owner->pos).SqLength2D() < 1800){
    +					StopMove();
    +					NonMoving(); 
     				}
     			} else {
    -				float3 pos(c.params[0],c.params[1],c.params[2]);
    -				SetGoal(pos,curPos);
    -				inCommand=true;
    +				StopSlowGuard();
     			}
     		}
    -		else if ((c.params.size() == 3) && (owner->commandShotCount > 0) && (commandQue.size() > 1)) {
    -			// the trailing CMD_SET_WANTED_MAX_SPEED in a command pair does not count
    -			if ((commandQue.size() != 2) || (commandQue.back().id != CMD_SET_WANTED_MAX_SPEED)) {
    -				StopMove();
    -				FinishCommand();
    -				break;
    -			}
    -		}
    +	} else {
    +		FinishCommand();
    +	}
    +	return;
    +}
     
    -		if(targetDied || (c.params.size() == 1 && UpdateTargetLostTimer(int(c.params[0])) == 0)){
    -			StopMove();		//cancel keeppointingto
    -			FinishCommand();
    -			break;
    +/**
    +* @breif executes the stop command c
    +*/
    +void CMobileCAI::ExecuteStop(Command &c){
    +	StopMove();
    +	return CCommandAI::ExecuteStop(c);
    +}
    +
    +/**
    +* @breif executes the DGun command c
    +*/
    +void CMobileCAI::ExecuteDGun(Command &c){
    +	if(uh->limitDgun && owner->unitDef->isCommander
    +			&& owner->pos.distance(gs->Team(owner->team)->startPos)>uh->dgunRadius){
    +		StopMove();
    +		return FinishCommand();
    +	}
    +	return ExecuteAttack(c);
    +}
    +
    +
    +/**
    +* @breif Causes this CMoblieCAI to execute the attack order c
    +*/
    +void CMobileCAI::ExecuteAttack(Command &c){
    +	assert(owner->unitDef->canAttack);
    +	if(tempOrder && owner->moveState < 2){		//limit how far away we fly
    +		if(orderTarget && LinePointDist(commandPos1,commandPos2,orderTarget->pos) > 500 + owner->maxRange){
    +			StopMove();
    +			return FinishCommand();
     		}
    -		if(orderTarget){
    -			//note that we handle aircrafts slightly differently
    -			if((((owner->AttackUnit(orderTarget, c.id==CMD_DGUN)
    -					&& owner->weapons.size() > 0 
    -					&& owner->weapons.front()->range -
    -						owner->weapons.front()->relWeaponPos.Length() >
    -						orderTarget->pos.distance(owner->pos))
    -					|| dynamic_cast<CTAAirMoveType*>(owner->moveType))
    -					&& (owner->pos-orderTarget->pos).Length2D() <
    -						owner->maxRange*0.9f)
    -					|| (owner->pos-orderTarget->pos).SqLength2D()<1024){
    -				StopMove();
    -				owner->moveType->KeepPointingTo(orderTarget,
    -					min((float)(owner->losRadius*SQUARE_SIZE*2),
    -					owner->maxRange*0.9f), true);
    -			} else if((orderTarget->pos+owner->posErrorVector*128).distance2D(goalPos) > 10+orderTarget->pos.distance2D(owner->pos)*0.2f){
    -				float3 fix=orderTarget->pos+owner->posErrorVector*128;
    -				SetGoal(fix,curPos);
    +	}
    +	if(!inCommand){
    +		if(c.params.size()==1){
    +			if(uh->units[int(c.params[0])] != 0 && uh->units[int(c.params[0])] != owner){
    +				float3 fix=uh->units[int(c.params[0])]->pos+owner->posErrorVector*128;
    +				SetGoal(fix, owner->pos);
    +				orderTarget=uh->units[int(c.params[0])];
    +				AddDeathDependence(orderTarget);
    +				inCommand=true;
    +			} else {
    +				StopMove();		//cancel keeppointingto
    +				return FinishCommand();
     			}
     		} else {
     			float3 pos(c.params[0],c.params[1],c.params[2]);
    -			if((owner->AttackGround(pos,c.id==CMD_DGUN) && owner->weapons.size() > 0
    -					&& (owner->pos-pos).Length() < 
    -						owner->weapons.front()->range -
    -						owner->weapons.front()->relWeaponPos.Length())
    -					|| (owner->pos-pos).SqLength2D()<1024){
    -				StopMove();
    -				owner->moveType->KeepPointingTo(pos, owner->maxRange*0.9f, true);
    -			} else if(pos.distance2D(goalPos)>10){
    -				SetGoal(pos,curPos);
    -			}
    +			SetGoal(pos, owner->pos);
    +			inCommand=true;
     		}
    -		break;
    -	case CMD_GUARD:
    -		assert(owner->unitDef->canGuard);
    -		if(int(c.params[0]) >= 0 && uh->units[int(c.params[0])] != NULL && UpdateTargetLostTimer(int(c.params[0]))){
    -			CUnit* guarded=uh->units[int(c.params[0])];
    -			if(owner->unitDef->canAttack && 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);
    -				nc.options=c.options;
    -				commandQue.push_front(nc);
    -				SlowUpdate();
    -				return;
    -			} else {
    -				float3 dif=guarded->pos-curPos;
    -				dif.Normalize();
    -				float3 goal=guarded->pos-dif*(guarded->radius+owner->radius+64);
    -				if((goal-curPos).SqLength2D()<8000){
    -					StopMove();
    -					NonMoving();
    -				}else{
    -					if((goalPos-goal).SqLength2D()>3600)
    -						SetGoal(goal,curPos);
    -				}
    -			}
    -		} else {
    -			FinishCommand();
    +		return;
    +	}
    +
    +	if(targetDied || (c.params.size() == 1 && UpdateTargetLostTimer(int(c.params[0])) == 0)){
    +		StopMove();		//cancel keeppointingto
    +		return FinishCommand();
    +	}
    +	if(orderTarget){
    +		//note that we handle aircrafts slightly differently
    +		if((((owner->AttackUnit(orderTarget, c.id==CMD_DGUN)
    +				&& owner->weapons.size() > 0 
    +				&& owner->weapons.front()->range -
    +					owner->weapons.front()->relWeaponPos.Length() >
    +					orderTarget->pos.distance(owner->pos))
    +				|| dynamic_cast<CTAAirMoveType*>(owner->moveType))
    +				&& (owner->pos-orderTarget->pos).Length2D() <
    +					owner->maxRange*0.9f)
    +				|| (owner->pos-orderTarget->pos).SqLength2D()<1024){
    +			StopMove();
    +			owner->moveType->KeepPointingTo(orderTarget,
    +				min((float)(owner->losRadius*SQUARE_SIZE*2),
    +				owner->maxRange*0.9f), true);
    +		} else if((orderTarget->pos+owner->posErrorVector*128).distance2D(goalPos) > 10+orderTarget->pos.distance2D(owner->pos)*0.2f){
    +			float3 fix=orderTarget->pos+owner->posErrorVector*128;
    +			SetGoal(fix, owner->pos);
     		}
    -		break;
    -	default:
    -		CCommandAI::SlowUpdate();
    -		break;
    +	} else {
    +		float3 pos(c.params[0],c.params[1],c.params[2]);
    +		if((owner->AttackGround(pos,c.id==CMD_DGUN) && owner->weapons.size() > 0
    +				&& (owner->pos-pos).Length() < 
    +					owner->weapons.front()->range -
    +					owner->weapons.front()->relWeaponPos.Length())
    +				|| (owner->pos-pos).SqLength2D()<1024){
    +			StopMove();
    +			owner->moveType->KeepPointingTo(pos, owner->maxRange*0.9f, true);
    +		} else if(pos.distance2D(goalPos)>10){
    +			SetGoal(pos, owner->pos);
    +		}
     	}
     }
     
    @@ -471,9 +527,9 @@
     
     void CMobileCAI::SetGoal(const float3 &pos, const float3& curPos, float goalRadius)
     {
    -	if(pos==goalPos)
    +	if(pos == goalPos)
     		return;
    -	goalPos=pos;
    +	goalPos = pos;
     	owner->moveType->StartMoving(pos, goalRadius);
     }
     
    @@ -563,19 +619,19 @@
     		float length=dif.Length();
     		if(!length) {
     			length=0.1f;
    -			dif=float3(0.1f,0.0f,0.0f);
    +			dif = float3(0.1f, 0.0f, 0.0f);
     		}
     		if(length<buggerOffRadius){
    -			float3 goalPos=buggerOffPos+dif*((buggerOffRadius+128)/length);
    +			float3 goalPos = buggerOffPos + dif * ((buggerOffRadius + 128) / length);
     			Command c;
    -			c.id=CMD_MOVE;
    -			c.options=0;//INTERNAL_ORDER;
    +			c.id = CMD_MOVE;
    +			c.options = 0;//INTERNAL_ORDER;
     			c.params.push_back(goalPos.x);
     			c.params.push_back(goalPos.y);
     			c.params.push_back(goalPos.z);
    -			c.timeOut=gs->frameNum+40;
    +			c.timeOut = gs->frameNum + 40;
     			commandQue.push_front(c);
    -			unimportantMove=true;
    +			unimportantMove = true;
     		}
     	}
     }
    @@ -586,6 +642,7 @@
     		lastUserGoal=owner->pos;
     //		logOutput.Print("Reseting user goal");
     	}
    +	StopSlowGuard();
     	CCommandAI::FinishCommand();
     }
     
    @@ -634,3 +691,28 @@
     		NonMoving();
     	}
     }
    +
    +void CMobileCAI::StopSlowGuard(){
    +	if(slowGuard){
    +		slowGuard = false;
    +		owner->moveType->SetMaxSpeed(owner->maxSpeed);
    +	}
    +}
    +
    +void CMobileCAI::StartSlowGuard(float speed){
    +	if(!slowGuard){
    +		slowGuard = true;
    +		//speed /= 30;
    +		if(owner->maxSpeed >= speed){
    +			speed;
    +			if(!commandQue.empty()){
    +				Command currCommand = commandQue.front();
    +				if(commandQue.size() <= 1
    +						|| commandQue[1].id != CMD_SET_WANTED_MAX_SPEED
    +						|| commandQue[1].params[0] > speed){
    +					owner->moveType->SetMaxSpeed(speed);
    +				}
    +			}
    +		}
    +	}
    +}
    \ No newline at end of file
    Index: rts/Sim/Units/CommandAI/MobileCAI.h
    ===================================================================
    --- rts/Sim/Units/CommandAI/MobileCAI.h	(revision 2593)
    +++ rts/Sim/Units/CommandAI/MobileCAI.h	(working copy)
    @@ -8,10 +8,10 @@
     {
     public:
     	CMobileCAI(CUnit* owner);
    -	~CMobileCAI(void);
    +	virtual ~CMobileCAI(void);
     
     	void StopMove();
    -	void SetGoal(const float3& pos, const float3& curPos, float goalRadius = SQUARE_SIZE);
    +	virtual void SetGoal(const float3& pos, const float3& curPos, float goalRadius = SQUARE_SIZE);
     	int GetDefaultCmd(CUnit* pointed,CFeature* feature);
     	void SlowUpdate();
     	void GiveCommand(const Command &c);
    @@ -21,7 +21,19 @@
     	void FinishCommand(void);
     	void IdleCheck(void);
     	bool CanSetMaxSpeed() const { return true; }
    +	void StopSlowGuard();
    +	void StartSlowGuard(float speed);
    +	void ExecuteAttack(Command &c);
    +	void ExecuteDGun(Command &c);
    +	void ExecuteStop(Command &c);
     
    +	virtual void Execute();
    +	virtual void ExecuteGuard(Command &c);
    +	virtual void ExecuteFight(Command &c);
    +	virtual void ExecutePatrol(Command &c);
    +	virtual void ExecuteMove(Command &c);
    +	virtual void ExecuteSetWantedMaxSpeed(Command &c);
    +
     	float3 goalPos;
     	float3 lastUserGoal;
     
    @@ -41,7 +53,10 @@
     	float3 commandPos1;			//used to avoid stuff in maneuvre mode moving to far away from patrol path
     	float3 commandPos2;
     
    +
     protected:
    +	int cancelDistance;
    +	bool slowGuard;
     	void PushOrUpdateReturnFight() {
     		CCommandAI::PushOrUpdateReturnFight(commandPos1, commandPos2);
     	}
    Index: rts/Sim/Units/CommandAI/TransportCAI.cpp
    ===================================================================
    --- rts/Sim/Units/CommandAI/TransportCAI.cpp	(revision 2593)
    +++ rts/Sim/Units/CommandAI/TransportCAI.cpp	(working copy)
    @@ -65,162 +65,173 @@
     		return;
     	}
     
    -	CTransportUnit* transport=(CTransportUnit*)owner;
     	Command& c=commandQue.front();
     	switch(c.id){
     	case CMD_LOAD_UNITS:
    -		if(c.params.size()==1){		//load single unit
    -			if(transport->transportCapacityUsed >= owner->unitDef->transportCapacity){
    +		return ExecuteLoadUnits(c);
    +	case CMD_UNLOAD_UNITS:
    +		return ExecuteUnloadUnits(c);
    +	case CMD_UNLOAD_UNIT:
    +		return ExecuteUnloadUnit(c);
    +	default:
    +		return CMobileCAI::SlowUpdate();
    +	}
    +}
    +
    +void CTransportCAI::ExecuteLoadUnits(Command &c){
    +	CTransportUnit* transport=(CTransportUnit*)owner;
    +	if(c.params.size()==1){		//load single unit
    +		if(transport->transportCapacityUsed >= owner->unitDef->transportCapacity){
    +			FinishCommand();
    +			return;
    +		}
    +		if(inCommand){
    +			if(!owner->cob->busy)
     				FinishCommand();
    +			return;
    +		}
    +		CUnit* unit=uh->units[(int)c.params[0]];
    +		if(unit && CanTransport(unit) && UpdateTargetLostTimer(int(c.params[0]))){
    +			toBeTransportedUnitId=unit->id;
    +			unit->toBeTransported=true;
    +			if(unit->mass+transport->transportMassUsed > owner->unitDef->transportMass){
    +				FinishCommand();
     				return;
     			}
    -			if(inCommand){
    -				if(!owner->cob->busy)
    -					FinishCommand();
    -				return;
    +			if(goalPos.distance2D(unit->pos)>10){
    +				float3 fix = unit->pos;
    +				SetGoal(fix,owner->pos,64);
     			}
    -			CUnit* unit=uh->units[(int)c.params[0]];
    -			if(unit && CanTransport(unit) && UpdateTargetLostTimer(int(c.params[0]))){
    -				toBeTransportedUnitId=unit->id;
    -				unit->toBeTransported=true;
    -				if(unit->mass+transport->transportMassUsed > owner->unitDef->transportMass){
    -					FinishCommand();
    -					return;
    -				}
    -				if(goalPos.distance2D(unit->pos)>10){
    -					float3 fix = unit->pos;
    -					SetGoal(fix,owner->pos,64);
    -				}
    -				if(unit->pos.distance2D(owner->pos)<owner->unitDef->loadingRadius*0.9f){
    -					if(CTAAirMoveType* am=dynamic_cast<CTAAirMoveType*>(owner->moveType)){		//handle air transports differently
    -						float3 wantedPos=unit->pos+UpVector*unit->model->height;
    -						SetGoal(wantedPos,owner->pos);
    -						am->dontCheckCol=true;
    -						am->ForceHeading(unit->heading);
    -						am->SetWantedAltitude(unit->model->height);
    -						am->maxDrift=1;
    -						//logOutput.Print("cai dist %f %f %f",owner->pos.distance(wantedPos),owner->pos.distance2D(wantedPos),owner->pos.y-wantedPos.y);
    -						if(owner->pos.distance(wantedPos)<4 && abs(owner->heading-unit->heading)<50 && owner->updir.dot(UpVector)>0.995f){
    -							am->dontCheckCol=false;
    -							am->dontLand=true;
    -							std::vector<int> args;
    -							args.push_back((int)(unit->model->height*65536));
    -							owner->cob->Call("BeginTransport",args);
    -							std::vector<int> args2;
    -							args2.push_back(0);
    -							args2.push_back((int)(unit->model->height*65536));
    -							owner->cob->Call("QueryTransport",args2);
    -							((CTransportUnit*)owner)->AttachUnit(unit,args2[0]);
    -							am->SetWantedAltitude(0);
    -							FinishCommand();
    -							return;
    -						}
    -					} else {
    -						inCommand=true;
    -						scriptReady=false;
    -						StopMove();
    +			if(unit->pos.distance2D(owner->pos)<owner->unitDef->loadingRadius*0.9f){
    +				if(CTAAirMoveType* am=dynamic_cast<CTAAirMoveType*>(owner->moveType)){		//handle air transports differently
    +					float3 wantedPos=unit->pos+UpVector*unit->model->height;
    +					SetGoal(wantedPos,owner->pos);
    +					am->dontCheckCol=true;
    +					am->ForceHeading(unit->heading);
    +					am->SetWantedAltitude(unit->model->height);
    +					am->maxDrift=1;
    +					//logOutput.Print("cai dist %f %f %f",owner->pos.distance(wantedPos),owner->pos.distance2D(wantedPos),owner->pos.y-wantedPos.y);
    +					if(owner->pos.distance(wantedPos)<4 && abs(owner->heading-unit->heading)<50 && owner->updir.dot(UpVector)>0.995f){
    +						am->dontCheckCol=false;
    +						am->dontLand=true;
     						std::vector<int> args;
    -						args.push_back(unit->id);
    -						owner->cob->Call("TransportPickup",args,ScriptCallback,this,0);
    +						args.push_back((int)(unit->model->height*65536));
    +						owner->cob->Call("BeginTransport",args);
    +						std::vector<int> args2;
    +						args2.push_back(0);
    +						args2.push_back((int)(unit->model->height*65536));
    +						owner->cob->Call("QueryTransport",args2);
    +						((CTransportUnit*)owner)->AttachUnit(unit,args2[0]);
    +						am->SetWantedAltitude(0);
    +						FinishCommand();
    +						return;
     					}
    +				} else {
    +					inCommand=true;
    +					scriptReady=false;
    +					StopMove();
    +					std::vector<int> args;
    +					args.push_back(unit->id);
    +					owner->cob->Call("TransportPickup",args,ScriptCallback,this,0);
     				}
    -			} else {
    -				FinishCommand();
     			}
    -		} else if(c.params.size()==4){		//load in radius
    -			if(lastCall==gs->frameNum)	//avoid infinite loops
    -				return;
    -			lastCall=gs->frameNum;
    -			float3 pos(c.params[0],c.params[1],c.params[2]);
    -			float radius=c.params[3];
    -			CUnit* unit=FindUnitToTransport(pos,radius);
    -			if(unit && ((CTransportUnit*)owner)->transportCapacityUsed < owner->unitDef->transportCapacity){
    -				Command c2;
    -				c2.id=CMD_LOAD_UNITS;
    -				c2.params.push_back(unit->id);
    -				c2.options=c.options | INTERNAL_ORDER;
    -				commandQue.push_front(c2);
    -				inCommand=false;
    -				SlowUpdate();
    -				return;
    -			} else {
    -				FinishCommand();
    -				return;
    -			}
    +		} else {
    +			FinishCommand();
     		}
    -		break;
    -	case CMD_UNLOAD_UNITS:{
    +	} else if(c.params.size()==4){		//load in radius
     		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;
    -		bool canUnload=FindEmptySpot(pos,max(16.0f,radius),((CTransportUnit*)owner)->transported.front().unit->radius,found);
    -		if(canUnload){
    +		CUnit* unit=FindUnitToTransport(pos,radius);
    +		if(unit && ((CTransportUnit*)owner)->transportCapacityUsed < owner->unitDef->transportCapacity){
     			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.id=CMD_LOAD_UNITS;
    +			c2.params.push_back(unit->id);
     			c2.options=c.options | INTERNAL_ORDER;
     			commandQue.push_front(c2);
    +			inCommand=false;
     			SlowUpdate();
     			return;
     		} else {
     			FinishCommand();
    +			return;
     		}
    -		break;}
    -	case CMD_UNLOAD_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]);
    -			if(goalPos.distance2D(pos)>20){
    -				SetGoal(pos,owner->pos);
    -			}
    -			if(pos.distance2D(owner->pos)<owner->unitDef->loadingRadius*0.9f){
    -				if(CTAAirMoveType* am=dynamic_cast<CTAAirMoveType*>(owner->moveType)){		//handle air transports differently
    -					pos.y=ground->GetHeight(pos.x,pos.z);
    -					CUnit* unit=((CTransportUnit*)owner)->transported.front().unit;
    -					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){
    -						am->dontLand=false;
    -						owner->cob->Call("EndTransport");
    -						((CTransportUnit*)owner)->DetachUnit(unit);
    -						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(((CTransportUnit*)owner)->transported.front().unit->id);
    -					args.push_back(PACKXZ(pos.x, pos.z));
    -					owner->cob->Call("TransportDrop",args,ScriptCallback,this,0);
    +	}
    +	return;
    +}
    +
    +void CTransportCAI::ExecuteUnloadUnits(Command &c){
    +	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;
    +	bool canUnload=FindEmptySpot(pos,max(16.0f,radius),((CTransportUnit*)owner)->transported.front().unit->radius,found);
    +	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);
    +		SlowUpdate();
    +		return;
    +	} else {
    +		FinishCommand();
    +	}
    +	return;
    +}
    +
    +void CTransportCAI::ExecuteUnloadUnit(Command &c){
    +	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]);
    +		if(goalPos.distance2D(pos)>20){
    +			SetGoal(pos,owner->pos);
    +		}
    +		if(pos.distance2D(owner->pos)<owner->unitDef->loadingRadius*0.9f){
    +			if(CTAAirMoveType* am=dynamic_cast<CTAAirMoveType*>(owner->moveType)){		//handle air transports differently
    +				pos.y=ground->GetHeight(pos.x,pos.z);
    +				CUnit* unit=((CTransportUnit*)owner)->transported.front().unit;
    +				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){
    +					am->dontLand=false;
    +					owner->cob->Call("EndTransport");
    +					((CTransportUnit*)owner)->DetachUnit(unit);
    +					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(((CTransportUnit*)owner)->transported.front().unit->id);
    +				args.push_back(PACKXZ(pos.x, pos.z));
    +				owner->cob->Call("TransportDrop",args,ScriptCallback,this,0);
     			}
     		}
    -		break;
    -	default:
    -		CMobileCAI::SlowUpdate();
    -		break;
     	}
    +	return;
     }
     
     void CTransportCAI::ScriptReady(void)
    Index: rts/Sim/Units/CommandAI/TransportCAI.h
    ===================================================================
    --- rts/Sim/Units/CommandAI/TransportCAI.h	(revision 2593)
    +++ rts/Sim/Units/CommandAI/TransportCAI.h	(working copy)
    @@ -19,6 +19,10 @@
     	void DrawCommands(void);
     	void FinishCommand(void);
     
    +	virtual void ExecuteUnloadUnit(Command &c);
    +	virtual void ExecuteUnloadUnits(Command &c);
    +	virtual void ExecuteLoadUnits(Command &c);
    +
     	int toBeTransportedUnitId;
     	bool scriptReady;
     	int lastCall;
    
    patch file icon CommandAIReformat.patch (91,461 bytes) 2006-11-13 06:45 +

-Relationships
+Relationships

-Notes

~0000450

ILMTitan (reporter)

Ok, I know I posted this here without much fanfare, but #1 at least really needs to be fixed.

~0000452

tvo (reporter)

Ack, I've seen the report, just didn't really have time to take a closer look.

~0000461

tvo (reporter)

committed
+Notes

-Issue History
Date Modified Username Field Change
2006-11-13 06:45 ILMTitan New Issue
2006-11-13 06:45 ILMTitan File Added: CommandAIReformat.patch
2006-12-02 06:27 ILMTitan Note Added: 0000450
2006-12-05 16:50 tvo Note Added: 0000452
2006-12-11 20:21 tvo Status new => resolved
2006-12-11 20:21 tvo Resolution open => fixed
2006-12-11 20:21 tvo Assigned To => tvo
2006-12-11 20:21 tvo Note Added: 0000461
+Issue History