コード例 #1
0
  /// Use guided matching to find corresponding 2-view correspondences
  void match(
    const SfM_Data & sfm_data,
    const Pair_Set & pairs,
    const std::shared_ptr<Regions_Provider> & regions_provider)
  {
    C_Progress_display my_progress_bar( pairs.size(), std::cout,
      "Compute pairwise fundamental guided matching:\n" );
  #ifdef OPENMVG_USE_OPENMP
    #pragma omp parallel
  #endif // OPENMVG_USE_OPENMP
    for (Pair_Set::const_iterator it = pairs.begin(); it != pairs.end(); ++it)
    {
  #ifdef OPENMVG_USE_OPENMP
      #pragma omp single nowait
  #endif // OPENMVG_USE_OPENMP
      {
      // --
      // Perform GUIDED MATCHING
      // --
      // Use the computed model to check valid correspondences
      // - by considering geometric error and descriptor distance ratio.
      std::vector<IndMatch> vec_corresponding_indexes;

      const View * viewL = sfm_data.getViews().at(it->first).get();
      const Poses::const_iterator iterPoseL = sfm_data.getPoses().find(viewL->id_pose);
      const Intrinsics::const_iterator iterIntrinsicL = sfm_data.getIntrinsics().find(viewL->id_intrinsic);
      const View * viewR = sfm_data.getViews().at(it->second).get();
      const Poses::const_iterator iterPoseR = sfm_data.getPoses().find(viewR->id_pose);
      const Intrinsics::const_iterator iterIntrinsicR = sfm_data.getIntrinsics().find(viewR->id_intrinsic);

      Mat xL, xR;
      PointsToMat(iterIntrinsicL->second.get(), regions_provider->regions_per_view.at(it->first)->GetRegionsPositions(), xL);
      PointsToMat(iterIntrinsicR->second.get(), regions_provider->regions_per_view.at(it->second)->GetRegionsPositions(), xR);

      const Mat34 P_L = iterIntrinsicL->second.get()->get_projective_equivalent(iterPoseL->second);
      const Mat34 P_R = iterIntrinsicR->second.get()->get_projective_equivalent(iterPoseR->second);

      const Mat3 F_lr = F_from_P(P_L, P_R);
      const double thresholdF = 4.0;

#if defined(EXHAUSTIVE_MATCHING)
      // Guided matching considering geometric error and descriptor distance ratio
      geometry_aware::GuidedMatching
        <Mat3, openMVG::fundamental::kernel::EpipolarDistanceError,
        DescriptorT, L2_Vectorized<DescriptorT::bin_type> >(
        F_lr, xL, desc_provider.at(it->first), xR, desc_provider.at(it->second),
        Square(thresholdF), Square(0.8),
        vec_corresponding_indexes);
#else
      const Vec3 epipole2  = epipole_from_P(P_R, iterPoseL->second);

      const features::Regions * regions = regions_provider->regions_per_view.at(it->first).get();
      if (regions->IsScalar())
      {
        // L2 Metric (Handle descriptor internal type)
        if(regions->Type_id() == typeid(unsigned char).name())
        {
          geometry_aware::GuidedMatching_Fundamental_Fast<
          openMVG::fundamental::kernel::EpipolarDistanceError,
          L2_Vectorized<unsigned char> >
          ( F_lr,
            epipole2,
            regions_provider->regions_per_view.at(it->first).get(),
            iterIntrinsicR->second.get()->w(), iterIntrinsicR->second.get()->h(),
            regions_provider->regions_per_view.at(it->second).get(),
            Square(thresholdF), Square(0.8),
            vec_corresponding_indexes);
        }
        else
        if(regions->Type_id() == typeid(float).name())
        {
          geometry_aware::GuidedMatching_Fundamental_Fast<
          openMVG::fundamental::kernel::EpipolarDistanceError,
          L2_Vectorized<float> >
          ( F_lr,
            epipole2,
            regions_provider->regions_per_view.at(it->first).get(),
            iterIntrinsicR->second.get()->w(), iterIntrinsicR->second.get()->h(),
            regions_provider->regions_per_view.at(it->second).get(),
            Square(thresholdF), Square(0.8),
            vec_corresponding_indexes);
        }
        else
        if(regions->Type_id() == typeid(double).name())
        {
          geometry_aware::GuidedMatching_Fundamental_Fast<
          openMVG::fundamental::kernel::EpipolarDistanceError,
          L2_Vectorized<double> >
          ( F_lr,
            epipole2,
            regions_provider->regions_per_view.at(it->first).get(),
            iterIntrinsicR->second.get()->w(), iterIntrinsicR->second.get()->h(),
            regions_provider->regions_per_view.at(it->second).get(),
            Square(thresholdF), Square(0.8),
            vec_corresponding_indexes);
        }
      }
      else
      if (regions->IsBinary() && regions->Type_id() == typeid(unsigned char).name())
      {
        // Hamming metric
        geometry_aware::GuidedMatching_Fundamental_Fast<
        openMVG::fundamental::kernel::EpipolarDistanceError,
        Hamming<unsigned char> >
        ( F_lr,
          epipole2,
          regions_provider->regions_per_view.at(it->first).get(),
          iterIntrinsicR->second.get()->w(), iterIntrinsicR->second.get()->h(),
          regions_provider->regions_per_view.at(it->second).get(),
          Square(thresholdF), 0.8,
          vec_corresponding_indexes);
      }

#endif

  #ifdef OPENMVG_USE_OPENMP
      #pragma omp critical
  #endif // OPENMVG_USE_OPENMP
        {
          ++my_progress_bar;
          for (size_t i = 0; i < vec_corresponding_indexes.size(); ++i)
            putatives_matches[*it].push_back(vec_corresponding_indexes[i]);
        }
      }
    }
  }
コード例 #2
0
 double Error(size_t sample, const Model &model) const {
   return Square(ErrorT::Error(model, x1_.col(sample), x2_.col(sample)));
 }
コード例 #3
0
void CTorpedoProjectile::Update()
{
	// tracking only works when we are underwater
	if (!weaponDef->submissile && pos.y > 0.0f) {
		if (!luaMoveCtrl) {
			// must update dir and speed.w here
			SetVelocityAndSpeed(speed + (UpVector * mygravity));
		}
	} else {
		if (--ttl > 0) {
			if (!luaMoveCtrl) {
				float3 targetVel;

				if (speed.w < maxSpeed)
					speed.w += std::max(0.2f, tracking);

				if (target != NULL) {
					const CSolidObject* so = dynamic_cast<const CSolidObject*>(target);
					const CWeaponProjectile* po = dynamic_cast<const CWeaponProjectile*>(target);

					targetPos = target->pos;

					if (so != NULL) {
						targetPos = so->aimPos;
						targetVel = so->speed;

						if (allyteamID != -1 && pos.SqDistance(so->aimPos) > Square(150.0f)) {
							const CUnit* u = dynamic_cast<const CUnit*>(so);

							if (u != NULL) {
								targetPos = u->GetErrorPos(allyteamID, true);
							}
						}
					}
					if (po != NULL) {
						targetVel = po->speed;
					}
				}

				if (!weaponDef->submissile && targetPos.y > 0.0f) {
					targetPos.y = 0.0f;
				}

				const float3 targetLeadVec = targetVel * (pos.distance(targetPos) / maxSpeed) * 0.7f;
				const float3 targetLeadDir = (targetPos + targetLeadVec - pos).Normalize();

				float3 targetDirDif = targetLeadDir - dir;

				if (targetDirDif.Length() < tracking) {
					dir = targetLeadDir;
				} else {
					// <tracking> is the projectile's turn-rate
					targetDirDif = (targetDirDif - (dir * targetDirDif.dot(dir))).SafeNormalize();
					dir = (dir + (targetDirDif * tracking)).SafeNormalize();
				}

				// do not need to update dir or speed.w here
				CWorldObject::SetVelocity(dir * speed.w);
			}

			explGenHandler->GenExplosion(cegID, pos, speed, ttl, areaOfEffect, 0.0f, NULL, NULL);
		} else {
			if (!luaMoveCtrl) {
				// must update dir and speed.w here
				SetVelocityAndSpeed((speed * 0.98f) + (UpVector * mygravity));
			}
		}
	}

	if (!luaMoveCtrl) {
		SetPosition(pos + speed);
	}

	if (pos.y < -2.0f) {
		--nextBubble;

		if (nextBubble == 0) {
			nextBubble = 1 + (int) (gs->randFloat() * 1.5f);

			const float3 pspeed = (gs->randVector() * 0.1f) + float3(0.0f, 0.2f, 0.0f);

			new CBubbleProjectile(
				owner(),
				pos + gs->randVector(), pspeed, 40 + gs->randFloat() * GAME_SPEED,
				1 + gs->randFloat() * 2, 0.01f, 0.3f + gs->randFloat() * 0.3f
			);
		}
	}

	UpdateGroundBounce();
	UpdateInterception();
}
コード例 #4
0
/*
==================
idBotAI::Bot_PickBestVehicleWeapon

See what the best weapon is that we have at our disposal - we'll change our position in this vehicle if need be to get access to a ( better ) weapon.
==================
*/
void idBotAI::Bot_PickBestVehicleWeapon() {

	bool enemyInAirborneVehicle = false;
	bool enemyInGroundVehicle = false;
	bool needMovementUpdate = false;
	bool enemyOnFoot = false;
	bool hasGunnerSeatOpen;
	bool enemyReachable = false;

	if ( weapSwitchTime > botWorld->gameLocalInfo.time ) {
		return;
	}

	if ( botVehicleInfo->type == ICARUS ) {
		return;
	}

	proxyInfo_t enemyVehicleInfo;

	idVec3 vec = botWorld->clientInfo[ enemy ].origin - botInfo->origin;

	float dist = vec.LengthSqr();

	hasGunnerSeatOpen = VehicleHasGunnerSeatOpen( botInfo->proxyInfo.entNum );

	if ( botWorld->clientInfo[ enemy ].proxyInfo.entNum != CLIENT_HAS_NO_VEHICLE ) {
        GetVehicleInfo( botWorld->clientInfo[ enemy ].proxyInfo.entNum, enemyVehicleInfo );

		if ( enemyVehicleInfo.isAirborneVehicle ) {
			enemyInAirborneVehicle = true;
		} else {
			enemyInGroundVehicle = true;
		}
	} else {
		enemyOnFoot = true;
	}

	Bot_SetupVehicleMove( vec3_zero, enemy, ACTION_NULL );

    if ( botAAS.hasPath && botAAS.path.travelTime < Bot_ApproxTravelTimeToLocation( botInfo->origin, botWorld->clientInfo[ enemy ].origin, true ) * TRAVEL_TIME_MULTIPLY ) {
		enemyReachable = true;
	}

	switch( botVehicleInfo->type ) {

		case TITAN:
			if ( botVehicleInfo->driverEntNum == botNum ) {
				if ( enemyInAirborneVehicle && enemyInfo.enemyDist <= TANK_MINIGUN_RANGE && hasGunnerSeatOpen ) {
					botUcmd->botCmds.becomeGunner = true; 
					needMovementUpdate = true;
					break;
				}
			} else {
				if ( ( enemyInAirborneVehicle && enemyInfo.enemyDist > TANK_MINIGUN_RANGE && botVehicleInfo->driverEntNum == -1 ) || !enemyInAirborneVehicle ) {
					botUcmd->botCmds.becomeDriver = true;
					needMovementUpdate = true;
					break;
				}
			}

			break;

		case TROJAN:
			if ( botInfo->proxyInfo.weapon == LAW ) {
				if ( botVehicleInfo->driverEntNum == -1 ) {
					if ( ( !enemyInAirborneVehicle && !enemyInGroundVehicle ) || enemyInfo.enemyDist < 700.0f || enemyInfo.enemyDist > WEAPON_LOCK_DIST ) {
                        botUcmd->botCmds.becomeDriver = true; //mal: using the LAW to lock onto our vehicle enemy makes sense ( the drivers MG is a joke in this case ).
						needMovementUpdate = true;
						break;
					}
				}
			}

			if ( botVehicleInfo->driverEntNum == botNum ) {
				if ( ( enemyInAirborneVehicle || enemyInGroundVehicle ) && hasGunnerSeatOpen && dist < Square( WEAPON_LOCK_DIST ) ) {
					botUcmd->botCmds.becomeGunner = true; //mal: using the LAW to lock onto our airborne enemy makes sense ( the drivers MG is a joke in this case ).
					needMovementUpdate = true;
					break;
				}
			}

			if ( botInfo->proxyInfo.weapon == NULL_VEHICLE_WEAPON ) {
				if ( botVehicleInfo->driverEntNum == -1 ) {
					botUcmd->botCmds.becomeDriver = true;
					needMovementUpdate = true;
				} else if ( VehicleHasGunnerSeatOpen( botVehicleInfo->entNum ) ) {
					botUcmd->botCmds.becomeGunner = true;
					needMovementUpdate = true;
				}
				break;
			}//mal: if we're the driver, stay as the driver!

			break;

		case BADGER:
			if ( botVehicleInfo->driverEntNum == botNum ) { //mal: we're the driver, if the turret is available, we may jump into it to fight enemies.
				if ( hasGunnerSeatOpen && vehicleDriverTime < botWorld->gameLocalInfo.time && enemyReachable && enemyInfo.enemyDist > 700.0f && enemyVehicleInfo.type != HOG ) {
                    if ( botThreadData.random.RandomInt( 100 ) > 50 ) {
						vehicleDriverTime = botWorld->gameLocalInfo.time + 15000;
						break;
					}
					
					if ( ( enemyInAirborneVehicle || ( enemyInfo.enemyDist < 3000.0f && enemyInfo.enemyDist > 700.0f ) ) && vehicleGunnerTime + 30000 < botWorld->gameLocalInfo.time && enemyInfo.enemyVisible ) { //mal: dont do this if enemy too far away, or its been too soon since we last did this.
						botUcmd->botCmds.becomeGunner = true;
						vehicleGunnerTime = botWorld->gameLocalInfo.time + 15000;
						needMovementUpdate = true;
						break;
					}
				}
			}

			if ( botInfo->proxyInfo.weapon == PERSONAL_WEAPON ) {
				if ( hasGunnerSeatOpen && botVehicleInfo->driverEntNum != -1 ) {
					botUcmd->botCmds.becomeGunner = true;
					needMovementUpdate = true;
					break;
				} //mal: our gunner may have been killed, or maybe he jumped out some time ago - take his place.

				if ( botVehicleInfo->driverEntNum == -1 ) {
                    botUcmd->botCmds.becomeDriver = true;
					needMovementUpdate = true;
					break;
				}
			}

			if ( botInfo->proxyInfo.weapon == MINIGUN ) {
				if ( botVehicleInfo->driverEntNum == -1 ) {
					if ( vehicleGunnerTime < botWorld->gameLocalInfo.time || !enemyInfo.enemyVisible ) { //mal: even if we had a driver and he bailed, become the driver for a better shot, then can go back to the gun.
						botUcmd->botCmds.becomeDriver = true;
						needMovementUpdate = true;
						break;
					}
				}
			}

			if ( botInfo->proxyInfo.weapon == NULL_VEHICLE_WEAPON && botVehicleInfo->driverEntNum != botNum ) {
				if ( botVehicleInfo->driverEntNum == -1 ) {
					botUcmd->botCmds.becomeDriver = true;
					needMovementUpdate = true;
				} else if ( VehicleHasGunnerSeatOpen( botVehicleInfo->entNum ) ) {
					botUcmd->botCmds.becomeGunner = true;
					needMovementUpdate = true;
				} else if ( botVehicleInfo->hasFreeSeat ) {
					needMovementUpdate = true;
					botUcmd->botCmds.activate = true; //mal: rotate to one of the back seats.
				}
			}//mal: if we're the driver, stay as the driver!

			break;

		case PLATYPUS:
			if ( botVehicleInfo->driverEntNum == botNum ) { //mal: we're the driver, if the turret is available, we may jump into it to fight enemies.
				if ( hasGunnerSeatOpen ) {
					if ( enemyInfo.enemyDist < 1500.0f && vehicleGunnerTime + 30000 < botWorld->gameLocalInfo.time && enemyInfo.enemyVisible ) { //mal: dont do this if enemy too far away, or its been too soon since we last did this.
						botUcmd->botCmds.becomeGunner = true;
						vehicleGunnerTime = botWorld->gameLocalInfo.time + 10000;
						needMovementUpdate = true;
					}
				} //mal: if we have a gunner, we'll try to get a better shot for him, so that he can cut down our enemies.
			}

			if ( botInfo->proxyInfo.weapon == MINIGUN ) {
				if ( botVehicleInfo->driverEntNum == -1 ) {
					if ( vehicleGunnerTime < botWorld->gameLocalInfo.time || !enemyInfo.enemyVisible ) { //mal: even if we had a driver and he bailed, become the driver for a better shot, then can go back to the gun.
						botUcmd->botCmds.becomeDriver = true;
						needMovementUpdate = true;
					}
				}
			}

			break;

		case DESECRATOR:
			if ( botVehicleInfo->driverEntNum == botNum ) {
				if ( enemyInAirborneVehicle && enemyInfo.enemyDist <= TANK_MINIGUN_RANGE && hasGunnerSeatOpen ) {
					botUcmd->botCmds.becomeGunner = true; 
					needMovementUpdate = true;
					break;
				}
			} else {
				if ( ( enemyInAirborneVehicle && enemyInfo.enemyDist > TANK_MINIGUN_RANGE && botVehicleInfo->driverEntNum == -1 ) || !enemyInAirborneVehicle ) {
					botUcmd->botCmds.becomeDriver = true;
					needMovementUpdate = true;
					break;
				}
			}

			break;

		case HOG:
			if ( botInfo->proxyInfo.weapon == MINIGUN ) {
				if ( botVehicleInfo->driverEntNum == -1 ) {
					if ( vehicleGunnerTime < botWorld->gameLocalInfo.time || !enemyInfo.enemyVisible || botWorld->clientInfo[ enemy ].proxyInfo.entNum != CLIENT_HAS_NO_VEHICLE && !enemyInAirborneVehicle ) { //mal: even if we had a driver and he bailed, become the driver for a better shot, then can go back to the gun.
						botUcmd->botCmds.becomeDriver = true;
						needMovementUpdate = true;
					} //mal: we'll prefer to ram our enemies who are in vehicles
				}
			}

			if ( botVehicleInfo->driverEntNum == botNum && ( !Bot_VehicleCanRamClient( enemy ) || VEHICLE_COMBAT_MOVEMENT_STATE == NULL || combatMoveType != VEHICLE_RAM_ATTACK_MOVEMENT ) ) {
				if ( ( enemyInAirborneVehicle || ( enemyInfo.enemyDist < 3000.0f && enemyInfo.enemyDist > 700.0f ) ) && vehicleGunnerTime + 30000 < botWorld->gameLocalInfo.time && enemyInfo.enemyVisible ) {
					botUcmd->botCmds.becomeGunner = true;
					vehicleGunnerTime = botWorld->gameLocalInfo.time + 10000;
					needMovementUpdate = true;
				}
			}

			break;

		case ANANSI:
		case HORNET:
			if ( botInfo->proxyInfo.weapon == MINIGUN ) {
				if ( botVehicleInfo->driverEntNum == -1 ) {
					botUcmd->botCmds.becomeDriver = true; //mal: our coward of a pilot bailed on us... take the controls!
					needMovementUpdate = true;
				}
			}

			if ( botVehicleInfo->driverEntNum == botNum ) {
				if ( botInfo->proxyInfo.weapon == LAW ) { //mal: law is better against other vehicles
					if ( botWorld->clientInfo[ enemy ].proxyInfo.entNum == CLIENT_HAS_NO_VEHICLE ) {
						botUcmd->botCmds.switchVehicleWeap = true;
					} else {
						if ( botInfo->proxyInfo.weaponIsReady == false && rocketTime < botWorld->gameLocalInfo.time && botWorld->gameLocalInfo.botSkill > BOT_SKILL_EASY ) { //mal: use rockets if LAW outta charge
							rocketTime = botWorld->gameLocalInfo.time + 2000;
							botUcmd->botCmds.switchVehicleWeap = true;
						}
					}
				}

				if ( botInfo->proxyInfo.weapon == ROCKETS ) { //mal: rockets are nice against slow moving ground targets.
					if ( botWorld->clientInfo[ enemy ].proxyInfo.entNum != CLIENT_HAS_NO_VEHICLE && rocketTime < botWorld->gameLocalInfo.time ) {
						botUcmd->botCmds.switchVehicleWeap = true;
					}
				}
			}

			break;		
	}

	if ( needMovementUpdate ) {
		COMBAT_MOVEMENT_STATE = NULL;
		VEHICLE_COMBAT_MOVEMENT_STATE = NULL;
		vehicleUpdateTime = botWorld->gameLocalInfo.time + 500;
	}

	weapSwitchTime = botWorld->gameLocalInfo.time + 1500;
}
コード例 #5
0
ファイル: GameObject.cpp プロジェクト: cdrandin/CPSC-486
	void GameObject::setSquare(const Square& s)
	{
		_square = Square(s);
	}
コード例 #6
0
/*
================
idBotAI::ClientIsAudibleToVehicle

Cheaply tells us if the client is question is making enough noise for this vehicle
to "notice" them and possibly consider them an enemy.
================
*/
bool idBotAI::ClientIsAudibleToVehicle( int clientNum ) {
	heardClient = -1; // reset this every frame.

	if ( botWorld->gameLocalInfo.botSkill == BOT_SKILL_EASY ) { // stupid bot - you can't hear anyone!
		return false;
	}

	if ( botWorld->botGoalInfo.teamRetreatInfo[ botInfo->team ].retreatTime > botWorld->gameLocalInfo.time ) {
		return false;
	}

	const clientInfo_t& client = botWorld->clientInfo[ clientNum ];

	if ( botWorld->gameLocalInfo.botSkill == BOT_SKILL_DEMO && !botWorld->botGoalInfo.gameIsOnFinalObjective && !client.isBot ) { //mal: dont worry about hearing human targets in training mode, unless its the final obj...
		return false;
	}

	float hearingRange = ( client.proxyInfo.entNum == CLIENT_HAS_NO_VEHICLE ) ? PLAYER_HEARING_DIST : VEHICLE_HEARING_DIST;

	idVec3 vec = client.origin - botInfo->origin;
	float dist = vec.LengthSqr();

	float distTemp = vec.LengthFast();

	if ( client.proxyInfo.entNum == CLIENT_HAS_NO_VEHICLE && client.weapInfo.weapon == SNIPERRIFLE && botWorld->gameLocalInfo.botSkill > BOT_SKILL_EASY ) {
		hearingRange = SNIPER_HEARING_DIST;
	}

	if ( client.weapInfo.isFiringWeap && dist < Square( hearingRange ) ) {
		heardClient = clientNum;
		return true;
	}

	if ( dist < Square( FOOTSTEP_DIST )  ) {
		heardClient = clientNum;
		return true;
	}

	if ( ClientHasObj( clientNum ) && ( botWorld->gameLocalInfo.botSkill > BOT_SKILL_EASY || client.isInRadar ) ) {
		return true;
	}

	if ( client.isInRadar && dist < Square( 1500.0f ) && ( client.abilities.gdfStealthToRadar == false || client.classType != COVERTOPS ) ) { //mal_TODO: test me!!!
		return true;
	}

	if ( ClientIsMarkedForDeath( clientNum, false ) ) {
		return true;
	}

	if ( ClientIsDangerous( clientNum ) ) { //mal: we're "aware" of campers, and will kill them if they're vis to us.
		heardClient = clientNum;
		return true;
	}

	if ( botInfo->lastAttacker == clientNum && botInfo->lastAttackerTime + 3000 > botWorld->gameLocalInfo.time ) {
		return true;
	}

	if ( ( client.targetLockEntNum == botNum || client.targetLockEntNum == botInfo->proxyInfo.entNum ) && client.targetLockTime + 3000 < botWorld->gameLocalInfo.time ) {
		return true;
	}

	return false;
}
コード例 #7
0
/*
================
idBotAI::Bot_VehicleFindBetterEnemy
================
*/
bool idBotAI::Bot_VehicleFindBetterEnemy() {
	int i;
	int entClientNum = enemy;
	float dist;
	float entDist;
	proxyInfo_t vehicleInfo;
	proxyInfo_t enemyVehicleInfo;
	idVec3 vec;

	if ( enemy == -1 ) { //mal: we lost our enemy for some reason, so just skip finding a new one til next frame.
		return false;
	}

	if ( ignoreNewEnemiesWhileInVehicleTime > botWorld->gameLocalInfo.time ) {
		return false;
	}

	if ( botWorld->clientInfo[ enemy ].proxyInfo.entNum != CLIENT_HAS_NO_VEHICLE ) { //mal: if we're attacking the MCP, its the priority.
		if ( botWorld->clientInfo[ enemy ].proxyInfo.entNum == botWorld->botGoalInfo.botGoal_MCP_VehicleNum ) {
			return false;
		}
	}

	GetVehicleInfo( botWorld->clientInfo[ enemy ].proxyInfo.entNum, enemyVehicleInfo );

	if ( enemyVehicleInfo.entNum > 0 && ( enemyVehicleInfo.type == ANANSI || enemyVehicleInfo.type == HORNET ) ) { //mal: stay in dogfights!
		return false;
	}

	const clientInfo_t& enemyPlayerInfo = botWorld->clientInfo[ enemy ];

    vec = enemyPlayerInfo.origin - botInfo->origin;
	entDist = vec.LengthSqr();

	if ( !enemyInfo.enemyVisible ) { //mal: if we can't see our current enemy, more likely to attack a visible enemy.
		entDist = idMath::INFINITY;
	}

	if ( botWorld->gameLocalInfo.botSkill == BOT_SKILL_DEMO && !botWorld->botGoalInfo.gameIsOnFinalObjective && ( !enemyPlayerInfo.isBot || enemyPlayerInfo.isActor ) ) { //mal: dont worry about keeping our human target in training mode, unless its the final obj...
		entDist += Square( TRAINING_MODE_RANGE_ADDITION );
	}

	bool curEnemyNotInVehicle = false;

	if ( botWorld->clientInfo[ enemy ].proxyInfo.entNum == CLIENT_HAS_NO_VEHICLE && !ClientIsDefusingOurTeamCharge( enemy ) && !vehicleEnemyWasInheritedFromFootCombat ) { //mal: if our current enemy is on foot, more likely to pick a better target. Unless they're defusing our charge, or an enemy we jumped in this vehicle for, then we artificially raise their importance.
		curEnemyNotInVehicle = true;
	}
	
	numVisEnemies = 1; //mal: our current enemy is always visible to us

	for ( i = 0; i < MAX_CLIENTS; i++ ) {

		if ( !ClientIsValid( i, -1 ) ) {
			continue; //mal: no valid client in this client slot!
		}

		if ( i == botNum ) {
			continue; //mal: dont try to fight ourselves!
		}

		if ( i == enemy ) { //mal: ignore an enemy we already have
			continue;
		}

		if ( EnemyIsIgnored( i ) ) {
			continue; //mal: dont try to fight someone we've flagged to ignore for whatever reason!
		}

//mal: if we're in the middle of a critical obj, dont go looking for trouble, unless they're shooting us!
		if ( Client_IsCriticalForCurrentObj( botNum, -1.0f ) && ( botInfo->lastAttacker != i || botInfo->lastAttackerTime + 3000 < botWorld->gameLocalInfo.time ) && !ClientIsDefusingOurTeamCharge( i ) ) {
			continue;
		}

		const clientInfo_t& playerInfo = botWorld->clientInfo[ i ];

		if ( playerInfo.isNoTarget ) {
			continue;
		} //mal: dont target clients that have notarget set - this is useful for debugging, etc.

		if ( playerInfo.isDisguised && playerInfo.disguisedClient != botNum ) {
			continue; //mal: won't "see" disguised clients, unless they look like us!
		}

		if ( playerInfo.inLimbo ) {
			continue;
		}

		if ( playerInfo.isActor ) {
			continue;
		}

		if ( playerInfo.invulnerableEndTime > botWorld->gameLocalInfo.time ) {
			continue; //mal: ignore revived/just spawned in clients - get the ppl around them!
		}

		if ( playerInfo.health <= 0 ) {
			continue;
		}

		if ( playerInfo.team == botInfo->team ) {
			continue;
		}

		if ( botWorld->gameLocalInfo.botSkill == BOT_SKILL_DEMO && !botWorld->botGoalInfo.gameIsOnFinalObjective && !playerInfo.isBot && enemyPlayerInfo.isBot ) { //mal: dont worry about human targets in training mode if we have a bot one, unless its the final obj...
			continue;
		}

		if ( botWorld->gameLocalInfo.botSkill > BOT_SKILL_EASY ) { //mal: st00pid bot - your not smart enough to pick your targets wisely
			if ( enemyVehicleInfo.entNum > 0 && enemyInfo.enemyVisible ) {

				if ( !( enemyVehicleInfo.flags & PERSONAL ) && !( enemyVehicleInfo.flags & WATER ) && ( enemyVehicleInfo.isAirborneVehicle && enemyVehicleInfo.xyspeed > 900.0f && entDist > Square( 2000.0f ) ) ) {
                    if ( playerInfo.proxyInfo.entNum == CLIENT_HAS_NO_VEHICLE && !Client_IsCriticalForCurrentObj( i, 1500.0f ) && !ClientHasObj( i ) ) {
						continue;
					} //mal: dont worry about an enemy in a vehicle if the vehicle is far away, moving too fast, is not a real threat
				}
			}
		} //mal: if our current enemy is in a vehicle, and this guy isn't, and this guy doesn't have an obj, or isn't important, hes not worth fighting.

		bool enemyIsInAirAttackVehicle = false;

		if ( playerInfo.proxyInfo.entNum != CLIENT_HAS_NO_VEHICLE ) { //mal: pick the driver of a vehicle as the target, NOT passengers, unless there is no driver - then kill whoever.
			
			GetVehicleInfo( playerInfo.proxyInfo.entNum, vehicleInfo );

			if ( vehicleInfo.driverEntNum != i && vehicleInfo.driverEntNum != -1 ) {
				continue;
			}

			if ( vehicleInfo.type == ANANSI || vehicleInfo.type == HORNET ) {
				enemyIsInAirAttackVehicle = true;
			} else {
				vec = vehicleInfo.origin - botInfo->origin;				

				if ( vehicleInfo.xyspeed > 600.0f && vec.LengthSqr() > Square( 1900.0f ) && !InFrontOfVehicle( vehicleInfo.entNum, botInfo->origin ) ) { //mal: if they're in a mad dash away from us, forget about them!
					continue;
				}
			}
		}

		vec = playerInfo.origin - botInfo->origin;
		dist = vec.LengthSqr();

		if ( !enemyIsInAirAttackVehicle ) {
			if ( dist > Square( ENEMY_SIGHT_BUSY_DIST * 2.0f ) ) {
				continue;
			}
		}

		float tempDist = entDist;

		if ( curEnemyNotInVehicle && playerInfo.proxyInfo.entNum != CLIENT_HAS_NO_VEHICLE ) {
			tempDist += Square( 3000.0f );
		}

		if ( !enemyIsInAirAttackVehicle ) {
			if ( dist > tempDist ) {
				continue;
			}
		} else {
			if ( dist > Square( AIRCRAFT_ATTACK_DIST ) ) {
				continue;
			}
		}

		if ( !ClientIsVisibleToBot ( i, true, false ) ) {
			continue;
		}

		if ( Client_IsCriticalForCurrentObj( i, 1500.0f ) && botWorld->gameLocalInfo.botSkill > BOT_SKILL_EASY ) { //mal: if a critical class, get high priority
			dist = Square( 600.0f );
			ignoreNewEnemiesWhileInVehicleTime = botWorld->gameLocalInfo.time + IGNORE_NEW_ENEMIES_TIME;
		}

		if ( ClientHasObj( i ) && botWorld->gameLocalInfo.botSkill > BOT_SKILL_EASY ) { //mal: if have docs, get HIGHER priority.
			dist = Square( 500.0f );
			ignoreNewEnemiesWhileInVehicleTime = botWorld->gameLocalInfo.time + IGNORE_NEW_ENEMIES_TIME;
		}

		if ( ClientIsDefusingOurTeamCharge( i ) && botWorld->gameLocalInfo.botSkill > BOT_SKILL_EASY ) { //mal: if defusing our charge, get HIGHER priority.
			dist = Square( 100.0f );
			ignoreNewEnemiesWhileInVehicleTime = botWorld->gameLocalInfo.time + IGNORE_NEW_ENEMIES_TIME;
		}

		if ( botWorld->botGoalInfo.mapHasMCPGoal && botWorld->gameLocalInfo.botSkill > BOT_SKILL_EASY ) {
			if ( playerInfo.proxyInfo.entNum == botWorld->botGoalInfo.botGoal_MCP_VehicleNum ) {
				dist = Square( 400.0f );
				ignoreNewEnemiesWhileInVehicleTime = botWorld->gameLocalInfo.time + IGNORE_NEW_ENEMIES_TIME;
			}
		}

		if ( enemyIsInAirAttackVehicle && botWorld->gameLocalInfo.botSkill > BOT_SKILL_EASY ) { //mal: dont ignore a chance to dogfight!
			dist = Square( 100.0f );
			ignoreNewEnemiesWhileInVehicleTime = botWorld->gameLocalInfo.time + IGNORE_NEW_ENEMIES_TIME;
		}

		numVisEnemies++;
		entClientNum = i;
		entDist = dist;
	}

	if ( entClientNum != enemy ) {
		enemy = entClientNum;
		enemySpawnID = botWorld->clientInfo[ entClientNum ].spawnID;

		enemyInfo.enemy_FS_Pos = botWorld->clientInfo[ entClientNum ].origin;
		enemyInfo.enemy_LS_Pos = enemyInfo.enemy_FS_Pos;

		enemyInfo.enemyLastVisTime = botWorld->gameLocalInfo.time;

		enemyAcquireTime = botWorld->gameLocalInfo.time;

		bot_FS_Enemy_Pos = botInfo->origin;
		bot_LS_Enemy_Pos = bot_FS_Enemy_Pos;

		VEHICLE_COMBAT_AI_SUB_NODE = NULL; //mal: reset the bot's combat AI node and movement state.
		COMBAT_MOVEMENT_STATE = NULL;
		return true;
	}

	return false;
}
コード例 #8
0
ファイル: ckmath_vector.cpp プロジェクト: chronokun/CkMath
const float Magnitude(const TVector2f& _krV)
{
	return(SquareRoot(		Square(_krV.m_fX)
						+	Square(_krV.m_fY)));
}
コード例 #9
0
ファイル: MobileCAI.cpp プロジェクト: Mocahteam/SpringPP
void CMobileCAI::IdleCheck(void)
{
	if(owner->unitDef->canAttack && owner->fireState
			&& !owner->weapons.empty() && owner->haveTarget) {
		if(!owner->userTarget) {
			owner->haveTarget = false;
		} else if(owner->pos.SqDistance2D(owner->userTarget->pos) <
				Square(owner->maxRange + 200*owner->moveState*owner->moveState)) {
			Command c;
			c.id = CMD_ATTACK;
			c.options=INTERNAL_ORDER;
			c.params.push_back(owner->userTarget->id);
			c.timeOut = gs->frameNum + 140;
			commandQue.push_front(c);
			tempOrder = true;
			commandPos1 = owner->pos;
			commandPos2 = owner->pos;
			return;
		}
	}
	if(owner->unitDef->canAttack && owner->fireState
				&& !owner->weapons.empty() && !owner->haveTarget) {
		if(owner->lastAttacker && owner->lastAttack + 200 > gs->frameNum
				&& !(owner->unitDef->noChaseCategory & owner->lastAttacker->category)){
			float3 apos=owner->lastAttacker->pos;
			float dist=apos.SqDistance2D(owner->pos);
			if(dist<Square(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);
				tempOrder = true;
				commandPos1 = owner->pos;
				commandPos2 = owner->pos;
				return;
			}
		}
	}
	if (owner->unitDef->canAttack && (gs->frameNum >= lastIdleCheck + 10)
			&& owner->fireState >= 2 && !owner->weapons.empty() && !owner->haveTarget)
	{
		const float searchRadius = owner->maxRange + 150 * owner->moveState * owner->moveState;
		CUnit* enemy = helper->GetClosestValidTarget(owner->pos, searchRadius, owner->allyteam, this);
		if (enemy != NULL) {
			Command c;
			c.id=CMD_ATTACK;
			c.options=INTERNAL_ORDER;
			c.params.push_back(enemy->id);
			c.timeOut=gs->frameNum+140;
			commandQue.push_front(c);
			tempOrder = true;
			commandPos1 = owner->pos;
			commandPos2 = owner->pos;
			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();
	}
}
コード例 #10
0
void CStarburstProjectile::Update(void)
{
	ttl--;
	uptime--;
	missileAge++;
	if (target && weaponDef->tracks && owner()) {
		targetPos = helper->GetUnitErrorPos(target, owner()->allyteam);
	}
	if (interceptTarget) {
		targetPos = interceptTarget->pos;
		if (targetPos.SqDistance(pos) < Square(areaOfEffect * 2)) {
			interceptTarget->Collision();
			Collision();
		}
	}
	if (uptime > 0) {
		if (curSpeed < maxSpeed)
			curSpeed += weaponDef->weaponacceleration;
		speed = dir * curSpeed;
	} else if (doturn && ttl > 0 && distanceToTravel > 0) {
		float3 dif(targetPos-pos);
		dif.Normalize();
		dif += aimError;
		dif.Normalize();
		if (dif.dot(dir) > 0.99f) {
			dir = dif;
			doturn = false;
		} else {
			dif = dif - dir;
			dif -= dir * (dif.dot(dir));
			dif.Normalize();
			if (weaponDef->turnrate != 0) {
				dir += dif * weaponDef->turnrate;
			}
			else {
				dir += dif * 0.06;
			}
			dir.Normalize();
		}
		speed = dir * curSpeed;
		if (distanceToTravel != MAX_WORLD_SIZE)
			distanceToTravel -= speed.Length2D();
	} else if (ttl > 0 && distanceToTravel > 0) {
		if (curSpeed < maxSpeed)
			curSpeed += weaponDef->weaponacceleration;
		float3 dif(targetPos - pos);
		dif.Normalize();
		if (dif.dot(dir) > maxGoodDif) {
			dir = dif;
		} else {
			dif = dif - dir;
			dif -= dir * (dif.dot(dir));
			dif.SafeNormalize();
			dir += dif * tracking;
			dir.SafeNormalize();
		}
		speed = dir * curSpeed;
		if (distanceToTravel != MAX_WORLD_SIZE)
			distanceToTravel -= speed.Length2D();
	} else {
		dir.y += gravity;
		dir.Normalize();
		curSpeed -= gravity;
		speed = dir * curSpeed;
	}

	pos += speed;

	if (ttl > 0) {
		if (cegTag.size() > 0) {
			ceg.Explosion(pos, ttl, areaOfEffect, 0x0, 0.0f, 0x0, dir);
		}
	}

	OldInfo* tempOldInfo = oldInfos[4];
	for (int a = 3; a >= 0; --a) {
		oldInfos[a + 1] = oldInfos[a];
	}
	oldInfos[0] = tempOldInfo;
	oldInfos[0]->pos = pos;
	oldInfos[0]->dir = dir;
	oldInfos[0]->speedf = curSpeed;
	int newsize = 0;
	for(float aa = 0; aa < curSpeed + 0.6f; aa += 0.15f, ++newsize) {
		float ageMod = (missileAge < 20) ? 1 : 0.6f + rand() * 0.8f / RAND_MAX;
		if(oldInfos[0]->ageMods.size()<=newsize)
			oldInfos[0]->ageMods.push_back(ageMod);
		else
			oldInfos[0]->ageMods[newsize] = ageMod;
	}
	if(oldInfos[0]->ageMods.size() != newsize)
		oldInfos[0]->ageMods.resize(newsize);

	age++;
	numParts++;

	if (weaponDef->visuals.smokeTrail && !(age & 7)) {
		if (curCallback)
			curCallback->drawCallbacker = 0;
		curCallback = new CSmokeTrailProjectile(pos, oldSmoke, dir, oldSmokeDir, owner(), age == 8,
			false, 7, Smoke_Time, 0.7f, drawTrail, this, weaponDef->visuals.texture2);
		oldSmoke = pos;
		oldSmokeDir = dir;
		numParts = 0;
		useAirLos = curCallback->useAirLos;
		if (!drawTrail) {
			float3 camDir = (pos - camera->pos).Normalize();
			if (camera->pos.distance(pos) * 0.2f + (1 - fabs(camDir.dot(dir))) * 3000 > 300)
				drawTrail = true;
		}
	}
}
コード例 #11
0
ファイル: ckmath_vector.cpp プロジェクト: chronokun/CkMath
const double Magnitude(const TVector2d& _krV)
{
	return(SquareRoot(		Square(_krV.m_dX)
						+	Square(_krV.m_dY)));
}
コード例 #12
0
ファイル: lab4tests.cpp プロジェクト: rogerpaul/quiz3
TEST(ShapePtr, DrawSquare) {
  // change this to make the test pass
  std::shared_ptr<Shape> s = Square(1);

  EXPECT_EQ("drew a square", s->draw());
}
コード例 #13
0
ファイル: Level.cpp プロジェクト: ClemKwz/keep-it-empty
void Level::Update()
{
	for(int i = 0;i < m_nElements;i++)
	{
		m_ppElements[i]->Update();
		if(m_ppElements[i]->GetState() == Ready)
		{
			bool bAlreadyExploded = false;
			bool bReasonToExplode = m_pGame->GetPlayer()->GetState() == Explode || m_pGame->GetPlayer()->GetState() == Dying;
			if(bReasonToExplode)
			{
				float x1 = m_ppElements[i]->GetPosX();
				float y1 = m_ppElements[i]->GetPosY();
				float x2 = m_pGame->GetPlayer()->GetPosX();
				float y2 = m_pGame->GetPlayer()->GetPosY();
				float fDistance = sqrt(Square(x2 - x1) + Square(y2 - y1));
				if(fDistance <= m_pGame->GetPlayer()->GetRadius() + m_ppElements[i]->GetRadius())
				{
					if(m_pGame->GetPlayer()->GetTypeClick() == 1)
					{
						m_ppElements[i]->SetExploded();
						m_nScore++;
					}
					else
					{
						for(int cpt = 0;cpt < m_nElements;cpt++)
						{
							if(m_ppElements[cpt]->GetState() == Dead && !m_ppElements[i]->GetAlreadyMultiply())
							{
								m_ppElements[i]->SetAlreadyMultiply(true);
								m_ppElements[cpt] = new Element(m_pGame, (int)m_ppElements[i]->GetPosX(), (int)m_ppElements[i]->GetPosY(),m_pGame->nRadius, m_pGame->fSpeed);
								for(int cpt2 = cpt+1;cpt2 < cpt+12;cpt2++)
								{
									if(cpt2 < m_nElements)
									{
										if(m_ppElements[cpt2]->GetState() == Dead)
										{
											m_ppElements[cpt2] = new Element(m_pGame, (int)m_ppElements[i]->GetPosX(), (int)m_ppElements[i]->GetPosY(),m_pGame->nRadius, m_pGame->fSpeed);
										}
									}
								}
								m_ppElements[cpt]->SetAlreadyMultiply(true);
								cpt = m_nElements;
							}
						}
					}
					bAlreadyExploded = true;
				}
			}
			if(bReasonToExplode || m_pGame->GetPlayer()->GetState() == Dead || m_pGame->GetPlayer()->GetType() == 2 && !bAlreadyExploded)
			{
				float x1 = m_ppElements[i]->GetPosX();
				float y1 = m_ppElements[i]->GetPosY();
				for(int j = 0;j < m_nElements;j++)
				{
					if(i != j && (m_ppElements[j]->GetState() == Explode || m_ppElements[j]->GetState() == Dying) && !bAlreadyExploded)
					{
						float x2 = m_ppElements[j]->GetPosX();
						float y2 = m_ppElements[j]->GetPosY();
						float fDistance = sqrt(Square(x2 - x1) + Square(y2 - y1));
						if(fDistance <= m_ppElements[i]->GetRadius() + m_ppElements[j]->GetRadius())
						{
							m_ppElements[i]->SetExploded();
							m_nScore++;
							bAlreadyExploded = true;
						}
					}
				}
			}
		}
	}
	if(m_eState == Running)
	{
		if(m_nScore >= m_nGoal)
			m_eState = Won;
		else
		{
			float dt = m_pGame->GetHGE()->Timer_GetDelta();
			m_fTimeCheckLoose += dt;
			if(m_fTimeCheckLoose > 1)
			{
				m_fTimeCheckLoose = 0.0;
				int nCptExploded = 0;
				for(int i = 0;i < m_nElements;i++)
				{
					if(m_ppElements[i]->GetState() == Explode || m_ppElements[i]->GetState() == Dying)
						nCptExploded++;
				}
				if(nCptExploded == 0 && (m_pGame->GetPlayer()->GetState() == Dead || m_pGame->GetPlayer()->GetType() == 2))
					m_eState = Lost;
			}
		}
	}
}
コード例 #14
0
static MagickPassFail GetImageStatisticsVariance(void *mutable_data,
                                                 const void *immutable_data,
                                                 const Image *image,
                                                 const PixelPacket *pixel,
                                                 const IndexPacket *indexes,
                                                 const long npixels,
                                                 ExceptionInfo *exception)
{
  ImageStatistics
    lstatistics,
    *statistics=(ImageStatistics *) mutable_data;

  const StatisticsContext
    *context=(const StatisticsContext *) immutable_data;

  double
    normalized;

  register long
    i;

  ARG_NOT_USED(indexes);
  ARG_NOT_USED(exception);

  (void) memset(&lstatistics, 0, sizeof(ImageStatistics));
#if defined(HAVE_OPENMP)
#  pragma omp critical (GM_GetImageStatisticsVariance)
#endif
  {
    lstatistics.red.mean=statistics->red.mean;
    lstatistics.green.mean=statistics->green.mean;
    lstatistics.blue.mean=statistics->blue.mean;
    lstatistics.opacity.mean=statistics->opacity.mean;
  }

  for (i=0; i < npixels; i++)
    {
      normalized=(double) pixel[i].red/MaxRGB;
      lstatistics.red.variance +=
        Square(normalized-lstatistics.red.mean)/context->variance_divisor;
      
      normalized=(double) pixel[i].green/MaxRGB;
      lstatistics.green.variance +=
        Square(normalized-lstatistics.green.mean)/context->variance_divisor;
      
      normalized=(double) pixel[i].blue/MaxRGB;
      lstatistics.blue.variance +=
        Square(normalized-lstatistics.blue.mean)/context->variance_divisor;
      
      if (image->matte)
        {
          normalized=(double) pixel[i].opacity/MaxRGB;
          lstatistics.opacity.variance +=
            Square(normalized-lstatistics.opacity.mean)/context->variance_divisor;
        }
    }

#if defined(HAVE_OPENMP)
#  pragma omp critical (GM_GetImageStatisticsVariance)
#endif
  {
    statistics->red.variance += lstatistics.red.variance;
    statistics->green.variance += lstatistics.green.variance;
    statistics->blue.variance += lstatistics.blue.variance;
    statistics->opacity.variance += lstatistics.opacity.variance;
  }

  return MagickPass;
}
コード例 #15
0
ファイル: CirclingWind.cpp プロジェクト: Advi42/XCSoar
CirclingWind::Result
CirclingWind::CalcWind()
{
  assert(circle_count > 0);
  assert(!samples.empty());

  // reject if average time step greater than 2.0 seconds
  if ((samples.back().time - samples[0].time) / (samples.size() - 1) > 2)
    return Result(0);

  // find average
  double av = 0;
  for (unsigned i = 0; i < samples.size(); i++)
    av += samples[i].vector.norm;

  av /= samples.size();

  // find zero time for times above average
  double rthismax = 0;
  double rthismin = 0;
  int jmax = -1;
  int jmin = -1;

  for (unsigned j = 0; j < samples.size(); j++) {
    double rthisp = 0;

    for (unsigned i = 1; i < samples.size(); i++) {
      const unsigned ithis = (i + j) % samples.size();
      unsigned idiff = i;

      if (idiff > samples.size() / 2)
        idiff = samples.size() - idiff;

      rthisp += samples[ithis].vector.norm * idiff;
    }

    if ((rthisp < rthismax) || (jmax == -1)) {
      rthismax = rthisp;
      jmax = j;
    }

    if ((rthisp > rthismin) || (jmin == -1)) {
      rthismin = rthisp;
      jmin = j;
    }
  }

  // attempt to fit cycloid
  const auto mag = (samples[jmax].vector.norm - samples[jmin].vector.norm) / 2;
  if (mag >= 30)
    // limit to reasonable values (60 knots), reject otherwise
    return Result(0);

  double rthis = 0;

  for (const Sample &sample : samples) {
    const auto sc = sample.vector.bearing.SinCos();
    auto wx = sc.second, wy = sc.first;
    wx = wx * av + mag;
    wy *= av;
    auto cmag = hypot(wx, wy) - sample.vector.norm;
    rthis += Square(cmag);
  }

  rthis /= samples.size();
  rthis = sqrt(rthis);

  int quality;

  if (mag > 1)
    quality = 5 - iround(rthis / mag * 3);
  else
    quality = 5 - iround(rthis);

  if (circle_count < 3)
    quality--;
  if (circle_count < 2)
    quality--;

  if (quality < 1)
    //measurment quality too low
    return Result(0);

  /* 5 is maximum quality, make sure we honour that */
  quality = std::min(quality, 5);

  // jmax is the point where most wind samples are below
  SpeedVector wind(samples[jmax].vector.bearing.Reciprocal(), mag);
  return Result(quality, wind);
}
コード例 #16
0
ファイル: MobileCAI.cpp プロジェクト: Mocahteam/SpringPP
/**
* @brief Causes this CMobileCAI to execute the attack order c
*/
void CMobileCAI::ExecuteAttack(Command &c)
{
	assert(owner->unitDef->canAttack);

	// limit how far away we fly
	if (tempOrder && (owner->moveState < 2) && orderTarget
			&& LinePointDist(ClosestPointOnLine(commandPos1, commandPos2, owner->pos),
					commandPos2, orderTarget->pos)
			> (500 * owner->moveState + owner->maxRange)) {
		StopMove();
		FinishCommand();
		return;
	}

	// check if we are in direct command of attacker
	if (!inCommand) {
		// don't start counting until the owner->AttackGround() order is given
		owner->commandShotCount = -1;

		if (c.params.size() == 1) {
			CUnit* targetUnit = uh->GetUnit(c.params[0]);

			// check if we have valid target parameter and that we aren't attacking ourselves
			if (targetUnit != NULL && targetUnit != owner) {
				float3 fix = targetUnit->pos + owner->posErrorVector * 128;
				float3 diff = float3(fix - owner->pos).Normalize();

				SetGoal(fix - diff * targetUnit->radius, owner->pos);

				orderTarget = targetUnit;
				AddDeathDependence(orderTarget);
				inCommand = true;
			} else {
				// unit may not fire on itself, cancel order
				StopMove();
				FinishCommand();
				return;
			}
		}
		else if (c.params.size() >= 3) {
			// user gave force-fire attack command
			float3 pos(c.params[0], c.params[1], c.params[2]);
			SetGoal(pos, owner->pos);
			inCommand = true;
		}
	}
	else if ((c.params.size() == 3) && (owner->commandShotCount > 0) && (commandQue.size() > 1)) {
		// the trailing CMD_SET_WANTED_MAX_SPEED in a command pair does not count
		if ((commandQue.size() > 2) || (commandQue.back().id != CMD_SET_WANTED_MAX_SPEED)) {
			StopMove();
			FinishCommand();
			return;
		}
	}

	// if our target is dead or we lost it then stop attacking
	// NOTE: unit should actually just continue to target area!
	if (targetDied || (c.params.size() == 1 && UpdateTargetLostTimer(int(c.params[0])) == 0)) {
		// cancel keeppointingto
		StopMove();
		FinishCommand();
		return;
	}


	// user clicked on enemy unit (note that we handle aircrafts slightly differently)
	if (orderTarget) {
		//bool b1 = owner->AttackUnit(orderTarget, c.id == CMD_DGUN);
		bool b2 = false;
		bool b3 = false;
		bool b4 = false;
		float edgeFactor = 0.f; // percent offset to target center
		float3 diff = owner->pos - orderTarget->midPos;

		if (owner->weapons.size() > 0) {
			if (!(c.options & ALT_KEY) && SkipParalyzeTarget(orderTarget)) {
				StopMove();
				FinishCommand();
				return;
			}
			CWeapon* w = owner->weapons.front();
			// if we have at least one weapon then check if we
			// can hit target with our first (meanest) one
			b2 = w->TryTargetRotate(orderTarget, c.id == CMD_DGUN);
			b3 = Square(w->range - (w->relWeaponPos).Length())
					> (orderTarget->pos.SqDistance(owner->pos));
			b4 = w->TryTargetHeading(GetHeadingFromVector(-diff.x, -diff.z),
					orderTarget->pos, orderTarget != NULL, orderTarget);
			edgeFactor = fabs(w->targetBorder);
		}

		float diffLength2d = diff.Length2D();

		// if w->AttackUnit() returned true then we are already
		// in range with our biggest weapon so stop moving
		// also make sure that we're not locked in close-in/in-range state loop
		// due to rotates invoked by in-range or out-of-range states
		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->midPos,
							std::min((float) owner->losRadius * loshandler->losDiv,
								owner->maxRange * 0.9f), true);
				}
			}
			owner->AttackUnit(orderTarget, c.id == CMD_DGUN);
		}

		// if we're on hold pos in a temporary order, then none of the close-in
		// code below should run, and the attack command is cancelled.
		else if (tempOrder && owner->moveState == 0) {
			StopMove();
			FinishCommand();
			return;
		}

		// 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->midPos,
						std::min((float) owner->losRadius * loshandler->losDiv,
							owner->maxRange * 0.9f), true);
			}

			// 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.
			//assumption is flawed: The unit may be aiming or otherwise unable to shoot
			else if (owner->unitDef->strafeToAttack && b3 && diffLength2d < (owner->maxRange * 0.9f))
			{
				moveDir ^= (owner->moveType->progressState == AMoveType::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).SqDistance2D(goalPos)
				> Square(10 + orderTarget->pos.distance2D(owner->pos) * 0.2f)) {
			// if the target isn't in LOS, go to its approximate position
			// otherwise try to go precisely to the target
			// this should fix issues with low range weapons (mainly melee)
			float3 fix = orderTarget->pos +
					(orderTarget->losStatus[owner->allyteam] & LOS_INLOS ?
						float3(0.f,0.f,0.f) :
						owner->posErrorVector * 128);
			float3 norm = float3(fix - owner->pos).Normalize();
			float3 goal = fix - norm*(orderTarget->radius*edgeFactor*0.8f);
			SetGoal(goal, owner->pos);
			if (lastCloseInTry < gs->frameNum + MAX_CLOSE_IN_RETRY_TICKS)
				lastCloseInTry = gs->frameNum;
		}
	}

	// user is attacking ground
	else if (c.params.size() >= 3) {
		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.SqLength2D() < Square(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.SqDistance2D(goalPos) > 100) {
			SetGoal(pos, owner->pos);
		}
	}
}
コード例 #17
0
ファイル: PathManager.cpp プロジェクト: horazont/spring
/*
Removes and return the next waypoint in the multipath corresponding to given id.
*/
float3 CPathManager::NextWaypoint(unsigned int pathId, float3 callerPos, float minDistance,
		int numRetries, int ownerId, bool synced) const
{
	SCOPED_TIMER("PFS");

	// 0 indicates a no-path id
	if (pathId == 0)
		return float3(-1.0f, -1.0f, -1.0f);

	if (numRetries > 4)
		return float3(-1.0f, -1.0f, -1.0f);

	//Find corresponding multipath.
	std::map<unsigned int, MultiPath*>::const_iterator pi = pathMap.find(pathId);
	if (pi == pathMap.end())
		return float3(-1.0f, -1.0f, -1.0f);
	MultiPath* multiPath = pi->second;

	if (callerPos == ZeroVector) {
		if (!multiPath->detailedPath.path.empty())
			callerPos = multiPath->detailedPath.path.back();
	}

	// check if detailed path needs bettering
	if (!multiPath->estimatedPath.path.empty() &&
		(multiPath->estimatedPath.path.back().SqDistance2D(callerPos) < Square(MIN_DETAILED_DISTANCE * SQUARE_SIZE) ||
		multiPath->detailedPath.path.size() <= 2)) {

		if (!multiPath->estimatedPath2.path.empty() &&  // if so, check if estimated path also needs bettering
			(multiPath->estimatedPath2.path.back().SqDistance2D(callerPos) < Square(MIN_ESTIMATE_DISTANCE * SQUARE_SIZE) ||
			multiPath->estimatedPath.path.size() <= 2)) {

			Estimate2ToEstimate(*multiPath, callerPos, ownerId, synced);
		}

		if (multiPath->caller) {
			multiPath->caller->UnBlock();
		}

		EstimateToDetailed(*multiPath, callerPos, ownerId);

		if (multiPath->caller) {
			multiPath->caller->Block();
		}
	}

	float3 waypoint;
	do {
		// get the next waypoint from the high-res path
		//
		// if this is not possible, then either we are
		// at the goal OR the path could not reach all
		// the way to it (ie. a GoalOutOfRange result)
		if (multiPath->detailedPath.path.empty()) {
			if (multiPath->estimatedPath2.path.empty() && multiPath->estimatedPath.path.empty()) {
				if (multiPath->searchResult == IPath::Ok) {
					return multiPath->finalGoal;
				} else {
					return float3(-1.0f, -1.0f, -1.0f);
				}
			} else {
				return NextWaypoint(pathId, callerPos, minDistance, numRetries + 1, ownerId, synced);
			}
		} else {
			waypoint = multiPath->detailedPath.path.back();
			multiPath->detailedPath.path.pop_back();
		}
	} while (callerPos.SqDistance2D(waypoint) < Square(minDistance) && waypoint != multiPath->detailedPath.pathGoal);

	return waypoint;
}
コード例 #18
0
ファイル: replaycommand.cpp プロジェクト: pupok1920/chess
ReplayCommand::ReplayCommand(BoardData *data, QPair<int, int> &move, QUndoCommand *parent)
    : QUndoCommand(parent),
      _data(data),
      _from(Square(move.second)),
      _to(Square(move.first)),
      _removedCur(nullptr) {}
コード例 #19
0
/*
================
idBotAI::Bot_VehicleFindEnemy

We'll sort thru the clients, and ignore certain clients if we're too busy
to be buggered (carrying obj, planting/hacking, etc) or they're not valid enemies
(in disguise, hidden by smoke, etc).
================
*/
bool idBotAI::Bot_VehicleFindEnemy() {
	bool hasAttackedMate;
	bool hasAttackedCriticalMate;
	bool hasObj;
	bool isDefusingOurBomb;
	bool inFront;
	bool botGotShotRecently;
	bool botIsBigShot;
	bool audible;
	bool isVisible;
	bool isFacingUs;
	bool isFiringWeapon;
	bool isNearOurObj;
	bool isAttackingDeployable = false;
	bool inAttackAirCraft = false;
	int i;
	int entClientNum = -1;
	float dist;
	float botSightDist;
	float tempSightDist;
	float entDist = idMath::INFINITY;
	proxyInfo_t enemyVehicleInfo;
	enemyVehicleInfo.entNum = 0;
	idVec3 vec;

	numVisEnemies = 0;

	vehicleEnemyWasInheritedFromFootCombat = false;

	botSightDist = Square( ENEMY_VEHICLE_SIGHT_DIST ); //mal_FIXME: break this out into a script cmd!

/*
	if ( botSightDist > Square( 8000.0f ) ) {
		botSightDist = Square( 8000.0f );
	} else if ( botSightDist < Square( 3000.0f ) ) {
		botSightDist = Square( 3000.0f );
	}
*/

//mal: some debugging stuff....
	if ( botWorld->gameLocalInfo.botIgnoreEnemies == 1 ) {
			return false;
	} else if ( botWorld->gameLocalInfo.botIgnoreEnemies == 2 ) {
			if ( botInfo->team == GDF ) {
				return false;
			}
	} else if ( botWorld->gameLocalInfo.botIgnoreEnemies == 3 ) {
			if ( botInfo->team == STROGG ) {
				return false;
			}
		}

	if ( botVehicleInfo->type != BUFFALO && Bot_VehicleIsUnderAVTAttack() != -1 && ( ( botVehicleInfo->flags & ARMOR ) || botVehicleInfo->type > ICARUS ) ) {
		return false;
	}

	if ( botVehicleInfo->type > ICARUS ) {
		botSightDist = Square( 6000.0f );
	}

	if ( botVehicleInfo->type == BUFFALO ) {
		botSightDist = Square( 3500.0f );
	}

	if ( botVehicleInfo->type == GOLIATH || botVehicleInfo->type == DESECRATOR ) { //mal: these 2 are really limited
		botSightDist = Square( PLASMA_CANNON_RANGE - 1000.0f );
	}

	if ( botVehicleInfo->type == HUSKY ) { //mal: we're no match for anybody!
		return false;
	}

#ifdef _XENON
	if ( botVehicleInfo->type == MCP && botVehicleInfo->driverEntNum == botNum ) {
		return false;
	}

	if ( botVehicleInfo->type == PLATYPUS && botVehicleInfo->driverEntNum == botNum ) {
		return false;
	}
#endif

	if ( botVehicleInfo->type > ICARUS && Client_IsCriticalForCurrentObj( botNum, -1.0f ) ) {
		return false;
	}

	botIsBigShot = Client_IsCriticalForCurrentObj( botNum, 3500.0f );

	if ( aiState == VLTG && vLTGType == V_DESTROY_DEPLOYABLE ) {
		deployableInfo_t deployable;
		if ( GetDeployableInfo( false, vLTGTarget, deployable ) ) {
			if ( deployable.type == APT || deployable.type == AVT || deployable.type == AIT ) { //mal: these are the priorities
				isAttackingDeployable = true;
			}
		}
	}

	for ( i = 0; i < MAX_CLIENTS; i++ ) {

		if ( !ClientIsValid( i, -1 ) ) {
			continue; //mal: no valid client in this client slot!
		}

		if ( i == botNum ) {
			continue; //mal: dont try to fight ourselves!
		}

		if ( EnemyIsIgnored( i ) ) {
			continue; //mal: dont try to fight someone we've flagged to ignore for whatever reason!
		}

		if ( !Bot_VehicleCanAttackEnemy( i ) ) { //mal: check if the bot has access to a weapon in the vehicle, that can hit this client.
			continue;
		}

		const clientInfo_t& playerInfo = botWorld->clientInfo[ i ];

		if ( playerInfo.isNoTarget ) {
			continue;
		} //mal: dont target clients that have notarget set - this is useful for debugging, etc.

		bool enemyIsBigShot = Client_IsCriticalForCurrentObj( i, 2500.0f );

		if ( playerInfo.inLimbo ) {
			continue;
		}

		if ( playerInfo.invulnerableEndTime > botWorld->gameLocalInfo.time ) {
			continue; //mal: ignore revived/just spawned in clients - get the ppl around them!
		}

		if ( playerInfo.isActor ) {
			continue;
		}

		if ( playerInfo.health <= 0 ) {
			continue;
		}

		if ( playerInfo.team == botInfo->team ) {
			continue;
		}

		if ( botVehicleInfo->type == MCP && botVehicleInfo->driverEntNum == botNum ) {
			if ( !InFrontOfVehicle( botInfo->proxyInfo.entNum, playerInfo.origin ) ) {
				continue;
			}
		}

		if ( botWorld->gameLocalInfo.botSkill == BOT_SKILL_DEMO && botVehicleInfo->type > ICARUS && !playerInfo.isBot ) { //mal: don't attack human players in training mode when we're in flyers.
			continue;
		}

		hasAttackedCriticalMate = ClientHasAttackedTeammate( i, true, 3000 );
		hasAttackedMate = ClientHasAttackedTeammate( i, false, 3000 );
		hasObj = ClientHasObj( i );
		isDefusingOurBomb = ClientIsDefusingOurTeamCharge( i );
		inFront = ( botInfo->proxyInfo.weapon == PERSONAL_WEAPON ) ? InFrontOfClient( botNum, playerInfo.origin) : InFrontOfVehicle( botInfo->proxyInfo.entNum, playerInfo.origin );
		isFacingUs = ( playerInfo.proxyInfo.entNum == CLIENT_HAS_NO_VEHICLE ) ? InFrontOfClient( i, botInfo->origin ) : InFrontOfVehicle( playerInfo.proxyInfo.entNum, botInfo->origin );
		botGotShotRecently = ( botInfo->lastAttackerTime + 3000 < botWorld->gameLocalInfo.time ) ? false : true;
		isFiringWeapon = playerInfo.weapInfo.isFiringWeap;
		isNearOurObj = ( LocationDistFromCurrentObj( botInfo->team, playerInfo.origin ) < 2500.0f ) ? true : false;
		bool isCriticalEnemy = Client_IsCriticalForCurrentObj( i, 2500.0f );

		if ( playerInfo.proxyInfo.entNum != CLIENT_HAS_NO_VEHICLE ) { 
			GetVehicleInfo( playerInfo.proxyInfo.entNum, enemyVehicleInfo );
		}

		if ( isAttackingDeployable ) {
			if ( botInfo->team == botWorld->botGoalInfo.attackingTeam ) {
				if ( playerInfo.proxyInfo.entNum == CLIENT_HAS_NO_VEHICLE ) {
					if ( playerInfo.weapInfo.weapon != ROCKET && !isDefusingOurBomb ) {
						continue;
					}
				} else {
					if ( !( enemyVehicleInfo.flags & ARMOR ) && enemyVehicleInfo.type != ANANSI && enemyVehicleInfo.type != HORNET ) {
			continue;
		}
				}
			} else {
				if ( !isDefusingOurBomb && playerInfo.proxyInfo.entNum == CLIENT_HAS_NO_VEHICLE && !hasObj && playerInfo.weapInfo.weapon != ROCKET && ( !isCriticalEnemy || !isNearOurObj ) ) {
					continue;
				}
			}
		}

		if ( botIsBigShot && !isFacingUs && ( !botGotShotRecently || botInfo->lastAttacker != i ) && !isFiringWeapon && !hasObj && !isNearOurObj ) {
			continue;
		} //mal: if we're trying to do an important obj, dont get into a fight with everyone.

		vec = playerInfo.origin - botInfo->origin;

		if ( botVehicleInfo->isAirborneVehicle ) {
			vec.z = 0.0f;
		}

		dist = vec.LengthSqr();

		if ( botIsBigShot && !inFront && dist > Square( 2500.0f ) && ( !botGotShotRecently || botInfo->lastAttacker != i ) && botVehicleInfo->driverEntNum == botNum ) {
			continue;
		}

		if ( playerInfo.proxyInfo.entNum != CLIENT_HAS_NO_VEHICLE ) { //mal: pick the driver of a vehicle as the target, NOT passengers, unless there is no driver - then kill whoever.
			if ( enemyVehicleInfo.type == ANANSI || enemyVehicleInfo.type == HORNET ) {
				inAttackAirCraft = true;
			}

			if ( botIsBigShot && enemyVehicleInfo.type <= ICARUS ) {
				continue;
			}

			if ( enemyVehicleInfo.type == BUFFALO && botVehicleInfo->flags & ARMOR && playerInfo.isBot ) {
				continue;
			}

			if ( enemyVehicleInfo.type == MCP && enemyVehicleInfo.isImmobilized && enemyVehicleInfo.driverEntNum == i ) {
				continue;
			}

			if ( botVehicleInfo->type == ANANSI && enemyVehicleInfo.type == ICARUS ) { //mal: this is funny to watch, but is a waste of time. :-)
				continue;
			}

			if ( isAttackingDeployable ) {
				if ( botVehicleInfo->isAirborneVehicle && ( enemyVehicleInfo.type <= ICARUS || enemyVehicleInfo.type == BUFFALO ) ) { //mal: if attacking from the air, only worry about air vehicles.
					continue;
				}
			}

			if ( enemyVehicleInfo.driverEntNum != i && enemyVehicleInfo.driverEntNum != -1 ) {
				continue;
			}

			if ( inAttackAirCraft && enemyVehicleInfo.xyspeed > 500.0f && dist > Square( TANK_MINIGUN_RANGE ) && botVehicleInfo->flags & ARMOR ) { //mal: tanks won't attack fast moving aircraft that are too far away for their MGs
				continue;
			}

			if ( botVehicleInfo->type == BADGER ) {
				if ( botInfo->proxyInfo.weapon == NULL_VEHICLE_WEAPON && enemyVehicleInfo.flags & ARMOR || enemyVehicleInfo.inWater || ( enemyVehicleInfo.isAirborneVehicle && dist > Square( 3000.0f ) || enemyVehicleInfo.type == HOG ) ) {
                    continue;
				}
			}

			if ( botVehicleInfo->inWater && botInfo->proxyInfo.weapon == NULL_VEHICLE_WEAPON ) {
				continue;
			}

			if ( botVehicleInfo->type != ANANSI && botVehicleInfo->type != HORNET ) {
                if ( enemyVehicleInfo.xyspeed > 600.0f && dist > Square( 1900.0f ) && !InFrontOfVehicle( enemyVehicleInfo.entNum, botInfo->origin ) && !ClientHasObj( i ) && !enemyIsBigShot ) { //mal: if they're in a mad dash away from us, forget about them!
					continue;
				}
			}
		}

		if ( botVehicleInfo->type == BUFFALO && !inAttackAirCraft ) { //mal_TODO: need to make the buffalo a more effective fighting platform!
			continue;
		}

		tempSightDist = botSightDist;

		if ( !ClientHasObj( i ) && !enemyIsBigShot && playerInfo.proxyInfo.entNum == CLIENT_HAS_NO_VEHICLE && !playerInfo.isCamper && playerInfo.killsSinceSpawn < KILLING_SPREE && botVehicleInfo->driverEntNum == botNum && !isDefusingOurBomb ) { //mal: vehicles will prefer to fight other vehicles, not some guy on foot a mile away....
			tempSightDist = Square( 3500.0f );
		}

		if ( inAttackAirCraft && ( botVehicleInfo->type == ANANSI || botVehicleInfo->type == HORNET ) && botWorld->gameLocalInfo.botSkill > BOT_SKILL_EASY ) {
			tempSightDist = Square( AIRCRAFT_ATTACK_DIST );
		}

		if ( dist > tempSightDist ) {
            continue;
		}

		if ( playerInfo.isDisguised ) { //mal: when in a vehicle, bots are much less likely to notice or worry about coverts
			if ( botThreadData.GetBotSkill() == BOT_SKILL_EASY ) {
				continue;
			} else {
				if ( ( playerInfo.disguisedClient != botNum && !hasAttackedMate ) || dist > Square( 2500.0f ) ) {
                    continue;
				}
			}
		} 

 		if ( !ClientHasObj( i ) ) {
            audible = ClientIsAudibleToVehicle( i ); //mal: if we can hear you, we'll skip the FOV test in the vis check below
		} else {
            audible = true;
			dist = Square( 500.0f ); //mal: if you've got the docs, your our priority target, unless someone else is right on top of us!
		}

		isVisible = ClientIsVisibleToBot( i, !audible, false );

		if ( !isVisible && !ClientHasObj( i ) ) {
			continue;
		}

		if ( botWorld->gameLocalInfo.botSkill != BOT_SKILL_DEMO || botWorld->botGoalInfo.gameIsOnFinalObjective || botWorld->botGoalInfo.attackingTeam == botInfo->team ) {
			if ( isDefusingOurBomb ) {
				dist = Square( 100.0f );
			}

			if ( hasAttackedCriticalMate && inFront && botWorld->gameLocalInfo.botSkill > BOT_SKILL_EASY ) {
				dist = Square( 600.0f ); //mal: will give higher priority to someone attacking a critical mate, if we can see it happening.
			}

			if ( botWorld->gameLocalInfo.botSkill > BOT_SKILL_EASY ) {
				if ( Client_IsCriticalForCurrentObj( i, 6000.0f ) ) {
					dist = Square( 700.0f ); //mal: if your a critical client, we're more likely to kill you.
				}
			}

			if ( botWorld->botGoalInfo.mapHasMCPGoal ) {
				if ( playerInfo.proxyInfo.entNum == botWorld->botGoalInfo.botGoal_MCP_VehicleNum ) {
					dist = 400.0f;
				}
			} //mal: if your in MCP, you get higher priority then a normal enemy. Especially when we're in a vehicle!

			if ( botVehicleInfo->type > ICARUS && botVehicleInfo->type != BUFFALO && ( playerInfo.isCamper || playerInfo.killsSinceSpawn >= KILLING_SPREE ) && botWorld->gameLocalInfo.botSkill > BOT_SKILL_EASY && !playerInfo.isBot ) {
				dist = Square( 600.0f );
			} //mal: target trouble making humans!
		} else {
			if ( !playerInfo.isBot || playerInfo.isActor ) {
				dist += Square( TRAINING_MODE_RANGE_ADDITION );
			}
		}

		numVisEnemies++;

		if ( dist < entDist ) {
			entClientNum = i;
			entDist = dist;
		}
	}

	if ( entClientNum != -1 ) {
		enemy = entClientNum;
		enemySpawnID = botWorld->clientInfo[ entClientNum ].spawnID;

		enemyInfo.enemy_FS_Pos = botWorld->clientInfo[ entClientNum ].origin;
		enemyInfo.enemy_LS_Pos = enemyInfo.enemy_FS_Pos;

		bot_FS_Enemy_Pos = botInfo->origin;
		bot_LS_Enemy_Pos = bot_FS_Enemy_Pos;
		enemyInfo.enemyLastVisTime = botWorld->gameLocalInfo.time;
		enemyAcquireTime = botWorld->gameLocalInfo.time;

		Bot_SetAttackTimeDelay( inFront ); //mal: this sets a delay on how long the bot should take to see enemy, based on bot's state.

		VEHICLE_COMBAT_AI_SUB_NODE = NULL; //mal: reset the bot's combat AI node
		COMBAT_MOVEMENT_STATE = NULL;
		return true;
	}

	return false;
}
コード例 #20
0
/*
========================
idCommonLocal::RunNetworkSnapshotFrame
========================
*/
void idCommonLocal::RunNetworkSnapshotFrame() {

    // Process any reliable messages we've received
    for ( int i = 0; i < reliableQueue.Num(); i++ ) {
        game->ProcessReliableMessage( reliableQueue[i].client, reliableQueue[i].type, idBitMsg( (const byte *)reliableQueue[i].data, reliableQueue[i].dataSize ) );
        Mem_Free( reliableQueue[i].data );
    }
    reliableQueue.Clear();

    // abuse the game timing to time presentable thinking on clients
    time_gameFrame = Sys_Microseconds();
    time_maxGameFrame = 0;
    count_numGameFrames = 0;

    if ( snapPrevious.serverTime >= 0 ) {

        int	msec_interval = 1 + idMath::Ftoi( (float)initialBaseTicksPerSec  );

        static int clientTimeResidual = 0;
        static int lastTime = Sys_Milliseconds();
        int currentTime = Sys_Milliseconds();
        int deltaFrameTime = idMath::ClampInt( 1, 33, currentTime - lastTime );

        clientTimeResidual += idMath::ClampInt( 0, 50, currentTime - lastTime );
        lastTime = currentTime;

        extern idCVar com_fixedTic;
        if ( com_fixedTic.GetBool() ) {
            clientTimeResidual = 0;
        }

        do {
            // If we are extrapolating and have fresher snapshots, then use the freshest one
            while ( ( snapCurrentTime >= snapRate || com_forceLatestSnap.GetBool() ) && readSnapshotIndex < writeSnapshotIndex ) {
                snapCurrentTime -= snapRate;
                ProcessNextSnapshot();
            }

            // this only matters when running < 60 fps
            // JAF Game()->GetRenderWorld()->UpdateDeferredPositions();

            // Clamp the current time so that it doesn't fall outside of our extrapolation bounds
            snapCurrentTime = idMath::ClampInt( 0, snapRate + Min( (int)snapRate, (int)net_maxExtrapolationInMS.GetInteger() ), snapCurrentTime );

            if ( snapRate <= 0 ) {
                idLib::Warning("snapRate <= 0. Resetting to 100");
                snapRate = 100;
            }

            float fraction = (float)snapCurrentTime / (float)snapRate;
            if ( !IsValid( fraction ) ) {
                idLib::Warning("Interpolation Fraction invalid: snapCurrentTime %d / snapRate %d", (int)snapCurrentTime, (int)snapRate );
                fraction = 0.0f;
            }

            InterpolateSnapshot( snapPrevious, snapCurrent, fraction, true );

            // Default to a snap scale of 1
            float snapRateScale = net_interpolationBaseRate.GetFloat();

            snapTimeBuffered = CalcSnapTimeBuffered( totalBufferedTime, totalRecvTime );
            effectiveSnapRate = static_cast< float > ( totalBufferedTime ) / static_cast< float > ( totalRecvTime );

            if ( net_minBufferedSnapPCT_Static.GetFloat() > 0.0f ) {
                optimalPCTBuffer = session->GetTitleStorageFloat( "net_minBufferedSnapPCT_Static", net_minBufferedSnapPCT_Static.GetFloat() );
            }

            // Calculate optimal amount of buffered time we want
            if ( net_optimalDynamic.GetBool() ) {
                optimalTimeBuffered = idMath::ClampInt( 0, net_maxBufferedSnapMS.GetInteger(), snapRate * optimalPCTBuffer );
                optimalTimeBufferedWindow = snapRate * net_minBufferedSnapWinPCT_Static.GetFloat();
            } else {
                optimalTimeBuffered = net_optimalSnapTime.GetFloat();
                optimalTimeBufferedWindow = net_optimalSnapWindow.GetFloat();
            }

            // Scale snapRate based on where we are in the buffer
            if ( snapTimeBuffered <= optimalTimeBuffered ) {
                if ( snapTimeBuffered <= idMath::FLT_SMALLEST_NON_DENORMAL ) {
                    snapRateScale = 0;
                } else {
                    snapRateScale = net_interpolationFallbackRate.GetFloat();
                    // When we interpolate past our cushion of buffered snapshot, we want to slow smoothly slow the
                    // rate of interpolation. frac will go from 1.0 to 0.0 (if snapshots stop coming in).
                    float startSlowdown = ( net_interpolationSlowdownStart.GetFloat() * optimalTimeBuffered );
                    if ( startSlowdown > 0 && snapTimeBuffered < startSlowdown ) {
                        float frac = idMath::ClampFloat( 0.0f, 1.0f, snapTimeBuffered / startSlowdown );
                        if ( !IsValid( frac ) ) {
                            frac = 0.0f;
                        }
                        snapRateScale = Square( frac ) * snapRateScale;
                        if ( !IsValid( snapRateScale ) ) {
                            snapRateScale = 0.0f;
                        }
                    }
                }


            } else if ( snapTimeBuffered > optimalTimeBuffered + optimalTimeBufferedWindow ) {
                // Go faster
                snapRateScale = net_interpolationCatchupRate.GetFloat();

            }

            float delta_interpolate = (float)initialBaseTicksPerSec * snapRateScale;
            if ( net_effectiveSnapRateEnable.GetBool() ) {

                float deltaFrameGameMS = static_cast<float>( initialBaseTicksPerSec ) * static_cast<float>( deltaFrameTime / 1000.0f );
                delta_interpolate = ( deltaFrameGameMS * snapRateScale * effectiveSnapRate ) + snapCurrentResidual;
                if ( !IsValid( delta_interpolate ) ) {
                    delta_interpolate = 0.0f;
                }

                snapCurrentResidual = idMath::Frac( delta_interpolate ); // fixme: snapCurrentTime should just be a float, but would require changes in d4 too
                if ( !IsValid( snapCurrentResidual ) ) {
                    snapCurrentResidual = 0.0f;
                }

                if ( net_effectiveSnapRateDebug.GetBool() ) {
                    idLib::Printf("%d/%.2f snapRateScale: %.2f effectiveSR: %.2f d.interp: %.2f snapTimeBuffered: %.2f res: %.2f\n", deltaFrameTime, deltaFrameGameMS, snapRateScale, effectiveSnapRate, delta_interpolate, snapTimeBuffered, snapCurrentResidual );
                }
            }

            assert( IsValid( delta_interpolate ) );
            int interpolate_interval = idMath::Ftoi( delta_interpolate );

            snapCurrentTime += interpolate_interval;	// advance interpolation time by the scaled interpolate_interval
            clientTimeResidual -= msec_interval;		// advance local client residual time (fixed step)

        } while ( clientTimeResidual >= msec_interval );

        if ( clientTimeResidual < 0 ) {
            clientTimeResidual = 0;
        }
    }

    time_gameFrame = Sys_Microseconds() - time_gameFrame;
}
コード例 #21
0
/*
================
idBotAI::Bot_ShouldVehicleChaseHiddenEnemy
================
*/
bool idBotAI::Bot_ShouldVehicleChaseHiddenEnemy() {

	proxyInfo_t enemyVehicleInfo;
	idVec3 vec;
	chasingEnemy = false;

	if ( ClientHasObj( botNum ) || Client_IsCriticalForCurrentObj( botNum, -1.0f ) ) { //mal: never chase if we are important!
		return false;
	}

	if ( botVehicleInfo->driverEntNum != botNum ) { //mal: we dont get the choice to chase someone if we're not the driver!
		return false;
	}

	if ( botVehicleInfo->health <= ( botVehicleInfo->maxHealth / 4 ) && !ClientHasObj( enemy ) ) { //mal: if we're in pretty bad shape, randomly decide to sometimes give up the fight....
		if ( botThreadData.random.RandomInt( 100 ) > 50 ) {
            return false;
		}
	}

	if ( ( botVehicleInfo->flags & PERSONAL ) || botInfo->proxyInfo.weapon == NULL_VEHICLE_WEAPON && !ClientHasObj( enemy ) ) {
		return false;
	} //mal: if we dont have a vehicle weapon to fight with, or we're in a personal transport, dont go chasing ppl.

	if ( botWorld->clientInfo[ enemy ].proxyInfo.entNum != CLIENT_HAS_NO_VEHICLE ) {

		GetVehicleInfo( botWorld->clientInfo[ enemy ].proxyInfo.entNum, enemyVehicleInfo );

		if ( enemyVehicleInfo.inWater && !botVehicleInfo->isAirborneVehicle || !( botVehicleInfo->flags & WATER ) ) {
			return false;
		} //mal: hes in the water, but we can't chase him, so forget him!

		if ( !ClientHasObj( enemy ) && !Client_IsCriticalForCurrentObj( enemy, 2000.0f ) ) {
            if ( botThreadData.random.RandomInt( 100 ) > 50 ) {
				return false;
			}
		}
	}

	if ( AIStack.STACK_AI_NODE != NULL && AIStack.isPriority != false && !ClientHasObj( enemy ) ) {
		return false;
	} // we have something important on our mind, and cant chase ATM - UNLESS they have the obj! Always chase them!

	vec = enemyInfo.enemy_LS_Pos - botInfo->origin;
	
	if ( vec.LengthSqr() > Square( ENEMY_CHASE_DIST ) ) {
		return false;
	} // too far away to chase

	vec = enemyInfo.enemy_LS_Pos - botWorld->clientInfo[ enemy ].origin;

	if ( vec.LengthSqr() > Square( 900.0f ) && !ClientHasObj( enemy ) && !Client_IsCriticalForCurrentObj( enemy, 1500.0f ) ) { // unless he's REALLY close or a threat, sometimes we'll stop the chase, just because....
		if ( botThreadData.random.RandomInt( 100 ) > 50 ) {
            return false;
		}
	}

	chasingEnemy = true;

	if ( ClientHasObj( enemy ) ) {
		chaseEnemyTime = botWorld->gameLocalInfo.time + 30000;
	} else if ( Client_IsCriticalForCurrentObj( enemy, 1500.0f ) ) {
		chaseEnemyTime = botWorld->gameLocalInfo.time + 15000;
	} else {
		chaseEnemyTime = botWorld->gameLocalInfo.time + 7000;
	}

	return true;
}
コード例 #22
0
ファイル: Fx.cpp プロジェクト: revelator/MHDoom
/*
================
idEntityFx::Run
================
*/
void idEntityFx::Run( int time )
{
	int ieff, j;
	idEntity *ent = NULL;
	const idDict *projectileDef = NULL;
	idProjectile *projectile = NULL;
	
	if( !fxEffect )
	{
		return;
	}
	
	for( ieff = 0; ieff < fxEffect->events.Num(); ieff++ )
	{
		const idFXSingleAction &fxaction = fxEffect->events[ieff];
		idFXLocalAction &laction = actions[ieff];
		
		//
		// if we're currently done with this one
		//
		if( laction.start == -1 )
		{
			continue;
		}
		
		//
		// see if it's delayed
		//
		if( laction.delay )
		{
			if( laction.start + ( time - laction.start ) < laction.start + ( laction.delay * 1000 ) )
			{
				continue;
			}
		}
		
		//
		// each event can have it's own delay and restart
		//
		int actualStart = laction.delay ? laction.start + ( int )( laction.delay * 1000 ) : laction.start;
		float pct = ( float )( time - actualStart ) / ( 1000 * fxaction.duration );
		if( pct >= 1.0f )
		{
			laction.start = -1;
			float totalDelay = 0.0f;
			if( fxaction.restart )
			{
				if( fxaction.random1 || fxaction.random2 )
				{
					totalDelay = fxaction.random1 + gameLocal.random.RandomFloat() * ( fxaction.random2 - fxaction.random1 );
				}
				else
				{
					totalDelay = fxaction.delay;
				}
				laction.delay = totalDelay;
				laction.start = time;
			}
			continue;
		}
		
		if( fxaction.fire.Length() )
		{
			for( j = 0; j < fxEffect->events.Num(); j++ )
			{
				if( fxEffect->events[j].name.Icmp( fxaction.fire ) == 0 )
				{
					actions[j].delay = 0;
				}
			}
		}
		
		idFXLocalAction *useAction;
		if( fxaction.sibling == -1 )
		{
			useAction = &laction;
		}
		else
		{
			useAction = &actions[fxaction.sibling];
		}
		assert( useAction );
		
		switch( fxaction.type )
		{
			case FX_ATTACHLIGHT:
			case FX_LIGHT:
			{
				if( useAction->lightDefHandle == -1 )
				{
					if( fxaction.type == FX_LIGHT )
					{
						memset( &useAction->renderLight, 0, sizeof( renderLight_t ) );
						useAction->renderLight.origin = GetPhysics()->GetOrigin() + fxaction.offset;
						useAction->renderLight.axis = GetPhysics()->GetAxis();
						useAction->renderLight.lightRadius[0] = fxaction.lightRadius;
						useAction->renderLight.lightRadius[1] = fxaction.lightRadius;
						useAction->renderLight.lightRadius[2] = fxaction.lightRadius;
						useAction->renderLight.shader = declManager->FindMaterial( fxaction.data, false );
						useAction->renderLight.shaderParms[ SHADERPARM_RED ]	= fxaction.lightColor.x;
						useAction->renderLight.shaderParms[ SHADERPARM_GREEN ]	= fxaction.lightColor.y;
						useAction->renderLight.shaderParms[ SHADERPARM_BLUE ]	= fxaction.lightColor.z;
						useAction->renderLight.shaderParms[ SHADERPARM_TIMESCALE ]	= 1.0f;
						useAction->renderLight.shaderParms[ SHADERPARM_TIMEOFFSET ] = -MS2SEC( time );
						useAction->renderLight.referenceSound = refSound.referenceSound;
						useAction->renderLight.pointLight = true;
						if( fxaction.noshadows )
						{
							useAction->renderLight.noShadows = true;
						}
						useAction->lightDefHandle = gameRenderWorld->AddLightDef( &useAction->renderLight );
					}
					if( fxaction.noshadows )
					{
						for( j = 0; j < fxEffect->events.Num(); j++ )
						{
							idFXLocalAction &laction2 = actions[j];
							if( laction2.modelDefHandle != -1 )
							{
								laction2.renderEntity.noShadow = true;
							}
						}
					}
				}
				ApplyFade( fxaction, *useAction, time, actualStart );
				break;
			}
			case FX_SOUND:
			{
				if( !useAction->soundStarted )
				{
					useAction->soundStarted = true;
					const idSoundShader *shader = declManager->FindSound( fxaction.data );
					StartSoundShader( shader, SND_CHANNEL_ANY, 0, false, NULL );
					for( j = 0; j < fxEffect->events.Num(); j++ )
					{
						idFXLocalAction &laction2 = actions[j];
						if( laction2.lightDefHandle != -1 )
						{
							laction2.renderLight.referenceSound = refSound.referenceSound;
							gameRenderWorld->UpdateLightDef( laction2.lightDefHandle, &laction2.renderLight );
						}
					}
				}
				break;
			}
			case FX_DECAL:
			{
				if( !useAction->decalDropped )
				{
					useAction->decalDropped = true;
					gameLocal.ProjectDecal( GetPhysics()->GetOrigin(), GetPhysics()->GetGravity(), 8.0f, true, fxaction.size, fxaction.data );
				}
				break;
			}
			case FX_SHAKE:
			{
				if( !useAction->shakeStarted )
				{
					idDict args;
					args.Clear();
					args.SetFloat( "kick_time", fxaction.shakeTime );
					args.SetFloat( "kick_amplitude", fxaction.shakeAmplitude );
					for( j = 0; j < gameLocal.numClients; j++ )
					{
						idPlayer *player = gameLocal.GetClientByNum( j );
						if( player && ( player->GetPhysics()->GetOrigin() - GetPhysics()->GetOrigin() ).LengthSqr() < Square( fxaction.shakeDistance ) )
						{
							if( !gameLocal.isMultiplayer || !fxaction.shakeIgnoreMaster || GetBindMaster() != player )
							{
								player->playerView.DamageImpulse( fxaction.offset, &args );
							}
						}
					}
					if( fxaction.shakeImpulse != 0.0f && fxaction.shakeDistance != 0.0f )
					{
						idEntity *ignore_ent = NULL;
						if( gameLocal.isMultiplayer )
						{
							ignore_ent = this;
							if( fxaction.shakeIgnoreMaster )
							{
								ignore_ent = GetBindMaster();
							}
						}
						// lookup the ent we are bound to?
						gameLocal.RadiusPush( GetPhysics()->GetOrigin(), fxaction.shakeDistance, fxaction.shakeImpulse, this, ignore_ent, 1.0f, true );
					}
					useAction->shakeStarted = true;
				}
				break;
			}
			case FX_ATTACHENTITY:
			case FX_PARTICLE:
			case FX_MODEL:
			{
				if( useAction->modelDefHandle == -1 )
				{
					memset( &useAction->renderEntity, 0, sizeof( renderEntity_t ) );
					useAction->renderEntity.origin = GetPhysics()->GetOrigin() + fxaction.offset;
					useAction->renderEntity.axis = ( fxaction.explicitAxis ) ? fxaction.axis : GetPhysics()->GetAxis();
					useAction->renderEntity.hModel = renderModelManager->FindModel( fxaction.data );
					useAction->renderEntity.shaderParms[ SHADERPARM_RED ]		= 1.0f;
					useAction->renderEntity.shaderParms[ SHADERPARM_GREEN ]		= 1.0f;
					useAction->renderEntity.shaderParms[ SHADERPARM_BLUE ]		= 1.0f;
					useAction->renderEntity.shaderParms[ SHADERPARM_TIMEOFFSET ] = -MS2SEC( time );
					useAction->renderEntity.shaderParms[3] = 1.0f;
					useAction->renderEntity.shaderParms[5] = 0.0f;
					if( useAction->renderEntity.hModel )
					{
						useAction->renderEntity.bounds = useAction->renderEntity.hModel->Bounds( &useAction->renderEntity );
					}
					useAction->modelDefHandle = gameRenderWorld->AddEntityDef( &useAction->renderEntity );
				}
				else if( fxaction.trackOrigin )
				{
					useAction->renderEntity.origin = GetPhysics()->GetOrigin() + fxaction.offset;
					useAction->renderEntity.axis = fxaction.explicitAxis ? fxaction.axis : GetPhysics()->GetAxis();
#ifdef _D3XP
					gameRenderWorld->UpdateEntityDef( useAction->modelDefHandle, &useAction->renderEntity );
#endif
				}
				ApplyFade( fxaction, *useAction, time, actualStart );
				break;
			}
			case FX_LAUNCH:
			{
				if( gameLocal.isClient )
				{
					// client never spawns entities outside of ClientReadSnapshot
					useAction->launched = true;
					break;
				}
				if( !useAction->launched )
				{
					useAction->launched = true;
					projectile = NULL;
					// FIXME: may need to cache this if it is slow
					projectileDef = gameLocal.FindEntityDefDict( fxaction.data, false );
					if( !projectileDef )
					{
						gameLocal.Warning( "projectile \'%s\' not found", fxaction.data.c_str() );
					}
					else
					{
						gameLocal.SpawnEntityDef( *projectileDef, &ent, false );
						if( ent && ent->IsType( idProjectile::Type ) )
						{
							projectile = ( idProjectile * )ent;
							projectile->Create( this, GetPhysics()->GetOrigin(), GetPhysics()->GetAxis()[0] );
							projectile->Launch( GetPhysics()->GetOrigin(), GetPhysics()->GetAxis()[0], vec3_origin );
						}
					}
				}
				break;
			}
#ifdef _D3XP
			case FX_SHOCKWAVE:
			{
				if( gameLocal.isClient )
				{
					useAction->shakeStarted = true;
					break;
				}
				if( !useAction->shakeStarted )
				{
					idStr	shockDefName;
					useAction->shakeStarted = true;
					
					shockDefName = fxaction.data;
					if( !shockDefName.Length() )
					{
						shockDefName = "func_shockwave";
					}
					
					projectileDef = gameLocal.FindEntityDefDict( shockDefName, false );
					if( !projectileDef )
					{
						gameLocal.Warning( "shockwave \'%s\' not found", shockDefName.c_str() );
					}
					else
					{
						gameLocal.SpawnEntityDef( *projectileDef, &ent );
						ent->SetOrigin( GetPhysics()->GetOrigin() + fxaction.offset );
						ent->PostEventMS( &EV_Remove, ent->spawnArgs.GetInt( "duration" ) );
					}
				}
				break;
			}
#endif
		}
	}
}
コード例 #23
0
// Returns an intersection if found with distance maxDistance
// viewDir must be a unit vector.
// intersectDistance and visPoint are returned values.
bool ViewableSphere::FindIntersectionNT ( 
		const VectorR3& viewPos, const VectorR3& viewDir, double maxDist,
		double *intersectDistance, VisiblePoint& returnedPoint ) const 
{
	VectorR3 tocenter(Center);
	tocenter -= viewPos;		// Vector view position to the center

	// D = Distance to pt on view line closest to sphere
	// v = vector from sphere center to the closest pt on view line
	// ASq = the distance from v to sphere center squared
	double D = (viewDir^tocenter);
	VectorR3 v(viewDir);
	v *= D;
	v -= tocenter;
	double ASq = v.NormSq();

	// Ray-line completely misses sphere, or just grazes it.
	if ( ASq >= RadiusSq ) {
		return false;
	}

	double BSq = RadiusSq-ASq;
	if ( D>0.0 && D*D>BSq && 
		(D<maxDist || BSq>Square(D-maxDist) ) ) {
		
		// Return the point where view intersects with the outside of
		//		the sphere.
		*intersectDistance = D-sqrt(BSq);
		v = viewDir;
		v *= *intersectDistance;
		v += viewPos;					//  Position of intersection
		returnedPoint.SetPosition( v );
		v -= Center;					
		v /= Radius;	// Normalize: normal out from intersection pt
		v.ReNormalize();
		returnedPoint.SetNormal( v );
		returnedPoint.SetMaterial ( *OuterMaterial );
		returnedPoint.SetFrontFace();	// Front face direction
		CalcUV( v, &(returnedPoint.GetUV()) );
		returnedPoint.SetFaceNumber( 0 );
		return true;
	}

	else if ( (D>0.0 || D*D<BSq) && D<maxDist && BSq<Square(D-maxDist) ) {

		// return the point where view exits the sphere
		*intersectDistance = D+sqrt(BSq);
		v = viewDir;
		v *= *intersectDistance;
		v += viewPos;
		returnedPoint.SetPosition( v );
		v -= Center;
		v /= Radius;	// Normalize, but still points outward
		v.ReNormalize(); // Just in case
		returnedPoint.SetNormal( v );
		returnedPoint.SetMaterial ( *InnerMaterial );
		returnedPoint.SetBackFace();
		CalcUV( v, &(returnedPoint.GetUV()) );
		return true;
	}

	else {
		return false;
	}
}
コード例 #24
0
void UOpenALAudioSubsystem::Update( FPointRegion Region, FCoords& Coords )
{
	guard(UOpenALAudioSubsystem::Update);

	if( !Viewport )
		return;

	AActor *ViewActor = FindViewActor();

	guard(UpdateMusic);
	if( Viewport->Actor->Song != PlayingSong )
	{
		StopMusic();
		PlayingSong = Viewport->Actor->Song;
		if( PlayingSong != NULL )
		{
			MODULE* Module = GetModuleFromUMusic( PlayingSong );
			Player_Start( Module );
		}
	}
	if( Player_Active() )
		MikMod_Update();
	unguard;

	// Update the listener.
	{
		FVector At = ViewActor->Rotation.Vector();
		FVector Up = -(GMath.UnitCoords / ViewActor->Rotation).ZAxis;
		FLOAT Orientation[6] = { At.X, At.Y, At.Z, Up.X, Up.Y, Up.Z };
		alListenerfv( AL_POSITION,		&ViewActor->Location.X );
		alListenerfv( AL_VELOCITY,		&ViewActor->Velocity.X );
		alListenerfv( AL_ORIENTATION,	Orientation );
	}

	// See if any new ambient sounds need to be started.
	UBOOL Realtime = Viewport->IsRealtime() && Viewport->Actor->Level->Pauser==TEXT("");
	if( Realtime )
	{
		guard(StartAmbience);
		for( INT i=0; i<Viewport->Actor->GetLevel()->Actors.Num(); i++ )
		{
			AActor* Actor = Viewport->Actor->GetLevel()->Actors(i);
			if
			(	Actor
			&&	Actor->AmbientSound
			&&	FDistSquared(ViewActor->Location,Actor->Location)<=Square(Actor->WorldSoundRadius()) )
			{
				INT Slot = Actor->GetIndex()*16+SLOT_Ambient*2;
				INT j;
				// See if there's already an existing slot.
				for( j=0; j<NumSources; j++ )
					if( Sources[j].Slot==Slot )
						break;
				// If not, start playing.
				if( j==NumSources )
					PlaySound(
						Actor, Slot, Actor->AmbientSound, Actor->Location,
						AmbientFactor*Actor->SoundVolume/255.0,
						Actor->WorldSoundRadius(),
						Actor->SoundPitch/64.0,
						1 );
			}
		}
		unguard;
	}

	// Update all playing ambient sounds.
	guard(UpdateAmbience);
	for( INT i=0; i<NumSources; i++ )
	{
		FAudioSource& Source = Sources[i];
		if( (Source.Slot&14)==SLOT_Ambient*2 )
		{
			check(Source.Actor);
			if
			(	FDistSquared(ViewActor->Location,Source.Actor->Location)>Square(Source.Actor->WorldSoundRadius())
			||	Source.Actor->AmbientSound!=Source.Sound 
			||  !Realtime )
			{
				// Ambient sound went out of range.
				StopSource( Source );
			}
			else
			{
				// Update basic sound properties.
				FLOAT Volume = 2.0 * (AmbientFactor*Source.Actor->SoundVolume/255.0);
				// XXX: Huh? What does light brightness have to do with it?
				if( Source.Actor->LightType!=LT_None )
					Volume *= Source.Actor->LightBrightness/255.0;
				Source.Volume = Volume;
				Source.Radius = Source.Actor->WorldSoundRadius();

				const ALuint Id = Source.Id;
				alSourcef( Id, AL_GAIN,			Source.Volume );
				alSourcef( Id, AL_MAX_DISTANCE,	Source.Radius );
				alSourcef( Id, AL_PITCH,		Source.Actor->SoundPitch/64.0 );
			}
		}
	}
	unguard;

	// Update all active sounds.
	guard(UpdateSounds);
	for( INT Index=0; Index<NumSources; Index++ )
	{
		FAudioSource& Source = Sources[Index];

		// We should've been notified about this.
		if( Source.Actor )
			check(Source.Actor->IsValid());

		// Check if the sound is playing.
		if( Source.Slot==0 )
			continue;

		// Check if the sound is finished.
		ALint state;
		alGetSourcei( Source.Id, AL_SOURCE_STATE, &state );
		if( state==AL_STOPPED )
		{
			StopSource( Source );
			continue;
		}

		// Update positioning from actor, if available.
		if( Source.Actor )
		{
			Source.Location = Source.Actor->Location;
			alSourcefv( Source.Id, AL_POSITION, &Source.Actor->Location.X );
			alSourcefv( Source.Id, AL_VELOCITY, &Source.Actor->Velocity.X );
		}

		// Update the priority.
		Source.Priority = SoundPriority( Source.Location, Source.Volume, Source.Radius );
	}
	unguard;

	unguard;
}
コード例 #25
0
ファイル: gamerules.cpp プロジェクト: Rahmstein/IOS
void CGameRules::RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrcIn, float flRadius, int iClassIgnore, CBaseEntity *pEntityIgnore )
{
	const int MASK_RADIUS_DAMAGE = MASK_SHOT&(~CONTENTS_HITBOX);
	CBaseEntity *pEntity = NULL;
	trace_t		tr;
	float		flAdjustedDamage, falloff;
	Vector		vecSpot;

	Vector vecSrc = vecSrcIn;

	if ( flRadius )
		falloff = info.GetDamage() / flRadius;
	else
		falloff = 1.0;

	int bInWater = (UTIL_PointContents ( vecSrc ) & MASK_WATER) ? true : false;

#ifdef HL2_DLL
	if( bInWater )
	{
		// Only muffle the explosion if deeper than 2 feet in water.
		if( !(UTIL_PointContents(vecSrc + Vector(0, 0, 24)) & MASK_WATER) )
		{
			bInWater = false;
		}
	}
#endif // HL2_DLL
	
	vecSrc.z += 1;// in case grenade is lying on the ground

	float flHalfRadiusSqr = Square( flRadius / 2.0f );

	// iterate on all entities in the vicinity.
	for ( CEntitySphereQuery sphere( vecSrc, flRadius ); (pEntity = sphere.GetCurrentEntity()) != NULL; sphere.NextEntity() )
	{
		// This value is used to scale damage when the explosion is blocked by some other object.
		float flBlockedDamagePercent = 0.0f;

		if ( pEntity == pEntityIgnore )
			continue;

		if ( pEntity->m_takedamage == DAMAGE_NO )
			continue;

		// UNDONE: this should check a damage mask, not an ignore
		if ( iClassIgnore != CLASS_NONE && pEntity->Classify() == iClassIgnore )
		{// houndeyes don't hurt other houndeyes with their attack
			continue;
		}

		// blast's don't tavel into or out of water
		if (bInWater && pEntity->GetWaterLevel() == 0)
			continue;

		if (!bInWater && pEntity->GetWaterLevel() == 3)
			continue;

		// Check that the explosion can 'see' this entity.
		vecSpot = pEntity->BodyTarget( vecSrc, false );
		UTIL_TraceLine( vecSrc, vecSpot, MASK_RADIUS_DAMAGE, info.GetInflictor(), COLLISION_GROUP_NONE, &tr );

		if( old_radius_damage.GetBool() )
		{
			if ( tr.fraction != 1.0 && tr.m_pEnt != pEntity )
			continue;
		}
		else
		{
			if ( tr.fraction != 1.0 )
			{
				if ( IsExplosionTraceBlocked(&tr) )
				{
					if( ShouldUseRobustRadiusDamage( pEntity ) )
					{
						if( vecSpot.DistToSqr( vecSrc ) > flHalfRadiusSqr )
						{
							// Only use robust model on a target within one-half of the explosion's radius.
							continue;
						}

						Vector vecToTarget = vecSpot - tr.endpos;
						VectorNormalize( vecToTarget );

						// We're going to deflect the blast along the surface that 
						// interrupted a trace from explosion to this target.
						Vector vecUp, vecDeflect;
						CrossProduct( vecToTarget, tr.plane.normal, vecUp );
						CrossProduct( tr.plane.normal, vecUp, vecDeflect );
						VectorNormalize( vecDeflect );

						// Trace along the surface that intercepted the blast...
						UTIL_TraceLine( tr.endpos, tr.endpos + vecDeflect * ROBUST_RADIUS_PROBE_DIST, MASK_RADIUS_DAMAGE, info.GetInflictor(), COLLISION_GROUP_NONE, &tr );
						//NDebugOverlay::Line( tr.startpos, tr.endpos, 255, 255, 0, false, 10 );

						// ...to see if there's a nearby edge that the explosion would 'spill over' if the blast were fully simulated.
						UTIL_TraceLine( tr.endpos, vecSpot, MASK_RADIUS_DAMAGE, info.GetInflictor(), COLLISION_GROUP_NONE, &tr );
						//NDebugOverlay::Line( tr.startpos, tr.endpos, 255, 0, 0, false, 10 );

						if( tr.fraction != 1.0 && tr.DidHitWorld() )
						{
							// Still can't reach the target.
							continue;
						}
						// else fall through
					}
					else
					{
						continue;
					}
				}

				// UNDONE: Probably shouldn't let children block parents either?  Or maybe those guys should set their owner if they want this behavior?
				// HL2 - Dissolve damage is not reduced by interposing non-world objects
				if( tr.m_pEnt && tr.m_pEnt != pEntity && tr.m_pEnt->GetOwnerEntity() != pEntity )
				{
					// Some entity was hit by the trace, meaning the explosion does not have clear
					// line of sight to the entity that it's trying to hurt. If the world is also
					// blocking, we do no damage.
					CBaseEntity *pBlockingEntity = tr.m_pEnt;
					//Msg( "%s may be blocked by %s...", pEntity->GetClassname(), pBlockingEntity->GetClassname() );

					UTIL_TraceLine( vecSrc, vecSpot, CONTENTS_SOLID, info.GetInflictor(), COLLISION_GROUP_NONE, &tr );

					if( tr.fraction != 1.0 )
					{
						continue;
					}
					
					// Now, if the interposing object is physics, block some explosion force based on its mass.
					if( pBlockingEntity->VPhysicsGetObject() )
					{
						const float MASS_ABSORB_ALL_DAMAGE = 350.0f;
						float flMass = pBlockingEntity->VPhysicsGetObject()->GetMass();
						float scale = flMass / MASS_ABSORB_ALL_DAMAGE;

						// Absorbed all the damage.
						if( scale >= 1.0f )
						{
							continue;
						}

						ASSERT( scale > 0.0f );
						flBlockedDamagePercent = scale;
						//Msg("  Object (%s) weighing %fkg blocked %f percent of explosion damage\n", pBlockingEntity->GetClassname(), flMass, scale * 100.0f);
					}
					else
					{
						// Some object that's not the world and not physics. Generically block 25% damage
						flBlockedDamagePercent = 0.25f;
					}
				}
			}
		}
		// decrease damage for an ent that's farther from the bomb.
		flAdjustedDamage = ( vecSrc - tr.endpos ).Length() * falloff;
		flAdjustedDamage = info.GetDamage() - flAdjustedDamage;

		if ( flAdjustedDamage <= 0 )
		{
			continue;
		}

		// the explosion can 'see' this entity, so hurt them!
		if (tr.startsolid)
		{
			// if we're stuck inside them, fixup the position and distance
			tr.endpos = vecSrc;
			tr.fraction = 0.0;
		}
		
		CTakeDamageInfo adjustedInfo = info;
		//Msg("%s: Blocked damage: %f percent (in:%f  out:%f)\n", pEntity->GetClassname(), flBlockedDamagePercent * 100, flAdjustedDamage, flAdjustedDamage - (flAdjustedDamage * flBlockedDamagePercent) );
		adjustedInfo.SetDamage( flAdjustedDamage - (flAdjustedDamage * flBlockedDamagePercent) );

		// Now make a consideration for skill level!
		if( info.GetAttacker() && info.GetAttacker()->IsPlayer() && pEntity->IsNPC() )
		{
			// An explosion set off by the player is harming an NPC. Adjust damage accordingly.
			adjustedInfo.AdjustPlayerDamageInflictedForSkillLevel();
		}

		Vector dir = vecSpot - vecSrc;
		VectorNormalize( dir );

		// If we don't have a damage force, manufacture one
		if ( adjustedInfo.GetDamagePosition() == vec3_origin || adjustedInfo.GetDamageForce() == vec3_origin )
		{
			if ( !( adjustedInfo.GetDamageType() & DMG_PREVENT_PHYSICS_FORCE ) )
			{
				CalculateExplosiveDamageForce( &adjustedInfo, dir, vecSrc );
			}
		}
		else
		{
			// Assume the force passed in is the maximum force. Decay it based on falloff.
			float flForce = adjustedInfo.GetDamageForce().Length() * falloff;
			adjustedInfo.SetDamageForce( dir * flForce );
			adjustedInfo.SetDamagePosition( vecSrc );
		}

		if ( tr.fraction != 1.0 && pEntity == tr.m_pEnt )
		{
			ClearMultiDamage( );
			pEntity->DispatchTraceAttack( adjustedInfo, dir, &tr );
			ApplyMultiDamage();
		}
		else
		{
			pEntity->TakeDamage( adjustedInfo );
		}

		// Now hit all triggers along the way that respond to damage... 
		pEntity->TraceAttackToTriggers( adjustedInfo, vecSrc, tr.endpos, dir );

#if defined( GAME_DLL )
		if ( info.GetAttacker() && info.GetAttacker()->IsPlayer() && ToBaseCombatCharacter( tr.m_pEnt ) )
		{

			// This is a total hack!!!
			bool bIsPrimary = true;
			CBasePlayer *player = ToBasePlayer( info.GetAttacker() );
			CBaseCombatWeapon *pWeapon = player->GetActiveWeapon();
			if ( pWeapon && FClassnameIs( pWeapon, "weapon_smg1" ) )
			{
				bIsPrimary = false;
			}

			gamestats->Event_WeaponHit( player, bIsPrimary, (pWeapon != NULL) ? player->GetActiveWeapon()->GetClassname() : "NULL", info );
		}
#endif
	}
}
コード例 #26
0
ファイル: Surface_Patch.cpp プロジェクト: Kaan88/doom3.gpl
/*
=================
idSurface_Patch::Subdivide
=================
*/
void idSurface_Patch::Subdivide( float maxHorizontalError, float maxVerticalError, float maxLength, bool genNormals ) {
	int			i, j, k, l;
	idDrawVert	prev, next, mid;
	idVec3		prevxyz, nextxyz, midxyz;
	idVec3		delta;
	float		maxHorizontalErrorSqr, maxVerticalErrorSqr, maxLengthSqr;

	// generate normals for the control mesh
	if ( genNormals ) {
		GenerateNormals();
	}

	maxHorizontalErrorSqr = Square( maxHorizontalError );
	maxVerticalErrorSqr = Square( maxVerticalError );
	maxLengthSqr = Square( maxLength );

	Expand();

	// horizontal subdivisions
	for ( j = 0; j + 2 < width; j += 2 ) {
		// check subdivided midpoints against control points
		for ( i = 0; i < height; i++ ) {
			for ( l = 0; l < 3; l++ ) {
				prevxyz[l] = verts[i*maxWidth + j+1].xyz[l] - verts[i*maxWidth + j  ].xyz[l];
				nextxyz[l] = verts[i*maxWidth + j+2].xyz[l] - verts[i*maxWidth + j+1].xyz[l];
				midxyz[l] = (verts[i*maxWidth + j  ].xyz[l] + verts[i*maxWidth + j+1].xyz[l] * 2.0f +
														   verts[i*maxWidth + j+2].xyz[l] ) * 0.25f;
			}

			if ( maxLength > 0.0f ) {
				// if the span length is too long, force a subdivision
				if ( prevxyz.LengthSqr() > maxLengthSqr || nextxyz.LengthSqr() > maxLengthSqr ) {
					break;
				}
			}
			// see if this midpoint is off far enough to subdivide
			delta = verts[i*maxWidth + j+1].xyz - midxyz;
			if ( delta.LengthSqr() > maxHorizontalErrorSqr ) {
				break;
			}
		}

		if ( i == height ) {
			continue;	// didn't need subdivision
		}

		if ( width + 2 >= maxWidth ) {
			ResizeExpanded( maxHeight, maxWidth + 4 );
		}

		// insert two columns and replace the peak
		width += 2;

		for ( i = 0; i < height; i++ ) {
			idSurface_Patch::LerpVert( verts[i*maxWidth + j  ], verts[i*maxWidth + j+1], prev );
			idSurface_Patch::LerpVert( verts[i*maxWidth + j+1], verts[i*maxWidth + j+2], next );
			idSurface_Patch::LerpVert( prev, next, mid );

			for ( k = width - 1; k > j + 3; k-- ) {
				verts[i*maxWidth + k] = verts[i*maxWidth + k-2];
			}
			verts[i*maxWidth + j+1] = prev;
			verts[i*maxWidth + j+2] = mid;
			verts[i*maxWidth + j+3] = next;
		}

		// back up and recheck this set again, it may need more subdivision
		j -= 2;
	}

	// vertical subdivisions
	for ( j = 0; j + 2 < height; j += 2 ) {
		// check subdivided midpoints against control points
		for ( i = 0; i < width; i++ ) {
			for ( l = 0; l < 3; l++ ) {
				prevxyz[l] = verts[(j+1)*maxWidth + i].xyz[l] - verts[j*maxWidth + i].xyz[l];
				nextxyz[l] = verts[(j+2)*maxWidth + i].xyz[l] - verts[(j+1)*maxWidth + i].xyz[l];
				midxyz[l] = (verts[j*maxWidth + i].xyz[l] + verts[(j+1)*maxWidth + i].xyz[l] * 2.0f +
														verts[(j+2)*maxWidth + i].xyz[l] ) * 0.25f;
			}

			if ( maxLength > 0.0f ) {
				// if the span length is too long, force a subdivision
				if ( prevxyz.LengthSqr() > maxLengthSqr || nextxyz.LengthSqr() > maxLengthSqr ) {
					break;
				}
			}
			// see if this midpoint is off far enough to subdivide
			delta = verts[(j+1)*maxWidth + i].xyz - midxyz;
			if ( delta.LengthSqr() > maxVerticalErrorSqr ) {
				break;
			}
		}

		if ( i == width ) {
			continue;	// didn't need subdivision
		}

		if ( height + 2 >= maxHeight ) {
			ResizeExpanded( maxHeight + 4, maxWidth );
		}

		// insert two columns and replace the peak
		height += 2;

		for ( i = 0; i < width; i++ ) {
			LerpVert( verts[j*maxWidth + i], verts[(j+1)*maxWidth + i], prev );
			LerpVert( verts[(j+1)*maxWidth + i], verts[(j+2)*maxWidth + i], next );
			LerpVert( prev, next, mid );

			for ( k = height - 1; k > j + 3; k-- ) {
				verts[k*maxWidth + i] = verts[(k-2)*maxWidth + i];
			}
			verts[(j+1)*maxWidth + i] = prev;
			verts[(j+2)*maxWidth + i] = mid;
			verts[(j+3)*maxWidth + i] = next;
		}

		// back up and recheck this set again, it may need more subdivision
		j -= 2;
	}

	PutOnCurve();

	RemoveLinearColumnsRows();

	Collapse();

	// normalize all the lerped normals
	if ( genNormals ) {
		for ( i = 0; i < width * height; i++ ) {
			verts[i].normal.Normalize();
		}
	}

	GenerateIndexes();
}
コード例 #27
0
 void Errors(const Model & model, std::vector<double> & vec_errors) const
 {
   vec_errors.resize(x1_.cols());
   for (size_t sample = 0; sample < x1_.cols(); ++sample)
     vec_errors[sample] = Square(ErrorT::Error(model, x1_.col(sample), x2_.col(sample)));
 }
コード例 #28
0
/* determine if two extraction areas overlap */
bool CExtractorBuilding::IsNeighbour(CExtractorBuilding* other)
{
	// circle vs. circle
	return (this->pos.SqDistance2D(other->pos) < Square(this->extractionRange + other->extractionRange));
}
コード例 #29
0
void idSurface_Patch::GenerateNormals( void ) {
	int			i, j, k, dist;
	idVec3		norm;
	idVec3		sum;
	int			count;
	idVec3		base;
	idVec3		delta;
	int			x, y;
	idVec3		around[8], temp;
	bool		good[8];
	bool		wrapWidth, wrapHeight;
	static int	neighbors[8][2] = {
		{0,1}, {1,1}, {1,0}, {1,-1}, {0,-1}, {-1,-1}, {-1,0}, {-1,1}
	};

	assert( expanded == false );

	//
	// if all points are coplanar, set all normals to that plane
	//
	idVec3		extent[3];
	float		offset;
	
	extent[0] = verts[width - 1].xyz - verts[0].xyz;
	extent[1] = verts[(height-1) * width + width - 1].xyz - verts[0].xyz;
	extent[2] = verts[(height-1) * width].xyz - verts[0].xyz;

	norm = extent[0].Cross( extent[1] );
	if ( norm.LengthSqr() == 0.0f ) {
		norm = extent[0].Cross( extent[2] );
		if ( norm.LengthSqr() == 0.0f ) {
			norm = extent[1].Cross( extent[2] );
		}
	}

	// wrapped patched may not get a valid normal here
	if ( norm.Normalize() != 0.0f ) {

		offset = verts[0].xyz * norm;
		for ( i = 1; i < width * height; i++ ) {
			float d = verts[i].xyz * norm;
			if ( idMath::Fabs( d - offset ) > COPLANAR_EPSILON ) {
				break;
			}
		}

		if ( i == width * height ) {
			// all are coplanar
			for ( i = 0; i < width * height; i++ ) {
				verts[i].normal = norm;
			}
			return;
		}
	}

	// check for wrapped edge cases, which should smooth across themselves
	wrapWidth = false;
	for ( i = 0; i < height; i++ ) {
		delta = verts[i * width].xyz - verts[i * width + width-1].xyz;
		if ( delta.LengthSqr() > Square( 1.0f ) ) {
			break;
		}
	}
	if ( i == height ) {
		wrapWidth = true;
	}

	wrapHeight = false;
	for ( i = 0; i < width; i++ ) {
		delta = verts[i].xyz - verts[(height-1) * width + i].xyz;
		if ( delta.LengthSqr() > Square( 1.0f ) ) {
			break;
		}
	}
	if ( i == width ) {
		wrapHeight = true;
	}

	for ( i = 0; i < width; i++ ) {
		for ( j = 0; j < height; j++ ) {
			count = 0;
			base = verts[j * width + i].xyz;
			for ( k = 0; k < 8; k++ ) {
				around[k] = vec3_origin;
				good[k] = false;

				for ( dist = 1; dist <= 3; dist++ ) {
					x = i + neighbors[k][0] * dist;
					y = j + neighbors[k][1] * dist;
					if ( wrapWidth ) {
						if ( x < 0 ) {
							x = width - 1 + x;
						} else if ( x >= width ) {
							x = 1 + x - width;
						}
					}
					if ( wrapHeight ) {
						if ( y < 0 ) {
							y = height - 1 + y;
						} else if ( y >= height ) {
							y = 1 + y - height;
						}
					}

					if ( x < 0 || x >= width || y < 0 || y >= height ) {
						break;					// edge of patch
					}
					temp = verts[y * width + x].xyz - base;
					if ( temp.Normalize() == 0.0f ) {
						continue;				// degenerate edge, get more dist
					} else {
						good[k] = true;
						around[k] = temp;
						break;					// good edge
					}
				}
			}

			sum = vec3_origin;
			for ( k = 0; k < 8; k++ ) {
				if ( !good[k] || !good[(k+1)&7] ) {
					continue;	// didn't get two points
				}
				norm = around[(k+1)&7].Cross( around[k] );
				if ( norm.Normalize() == 0.0f ) {
					continue;
				}
				sum += norm;
				count++;
			}
			if ( count == 0 ) {
				//idLib::common->Printf("bad normal\n");
				count = 1;
			}
			verts[j * width + i].normal = sum;
			verts[j * width + i].normal.Normalize();
		}
	}
}
コード例 #30
0
ファイル: AI_pathing.cpp プロジェクト: bagobor/doom3.gpl
/*
============
idAI::FindPathAroundObstacles

  Finds a path around dynamic obstacles using a path tree with clockwise and counter clockwise edge walks.
============
*/
bool idAI::FindPathAroundObstacles( const idPhysics *physics, const idAAS *aas, const idEntity *ignore, const idVec3 &startPos, const idVec3 &seekPos, obstaclePath_t &path ) {
	int numObstacles, areaNum, insideObstacle;
	obstacle_t obstacles[MAX_OBSTACLES];
	idBounds clipBounds;
	idBounds bounds;
	pathNode_t *root;
	bool pathToGoalExists;

	path.seekPos = seekPos;
	path.firstObstacle = NULL;
	path.startPosOutsideObstacles = startPos;
	path.startPosObstacle = NULL;
	path.seekPosOutsideObstacles = seekPos;
	path.seekPosObstacle = NULL;

	if ( !aas ) {
		return true;
	}

	bounds[1] = aas->GetSettings()->boundingBoxes[0][1];
	bounds[0] = -bounds[1];
	bounds[1].z = 32.0f;

	// get the AAS area number and a valid point inside that area
	areaNum = aas->PointReachableAreaNum( path.startPosOutsideObstacles, bounds, (AREA_REACHABLE_WALK|AREA_REACHABLE_FLY) );
	aas->PushPointIntoAreaNum( areaNum, path.startPosOutsideObstacles );

	// get all the nearby obstacles
	numObstacles = GetObstacles( physics, aas, ignore, areaNum, path.startPosOutsideObstacles, path.seekPosOutsideObstacles, obstacles, MAX_OBSTACLES, clipBounds );

	// get a source position outside the obstacles
	GetPointOutsideObstacles( obstacles, numObstacles, path.startPosOutsideObstacles.ToVec2(), &insideObstacle, NULL );
	if ( insideObstacle != -1 ) {
		path.startPosObstacle = obstacles[insideObstacle].entity;
	}

	// get a goal position outside the obstacles
	GetPointOutsideObstacles( obstacles, numObstacles, path.seekPosOutsideObstacles.ToVec2(), &insideObstacle, NULL );
	if ( insideObstacle != -1 ) {
		path.seekPosObstacle = obstacles[insideObstacle].entity;
	}

	// if start and destination are pushed to the same point, we don't have a path around the obstacle
	if ( ( path.seekPosOutsideObstacles.ToVec2() - path.startPosOutsideObstacles.ToVec2() ).LengthSqr() < Square( 1.0f ) ) {
		if ( ( seekPos.ToVec2() - startPos.ToVec2() ).LengthSqr() > Square( 2.0f ) ) {
			return false;
		}
	}

	// build a path tree
	root = BuildPathTree( obstacles, numObstacles, clipBounds, path.startPosOutsideObstacles.ToVec2(), path.seekPosOutsideObstacles.ToVec2(), path );

	// draw the path tree
	if ( ai_showObstacleAvoidance.GetBool() ) {
		DrawPathTree( root, physics->GetOrigin().z );
	}

	// prune the tree
	PrunePathTree( root, path.seekPosOutsideObstacles.ToVec2() );

	// find the optimal path
	pathToGoalExists = FindOptimalPath( root, obstacles, numObstacles, physics->GetOrigin().z, physics->GetLinearVelocity(), path.seekPos );

	// free the tree
	FreePathTree_r( root );

	return pathToGoalExists;
}