mobilecai.cpp

来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 1,090 行 · 第 1/3 页

CPP
1,090
字号
		if (b2) {
			if (!(tempOrder && owner->moveState == 0)
				&& (diffLength2d * 1.4f > owner->maxRange 
					- orderTarget->speed.SqLength()
							/ owner->unitDef->maxAcc)
				&& b4 && diff.dot(orderTarget->speed) < 0)
			{
				SetGoal(owner->pos + (orderTarget->speed * 80), owner->pos,
						SQUARE_SIZE, orderTarget->speed.Length() * 1.1f);
			} else {
				StopMove();
				// FIXME kill magic frame number
				if (gs->frameNum > lastCloseInTry + MAX_CLOSE_IN_RETRY_TICKS) {
					owner->moveType->KeepPointingTo(orderTarget,
							min((float) (owner->losRadius * SQUARE_SIZE * 2),
									owner->maxRange * 0.9f), true);
				}
			}
			owner->AttackUnit(orderTarget, c.id == CMD_DGUN);
		}
		// if ((our movetype has type TAAirMoveType and length of 2D vector from us to target
		// less than 90% of our maximum range) OR squared length of 2D vector from us to target
		// less than 1024) then we are close enough
		else if(diffLength2d < (owner->maxRange * 0.9f)){
			if (dynamic_cast<CTAAirMoveType*>(owner->moveType)
					|| (diff.SqLength2D() < 1024))
			{
				StopMove();
				owner->moveType->KeepPointingTo(orderTarget,
						min((float) (owner->losRadius * SQUARE_SIZE * 2),
								owner->maxRange * 0.9f), true);
			} else if(tempOrder && owner->moveState == 0){
				SetGoal(lastUserGoal, owner->pos);
			}

			// if (((first weapon range minus first weapon length greater than distance to target)
			// and length of 2D vector from us to target less than 90% of our maximum range)
			// then we are close enough, but need to move sideways to get a shot.
			else if (b3 && diffLength2d < (owner->maxRange * 0.9f))
			{
				moveDir ^= (owner->moveType->progressState == CMoveType::Failed);
				float sin = moveDir ? 3.0/5 : -3.0/5;
				float cos = 4.0/5;
				float3 goalDiff(0, 0, 0);
				goalDiff.x = diff.dot(float3(cos, 0, -sin));
				goalDiff.z = diff.dot(float3(sin, 0, cos));
				goalDiff *= (diffLength2d < (owner->maxRange * 0.3f)) ? 1/cos : cos;
				goalDiff += orderTarget->pos;
				SetGoal(goalDiff, owner->pos);
			}
		}

		// if 2D distance of (target position plus attacker error vector times 128)
		// to goal position greater than
		// (10 plus 20% of 2D distance between attacker and target) then we need to close
		// in on target more
		else if ((orderTarget->pos + owner->posErrorVector * 128).distance2D(goalPos)
				> (10 + orderTarget->pos.distance2D(owner->pos) * 0.2f)) {
			float3 fix = orderTarget->pos + owner->posErrorVector * 128;
			float3 norm = float3(fix - owner->pos).Normalize();
			SetGoal(fix - norm*(orderTarget->radius*edgeFactor*0.8f), owner->pos);
			if (lastCloseInTry < gs->frameNum + MAX_CLOSE_IN_RETRY_TICKS)
				lastCloseInTry = gs->frameNum;
		}
	}

	// user is attacking ground
	else {
		const float3 pos(c.params[0], c.params[1], c.params[2]);
		const float3 diff = owner->pos - pos;

		if (owner->weapons.size() > 0) {
			// if we have at least one weapon then check if
			// we can hit position with our first (assumed
			// to be meanest) one
			CWeapon* w = owner->weapons.front();

			// XXX hack - dgun overrides any checks
			if (c.id == CMD_DGUN) {
				float rr = owner->maxRange * owner->maxRange;

				for (vector<CWeapon*>::iterator it = owner->weapons.begin();
						it != owner->weapons.end(); ++it) {

					if (dynamic_cast<CDGunWeapon*>(*it))
						rr = (*it)->range * (*it)->range;
				}

				if (diff.SqLength() < rr) {
					StopMove();
					owner->AttackGround(pos, c.id == CMD_DGUN);
					owner->moveType->KeepPointingTo(pos, owner->maxRange * 0.9f, true);
				}
			} else {
				const bool inAngle = w->TryTargetRotate(pos, c.id == CMD_DGUN);
				const bool inRange = diff.Length2D() < (w->range - (w->relWeaponPos).Length2D());

				if (inAngle || inRange) {
					StopMove();
					owner->AttackGround(pos, c.id == CMD_DGUN);
					owner->moveType->KeepPointingTo(pos, owner->maxRange * 0.9f, true);
				}
			}
		}

		else if (diff.SqLength2D() < 1024) {
			StopMove();
			owner->moveType->KeepPointingTo(pos, owner->maxRange * 0.9f, true);
		}

		// if we are more than 10 units distant from target position then keeping moving closer
		else if (pos.distance2D(goalPos) > 10) {
			SetGoal(pos, owner->pos);
		}
	}
}




