2019-12-13 22:15 CET

View Issue Details Jump to Notes ]
IDProjectCategoryView StatusLast Update
0000291Spring engineGeneralpublic2006-10-01 16:05
ReporterILMTitan 
Assigned Totvo 
PrioritynormalSeverityfeatureReproducibilityalways
StatusresolvedResolutionfixed 
Product Version 
Target VersionFixed in Version 
Summary0000291: [Patch] Better behavior of Fight and Patrol
DescriptionCurrently, units on a fight/patrol command that attack a unit (or reclaim or repair) will return to the spot they left the fight command from before continuing. This patch changes it so that they return to closest point on their old path.
TagsNo tags attached.
Checked infolog.txt for Errors
Attached Files
  • patch file icon FightReturnChanges.patch (9,726 bytes) 2006-09-10 10:26 -
    Index: rts/Sim/Units/CommandAI/AirCAI.cpp
    ===================================================================
    --- rts/Sim/Units/CommandAI/AirCAI.cpp	(revision 2131)
    +++ rts/Sim/Units/CommandAI/AirCAI.cpp	(working copy)
    @@ -350,12 +350,21 @@
     			tempOrder=false;
     			inCommand=true;
     		}
    +		if(c.params.size() >= 6){
    +			if(!inCommand){
    +				commandPos1 = float3(c.params[3],c.params[4],c.params[5]);
    +			}
    +		} else {
    +			commandPos1 = curPos;
    +		}
     		goalPos=float3(c.params[0],c.params[1],c.params[2]);
     		if(!inCommand){
     			commandPos2=goalPos;
     			inCommand=true;
     		}
    -		commandPos1=curPos;
    +		if(c.params.size() >= 6){
    +			goalPos = ClosestPointOnLine(commandPos1, commandPos2, curPos);
    +		}
     		if(c.params.size()<3){		//this shouldnt happen but anyway ...
     			info->AddLine("Error: got fight cmd with less than 3 params on %s in aircai",
     				owner->unitDef->humanName.c_str());
    @@ -370,7 +379,8 @@
     				&& (owner->moveState!=1 || LinePointDist(commandPos1,commandPos2,enemy->pos) < 1000))
     			{
     				Command nc,c3;
    -				c3.id = CMD_MOVE; //keep it from being pulled too far off the path
    +				c3 = GetReturnFight(c);
    +				/*c3.id = CMD_MOVE; //keep it from being pulled too far off the path
     				float3 dir = goalPos-curPos;
     				dir.Normalize();
     				dir*=sqrtf(1024+owner->xsize*owner->xsize+owner->ysize*owner->ysize);
    @@ -378,7 +388,7 @@
     				c3.params.push_back(dir.x);
     				c3.params.push_back(dir.y);
     				c3.params.push_back(dir.z);
    -				c3.options = c.options|INTERNAL_ORDER;
    +				c3.options = c.options|INTERNAL_ORDER;*/
     				nc.id=CMD_ATTACK;
     				nc.params.push_back(enemy->id);
     				nc.options=c.options|INTERNAL_ORDER;
    Index: rts/Sim/Units/CommandAI/BuilderCAI.cpp
    ===================================================================
    --- rts/Sim/Units/CommandAI/BuilderCAI.cpp	(revision 2131)
    +++ rts/Sim/Units/CommandAI/BuilderCAI.cpp	(working copy)
    @@ -496,6 +496,9 @@
     			inCommand = true;
     			commandPos2=patrolGoal;
     		}
    +		if(c.params.size() >= 6){
    +			patrolGoal = ClosestPointOnLine(commandPos1, commandPos2, curPos);
    +		}
     		if(!(patrolGoal==goalPos)){
     			SetGoal(patrolGoal,curPos);
     		}
    @@ -608,7 +611,12 @@
     			}
     			case CMD_FIGHT:
     			case CMD_PATROL: {
    -				pos = float3(ci->params[0], ci->params[1], ci->params[2]);
    +				if(ci->params.size() >= 6){
    +					pos=ClosestPointOnLine(float3(ci->params[0],ci->params[1],ci->params[2]),
    +						float3(ci->params[3],ci->params[4],ci->params[5]), this->owner->pos);
    +				} else {
    +					pos = float3(ci->params[0],ci->params[1],ci->params[2]);
    +				}
     				glColor4f(0.5f, 0.5f, 1.0f, 0.4f);
     				draw = true;
     				break;
    @@ -844,8 +852,16 @@
     	std::vector<CFeature*> features=qf->GetFeaturesExact(pos,radius);
     	for(std::vector<CFeature*>::iterator fi=features.begin();fi!=features.end();++fi){
     		if((*fi)->def->destructable && (*fi)->allyteam!=owner->allyteam){
    -			float dist=(*fi)->pos.distance2D(owner->pos);
    -			if(dist<bestDist && (recAny
    +			float dist;
    +			float testDist;
    +			if(recAny){
    +				dist=(*fi)->pos.distance2D(owner->pos);
    +				testDist = dist;
    +			} else {
    +				dist=LinePointDist(commandPos1, commandPos2, (*fi)->pos);
    +				testDist = (*fi)->pos.distance2D(owner->pos);
    +			}
    +			if(testDist<bestDist && dist < 10000000 && (recAny
     			  ||((*fi)->def->energy > 0 && gs->Team(owner->team)->energy < gs->Team(owner->team)->energyStorage)
     			  ||((*fi)->def->metal > 0 && gs->Team(owner->team)->metal < gs->Team(owner->team)->metalStorage))){
     				bestDist=dist;
    Index: rts/Sim/Units/CommandAI/CommandAI.cpp
    ===================================================================
    --- rts/Sim/Units/CommandAI/CommandAI.cpp	(revision 2131)
    +++ rts/Sim/Units/CommandAI/CommandAI.cpp	(working copy)
    @@ -701,3 +701,37 @@
     		}
     	}
     }
    +
    +/**
    +* @brief gets the command that keeps the unit close to the path
    +* @return a Fight Command with 6 arguments, the first three being where to return to (the current position of the
    +*	unit), and the second being the location of the origional command.
    +* @param c the command to return to
    +**/
    +Command CCommandAI::GetReturnFight(Command c){
    +	Command c3;
    +	c3.id = CMD_FIGHT; //keep it from being pulled too far off the path
    +	float3 pos = float3(c.params[0],c.params[1],c.params[2]);
    +	const float3 &curPos = this->owner->pos;
    +	float3 dir = pos-curPos;
    +	dir.Normalize();
    +	dir*=sqrtf(abs(1024+owner->xsize*owner->xsize+owner->ysize*owner->ysize));
    +	dir+=curPos;
    +	if(c.params.size() >= 6){
    +		c3.params.push_back(c.params[0]);
    +		c3.params.push_back(c.params[1]);
    +		c3.params.push_back(c.params[2]);
    +		c3.params.push_back(c.params[3]);
    +		c3.params.push_back(c.params[4]);
    +		c3.params.push_back(c.params[5]);
    +	} else {
    +		c3.params.push_back(dir.x);
    +		c3.params.push_back(dir.y);
    +		c3.params.push_back(dir.z);
    +		c3.params.push_back(c.params[0]);
    +		c3.params.push_back(c.params[1]);
    +		c3.params.push_back(c.params[2]);
    +	}
    +	c3.options = c.options|INTERNAL_ORDER;
    +	return c3;
    +}
    Index: rts/Sim/Units/CommandAI/CommandAI.h
    ===================================================================
    --- rts/Sim/Units/CommandAI/CommandAI.h	(revision 2131)
    +++ rts/Sim/Units/CommandAI/CommandAI.h	(working copy)
    @@ -32,6 +32,7 @@
     	virtual bool WillCancelQueued(Command &c);
     	std::deque<Command>::iterator GetCancelQueued(Command &c);
     	std::vector<Command> GetOverlapQueued(Command &c);
    +	Command GetReturnFight(Command c);
     
     	void AddStockpileWeapon(CWeapon* weapon);
     	void StockpileChanged(CWeapon* weapon);
    Index: rts/Sim/Units/CommandAI/MobileCAI.cpp
    ===================================================================
    --- rts/Sim/Units/CommandAI/MobileCAI.cpp	(revision 2131)
    +++ rts/Sim/Units/CommandAI/MobileCAI.cpp	(working copy)
    @@ -266,10 +266,12 @@
     			inCommand = true;
     			commandPos2 = pos;
     		}
    +		if(c.params.size() >= 6){
    +			pos = ClosestPointOnLine(commandPos1, commandPos2, curPos);
    +		}
     		if(pos!=goalPos){
    -			SetGoal(pos,curPos);
    +				SetGoal(pos,curPos);
     		}
    -
     		if(owner->fireState==2){
     			CUnit* enemy=helper->GetClosestEnemyUnit(
     				curPos, owner->maxRange+100*owner->moveState*owner->moveState, owner->allyteam);
    @@ -446,7 +448,12 @@
     			break;
     		case CMD_PATROL:
     		case CMD_FIGHT:
    -			pos=float3(ci->params[0],ci->params[1],ci->params[2]);
    +			if(ci->params.size() >= 6){
    +				pos=ClosestPointOnLine(float3(ci->params[0],ci->params[1],ci->params[2]),
    +					float3(ci->params[3],ci->params[4],ci->params[5]), this->owner->pos);
    +			} else {
    +				pos = float3(ci->params[0],ci->params[1],ci->params[2]);
    +			}
     			glColor4f(0.5,0.5,1,0.4);
     			draw=true;
     			break;
    @@ -562,34 +569,3 @@
     		NonMoving();
     	}
     }
    -
    -/**
    -* @brief gets the command that keeps the unit close to the path
    -* @return a Fight Command with 6 arguments, the first three being where to return to (the current position of the
    -*	unit), and the second being the location of the origional command.
    -* @param c the command to return to
    -**/
    -Command CMobileCAI::GetReturnFight(Command c){
    -	Command c3;
    -	c3.id = CMD_FIGHT; //keep it from being pulled too far off the path
    -	float3 pos = float3(c.params[0],c.params[1],c.params[2]);
    -	const float3 &curPos = this->owner->pos;
    -	float3 dir = pos-curPos;
    -	dir.Normalize();
    -	dir*=sqrtf(abs(1024+owner->xsize*owner->xsize+owner->ysize*owner->ysize));
    -	dir+=curPos;
    -	c3.params.push_back(dir.x);
    -	c3.params.push_back(dir.y);
    -	c3.params.push_back(dir.z);
    -	if(c.params.size() >= 6){
    -		c3.params.push_back(c.params[3]);
    -		c3.params.push_back(c.params[4]);
    -		c3.params.push_back(c.params[5]);
    -	} else {
    -		c3.params.push_back(c.params[0]);
    -		c3.params.push_back(c.params[1]);
    -		c3.params.push_back(c.params[2]);
    -	}
    -	c3.options = c.options|INTERNAL_ORDER;
    -	return c3;
    -}
    Index: rts/Sim/Units/CommandAI/MobileCAI.h
    ===================================================================
    --- rts/Sim/Units/CommandAI/MobileCAI.h	(revision 2131)
    +++ rts/Sim/Units/CommandAI/MobileCAI.h	(working copy)
    @@ -20,7 +20,6 @@
     	void NonMoving(void);
     	void FinishCommand(void);
     	void IdleCheck(void);
    -	Command GetReturnFight(Command c);
     
     	float3 goalPos;
     	float3 patrolGoal;
    Index: rts/System/myMath.cpp
    ===================================================================
    --- rts/System/myMath.cpp	(revision 2131)
    +++ rts/System/myMath.cpp	(working copy)
    @@ -72,5 +72,48 @@
     	return p2.distance(l1);
     }
     
    +/**
    + * @breif returns the point in the line segment with start
    + * point l1 and stop point l2 closest to p
    + */
    +float3 ClosestPointOnLine(float3 l1, float3 l2i, float3 p){
    +	// set l1 as origin
    +	float3 l2(l2i-l1);
    +	p = p-l1;
    +	
    +	//fist rotation to remove y
    +	float alpha1 = -atan2(l2.y, l2.x);
    +	l2.x = l2.x*cos(alpha1) - l2.y*sin(alpha1);
    +	//l2.y = 0; not needed
    +	float tempx = p.x;
    +	p.x = tempx*cos(alpha1) - p.y*sin(alpha1);
    +	//p.y = tempx*sin(alpha1) + p.y*cos(alpha1); not needed
    +
    +	//second rotation to remove z
    +	float alpha2 = -atan2(l2.z, l2.x);
    +	l2.x = l2.x*cos(alpha2) - l2.z*sin(alpha2);
    +	//l2.z = 0; not needed
    +	p.x = p.x*cos(alpha2) - p.z*sin(alpha2);
    +
    +	//if p is beyond l1
    +	if(p.x < 0){
    +		return l1;
    +	//if p is beyond l2
    +	} else if(p.x > l2.x){
    +		return l2i;
    +	} else {
    +
    +		float3 temp(p.x, 0, 0);
    +		tempx = temp.x;
    +		temp.x = tempx*cos(-alpha2);
    +		temp.z = tempx*sin(-alpha2);
    +
    +		tempx = temp.x;
    +		temp.x = tempx*cos(-alpha1);
    +		temp.y = tempx*sin(-alpha1);
    +		return temp+l1;
    +	}
    +}
    +
     CMyMath dummyMathObject;
     
    Index: rts/System/myMath.h
    ===================================================================
    --- rts/System/myMath.h	(revision 2131)
    +++ rts/System/myMath.h	(working copy)
    @@ -123,4 +123,6 @@
     
     float LinePointDist(float3 l1,float3 l2,float3 p);
     
    +float3 ClosestPointOnLine(float3 l1, float3 l2, float3 p);
    +
     #endif /* MYMATH_H */
    
    patch file icon FightReturnChanges.patch (9,726 bytes) 2006-09-10 10:26 +

