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 + -
显示快捷键?