示例#1
0
void cCombatManager::UnitIdle(const int& unit, UnitInfo *U)
{
//*l<<"(cui) -eID="<<U->enemyID;
	if( ValidateEnemy(unit,U) && CanAttack(U,U->E,GetEnemyPosition(U->enemyID,U->E)) == 0 )
		U->enemyID=-1;
	float3 fPos=cb->GetUnitPos(unit);
	if( U->enemyID == -1 )
		while( (U->enemyID=GetClosestEnemy(fPos,U)) > 0 && !ValidateEnemy(unit,U) ) {}
	float distance = -1;
	if( U->enemyID >= 0 )
	{
		distance = fPos.distance(GetEnemyPosition(U->enemyID,U->E));
		if( distance == 0 )
			distance = 1;
	}
	if( U->enemyID == -1 || (U->udrBL->task != TASK_ASSAULT && distance > 2.5*8*U->ud->losRadius) )
	{
		U->inCombat=false;
		G->UpdateEventAdd(1,0,unit,U);
		return;
	}
	else if( CommandDGun(unit,U) )
		return;
	else if( U->enemyEff == 0 || (U->udrBL->task != TASK_ASSAULT && distance > 1.75*U->enemyEff->BestRange ) || (U->ud->isCommander && cb->GetUnitHealth(unit)/U->ud->health <= 0.66 ) ) // || G->Enemies.find(U->enemyID)->second.ud->kamikazeDist > distance
	{
		float3 EPos = GetEnemyPosition(U->enemyID,U->E);
		CommandRun(unit,U,EPos);
		return;
	}
	else if( CommandCapture(unit,U,distance) || CommandManeuver(unit,U,distance) )
		return;
	else
	{
		float3 EPos = GetEnemyPosition(U->enemyID,U->E);
		Command c;
		if( U->ud->canAttack && (U->E->inLOS || U->E->inRadar) )
		{
			c.id = CMD_ATTACK;
			c.params.push_back(U->enemyID);
		}
		else if( U->ud->canAttack && (U->udr->IsBomber && U->E->posLocked) )
		{
			c.id = CMD_ATTACK;
			c.params.push_back(EPos.x);
			c.params.push_back(EPos.y);
			c.params.push_back(EPos.z);
		}
		else // cant see enemy or Mod Workaround: Combat Lords - cant be given attack orders
		{
			c.id = CMD_MOVE;
			c.params.push_back(EPos.x -100.0 +rand()%201 );
			c.params.push_back(EPos.y);
			c.params.push_back(EPos.z -100.0 +rand()%201 );
		}

		cb->GiveOrder(unit, &c);
		G->UpdateEventAdd(1,int(GetNextUpdate(distance,U)),unit,U);
	}
}
示例#2
0
void cCombatManager::UnitDamaged(const int& unitID, UnitInfo* U, const int& attackerID, EnemyInfo* A, float3& dir)
{
	ValidateEnemy(unitID,U,false);
	if( attackerID >= 0 && attackerID != U->enemyID )
	{
		float3 Pos = cb->GetUnitPos(unitID);
		float3 APos = GetEnemyPosition(attackerID,A);
		if( U->enemyID == -1 || Pos.distance(APos) < Pos.distance(GetEnemyPosition(U->enemyID,U->E)) )
			if( CanAttack(U, A, APos) != 0 && (U->group == 0 || U->group->Enemies.find(attackerID) != U->group->Enemies.end()) )
			{
				U->enemyID=attackerID;
				U->E = A;
				U->enemyEff = CanAttack(U, A, APos);
			}
	}
	if( U->inCombat )
	{
		if( U->ud->isCommander )
		{
			if( int(cb->GetCurrentUnitCommands(unitID)->size()) == 0 )
				UnitIdle(unitID,U);
			else if( cb->GetCurrentUnitCommands(unitID)->front().id != CMD_MOVE )
			{
				if( cb->GetUnitHealth(unitID)/U->ud->health <= 0.66 ||
					(cb->GetUnitHealth(unitID)/U->ud->health <= 0.9 && cb->GetCurrentUnitCommands(unitID)->front().id == CMD_CAPTURE) )
					UnitIdle(unitID,U);
			}
		}
		return;
	}
	if( U->BuildQ != 0 && U->BuildQ->RS != 0 )
		U->BuildQ->tryCount = 4; // If the project is destroyed too many times, give up on it
	U->inCombat=true;
	if( U->enemyID == -1 )
	{
		if( attackerID >= 0 )
		{
			float3 APos = GetEnemyPosition(attackerID,A);
			CommandRun(unitID,U,APos);
		}
		else
		{
			float3 EPos = cb->GetUnitPos(unitID);
			EPos.x += dir.x*700;
			EPos.z += dir.z*700;
			EPos.y = cb->GetElevation(EPos.x,EPos.z);
			CommandRun(unitID,U,EPos);
		}
	}
	else
		UnitIdle(unitID,U);
}
示例#3
0
int cCombatManager::GetClosestEnemy(float3 Pos, UnitInfo* U)
{
	U->enemyID=-1;
	// these two function need improvement, for now I'll just use a short cut
	if( !G->UM->ActiveAttackOrders() && U->udrBL->task != TASK_SUICIDE )
		return GetClosestThreat(Pos, U);
	sWeaponEfficiency* weTemp;
	float distance,fTemp;
	float3 fE;
	for( map<int,EnemyInfo>::iterator E=G->Enemies.begin(); E!=G->Enemies.end(); E++ )
	{
		fE=GetEnemyPosition(E->first,&E->second);
		if( (weTemp = CanAttack(U,&E->second,fE)) != 0 )
		{
			fTemp=Pos.distance(fE);
			if( U->enemyID == -1 || fTemp < distance )
			{
				U->enemyID=E->first;
				U->E = &E->second;
				U->enemyEff = weTemp;
				distance=fTemp;
			}
		}
	}
	if( U->enemyID != -1 && U->group != 0 )
		G->UM->GroupAddEnemy(U->enemyID,U->E,U->group);
	return U->enemyID;
}
示例#4
0
bool cCombatManager::CommandDGun(const int& unitID, UnitInfo *U)
{
	if( U->udr->DGun == 0 || cb->GetEnergy() < U->udr->DGun->energycost )
		return false;

	float3 EPos = GetEnemyPosition(U->enemyID,U->E);
	float EDis = EPos.distance(cb->GetUnitPos(unitID));
	if( EDis > 1.05*U->udr->DGun->range )
		return false;

	if( U->ud->isCommander )
	{
		if( U->E->ud != 0 && U->E->ud->isCommander )
		{
			CommandRun(unitID,U,EPos);
			return true;
		}
	}
	Command c;
	c.id=CMD_DGUN;
	c.params.push_back(EPos.x);
	c.params.push_back(EPos.y);
	c.params.push_back(EPos.z);
	cb->GiveOrder(unitID, &c);
	G->UpdateEventAdd(1,cb->GetCurrentFrame()+5,unitID,U);
	return true;
}
示例#5
0
/*
bool cCombatManager::CommandTrap(const int& unitID, UnitInfo* U, const float& EDis)
{
	if( !U->E->inLOS || U->ud->transportMass < U->E->ud->mass )
		return false;
	if( U->ud->transportCapacity == 0 )
		return false;

	Command c;
	c.id = CMD_LOAD_UNITS;
	c.params.push_back(U->enemyID);
	cb->GiveOrder(unitID, &c);
	return true;
}
*/
bool cCombatManager::CommandManeuver(const int& unitID, UnitInfo *U, const float& EDis)
{
    if( U->ud->canfly || U->E->ud == 0 || !U->E->inLOS || U->enemyEff->BestRange <= 1.15*cb->GetUnitMaxRange(U->enemyID) || EDis > 3500.0 || int(G->UMobile.size()) > 60 )
        return false;

    float3 Pos=cb->GetUnitPos(unitID);
    float3 EPos=GetEnemyPosition(U->enemyID,U->E);

    if( U->ud->minWaterDepth < 0 && Pos.y <= 0 && U->udr->WeaponSeaEff.BestRange == 0 )
    {
        int iS=G->TM->GetSectorIndex(EPos);
        if( G->TM->IsSectorValid(iS) )
        {
            Pos = G->TM->GetClosestSector(G->TM->landSectorType,iS)->position;
            Pos.x+=128-rand()%256;
            Pos.z+=128-rand()%256;
            G->CorrectPosition(Pos);
            Command c;
            c.id = CMD_MOVE;
            c.params.push_back(Pos.x);
            c.params.push_back(Pos.y);
            c.params.push_back(Pos.z);
            cb->GiveOrder(unitID, &c);
            G->UpdateEventAdd(1,int(GetNextUpdate(EDis,U)),unitID,U);
            return true;
        }
    }
    if( EDis < 0.70*U->enemyEff->BestRange || EDis > U->enemyEff->BestRange )
    {
        float distanceAway=(0.87*U->enemyEff->BestRange-EDis);
        Pos.x+=(Pos.x-EPos.x)*(distanceAway/EDis);
        Pos.z+=(Pos.z-EPos.z)*(distanceAway/EDis);
        G->CorrectPosition(Pos);

        if( !G->TM->CanMoveToPos(U->area,Pos) )
            return false;

        Command c;
        c.id = CMD_MOVE;
        c.params.push_back(Pos.x);
        c.params.push_back(cb->GetElevation(Pos.x,Pos.z));
        c.params.push_back(Pos.z);
        cb->GiveOrder(unitID, &c);
        G->UpdateEventAdd(1,int(GetNextUpdate(EDis,U)),unitID,U);
        return true;
    }
    return false;
}
示例#6
0
int cCombatManager::GetClosestThreat(float3 Pos, UnitInfo* U)
{
    sWeaponEfficiency* weTemp;
    float distance,fTemp;
    distance=0.0f;
    float3 fE;
    set<int> deletion;
    for( map<int,EnemyInfo*>::iterator E=G->EThreat.begin(); E!=G->EThreat.end(); ++E )
    {
        fE=GetEnemyPosition(E->first,E->second);
        if( E->second->baseThreatFrame > cb->GetCurrentFrame()+3600 ||
                (E->second->baseThreatFrame > cb->GetCurrentFrame()+1200 && G->UImmobile.find(E->second->baseThreatID) == G->UImmobile.end() ) ||
                (E->second->ud != 0 && G->UImmobile.find(E->second->baseThreatID) != G->UImmobile.end() && 1.3*E->second->ud->maxWeaponRange < fE.distance(cb->GetUnitPos(E->second->baseThreatID)) ) )
        {
            E->second->baseThreatID = -1;
            E->second->baseThreatFrame = -1;
            deletion.insert(E->first);
        }
        else if( (weTemp = CanAttack(U,E->second,fE)) != 0 )
        {
            fTemp=Pos.distance(fE);
            if( U->enemyID == -1 || fTemp < distance )
            {
                U->enemyID=E->first;
                U->E = E->second;
                U->enemyEff = weTemp;
                distance=fTemp;
            }
        }
    }
    while( int(deletion.size()) > 0 )
    {
        if( !G->UM->ActiveAttackOrders() )
        {
            EnemyInfo* E = G->EThreat.find(*deletion.begin())->second;
            while( int(E->attackGroups.size()) > 0 )
                G->UM->GroupRemoveEnemy(*deletion.begin(),E,*E->attackGroups.begin());
        }
        G->EThreat.erase(*deletion.begin());
        deletion.erase(*deletion.begin());
    }
    if( U->enemyID != -1 && U->group != 0 )
        G->UM->GroupAddEnemy(U->enemyID,U->E,U->group);
    return U->enemyID;
}
示例#7
0
void
ParseSayText (edict_t * ent, char *text)
{
  static unsigned char buf[10240], infobuf[10240];
  char *p, *pbuf;

  p = text;
  pbuf = buf;
  *pbuf = 0;

  while (*p != 0)
    {
      if (((ptrdiff_t) pbuf - (ptrdiff_t) buf) > 225)
	{
	  break;
	}

      if (*p == '%')
	{
	  switch (*(p + 1))
	    {
	    case 'H':
	      GetHealth (ent, infobuf);
	      strcpy (pbuf, infobuf);
	      pbuf = SeekBufEnd (pbuf);
	      p += 2;
	      continue;
	    case 'A':
	      GetAmmo (ent, infobuf);
	      strcpy (pbuf, infobuf);
	      pbuf = SeekBufEnd (pbuf);
	      p += 2;
	      continue;
	    case 'W':
	      GetWeaponName (ent, infobuf);
	      strcpy (pbuf, infobuf);
	      pbuf = SeekBufEnd (pbuf);
	      p += 2;
	      continue;
	    case 'I':
	      GetItemName (ent, infobuf);
	      strcpy (pbuf, infobuf);
	      pbuf = SeekBufEnd (pbuf);
	      p += 2;
	      continue;
	    case 'T':
	      GetNearbyTeammates (ent, infobuf);
	      strcpy (pbuf, infobuf);
	      pbuf = SeekBufEnd (pbuf);
	      p += 2;
	      continue;
	    case 'M':
	      GetViewedTeammateName (ent, infobuf);
	      strcpy (pbuf, infobuf);
	      pbuf = SeekBufEnd (pbuf);
	      p += 2;
	      continue;
	    case 'E':
	      GetViewedEnemyName (ent, infobuf);
	      strcpy (pbuf, infobuf);
	      pbuf = SeekBufEnd (pbuf);
	      p += 2;
	      continue;
	    case 'F':
	      GetViewedEnemyWeapon (ent, infobuf);
	      strcpy (pbuf, infobuf);
	      pbuf = SeekBufEnd (pbuf);
	      p += 2;
	      continue;
	    case 'G':
	      GetEnemyPosition (ent, infobuf);
	      strcpy (pbuf, infobuf);
	      pbuf = SeekBufEnd (pbuf);
	      p += 2;
	      continue;
	    case 'K':
	      GetLastKilledTarget (ent, infobuf);
	      strcpy (pbuf, infobuf);
	      pbuf = SeekBufEnd (pbuf);
	      p += 2;
	      continue;
//AQ2:TNG Slicer - New Location Code
	      /*
	         case 'L':
	         GetOwnPosition (ent, infobuf);
	         strcpy (pbuf, infobuf);
	         pbuf = SeekBufEnd (pbuf);
	         p += 2;
	         continue;
	         case 'S':
	         GetViewedPosition (ent, infobuf);
	         strcpy (pbuf, infobuf);
	         pbuf = SeekBufEnd (pbuf);
	         p += 2;
	         continue;
	       */
	    case 'S':
	      GetSightedLocation (ent, infobuf);
	      strcpy (pbuf, infobuf);
	      pbuf = SeekBufEnd (pbuf);
	      p += 2;
	      continue;
	    case 'L':
	      GetPlayerLocation (ent, infobuf);
	      strcpy (pbuf, infobuf);
	      pbuf = SeekBufEnd (pbuf);
	      p += 2;
	      continue;
	      //AQ2:TNG Slicer Last Damage Location
	    case 'D':
	      GetLastDamagedPart (ent, infobuf);
	      strcpy (pbuf, infobuf);
	      pbuf = SeekBufEnd (pbuf);
	      p += 2;
	      continue;
	      //AQ2:TNG END
	      //AQ2:TNG Freud Last Player Damaged
	    case 'P':
	      GetLastDamagedPlayers (ent, infobuf);
	      strcpy (pbuf, infobuf);
	      pbuf = SeekBufEnd (pbuf);
	      p += 2;
	      continue;
	      //AQ2:TNG END
	    }
	}
      *pbuf++ = *p++;
    }

  *pbuf = 0;

  strncpy (text, buf, 225);
  text[225] = 0;		// in case it's 225

}
示例#8
0
void ParseSayText (edict_t * ent, char *text, size_t size)
{
	char buf[PARSE_BUFSIZE + 256] = "\0"; //Parsebuf + chatpuf size
	char *p, *pbuf;

	p = text;
	pbuf = buf;

	while (*p != 0)
	{
		if (*p == '%')
		{
			switch (*(p + 1))
			{
			case 'H':
				GetHealth (ent, pbuf);
				pbuf = SeekBufEnd (pbuf);
				p += 2;
				break;
			case 'A':
				GetAmmo (ent, pbuf);
				pbuf = SeekBufEnd (pbuf);
				p += 2;
				break;
			case 'W':
				GetWeaponName (ent, pbuf);
				pbuf = SeekBufEnd (pbuf);
				p += 2;
				break;
			case 'I':
				GetItemName (ent, pbuf);
				pbuf = SeekBufEnd (pbuf);
				p += 2;
				break;
			case 'T':
				GetNearbyTeammates (ent, pbuf);
				pbuf = SeekBufEnd (pbuf);
				p += 2;
				break;
			case 'M':
				GetViewedTeammateName (ent, pbuf);
				pbuf = SeekBufEnd (pbuf);
				p += 2;
				break;
			case 'E':
				GetViewedEnemyName (ent, pbuf);
				pbuf = SeekBufEnd (pbuf);
				p += 2;
				break;
			case 'F':
				GetViewedEnemyWeapon (ent, pbuf);
				pbuf = SeekBufEnd (pbuf);
				p += 2;
				break;
			case 'G':
				GetEnemyPosition (ent, pbuf);
				pbuf = SeekBufEnd (pbuf);
				p += 2;
				break;
			case 'K':
				GetLastKilledTarget (ent, pbuf);
				pbuf = SeekBufEnd (pbuf);
				p += 2;
				break;
			//AQ2:TNG Slicer - New Location Code
			/*
			case 'L':
				GetOwnPosition (ent, infobuf);
				strcpy (pbuf, infobuf);
				pbuf = SeekBufEnd (pbuf);
				p += 2;
				break;
			case 'S':
				GetViewedPosition (ent, infobuf);
				strcpy (pbuf, infobuf);
				pbuf = SeekBufEnd (pbuf);
				p += 2;
				break;
			*/
			case 'S':
				GetSightedLocation (ent, pbuf);
				pbuf = SeekBufEnd (pbuf);
				p += 2;
				break;
			case 'L':
				GetPlayerLocation (ent, pbuf);
				pbuf = SeekBufEnd (pbuf);
				p += 2;
				break;
			//AQ2:TNG Slicer Last Damage Location
			case 'D':
				GetLastDamagedPart (ent, pbuf);
				pbuf = SeekBufEnd (pbuf);
				p += 2;
				break;
			//AQ2:TNG END
			//AQ2:TNG Freud Last Player Damaged
			case 'P':
				GetLastDamagedPlayers (ent, pbuf);
				pbuf = SeekBufEnd (pbuf);
				p += 2;
				break;
			//AQ2:TNG END
			default:
				*pbuf++ = *p++;
				break;
			}
		}
		else
		{
			*pbuf++ = *p++;
		}

		if (buf[size-1])
		{
			buf[size-1] = 0;
			break;
		}
	}

	*pbuf = 0;
	strcpy(text, buf);
}