⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 groupai.cpp

📁 这是整套横扫千军3D版游戏的源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		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 + -