cancelCommandChanges.patch (18,365 bytes)
2006-06-12 18:41
Index: rts/Game/UI/GuiHandler.cpp
===================================================================
--- rts/Game/UI/GuiHandler.cpp (revision 1459)
+++ rts/Game/UI/GuiHandler.cpp (working copy)
@@ -32,6 +32,7 @@
#include "SDL_keysym.h"
#include "SDL_mouse.h"
#include "mmgr.h"
+#include "Sim/Units/CommandAI/CommandAI.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
@@ -717,7 +718,24 @@
for(std::vector<float3>::iterator bpi=buildPos.begin();bpi!=buildPos.end();++bpi){
float3 pos=*bpi;
- if(uh->ShowUnitBuildSquare(pos,unitdef))
+ std::vector<Command> cv;
+ if(keys[SDLK_LSHIFT]){
+ Command c;
+ c.id = -unitdef->id;
+ c.params.push_back(pos.x);
+ c.params.push_back(pos.y);
+ c.params.push_back(pos.z);
+ std::vector<Command> temp;
+ std::set<CUnit*>::iterator ui = selectedUnits.selectedUnits.begin();
+ for(; ui != selectedUnits.selectedUnits.end(); ui++){
+ temp = (*ui)->commandAI->GetOverlapQueued(c);
+ std::vector<Command>::iterator ti = temp.begin();
+ for(; ti != temp.end(); ti++){
+ cv.insert(cv.end(),*ti);
+ }
+ }
+ }
+ if(uh->ShowUnitBuildSquare(pos,unitdef,cv))
glColor4f(0.7,1,1,0.4);
else
glColor4f(1,0.5,0.5,0.4);
@@ -1300,13 +1318,32 @@
start=helper->Pos2BuildPos(start,unitdef);
end=helper->Pos2BuildPos(end,unitdef);
-
- CUnit* unit=0;
- float dist2=helper->GuiTraceRay(camera->pos,mouse->dir,gu->viewRange*1.4,unit,20,true);
+ float3 buildPos;
+ UnitDef* unitdef2=0;
+ if(keys[SDLK_LSHIFT] && keys[SDLK_LCTRL]){
+ CUnit* unit=0;
+ float dist2=helper->GuiTraceRay(camera->pos,mouse->dir,gu->viewRange*1.4,unit,20,true);
+ if(unit){
+ unitdef2=unit->unitDef;
+ buildPos = unit->pos;
+ } else {
+ Command c = uh->GetBuildCommand(camera->pos,mouse->dir);
+ if(c.id < 0){
+ unitdef2=unitDefHandler->GetUnitByID(-c.id);
+ buildPos.x = c.params[0];
+ buildPos.y = c.params[1];
+ buildPos.z = c.params[2];
+ }
+ }
+ }
+ if(unitdef2 && keys[SDLK_LSHIFT] && keys[SDLK_LCTRL]){ //circle build around building
+ Command c;
+ c.id = -unitdef->id;
+ c.params.push_back(0);
+ c.params.push_back(0);
+ c.params.push_back(0);
- if(unit && keys[SDLK_LSHIFT] && keys[SDLK_LCTRL]){ //circle build around building
- UnitDef* unitdef2=unit->unitDef;
- float3 pos2=unit->pos;
+ float3 pos2 = buildPos;
pos2=helper->Pos2BuildPos(pos2,unitdef2);
start=pos2;
end=pos2;
@@ -1321,7 +1358,19 @@
p2.x+=(unitdef->xsize/2)*SQUARE_SIZE;
p2.z-=(unitdef->ysize/2)*SQUARE_SIZE;
p2=helper->Pos2BuildPos(p2,unitdef);
- ret.push_back(p2);
+ c.params[0] = p2.x;
+ c.params[1] = p2.y;
+ c.params[2] = p2.z;
+ bool cancel = false;
+ std::set<CUnit*>::iterator ui = selectedUnits.selectedUnits.begin();
+ for(;ui != selectedUnits.selectedUnits.end() && !cancel; ++ui){
+ if((*ui)->commandAI->WillCancelQueued(c)){
+ cancel = true;
+ }
+ }
+ if(!cancel){
+ ret.push_back(p2);
+ }
}
pos=start;
pos.x=end.x;
@@ -1330,7 +1379,19 @@
p2.x+=(unitdef->xsize/2)*SQUARE_SIZE;
p2.z+=(unitdef->ysize/2)*SQUARE_SIZE;
p2=helper->Pos2BuildPos(p2,unitdef);
- ret.push_back(p2);
+ c.params[0] = p2.x;
+ c.params[1] = p2.y;
+ c.params[2] = p2.z;
+ bool cancel = false;
+ std::set<CUnit*>::iterator ui = selectedUnits.selectedUnits.begin();
+ for(;ui != selectedUnits.selectedUnits.end() && !cancel; ++ui){
+ if((*ui)->commandAI->WillCancelQueued(c)){
+ cancel = true;
+ }
+ }
+ if(!cancel){
+ ret.push_back(p2);
+ }
}
pos=end;
for(;pos.x>=start.x;pos.x-=unitdef->xsize*SQUARE_SIZE){
@@ -1338,7 +1399,19 @@
p2.x-=(unitdef->xsize/2)*SQUARE_SIZE;
p2.z+=(unitdef->ysize/2)*SQUARE_SIZE;
p2=helper->Pos2BuildPos(p2,unitdef);
- ret.push_back(p2);
+ c.params[0] = p2.x;
+ c.params[1] = p2.y;
+ c.params[2] = p2.z;
+ bool cancel = false;
+ std::set<CUnit*>::iterator ui = selectedUnits.selectedUnits.begin();
+ for(;ui != selectedUnits.selectedUnits.end() && !cancel; ++ui){
+ if((*ui)->commandAI->WillCancelQueued(c)){
+ cancel = true;
+ }
+ }
+ if(!cancel){
+ ret.push_back(p2);
+ }
}
pos=end;
pos.x=start.x;
@@ -1347,7 +1420,19 @@
p2.x-=(unitdef->xsize/2)*SQUARE_SIZE;
p2.z-=(unitdef->ysize/2)*SQUARE_SIZE;
p2=helper->Pos2BuildPos(p2,unitdef);
- ret.push_back(p2);
+ c.params[0] = p2.x;
+ c.params[1] = p2.y;
+ c.params[2] = p2.z;
+ bool cancel = false;
+ std::set<CUnit*>::iterator ui = selectedUnits.selectedUnits.begin();
+ for(;ui != selectedUnits.selectedUnits.end() && !cancel; ++ui){
+ if((*ui)->commandAI->WillCancelQueued(c)){
+ cancel = true;
+ }
+ }
+ if(!cancel){
+ ret.push_back(p2);
+ }
}
} else if(keys[SDLK_LALT]){ //build a rectangle
float xsize=unitdef->xsize*8+buildSpacing*16;
Index: rts/Sim/Units/CommandAI/BuilderCAI.cpp
===================================================================
--- rts/Sim/Units/CommandAI/BuilderCAI.cpp (revision 1459)
+++ rts/Sim/Units/CommandAI/BuilderCAI.cpp (working copy)
@@ -447,7 +447,7 @@
Command& c=commandQue[activeCommand];
if(c.params.size()<3){ //this shouldnt happen but anyway ...
- info->AddLine("Error: got patrol cmd with less than 3 params on %s",owner->unitDef->humanName.c_str());
+ info->AddLine("Error: got patrol cmd with less than 3 params on %s in BuilderCAI",owner->unitDef->humanName.c_str());
return;
}
patrolGoal=float3(c.params[0],c.params[1],c.params[2]);
Index: rts/Sim/Units/CommandAI/CommandAI.cpp
===================================================================
--- rts/Sim/Units/CommandAI/CommandAI.cpp (revision 1459)
+++ rts/Sim/Units/CommandAI/CommandAI.cpp (working copy)
@@ -2,6 +2,7 @@
#include "CommandAI.h"
#include "Sim/Units/UnitHandler.h"
#include "Sim/Units/Unit.h"
+#include "Sim/Units/UnitDefHandler.h"
#include "Sim/Weapons/Weapon.h"
#include "ExternalAI/Group.h"
#include "Rendering/GL/myGL.h"
@@ -320,33 +321,131 @@
orderTarget=0;
}
}
+ std::deque<Command>::iterator ci = CCommandAI::GetCancelQueued(c);
+ if(c.id<0 && ci != this->commandQue.end()){
+ do{
+ if(ci == this->commandQue.begin()){
+ this->commandQue.erase(ci);
+ Command c2;
+ c2.id = CMD_STOP;
+ this->commandQue.push_front(c2);
+ this->SlowUpdate();
+ } else {
+ this->commandQue.erase(ci);
+ }
+ ci = CCommandAI::GetCancelQueued(c);
+ }while(ci != this->commandQue.end());
+ return;
+ } else if(ci != this->commandQue.end()){
+ if(ci == this->commandQue.begin()){
+ this->commandQue.erase(ci);
+ Command c2;
+ c2.id = CMD_STOP;
+ this->commandQue.push_front(c2);
+ this->SlowUpdate();
+ } else {
+ this->commandQue.erase(ci);
+ }
+ ci = CCommandAI::GetCancelQueued(c);
+ return;
+ }
+ if(!this->GetOverlapQueued(c).empty()){
+ return;
+ }
+ if(c.id==CMD_ATTACK && owner->weapons.empty() && owner->unitDef->canKamikaze==false) //avoid weaponless units moving to 0 distance when given attack order
+ c.id=CMD_STOP;
+
+ commandQue.push_back(c);
+ if(commandQue.size()==1 && !owner->beingBuilt)
+ SlowUpdate();
+}
+
+/**
+* @brief Determins if c will cancel a queued command
+* @return true if c will cancel a queued command
+**/
+bool CCommandAI::WillCancelQueued(Command &c)
+{
+ return this->GetCancelQueued(c) != this->commandQue.end();
+}
+
+/**
+* @brief Finds the queued command that would be canceled by the Command c
+* @return An iterator located at the command, or commandQue.end() if no such queued command exsists
+**/
+std::deque<Command>::iterator CCommandAI::GetCancelQueued(Command &c){
if(!commandQue.empty()){
std::deque<Command>::iterator ci=commandQue.end();
- for(--ci;ci!=commandQue.begin();--ci){ //iterate from the end and dont check the current order
+ do{
+ --ci; //iterate from the end and dont check the current order
if((ci->id==c.id || (c.id<0 && ci->id<0)) && ci->params.size()==c.params.size()){
if(c.params.size()==1){ //we assume the param is a unit of feature id
if(ci->params[0]==c.params[0]){
- commandQue.erase(ci);
- return;
+ return ci;
}
} else if(c.params.size()>=3){ //we assume this means that the first 3 makes a position
float3 cpos(c.params[0],c.params[1],c.params[2]);
float3 cipos(ci->params[0],ci->params[1],ci->params[2]);
+ if(c.id < 0){
+ UnitDef* u1 = unitDefHandler->GetUnitByID(-c.id);
+ UnitDef* u2 = unitDefHandler->GetUnitByID(-ci->id);
+ if(u1 && u2
+ && abs(cpos.x-cipos.x)*2 <= max(u1->xsize, u2->xsize)*SQUARE_SIZE
+ && abs(cpos.z-cipos.z)*2 <= max(u1->ysize, u2->ysize)*SQUARE_SIZE)
+ {
+ return ci;
+ }
+ } else {
+ if((cpos-cipos).SqLength2D()<17*17){
+ return ci;
+ }
+ }
+ }
+ }
+ }while(ci!=commandQue.begin());
+ }
+ return commandQue.end();
+}
- if((cpos-cipos).SqLength2D()<17*17){
- commandQue.erase(ci);
- return;
+/**
+* @brief Returns commands that overlap c, but will not be canceled by c
+* @return a vector containing commands that overlap c
+*/
+std::vector<Command> CCommandAI::GetOverlapQueued(Command &c){
+ std::deque<Command>::iterator ci = commandQue.end();
+ std::vector<Command> v;
+ if(ci != commandQue.begin()){
+ do{
+ --ci; //iterate from the end and dont check the current order
+ if((ci->id==c.id || (c.id<0 && ci->id<0)) && ci->params.size()==c.params.size()){
+ if(c.params.size()==1){ //we assume the param is a unit of feature id
+ if(ci->params[0]==c.params[0]){
+ v.push_back(*ci);
}
+ } else if(c.params.size()>=3){ //we assume this means that the first 3 makes a position
+ float3 cpos(c.params[0],c.params[1],c.params[2]);
+ float3 cipos(ci->params[0],ci->params[1],ci->params[2]);
+ if(c.id < 0){
+ UnitDef* u1 = unitDefHandler->GetUnitByID(-c.id);
+ UnitDef* u2 = unitDefHandler->GetUnitByID(-ci->id);
+ if(u1 && u2
+ && (abs(cpos.x-cipos.x)*2 > max(u1->xsize, u2->xsize)*SQUARE_SIZE
+ || abs(cpos.z-cipos.z)*2 > max(u1->ysize, u2->ysize)*SQUARE_SIZE)
+ && abs(cpos.x-cipos.x)*2 < (u1->xsize + u2->xsize)*SQUARE_SIZE
+ && abs(cpos.z-cipos.z)*2 < (u1->ysize + u2->ysize)*SQUARE_SIZE)
+ {
+ v.push_back(*ci);
+ }
+ } else {
+ if((cpos-cipos).SqLength2D()<17*17){
+ v.push_back(*ci);
+ }
+ }
}
}
- }
+ }while(ci!=commandQue.begin());
}
- if(c.id==CMD_ATTACK && owner->weapons.empty() && owner->unitDef->canKamikaze==false) //avoid weaponless units moving to 0 distance when given attack order
- c.id=CMD_STOP;
-
- commandQue.push_back(c);
- if(commandQue.size()==1 && !owner->beingBuilt)
- SlowUpdate();
+ return v;
}
void CCommandAI::SlowUpdate()
Index: rts/Sim/Units/CommandAI/CommandAI.h
===================================================================
--- rts/Sim/Units/CommandAI/CommandAI.h (revision 1459)
+++ rts/Sim/Units/CommandAI/CommandAI.h (working copy)
@@ -29,6 +29,9 @@
virtual void WeaponFired(CWeapon* weapon);
virtual void BuggerOff(float3 pos, float radius);
virtual void LoadSave(CLoadSaveInterface* file, bool loading);
+ virtual bool WillCancelQueued(Command &c);
+ std::deque<Command>::iterator GetCancelQueued(Command &c);
+ std::vector<Command> GetOverlapQueued(Command &c);
void AddStockpileWeapon(CWeapon* weapon);
void StockpileChanged(CWeapon* weapon);
Index: rts/Sim/Units/CommandAI/FactoryCAI.cpp
===================================================================
--- rts/Sim/Units/CommandAI/FactoryCAI.cpp (revision 1459)
+++ rts/Sim/Units/CommandAI/FactoryCAI.cpp (working copy)
@@ -75,9 +75,14 @@
if(!(c.options & SHIFT_KEY)){
newUnitCommands.clear();
}
- if(c.id!=CMD_STOP)
- newUnitCommands.push_back(c);
-
+ if(c.id!=CMD_STOP){
+ std::deque<Command>::iterator ci = GetCancelQueued(c);
+ if(ci == this->newUnitCommands.end()){
+ newUnitCommands.push_back(c);
+ } else {
+ this->newUnitCommands.erase(ci);
+ }
+ }
return;
}
BuildOption &bo=boi->second;
@@ -243,3 +248,31 @@
}
glEnd();
}
+
+/**
+* @brief Finds the queued command that would be canceled by the Command c
+* @return An iterator located at the command, or commandQue.end() if no such queued command exsists
+**/
+std::deque<Command>::iterator CFactoryCAI::GetCancelQueued(Command &c){
+ if(!newUnitCommands.empty()){
+ std::deque<Command>::iterator ci=newUnitCommands.end();
+ do{
+ --ci; //iterate from the end and dont check the current order
+ if((ci->id==c.id || (c.id<0 && ci->id<0)) && ci->params.size()==c.params.size()){
+ if(c.params.size()==1){ //we assume the param is a unit of feature id
+ if(ci->params[0]==c.params[0]){
+ return ci;
+ }
+ } else if(c.params.size()>=3){ //we assume this means that the first 3 makes a position
+ float3 cpos(c.params[0],c.params[1],c.params[2]);
+ float3 cipos(ci->params[0],ci->params[1],ci->params[2]);
+
+ if((cpos-cipos).SqLength2D()<17*17){
+ return ci;
+ }
+ }
+ }
+ }while(ci!=newUnitCommands.begin());
+ }
+ return newUnitCommands.end();
+}
\ No newline at end of file
Index: rts/Sim/Units/CommandAI/FactoryCAI.h
===================================================================
--- rts/Sim/Units/CommandAI/FactoryCAI.h (revision 1459)
+++ rts/Sim/Units/CommandAI/FactoryCAI.h (working copy)
@@ -24,6 +24,7 @@
void GiveCommand(Command& c);
void DrawCommands(void);
void UpdateIconName(int id,BuildOption& bo);
+ std::deque<Command>::iterator GetCancelQueued(Command &c);
std::deque<Command> newUnitCommands;
Index: rts/Sim/Units/UnitHandler.cpp
===================================================================
--- rts/Sim/Units/UnitHandler.cpp (revision 1459)
+++ rts/Sim/Units/UnitHandler.cpp (working copy)
@@ -19,12 +19,15 @@
#include "Game/SelectedUnits.h"
#include "FileSystem/FileHandler.h"
#include "Game/UI/InfoConsole.h"
+#include "Game/SelectedUnits.h"
#include "Sim/Misc/Feature.h"
#include "Sim/Misc/FeatureHandler.h"
+#include "Sim/Units/Unit.h"
#include "LoadSaveInterface.h"
#include "UnitLoader.h"
#include "SyncTracer.h"
#include "Game/GameSetup.h"
+#include "Game/Command.h"
#include "Sim/Misc/AirBaseHandler.h"
#include "mmgr.h"
@@ -333,12 +336,22 @@
return 0;
if(groundheight>-unitdef->minWaterDepth)
return 0;
+ std::set<CUnit*>::iterator ui = selectedUnits.selectedUnits.begin();
+ std::vector<Command> cv;
+ for(;ui != selectedUnits.selectedUnits.end(); ui++){
+
+ }
return ret;
}
int CUnitHandler::ShowUnitBuildSquare(const float3& pos, const UnitDef *unitdef)
{
+ return ShowUnitBuildSquare(pos, unitdef, std::vector<Command>());
+}
+
+int CUnitHandler::ShowUnitBuildSquare(const float3& pos, const UnitDef *unitdef, const std::vector<Command> &cv)
+{
glDisable(GL_DEPTH_TEST );
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
@@ -376,7 +389,22 @@
CFeature* feature=0;
int tbs=TestBuildSquare(float3(x,pos.y,z),unitdef,feature);
if(tbs){
- if(feature || tbs==1)
+ UnitDef* ud;
+ float3 cPos;
+ std::vector<Command>::const_iterator ci = cv.begin();
+ for(;ci != cv.end() && tbs; ci++){
+ ud = unitDefHandler->GetUnitByID(-ci->id);
+ cPos.x = ci->params[0];
+ cPos.z = ci->params[2];
+ if(max(cPos.x-x-SQUARE_SIZE,x-cPos.x)*2 < ud->xsize*SQUARE_SIZE
+ && max(cPos.z-z-SQUARE_SIZE,z-cPos.z)*2 < ud->ysize*SQUARE_SIZE){
+ tbs=0;
+ }
+ }
+ if(!tbs){
+ nobuildpos.push_back(float3(x,h,z));
+ canbuild = 0;
+ } else if(feature || tbs==1)
featurepos.push_back(float3(x,h,z));
else
canbuildpos.push_back(float3(x,h,z));
@@ -495,3 +523,36 @@
}
return true;
}
+
+/**
+* returns a build Command that intersects the ray described by pos and dir from the command queues of the
+* units units on team number team
+* @breif returns a build Command that intersects the ray described by pos and dir
+* @return the build Command, or 0 if one is not found
+*/
+
+Command CUnitHandler::GetBuildCommand(float3 pos, float3 dir){
+ float3 tempF1 = pos;
+ std::list<CUnit*>::iterator ui = this->activeUnits.begin();
+ std::deque<Command>::iterator ci;
+ for(; ui != this->activeUnits.end(); ui++){
+ if((*ui)->team == gu->myTeam){
+ ci = (*ui)->commandAI->commandQue.begin();
+ for(; ci != (*ui)->commandAI->commandQue.end(); ci++){
+ if((*ci).id < 0 && (*ci).params.size() >= 3){
+ tempF1.x = (*ci).params[0];
+ tempF1.y = (*ci).params[1];
+ tempF1.z = (*ci).params[2];
+ tempF1 = pos + dir*((tempF1.y - pos.y)/dir.y) - tempF1;
+ UnitDef* ud = unitDefHandler->GetUnitByID(-(*ci).id);
+ if(ud && ud->xsize/2*SQUARE_SIZE > abs(tempF1.x) && ud->ysize/2*SQUARE_SIZE > abs(tempF1.z)){
+ return (*ci);
+ }
+ }
+ }
+ }
+ }
+ Command c;
+ c.id = 0;
+ return c;
+}
Index: rts/Sim/Units/UnitHandler.h
===================================================================
--- rts/Sim/Units/UnitHandler.h (revision 1459)
+++ rts/Sim/Units/UnitHandler.h (working copy)
@@ -14,6 +14,7 @@
#include <string>
#include "UnitDef.h"
+#include "Game\Command.h"
class CBuilderCAI;
class CFeature;
@@ -51,6 +52,7 @@
int TestUnitBuildSquare(const float3& pos, const UnitDef *unitdef,CFeature *&feature); //test if a unit can be built at specified position
int TestUnitBuildSquare(const float3& pos, std::string unit,CFeature *&feature); //test if a unit can be built at specified position
int ShowUnitBuildSquare(const float3& pos, const UnitDef *unitdef); //test if a unit can be built at specified position and show on the ground where it's to rough
+ int ShowUnitBuildSquare(const float3& pos, const UnitDef *unitdef, const std::vector<Command> &cv);
int TestBuildSquare(const float3& pos, const UnitDef *unitdef,CFeature *&feature); //test a singel mapsquare for build possibility
void AddBuilderCAI(CBuilderCAI*);
@@ -58,6 +60,7 @@
float GetBuildHeight(float3 pos, const UnitDef* unitdef);
void LoadSaveUnits(CLoadSaveInterface* file, bool loading);
+ Command GetBuildCommand(float3 pos, float3 dir);
std::list<CUnit*> activeUnits; //used to get all active units
std::deque<int> freeIDs;