-Relationships
+Relationships

-Notes

~0000381

jcnossen (reporter)

I think the closest point on line can be done better without trig (faster and clearer IMO):

float3 ClosestPointOnLine(const float3& l1, const float3& l2, const float3& p)
{
    float3 dir(l2-l1);
    float length=dir.Length();
    if(length==0)
        length=0.1f;
    dir/=length;

    float a=(p-l1).dot(dir);
    if(a<0)
        a=0;
    if(a>length)
        a=length;

    return l1+dir*a;
}

Otherwise, it looks ok, but we're waiting with committing until after the 0.73b1 release.

~0000406

tvo (reporter)

not committed, but implemented it myself from scratch while cleaning up a certain mess in the CommandAI code.
+Notes

-Issue History
Date Modified Username Field Change
2006-09-10 10:26 ILMTitan New Issue
2006-09-10 10:26 ILMTitan File Added: FightReturnChanges.patch
2006-09-19 22:51 jcnossen Note Added: 0000381
2006-10-01 16:04 tvo Status new => assigned
2006-10-01 16:04 tvo Assigned To => tvo
2006-10-01 16:05 tvo Status assigned => resolved
2006-10-01 16:05 tvo Resolution open => fixed
2006-10-01 16:05 tvo Note Added: 0000406
+Issue History