int CMobileCAI::GetDefaultCmd(CUnit* pointed, CFeature* feature)
{
	if (pointed) {
		if (!gs->Ally(gu->myAllyTeam,pointed->allyteam)) {
			if (owner->unitDef->canAttack) {
				return CMD_ATTACK;
			}
		} else {
			CTransportCAI* tran = dynamic_cast<CTransportCAI*>(pointed->commandAI);
			if(tran && tran->CanTransport(owner)) {
				return CMD_LOAD_ONTO;
			} else if (owner->unitDef->canGuard) {
				return CMD_GUARD;
			}
		}
	}
	return CMD_MOVE;
}

void CMobileCAI::SetGoal(const float3 &pos, const float3& curPos, float goalRadius)
{
	if (pos == goalPos)
		return;
	goalPos = pos;
	owner->moveType->StartMoving(pos, goalRadius);
}

void CMobileCAI::SetGoal(const float3 &pos, const float3& curPos, float goalRadius, float speed)
{
	if(pos == goalPos)
		return;
	goalPos = pos;
	owner->moveType->StartMoving(pos, goalRadius, speed);
}

void CMobileCAI::StopMove()
{
	owner->moveType->StopMoving();
	goalPos=owner->pos;
}

void CMobileCAI::DrawCommands(void)
{
	lineDrawer.StartPath(owner->midPos, cmdColors.start);

	if (owner->selfDCountdown != 0) {
		lineDrawer.DrawIconAtLastPos(CMD_SELFD);
	}

	CCommandQueue::iterator ci;
	for(ci=commandQue.begin();ci!=commandQue.end();++ci){
		switch(ci->id){
			case CMD_MOVE:{
				const float3 endPos(ci->params[0],ci->params[1],ci->params[2]);
				lineDrawer.DrawLineAndIcon(ci->id, endPos, cmdColors.move);
				break;
			}
			case CMD_PATROL:{
				const float3 endPos(ci->params[0],ci->params[1],ci->params[2]);
				lineDrawer.DrawLineAndIcon(ci->id, endPos, cmdColors.patrol);
				break;
			}
			case CMD_FIGHT:{
				if(ci->params.size() != 1){
					const float3 endPos(ci->params[0],ci->params[1],ci->params[2]);
					lineDrawer.DrawLineAndIcon(ci->id, endPos, cmdColors.fight);
					break;
				}
			}
			case CMD_ATTACK:
			case CMD_DGUN:{
				if(ci->params.size()==1){
					const CUnit* unit = uh->units[int(ci->params[0])];
					if((unit != NULL) && isTrackable(unit)) {
						const float3 endPos =
							helper->GetUnitErrorPos(unit, owner->allyteam);
						lineDrawer.DrawLineAndIcon(ci->id, endPos, cmdColors.attack);
					}
				} else {
					const float3 endPos(ci->params[0],ci->params[1],ci->params[2]);
					lineDrawer.DrawLineAndIcon(ci->id, endPos, cmdColors.attack);
				}
				break;
			}
			case CMD_GUARD:{
				const CUnit* unit = uh->units[int(ci->params[0])];
				if((unit != NULL) && isTrackable(unit)) {
					const float3 endPos =
						helper->GetUnitErrorPos(unit, owner->allyteam);
					lineDrawer.DrawLineAndIcon(ci->id, endPos, cmdColors.guard);
				}
				break;
			}
			case CMD_LOAD_ONTO:{
				const CUnit* unit = uh->units[int(ci->params[0])];
				lineDrawer.DrawLineAndIcon(ci->id, unit->pos, cmdColors.load);
				break;
			}
			case CMD_WAIT:{
				DrawWaitIcon(*ci);
				break;
			}
			case CMD_SELFD:{
				lineDrawer.DrawIconAtLastPos(ci->id);
				break;
			}
			default: {
				DrawDefaultCommand(*ci);
				break;
			}
		}
	}
	lineDrawer.FinishPath();
}


void CMobileCAI::BuggerOff(float3 pos, float radius)
{
	lastBuggerOffTime = gs->frameNum;
	buggerOffPos = pos;
	buggerOffRadius = radius + owner->radius;
}

void CMobileCAI::NonMoving(void)
{
	if (owner->usingScriptMoveType) {
		return;
	}
	if(lastBuggerOffTime>gs->frameNum-200){
		float3 dif=owner->pos-buggerOffPos;
		dif.y=0;
		float length=dif.Length();
		if(!length) {
			length=0.1f;
			dif = float3(0.1f, 0.0f, 0.0f);
		}
		if (length < buggerOffRadius) {
			float3 goalPos = buggerOffPos + dif * ((buggerOffRadius + 128) / length);
			Command c;
			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;
			commandQue.push_front(c);
			unimportantMove = true;
		}
	}
}

void CMobileCAI::FinishCommand(void)
{
	if(!(commandQue.front().options & INTERNAL_ORDER)){
		lastUserGoal=owner->pos;
	}
	StopSlowGuard();
	CCommandAI::FinishCommand();
}

void CMobileCAI::IdleCheck(void)
{
	if(owner->unitDef->canAttack && owner->moveState && owner->fireState
			&& !owner->weapons.empty() && (!owner->haveTarget || owner->weapons[0]->onlyForward)){
		if(owner->lastAttacker && owner->lastAttack + 200 > gs->frameNum
				&& !(owner->unitDef->noChaseCategory & owner->lastAttacker->category)){
			float3 apos=owner->lastAttacker->pos;
			float dist=apos.distance2D(owner->pos);
			if(dist<owner->maxRange+200*owner->moveState*owner->moveState){
				Command c;
				c.id=CMD_ATTACK;
				c.options=INTERNAL_ORDER;
				c.params.push_back(owner->lastAttacker->id);
				c.timeOut=gs->frameNum+140;
				commandQue.push_front(c);
				return;
			}
		}
	}
	if (owner->unitDef->canAttack && !owner->unitDef->noAutoFire &&
	    (gs->frameNum >= lastIdleCheck+10) && owner->moveState &&
	    owner->fireState>=2 && !owner->weapons.empty() &&
	    (!owner->haveTarget || owner->weapons[0]->onlyForward)) {
		CUnit* u = helper->GetClosestEnemyUnit(owner->pos,
				owner->maxRange + 150 * owner->moveState * owner->moveState, owner->allyteam);
		if(u && !(owner->unitDef->noChaseCategory & u->category) && !u->neutral) {
			Command c;
			c.id=CMD_ATTACK;
			c.options=INTERNAL_ORDER;
			c.params.push_back(u->id);
			c.timeOut=gs->frameNum+140;
			commandQue.push_front(c);
			return;
		}
	}
	if (owner->usingScriptMoveType) {
		return;
	}
	lastIdleCheck = gs->frameNum;
	if (((owner->pos - lastUserGoal).SqLength2D() > 10000.0f) &&
	    !owner->haveTarget && !dynamic_cast<CTAAirMoveType*>(owner->moveType)) {
		//note that this is not internal order so that we dont keep generating
		//new orders if we cant get to that pos
		Command c;
		c.id=CMD_MOVE;
		c.options=0;
		c.params.push_back(lastUserGoal.x);
		c.params.push_back(lastUserGoal.y);
		c.params.push_back(lastUserGoal.z);
		commandQue.push_front(c);
		unimportantMove=true;
	} else {
		NonMoving();
	}
}

void CMobileCAI::StopSlowGuard(){
	if(slowGuard){
		slowGuard = false;
		if (owner->maxSpeed)
			owner->moveType->SetMaxSpeed(owner->maxSpeed);
	}
}

void CMobileCAI::StartSlowGuard(float speed){
	if(!slowGuard){
		slowGuard = true;
		//speed /= 30;
		if(owner->maxSpeed >= 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){
					if (speed > 0)
						owner->moveType->SetMaxSpeed(speed);
				}
			}
		}
	}
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?