📄 groupai.cpp
字号:
for(map<int,QuedBuilding*>::iterator qbi=quedBuildngs.begin();qbi!=quedBuildngs.end();++qbi){
std::set<int>* uot=&qbi->second->unitsOnThis;
for(std::set<int>::iterator ui=uot->begin();ui!=uot->end();++ui){
aicb->CreateLineFigure(qbi->second->pos+float3(0,10,0),aicb->GetUnitPos(*ui)+float3(0,10,0),3,1,4,0);
}
}/**/
}
}
void CGroupAI::UpdateAvailableCommands(void)
{
commands.clear();
CommandDescription cd;
cd.id=CMD_STOP;
cd.name="Stop";
cd.action="stop";
cd.hotkey="s";
commands.push_back(cd); //should always have a stop command since it is the default
set<int> alreadyFound;
for(map<int,UnitInfo*>::iterator ui=myUnits.begin();ui!=myUnits.end();++ui){
for(vector<int>::iterator oi=ui->second->orderedBuildOrders.begin();oi!=ui->second->orderedBuildOrders.end();++oi){
if(alreadyFound.find(*oi)==alreadyFound.end()){ //skip if this command has already been added
CommandDescription cd;
cd.id=*oi;
cd.name=buildOptions[*oi]->name;
cd.type=buildOptions[*oi]->type;
cd.action = "buildunit_" + cd.name;
if(cd.type==CMDTYPE_ICON){
UpdateFactoryIcon(&cd,buildOptions[*oi]->numQued);
}
commands.push_back(cd);
alreadyFound.insert(*oi);
}
}
}
callback->UpdateIcons();
}
void CGroupAI::UpdateFactoryIcon(CommandDescription* cd, int numQued)
{
cd->params.clear();
if(numQued){
char t[32];
SNPRINTF(t,10,"%d",numQued);
cd->params.push_back(t);
}
}
void CGroupAI::FindNewJob(int unit)
{
UnitInfo* info=myUnits[unit];
bool isFactory=info->moveSpeed==0;
const CCommandQueue* curCommands=aicb->GetCurrentUnitCommands(unit);
if(!isFactory && info->lastGivenOrder && !curCommands->empty()){
if(info->lastGivenOrder>0 && curCommands->front().id!=CMD_GUARD){
QuedBuilding* qb=quedBuildngs[info->lastGivenOrder];
int foundUnits[1000];
int num=aicb->GetFriendlyUnits(foundUnits,qb->pos,10);
for(int a=0;a<num;++a){
const UnitDef* ud=aicb->GetUnitDef(foundUnits[a]);
if(ud->id==-qb->type){ //ok found the right unit
float health=aicb->GetUnitHealth(foundUnits[a]);
float maxHealth=aicb->GetUnitMaxHealth(foundUnits[a]);
qb->buildTimeLeft=buildOptions[qb->type]->buildTime*((maxHealth-health)/maxHealth); //we have no direct access to the current build status of a unit so we assumes that the health is a good indicator
break;
}
}
qb->buildTimeLeft=buildOptions[qb->type]->buildTime; //didnt find a unit so assume we havent started building
return;
}
if(info->lastGivenOrder<0)
return;
}
if(isFactory && curCommands->size()){
return;
}
if(info->lastGivenOrder){
// SendTxt("Free unit with order %i %i",unit,info->lastGivenOrder);
if(info->lastGivenOrder>0){
FinishBuilderTask(unit,true);
} else {
SendTxt("Free unit with guard order? %i %i",unit,info->lastGivenOrder);
if(myUnits.find(-info->lastGivenOrder)!=myUnits.end()){
myUnits[-info->lastGivenOrder]->unitsGuardingMe.erase(unit);
}
info->lastGivenOrder=0;
}
}
float bestValue=0;
int bestJob=0;
if(!isFactory){ //mobile builder
float3 myPos=aicb->GetUnitPos(unit);
for(map<int,QuedBuilding*>::iterator qbi=quedBuildngs.begin();qbi!=quedBuildngs.end();++qbi){ //check for building to build
QuedBuilding* qb=qbi->second;
bool canBuildThis=info->possibleBuildOrders.find(qb->type)!=info->possibleBuildOrders.end();
if(canBuildThis || !qb->unitsOnThis.empty()){ //can we build this directly or is there someone who can start if for us
float buildTime=qb->buildTimeLeft/(qb->totalBuildSpeed+info->buildSpeed);
float moveTime=max(0.01f,((qb->pos-myPos).Length()-150)/info->moveSpeed*10);
float travelMod=buildTime/(buildTime+moveTime); //units prefer stuff with low travel time compared to build time
float finishMod=buildOptions[qb->type]->buildTime/(qb->buildTimeLeft+buildOptions[qb->type]->buildTime*0.1f); //units prefer stuff that is nearly finished
float canBuildThisMod=canBuildThis?1.5f:1; //units prefer to do stuff they have in their build options (less risk of guarded unit dying etc)
float ageMod=20+sqrtf((float)(frameNum+1)-qb->startFrame);
// float buildSpeedMod=info->buildSpeed/(qb->totalBuildSpeed+info->buildSpeed);
float value=finishMod*canBuildThisMod*travelMod*ageMod;
/* char c[6000];
sprintf(c,"value %f %f",moveTime,buildTime);
aicb->SendTextMsg(c,0);
*/ if(value>bestValue){
bestValue=value;
if(!qb->unitsOnThis.empty())
bestJob=-*qb->unitsOnThis.begin(); //negative number=pick a unit to guard
else
bestJob=qbi->first; //positive number=do this build project
}
}
}
for(map<int,UnitInfo*>::iterator ui=myUnits.begin();ui!=myUnits.end();++ui){ //find factories to guard
if(ui->second->moveSpeed==0 && !aicb->GetCurrentUnitCommands(ui->first)->empty()){
float moveTime=max(1.0f,((aicb->GetUnitPos(ui->first)-myPos).Length()-150)/info->moveSpeed*2);
float value=3.0f*(ui->second->buildSpeed/(ui->second->totalGuardSpeed+ui->second->buildSpeed))/moveTime;
if(value>bestValue && ui->second->unitsGuardingMe.size()<5){
bestValue=value;
bestJob=-ui->first;
}
}
}
if(bestJob){ //we have found something to do
// SendTxt("Best job found %i %i %.2f",unit,bestJob,bestValue);
info->lastGivenOrder=bestJob;
Command c;
if(bestJob>0){ //build building
QuedBuilding* qb=quedBuildngs[bestJob];
c.id=qb->type;
c.params.push_back(qb->pos.x);
c.params.push_back(qb->pos.y);
c.params.push_back(qb->pos.z);
qb->totalBuildSpeed+=info->buildSpeed;
qb->unitsOnThis.insert(unit);
} else { //guard unit
c.id=CMD_GUARD;
c.params.push_back((float)-bestJob);
UnitInfo* guardInfo=myUnits[-bestJob];
guardInfo->unitsGuardingMe.insert(unit);
guardInfo->totalGuardSpeed+=info->buildSpeed;
if(guardInfo->moveSpeed!=0){
QuedBuilding* qb=quedBuildngs[guardInfo->lastGivenOrder];
qb->totalBuildSpeed+=info->buildSpeed;
}
}
aicb->GiveOrder(unit,&c);
}
} else { //factory
CommandDescription* bestCommandDescription;
for(std::vector<CommandDescription>::iterator cdi=commands.begin();cdi!=commands.end();++cdi){
if(cdi->type==CMDTYPE_ICON && info->possibleBuildOrders.find(cdi->id)!=info->possibleBuildOrders.end()){ //we can build this stuff
float value=(float)rand()*buildOptions[cdi->id]->numQued; //the probability to pick a certain unit to build is linear to the number of qued, maybe use some better choose method ?
if(value>bestValue){
bestValue=value;
bestCommandDescription=&*cdi;
bestJob=cdi->id;
}
}
}
if(bestJob){
Command c;
c.id=bestJob;
c.options=0;
aicb->GiveOrder(unit,&c);
// info->lastGivenOrder=bestJob;
UpdateFactoryIcon(bestCommandDescription,--buildOptions[bestJob]->numQued);
callback->UpdateIcons();
}
}
}
void CGroupAI::SendTxt(const char *fmt, ...)
{
char text[500];
va_list ap; // Pointer To List Of Arguments
if (fmt == NULL) // If There's No Text
return; // Do Nothing
va_start(ap, fmt); // Parses The String For Variables
vsprintf(text, fmt, ap); // And Converts Symbols To Actual Numbers
va_end(ap); // Results Are Stored In Text
aicb->SendTextMsg(text,0);
}
int CGroupAI::FindCloseQuedBuilding(float3 pos, float radius)
{
for(map<int,QuedBuilding*>::iterator qbi=quedBuildngs.begin();qbi!=quedBuildngs.end();++qbi){
if(qbi->second->pos.distance2D(pos)<radius)
return qbi->first;
}
return -1;
}
void CGroupAI::FinishBuilderTask(int unit,bool failure)
{
UnitInfo* info=myUnits[unit];
if(quedBuildngs.find(info->lastGivenOrder)!=quedBuildngs.end()){
QuedBuilding* qb=quedBuildngs[info->lastGivenOrder];
qb->unitsOnThis.erase(unit);
qb->totalBuildSpeed-=info->buildSpeed+info->totalGuardSpeed;
if(failure){
qb->failedTries++;
qb->startFrame=frameNum;
if(qb->failedTries>1){
aicb->SendTextMsg("Building failed",0);
delete qb;
quedBuildngs.erase(info->lastGivenOrder);
}
}
}
for(std::set<int>::iterator gi=info->unitsGuardingMe.begin();gi!=info->unitsGuardingMe.end();++gi){
UnitInfo* guardInfo=myUnits[*gi];
guardInfo->lastGivenOrder=0;
}
info->unitsGuardingMe.clear();
info->totalGuardSpeed=0;
info->lastGivenOrder=0;
Command c;
c.id=CMD_STOP;
aicb->GiveOrder(unit,&c);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -