Exemplo n.º 1
0
uint32_t isRightTriangle(const uint32_t x1, const uint32_t y1, const uint32_t x2, const uint32_t y2, const uint32_t x3, const uint32_t y3) {
  uint32_t lengthSquared_A, lengthSquared_B, lengthSquared_C;
  if(!pointsAreUnique(x1,y1,x2,y2,x3,y3))
    return 0;
  lengthSquared_A = distanceSquared(x1,y1,x2,y2);
  lengthSquared_B = distanceSquared(x2,y2,x3,y3);
  lengthSquared_C = distancesquared(x1,y1,x3,y3);
  orderLengths(&lengthSquared_A,&lengthSquared_B,&lengthSquared_C);
  return lengthSquared_A + lengthSquared_B == lengthSquared_C;
}
Exemplo n.º 2
0
TileCoord findTileLocationInRegionClosestToTileLocation(Region *region, TileCoord destination) {
    int closestDistanceSquared = distanceSquared(*region->begin(), destination);
    TileCoord closestTileLocation = *region->begin();
    
    for (Region::iterator i = region->begin(), iEnd = region->end(); i != iEnd; i++) {
        TileCoord testTileLocation = *i;
        int testTileLocationDistanceSquared = distanceSquared(testTileLocation, destination);
        if (testTileLocationDistanceSquared < closestDistanceSquared) {
            closestTileLocation = testTileLocation;
            closestDistanceSquared = testTileLocationDistanceSquared;
        }
    }
    
    return closestTileLocation;
}
Exemplo n.º 3
0
// Detector de colisões circulo / quadrado
bool checkCSCollision(Circle a, SDL_Rect b)
{
    // Ponto mais perto da collision boxes
    int cX, cY;
    
    // Acha a posição mais perto de X
    if(a.x < b.x){
        cX = b.x;
    } else if(a.x > b.x + b.w){
        cX = b.x + b.w;
    } else{
        cX = a.x;
    }
    
    // Acha a posição mais perto de y
    if(a.y < b.y){
        cY = b.y;
    } else if(a.y > b.y + b.h){
        cY = b.y + b.h;
    } else{
        cY = a.y;
    }
    
    // Se o ponto mais perto for dentro do circulo
    if(distanceSquared(a.x, a.y, cX, cY) < a.r * a.r){
        // Essa caixa e esse circulo colidiram
        return true;
    }
    
    // Se eles não colidiram
    return false;
}
Exemplo n.º 4
0
bool Entity::canMoveAbsolute(Point2 p, Level* level, bool force) {
    
    
    if (level->tileAt(p)->doesNotHaveAnyOfFlags(getSolidity())) {
        bool block = false;
        for (Entity* e : level->entityList) {
            if (e->uniqueId == uniqueId) {
                continue;
            }
            if ((bool)(e->getSolidity() & getSolidity())) {
                if (e->pos == p) {
                    block = true;
                    break;
                }
            }
        }
        if (!block || force) {
            if(distanceSquared(pos, p) > 1){
                Animator::renderFlash(pos, level, {defaultIcon, 'O', 'o', '.'}, 1, fgColor, getBgColor(0, pos, level));
                Point2 pp = pos;
                pos = p;
                //level->currentWorld->menuGame->viewUpdate();
                level->currentWorld->menuGame->render(level->currentWorld->worldTime);
                Animator::renderFlash(pos, level, {'.', 'o', 'O', defaultIcon}, 1, fgColor, getBgColor(0, pos, level));
                pos = pp;
            }
            return true;
        }
    }
    return false;
}
Exemplo n.º 5
0
bool checkCollision(Circle &a, SDL_Rect &b) {
  //Closest point on collision box
  int cX, cY;
  
  //Find closest x offset
  if(a.x < b.x) {
    cX = b.x;
  } else if (a.x > b.x + b.w) {
    cX = b.x + b.w;
  } else {
    cX = a.x;
  }

  //Find closest y offset
  if (a.y < b.y) {
    cY = b.y;
  } else if(a.y > b.y + b.h) {
    cY = b.y + b.h;
  } else {
    cY = a.y;
  }

  //If the closest point is inside the circle
  if(distanceSquared(a.x, a.y, cX, cY) < a.r * a.r) {
    //This box and the circle have collided
    return true;
  }

  //If the shapes have not collided
  return false;
}
//--------------------------------------------------------------------------------------------------
/// Get the distance from the point to the plane
//--------------------------------------------------------------------------------------------------
double Plane::distance(const Vec3d& point) const
{
    double factor = Math::sqrt(m_A*m_A + m_B*m_B + m_C*m_C);
    CVF_ASSERT(factor > 0.0);

    double dist = distanceSquared(point) / factor;

    return dist;
}
Exemplo n.º 7
0
void CAutomatonController::Move()
{
    float currentDistance = distanceSquared(PAutomaton->loc.p, PTarget->loc.p);
    if (isRanged() && (currentDistance > 225) || (PAutomaton->health.mp < 8 && PAutomaton->health.maxmp > 8))
    {
        PAutomaton->m_Behaviour &= ~BEHAVIOUR_STANDBACK;
    }
    CPetController::Move();
}
Exemplo n.º 8
0
        static inline bool IsColliding( Rect& b,Cone& a ){
            //Closest point on collision box
            float cX=b.x, cY=b.y;

            //Find closest x offset
            if( a.x <= b.x )
            {
                cX = b.x;
            }
            else if( a.x >= b.x + b.w )
            {
                cX = b.x + b.w;
            }
            else
            {
                cX = a.x;
            }
            if( a.y <= b.y )
            {
                cY = b.y;
            }
            else if( a.y >= b.y + b.h )
            {
                cY = b.y + b.h;
            }
            else
            {
                cY = a.y;
            }
            if( distanceSquared( a.x, a.y, cX, cY ) <= a.r * a.r )
            {

                float angle = atan2(cY-a.y,cX-a.x);
                if (angle < 0){
                    angle = (Geometry::PI()*2+angle);
                }
                if (a.start_angle > a.opening){
                    if (angle <= a.start_angle && angle >= (a.opening) ){
                        return false;
                    }else{
                        return true;
                    }
                }else{
                    if (angle >= a.start_angle && angle <= (a.opening) ){
                        return true;
                    }
                }

                return false;
            }



            return false;
        };
Exemplo n.º 9
0
	void addMutationCandidate(const Sample<value_t> & sample,
							  const contribution_t & contribution,
							  ValuatedRegionNode * viewCell) {
		/*
		 * Insert new mutation candidates at the front because their mutation
		 * count is zero. Therefore, the array stays sorted.
		 */
		const bool useOrigin = (sample.getNumHits() < 2);
		if(std::get<0>(contribution) > 0) {
			const auto originPoint = useOrigin ? sample.getOrigin() :
												 sample.getBackwardTerminationPoint();
			Node * originObject = useOrigin ? static_cast<Node *>(viewCell) :
											  sample.getBackwardResult();
			const auto terminationPoint = sample.getForwardTerminationPoint();
			if(originPoint.distanceSquared(terminationPoint) > 1.0e-3) {
				mutationCandidates.emplace_front(originPoint,
												 originObject,
												 terminationPoint,
												 sample.getForwardResult());
			}
		}
		if(std::get<1>(contribution) > 0) {
			const auto originPoint = useOrigin ? sample.getOrigin() :
												 sample.getForwardTerminationPoint();
			Node * originObject = useOrigin ? static_cast<Node *>(viewCell) :
											  sample.getForwardResult();
			const auto terminationPoint = sample.getBackwardTerminationPoint();
			if(originPoint.distanceSquared(terminationPoint) > 1.0e-3) {
				mutationCandidates.emplace_front(originPoint,
												 originObject,
												 terminationPoint,
												 sample.getBackwardResult());
			}
		}
		// Constant suggested in the article
		const uint32_t maxNumMutationCandidates = 2000000;
		while(mutationCandidates.size() > maxNumMutationCandidates) {
			mutationCandidates.pop_back();
		}
	}
Exemplo n.º 10
0
bool checkCollision(Circle &a, Circle &b) {
  //Calculate total radius squared
  int totalRadiusSquared = a.r + b.r;
  totalRadiusSquared = totalRadiusSquared * totalRadiusSquared;

  //If the distance between the centers of the circles is less than the sum of their radii
  if(distanceSquared(a.x, a.y, b.x, b.y) < totalRadiusSquared) {
    //The circles have collided
    return true;
  }
  //If not
  return false;
}
Exemplo n.º 11
0
bool CMagicState::CanCastSpell(CBattleEntity* PTarget)
{
    auto ret = m_PEntity->CanUseSpell(GetSpell());

    if (!ret)
    {
        m_errorMsg = std::make_unique<CMessageBasicPacket>(m_PEntity, m_PEntity, m_PSpell->getID(), 0, MSGBASIC_CANNOT_CAST_SPELL);
        return ret;
    }
    if (m_PEntity->StatusEffectContainer->HasStatusEffect({EFFECT_SILENCE, EFFECT_MUTE, EFFECT_OMERTA}))
    {
        m_errorMsg = std::make_unique<CMessageBasicPacket>(m_PEntity, m_PEntity, m_PSpell->getID(), 0, MSGBASIC_UNABLE_TO_CAST_SPELLS);
        return false;
    }
    if (!HasCost())
    {
        return false;
    }
    if (!PTarget)
    {
        m_errorMsg = std::make_unique<CMessageBasicPacket>(m_PEntity, m_PEntity, m_PSpell->getID(), 0, MSGBASIC_CANNOT_ON_THAT_TARG);
        return false;
    }
    if (PTarget->IsNameHidden())
    {
        return false;
    }
    if (distance(m_PEntity->loc.p, PTarget->loc.p) > 40)
    {
        m_errorMsg = std::make_unique<CMessageBasicPacket>(m_PEntity, PTarget, m_PSpell->getID(), 0, MSGBASIC_TOO_FAR_AWAY);
        return false;
    }
    if (m_PEntity->objtype == TYPE_PC && distance(m_PEntity->loc.p, PTarget->loc.p) > m_PSpell->getRange())
    {
        m_errorMsg = std::make_unique<CMessageBasicPacket>(m_PEntity, PTarget, m_PSpell->getID(), 0, MSGBASIC_OUT_OF_RANGE_UNABLE_CAST);
        return false;
    }
    if (dynamic_cast<CMobEntity*>(m_PEntity))
    {
        if (distanceSquared(m_PEntity->loc.p, PTarget->loc.p) > square(28.5f))
        {
            return false;
        }
    }
    if (!m_PEntity->PAI->TargetFind->canSee(&PTarget->loc.p))
    {
        m_errorMsg = std::make_unique<CMessageBasicPacket>(m_PEntity, PTarget, m_PSpell->getID(), 0, MSGBASIC_CANNOT_PERFORM_ACTION);
        return false;
    }
    return true;
}
Exemplo n.º 12
0
//
// Pour savoir s'il y a un joueur dans le radius
//
Player * Game::playerInRadius(CVector3f position, float radius, int ignore )
{
	for (int i=0;i<MAX_PLAYER;++i)
	{
		if (players[i])
		{
			if (players[i]->status == PLAYER_STATUS_ALIVE && i != ignore)
			{
				if (distanceSquared(position, players[i]->currentCF.position) <= (radius+.25f)*(radius+.25f)) return players[i];
			}
		}
	}
	return 0;
}
Exemplo n.º 13
0
// Detector de colisões circulo / circulo
bool checkCCCollision(Circle a, Circle b)
{
    // Calcula o raio total ao quadrado
    int totalRadiusSquared = a.r + b.r;
    totalRadiusSquared = totalRadiusSquared * totalRadiusSquared;
    
    // Se a distância entre os centros dos circulos e menor do que a soma de seus raios
    if(distanceSquared(a.x, a.y, b.x, b.y) < totalRadiusSquared){
        // Os circulos colidiram
        return true;
    }
    
    // Se não
    return false;
}
Exemplo n.º 14
0
//--------------------------------------------------------------------------------------------------
/// Classify where the point is located relative to the plane
///
/// \return Plane::FRONT if the point is located on the side the plane normal is pointing\n
///         Plane::BACK if the point is located on the opposite side the plane normal is pointing\n
///         Plane::ON if the point is located in the plane
///         
//--------------------------------------------------------------------------------------------------
Plane::Side Plane::side(const Vec3d& point) const
{
    double d = distanceSquared(point);

    if (d > 0.0)
    {
        return FRONT;
    }
    else if (d < 0.0)
    {
        return BACK;
    }
    else
    {
        return ON;
    }
}
Exemplo n.º 15
0
        static inline bool IsColliding( Rect b,Circle a ){
            float cX, cY;
            if( a.x <= b.x )
            {
                cX = b.x;
            }
            else if( a.x >= b.x + b.w )
            {
                cX = b.x + b.w;
            }
            else
            {
                cX = a.x;
            }

            //Find closest y offset
            if( a.y <= b.y )
            {
                cY = b.y;
            }
            else if( a.y >= b.y + b.h )
            {
                cY = b.y + b.h;
            }
            else
            {
                cY = a.y;
            }

            //If the closest point is inside the circle
            if( distanceSquared( a.x, a.y, cX, cY ) <= a.r * a.r )
            {
                //This box and the circle have collided
                return true;
            }

            //If the shapes have not collided
            return false;
        };
Exemplo n.º 16
0
GLfloat Vector3::distance(const Vector3& v) const
{
    return sqrt(distanceSquared(v));
}
Exemplo n.º 17
0
double		 Vector3d::distance(const Vector3d& v) const
{
  return sqrt(distanceSquared(v));
}
Exemplo n.º 18
0
bool Point::isEqual(const Point &other) const
{
  return distanceSquared(other) < sq(EPSILON);
}
Exemplo n.º 19
0
double Point::magnitudeSquared() {
	Point dummy; // dummy is (0,0,0)
	return( distanceSquared(dummy) );
}
Exemplo n.º 20
0
double Point::distance( Point v ) {
	return sqrt( distanceSquared(v) ) ; }
Exemplo n.º 21
0
 float distance(
   const Position3D& pPos1,
   const Position3D& pPos2)
 {
   return std::sqrt(distanceSquared(pPos1, pPos2));
 }
void
PeridigmNS::ShortRangeForceContactModel::computeForce(const double dt,
                                                      const int numOwnedPoints,
                                                      const int* ownedIDs,
                                                      const int* contactNeighborhoodList,
                                                      PeridigmNS::DataManager& dataManager) const
{
  // Zero out the forces
  dataManager.getData(m_contactForceDensityFieldId, PeridigmField::STEP_NP1)->PutScalar(0.0);

  double *cellVolume, *y, *contactForce, *velocity;
  dataManager.getData(m_volumeFieldId, PeridigmField::STEP_NONE)->ExtractView(&cellVolume);
  dataManager.getData(m_coordinatesFieldId, PeridigmField::STEP_NP1)->ExtractView(&y);
  dataManager.getData(m_velocityFieldId, PeridigmField::STEP_NP1)->ExtractView(&velocity);
  dataManager.getData(m_contactForceDensityFieldId, PeridigmField::STEP_NP1)->ExtractView(&contactForce);

  int neighborhoodListIndex(0), numNeighbors, nodeID, neighborID, iID, iNID;
  double nodeCurrentX[3], nodeCurrentV[3], nodeVolume, currentDistance, c, temp, neighborVolume;
  double normal[3], currentDotNormal, currentDotNeighbor, nodeCurrentVperp[3], nodeNeighborVperp[3], Vcm[3], nodeCurrentVrel[3], nodeNeighborVrel[3];
  double normCurrentVrel, normNeighborVrel, currentNormalForce[3], neighborNormalForce[3], normCurrentNormalForce, normNeighborNormalForce, currentFrictionForce[3], neighborFrictionForce[3];

  double currentDistanceSquared;
  double contactRadiusSquared = m_contactRadius*m_contactRadius;

  const double pi = boost::math::constants::pi<double>();

  for(iID=0 ; iID<numOwnedPoints ; ++iID){
    numNeighbors = contactNeighborhoodList[neighborhoodListIndex++];
    if(numNeighbors > 0){
      nodeID = ownedIDs[iID];
      nodeCurrentX[0] = y[nodeID*3];
      nodeCurrentX[1] = y[nodeID*3+1];
      nodeCurrentX[2] = y[nodeID*3+2];
      nodeCurrentV[0] = velocity[nodeID*3];
      nodeCurrentV[1] = velocity[nodeID*3+1];
      nodeCurrentV[2] = velocity[nodeID*3+2];
      nodeVolume = cellVolume[nodeID];
      for(iNID=0 ; iNID<numNeighbors ; ++iNID){
        neighborID = contactNeighborhoodList[neighborhoodListIndex++];
        TEUCHOS_TEST_FOR_EXCEPT_MSG(neighborID < 0, "Invalid neighbor list\n");
	currentDistanceSquared =  distanceSquared(nodeCurrentX[0], nodeCurrentX[1], nodeCurrentX[2],
						  y[neighborID*3], y[neighborID*3+1], y[neighborID*3+2]);
        if(currentDistanceSquared < contactRadiusSquared){
	  currentDistance = distance(nodeCurrentX[0], nodeCurrentX[1], nodeCurrentX[2],
				     y[neighborID*3], y[neighborID*3+1], y[neighborID*3+2]);
          c = 9.0*m_springConstant/(pi*m_horizon*m_horizon*m_horizon*m_horizon);	// half value (of 18) due to force being applied to both nodes
          temp = c*(m_contactRadius - currentDistance)/m_horizon;
          neighborVolume = cellVolume[neighborID];
          
          if (m_frictionCoefficient != 0.0){

            // calculate the perpendicular velocity of the current node wrt the vector between the nodes 

            normal[0] = (y[neighborID*3] - nodeCurrentX[0])/currentDistance;
            normal[1] = (y[neighborID*3+1] - nodeCurrentX[1])/currentDistance;
            normal[2] = (y[neighborID*3+2] - nodeCurrentX[2])/currentDistance;

            currentDotNormal = nodeCurrentV[0]*normal[0] + 
              nodeCurrentV[1]*normal[1] + 
              nodeCurrentV[2]*normal[2];

            currentDotNeighbor = velocity[neighborID*3]*normal[0] + 
              velocity[neighborID*3+1]*normal[1] + 
              velocity[neighborID*3+2]*normal[2]; 

            nodeCurrentVperp[0] = nodeCurrentV[0] - currentDotNormal*normal[0];
            nodeCurrentVperp[1] = nodeCurrentV[1] - currentDotNormal*normal[1];
            nodeCurrentVperp[2] = nodeCurrentV[2] - currentDotNormal*normal[2];

            nodeNeighborVperp[0] = velocity[neighborID*3] - currentDotNeighbor*normal[0];
            nodeNeighborVperp[1] = velocity[neighborID*3+1] - currentDotNeighbor*normal[1];
            nodeNeighborVperp[2] = velocity[neighborID*3+2] - currentDotNeighbor*normal[2];

            // calculate frame of reference for the perpendicular velocities

            Vcm[0] = 0.5*(nodeCurrentVperp[0] + nodeNeighborVperp[0]);
            Vcm[1] = 0.5*(nodeCurrentVperp[1] + nodeNeighborVperp[1]);
            Vcm[2] = 0.5*(nodeCurrentVperp[2] + nodeNeighborVperp[2]);
          
            // calculate the relative velocity of the current node wrt the neighboring node and vice versa

            nodeCurrentVrel[0] = nodeCurrentVperp[0] - Vcm[0];
            nodeCurrentVrel[1] = nodeCurrentVperp[1] - Vcm[1];
            nodeCurrentVrel[2] = nodeCurrentVperp[2] - Vcm[2];

            nodeNeighborVrel[0] = nodeNeighborVperp[0] - Vcm[0];
            nodeNeighborVrel[1] = nodeNeighborVperp[1] - Vcm[1];
            nodeNeighborVrel[2] = nodeNeighborVperp[2] - Vcm[2];

            normCurrentVrel = sqrt(nodeCurrentVrel[0]*nodeCurrentVrel[0] + 
                                   nodeCurrentVrel[1]*nodeCurrentVrel[1] + 
                                   nodeCurrentVrel[2]*nodeCurrentVrel[2]); 

            normNeighborVrel = sqrt(nodeNeighborVrel[0]*nodeNeighborVrel[0] + 
                                    nodeNeighborVrel[1]*nodeNeighborVrel[1] + 
                                    nodeNeighborVrel[2]*nodeNeighborVrel[2]);         
            
            // calculate the normal forces

            currentNormalForce[0] = -(temp*neighborVolume*(y[neighborID*3]   - nodeCurrentX[0])/currentDistance);
            currentNormalForce[1] = -(temp*neighborVolume*(y[neighborID*3+1] - nodeCurrentX[1])/currentDistance);
            currentNormalForce[2] = -(temp*neighborVolume*(y[neighborID*3+2] - nodeCurrentX[2])/currentDistance);

            neighborNormalForce[0] = (temp*nodeVolume*(y[neighborID*3]   - nodeCurrentX[0])/currentDistance);
            neighborNormalForce[1] = (temp*nodeVolume*(y[neighborID*3+1] - nodeCurrentX[1])/currentDistance);
            neighborNormalForce[2] = (temp*nodeVolume*(y[neighborID*3+2] - nodeCurrentX[2])/currentDistance);

            normCurrentNormalForce = sqrt(currentNormalForce[0]*currentNormalForce[0] + 
                                          currentNormalForce[1]*currentNormalForce[1] + 
                                          currentNormalForce[2]*currentNormalForce[2]);

            normNeighborNormalForce = sqrt(neighborNormalForce[0]*neighborNormalForce[0] + 
                                           neighborNormalForce[1]*neighborNormalForce[1] + 
                                           neighborNormalForce[2]*neighborNormalForce[2]);
            
            // calculate the friction forces

            if (normCurrentVrel != 0.0) {
              currentFrictionForce[0] = -m_frictionCoefficient*normCurrentNormalForce*nodeCurrentVrel[0]/normCurrentVrel;
              currentFrictionForce[1] = -m_frictionCoefficient*normCurrentNormalForce*nodeCurrentVrel[1]/normCurrentVrel;
              currentFrictionForce[2] = -m_frictionCoefficient*normCurrentNormalForce*nodeCurrentVrel[2]/normCurrentVrel;
            }
            else {
              currentFrictionForce[0] = 0.0;
              currentFrictionForce[1] = 0.0;
              currentFrictionForce[2] = 0.0;
            }

            if (normNeighborVrel != 0.0) {
              neighborFrictionForce[0] = -m_frictionCoefficient*normNeighborNormalForce*nodeNeighborVrel[0]/normNeighborVrel;
              neighborFrictionForce[1] = -m_frictionCoefficient*normNeighborNormalForce*nodeNeighborVrel[1]/normNeighborVrel;
              neighborFrictionForce[2] = -m_frictionCoefficient*normNeighborNormalForce*nodeNeighborVrel[2]/normNeighborVrel;
            }
            else {
              neighborFrictionForce[0] = 0.0;
              neighborFrictionForce[1] = 0.0;
              neighborFrictionForce[2] = 0.0;
            }

            // compute total contributions to force density

            contactForce[nodeID*3]       += currentNormalForce[0] + currentFrictionForce[0];
            contactForce[nodeID*3+1]     += currentNormalForce[1] + currentFrictionForce[1];
            contactForce[nodeID*3+2]     += currentNormalForce[2] + currentFrictionForce[2];
            contactForce[neighborID*3]   += neighborNormalForce[0] + neighborFrictionForce[0];
            contactForce[neighborID*3+1] += neighborNormalForce[1] + neighborFrictionForce[1];
            contactForce[neighborID*3+2] += neighborNormalForce[2] + neighborFrictionForce[2];
          }
          else {          

            // compute contributions to force density (Normal Force Only)

            contactForce[nodeID*3]       -= temp*neighborVolume*(y[neighborID*3]   - nodeCurrentX[0])/currentDistance;
            contactForce[nodeID*3+1]     -= temp*neighborVolume*(y[neighborID*3+1] - nodeCurrentX[1])/currentDistance;
            contactForce[nodeID*3+2]     -= temp*neighborVolume*(y[neighborID*3+2] - nodeCurrentX[2])/currentDistance;
            contactForce[neighborID*3]   += temp*nodeVolume*(y[neighborID*3]   - nodeCurrentX[0])/currentDistance;
            contactForce[neighborID*3+1] += temp*nodeVolume*(y[neighborID*3+1] - nodeCurrentX[1])/currentDistance;
            contactForce[neighborID*3+2] += temp*nodeVolume*(y[neighborID*3+2] - nodeCurrentX[2])/currentDistance;

          }
        }
      }
    }
  }
}
Exemplo n.º 23
0
float CVec3::distance(const CVec3 &other) const
{
	return sqrtf(distanceSquared(other));
}
Exemplo n.º 24
0
//
// Update
//
void Game::update(float delay)
{
  int i;
#ifndef CONSOLE
	dotAnim += delay * 720;
	while (dotAnim >= 360) dotAnim -= 360;
#endif
	if (voting.votingInProgress)
	{
		if (voting.update(delay))
		{
			if (isServerGame)
			{
				//--- Voting complete, check the result
				//    In order to the vote to pass, more than
				//    50% of ALL the players should have voted YES.
				/*voting.nbActivePlayers = 0;
				for (int i=0;i<MAX_PLAYER;++i)
				{
					if ( (players[i]) && (players[i]->teamID != PLAYER_TEAM_AUTO_ASSIGN) &&
						(players[i]->teamID != PLAYER_TEAM_AUTO_ASSIGN) )
						++voting.nbActivePlayers;
				}*/

				net_svcl_vote_result voteResult;
				voteResult.passed = (voting.votingResults[0] > (int)voting.activePlayersID.size() / 2);
				bb_serverSend((char*)(&voteResult), sizeof(net_svcl_vote_result), NET_SVCL_VOTE_RESULT);
				if (voteResult.passed)
				{
					//--- Vote passed!!!
					console->sendCommand(voting.votingWhat);
				}
				else
				{
					//--- Vote failed...
				}
			}
		}
	}

	if (roundState == GAME_PLAYING)
	{
		// On update les players
		for (int i=0;i<MAX_PLAYER;++i) 
		{
			if (players[i])
			{
				players[i]->update(delay);

				if (players[i]->incShot > 0)
				{
					players[i]->incShot--;
					if (players[i]->incShot%3 == 0)
					{
						// On test premièrement si on touche un autre joueur!
						Player * hitPlayer = 0;
						CVector3f p3 = players[i]->p2;
						for (int j=0;j<MAX_PLAYER;j++)
						{
							if (players[j])
							{
								if (j != i)
								{
#ifdef _PRO_
									if (players[j]->status == PLAYER_STATUS_ALIVE && (players[j]->teamID != players[i]->teamID || gameType == GAME_TYPE_DM || gameType == GAME_TYPE_SND || gameVar.sv_friendlyFire || gameVar.sv_reflectedDamage))
#else
									if (players[j]->status == PLAYER_STATUS_ALIVE && (players[j]->teamID != players[i]->teamID || gameType == GAME_TYPE_DM || gameVar.sv_friendlyFire))
#endif
									{
										// Ray to sphere test
										if (segmentToSphere(players[i]->p1, p3, players[j]->currentCF.position, .35f))
										{
											hitPlayer = players[j];
											p3 = players[i]->p2; // Full length

											// On décrémente sa vie
											hitPlayer->hitSV(gameVar.weapons[WEAPON_PHOTON_RIFLE], players[i], gameVar.weapons[WEAPON_PHOTON_RIFLE]->damage / 2.0f);
										}
									}
								}
							}
						}
					}
				}

				//--- Update les guns
				if (players[i]->weapon)
				{
					if (players[i]->weapon->weaponID == WEAPON_SMG)
					{
						if (!gameVar.sv_enableSMG)
						{
							players[i]->switchWeapon(SelectToAvailableWeapon(), true);
						}
					}
					if (players[i]->weapon->weaponID == WEAPON_SHOTGUN)
					{
						if (!gameVar.sv_enableShotgun)
						{
							players[i]->switchWeapon(SelectToAvailableWeapon(), true);
						}
					}
					if (players[i]->weapon->weaponID == WEAPON_SNIPER)
					{
						if (!gameVar.sv_enableSniper/* || map->size[0] * map->size[1] <= 512*/)
						{
							players[i]->switchWeapon(SelectToAvailableWeapon(), true);
						}
					}
					if (players[i]->weapon->weaponID == WEAPON_DUAL_MACHINE_GUN)
					{
						if (!gameVar.sv_enableDualMachineGun)
						{
							players[i]->switchWeapon(SelectToAvailableWeapon(), true);
						}
					}
					if (players[i]->weapon->weaponID == WEAPON_CHAIN_GUN)
					{
						if (!gameVar.sv_enableChainGun)
						{
							players[i]->switchWeapon(SelectToAvailableWeapon(), true);
						}
					}
					if (players[i]->weapon->weaponID == WEAPON_BAZOOKA)
					{
						if (!gameVar.sv_enableBazooka)
						{
							players[i]->switchWeapon(SelectToAvailableWeapon(), true);
						}
					}
					if (players[i]->weapon->weaponID == WEAPON_PHOTON_RIFLE)
					{
						if (!gameVar.sv_enablePhotonRifle)
						{
							players[i]->switchWeapon(SelectToAvailableWeapon(), true);
						}
					}
					if (players[i]->weapon->weaponID == WEAPON_FLAME_THROWER)
					{
						if (!gameVar.sv_enableFlameThrower)
						{
							players[i]->switchWeapon(SelectToAvailableWeapon(), true);
						}
					}
				}

				//--- Update les melee
				if (players[i]->meleeWeapon)
				{
					if (!gameVar.sv_enableSecondary)
					{
						players[i]->switchMeleeWeapon(SelectToAvailableMeleeWeapon(), true);
					}
					else
					{
						if (players[i]->meleeWeapon->weaponID == WEAPON_KNIVES)
						{
							if (!gameVar.sv_enableKnives)
							{
								players[i]->switchMeleeWeapon(SelectToAvailableMeleeWeapon(), true);
							}
						}
						if (players[i]->meleeWeapon->weaponID == WEAPON_NUCLEAR)
						{
							if (!gameVar.sv_enableNuclear)
							{
								players[i]->switchMeleeWeapon(SelectToAvailableMeleeWeapon(), true);
							}
						}
						if (players[i]->meleeWeapon->weaponID == WEAPON_SHIELD)
						{
							if (!gameVar.sv_enableShield)
							{
								players[i]->switchMeleeWeapon(SelectToAvailableMeleeWeapon(), true);
							}
						}
#ifdef _PRO_
						if (players[i]->meleeWeapon->weaponID == WEAPON_MINIBOT)
						{
							if (!gameVar.sv_enableMinibot)
							{
								players[i]->switchMeleeWeapon(SelectToAvailableMeleeWeapon(), true);
							}
						}
#endif
					}
				}
			}
		}
	}

#ifdef _PRO_
	//--- Perform bot collisions with walls
	if (isServerGame)
	{
		for (int i=0;i<MAX_PLAYER;++i)
		{
			if (players[i])
			{
				if (players[i]->status == PLAYER_STATUS_ALIVE)
				{
					if (players[i]->minibot)
					{
						if (map) map->performCollision(players[i]->minibot->lastCF, players[i]->minibot->currentCF, .15f);
						map->collisionClip(players[i]->minibot->currentCF, .15f);
					}
				}
			}
		}
	}
#endif

	// Si on tiens tab, on montre les stats
#ifndef CONSOLE
	if (!console->isActive() && dkiGetState(gameVar.k_showScore) || roundState != GAME_PLAYING)
	{
		showStats = true;
	}
	else
	{
		showStats = false;
	}

	for (i=0;i<(int)nikeFlashes.size();++i)
	{
		nikeFlashes[i]->update(delay);
		if (nikeFlashes[i]->life <= 0)	 
		{
			delete nikeFlashes[i];
			nikeFlashes.erase(nikeFlashes.begin() + i);
			--i;
		}
	}

	if (thisPlayer && roundState == GAME_PLAYING)
	{
		if (thisPlayer->teamID == PLAYER_TEAM_SPECTATOR && !console->isActive() && !writting && !showMenu && !(menuManager.root && menuManager.root->visible))
		{
			// On est spectateur, alors on peut se déplacer comme on veut dans la map
			// Pour l'instant les flèches (a,s,w,d, pomal temp)
			if (dkiGetState(gameVar.k_moveRight))
			{
				map->camLookAt[0] += 10 * delay;
			}
			if (dkiGetState(gameVar.k_moveLeft))
			{
				map->camLookAt[0] -= 10 * delay;
			}
			if (dkiGetState(gameVar.k_moveUp))
			{
				map->camLookAt[1] += 10 * delay;
			}
			if (dkiGetState(gameVar.k_moveDown))
			{
				map->camLookAt[1] -= 10 * delay;
			}
		}

		// On performe les collisions sur notre joueur
		if (thisPlayer->status == PLAYER_STATUS_ALIVE) 
		{
			for (int i=0;i<MAX_PLAYER;++i)
			{
				if (players[i] && players[i] != thisPlayer)
				{
					if (players[i]->status == PLAYER_STATUS_ALIVE && players[i]->timeAlive > 3.0f && thisPlayer->timeAlive > 3.0f) // player msut have been on the field for more than 3 second before we check collisions with him
					{
						float disSq = distanceSquared(thisPlayer->currentCF.position, players[i]->currentCF.position);
						if (disSq <= .5f*.5f)
						{
							CVector3f dis = players[i]->currentCF.position - thisPlayer->currentCF.position;
							normalize(dis);
							thisPlayer->currentCF.position = players[i]->currentCF.position - dis * .51f;
							thisPlayer->currentCF.vel = -thisPlayer->currentCF.vel * BOUNCE_FACTOR;
							if (map) map->performCollision(thisPlayer->lastCF, thisPlayer->currentCF, .25f);
							map->collisionClip(thisPlayer->currentCF, .25f);
							thisPlayer->lastCF.position = thisPlayer->currentCF.position;
						}
					}
				}
			}

			if (map) map->performCollision(thisPlayer->lastCF, thisPlayer->currentCF, .25f);

			// Performing a final clip cibole de caliss
			map->collisionClip(thisPlayer->currentCF, .25f);

			//--- Est-ce qu'on est stuck dans un wall??? Oui? on respawn request
			int x = (int)thisPlayer->currentCF.position[0];
			int y = (int)thisPlayer->currentCF.position[1];
			if ((!map->dko_map && !map->cells[(y)*map->size[0]+(x)].passable) ||
				(map->dko_map && 
				(x < 0 || x > map->size[0] || y < 0 || y > map->size[1])))
			{
				// Respawn request!
				if (!thisPlayer->spawnRequested)
				{
					// Ici on le call juste une fois, isshh sinon ça sera pas trop bon...
					// On request to spawn
					thisPlayer->spawnRequested = true;
					net_clsv_spawn_request spawnRequest;
					spawnRequest.playerID = thisPlayer->playerID;
					spawnRequest.weaponID = thisPlayer->nextSpawnWeapon;
					spawnRequest.meleeID = thisPlayer->nextMeleeWeapon;
					memcpy(spawnRequest.skin, thisPlayer->skin.s, (thisPlayer->skin.len() <= 6)?thisPlayer->skin.len()+1:7);
					spawnRequest.blueDecal[0] = (unsigned char)(thisPlayer->blueDecal[0] * 255.0f);
					spawnRequest.blueDecal[1] = (unsigned char)(thisPlayer->blueDecal[1] * 255.0f);
					spawnRequest.blueDecal[2] = (unsigned char)(thisPlayer->blueDecal[2] * 255.0f);
					spawnRequest.greenDecal[0] = (unsigned char)(thisPlayer->greenDecal[0] * 255.0f);
					spawnRequest.greenDecal[1] = (unsigned char)(thisPlayer->greenDecal[1] * 255.0f);
					spawnRequest.greenDecal[2] = (unsigned char)(thisPlayer->greenDecal[2] * 255.0f);
					spawnRequest.redDecal[0] = (unsigned char)(thisPlayer->redDecal[0] * 255.0f);
					spawnRequest.redDecal[1] = (unsigned char)(thisPlayer->redDecal[1] * 255.0f);
					spawnRequest.redDecal[2] = (unsigned char)(thisPlayer->redDecal[2] * 255.0f);
					bb_clientSend(scene->client->uniqueClientID, (char*)&spawnRequest, sizeof(net_clsv_spawn_request), NET_CLSV_SPAWN_REQUEST);
				}
			}
		}
	}

	// On update la map
	if (map && thisPlayer) 
	{
		map->update(delay, thisPlayer);

		//--- Est-ce qu'il pleut?
		if (map->weather == WEATHER_RAIN)
		{
			for (int i=0;i<5;++i)
			{
				//--- Spawn da rain!
				int idrip = getNextDrip();
				drips[idrip].life = 1;
				drips[idrip].position = rand(map->camPos + CVector3f(-5,-5,0), map->camPos + CVector3f(5,5,0));
				drips[idrip].position[2] = 0;
				drips[idrip].size = .15f;
				drips[idrip].fadeSpeed = 2;
			}

			//--- Spawn des drip sous les players
			for (int i=0;i<MAX_PLAYER;++i)
			{
				if (players[i])
				{
					if (players[i]->status == PLAYER_STATUS_ALIVE)
					{
						if (map->cells[(int)(players[i]->currentCF.position[1] - .5f) * map->size[0] + (int)(players[i]->currentCF.position[0] - .5f)].splater[0] > .5f)
						{
							if (players[i]->currentCF.vel.length() >= 2.25f)
							{
								//--- Spawn da rain!
								int idrip = getNextDrip();
								drips[idrip].life = .5f;
								drips[idrip].position = players[i]->currentCF.position;
								drips[idrip].position[2] = 0;
								drips[idrip].size = .3f;
								drips[idrip].fadeSpeed = 1;
							}
						}
					}
				}
			}
		}

		//--- Si on roule dans la lave, on spawn de la fumé :D
		if (map->theme == THEME_LAVA)
		{
			//--- Spawn des drip sous les players
			for (int i=0;i<MAX_PLAYER;++i)
			{
				if (players[i])
				{
					if (players[i]->status == PLAYER_STATUS_ALIVE && rand()%50 == 5)
					{
						if (map->cells[(int)(players[i]->currentCF.position[1] - .5f) * map->size[0] + (int)(players[i]->currentCF.position[0] - .5f)].splater[0] > .5f)
						{
							//--- Spawn da smoke psssiiii
							for (int j=0;j<4;++j)
							{
								dkpCreateParticle(	players[i]->currentCF.position.s,//float *position,
													CVector3f(0,0,(float)j* .25f).s,//float *vel,
													CVector4f(.7f,.7f,.7f,1).s,//float *startColor,
													CVector4f(.7f,.7f,.7f,0).s,//float *endColor,
													.25f,//float startSize,
													.5f,//float endSize,
													2,//float duration,
													0,//float gravityInfluence,
													0,//float airResistanceInfluence,
													30,//float rotationSpeed,
													gameVar.tex_smoke1,//unsigned int texture,
													DKP_SRC_ALPHA,//unsigned int srcBlend,
													DKP_ONE_MINUS_SRC_ALPHA,//unsigned int dstBlend,
													0);//int transitionFunc);
							}

							dksPlay3DSound(gameVar.sfx_lavaSteam, -1, 5, players[i]->currentCF.position,125);
						}
					}
				}
			}
		}

		// La view qui shake
		if (viewShake > 0)
		{
			if (viewShake > 2.5f) viewShake = 2.5f;

			CVector3f dir(1,0,0);
			dir = rotateAboutAxis(dir, rand(0.0f, 360.0f), CVector3f(0,0,1));
			dir *= viewShake * .10f;

			map->camPos += dir;
			viewShake -= delay*.75f;
			if (viewShake < 0) viewShake = 0;
		}


		//-- We check for all enable guns
		scene->client->btn_guns[WEAPON_SMG]->enable = gameVar.sv_enableSMG;
		scene->client->btn_guns[WEAPON_SHOTGUN]->enable = gameVar.sv_enableShotgun;
		scene->client->btn_guns[WEAPON_SNIPER]->enable = gameVar.sv_enableSniper;
		scene->client->btn_guns[WEAPON_DUAL_MACHINE_GUN]->enable = gameVar.sv_enableDualMachineGun;
		scene->client->btn_guns[WEAPON_CHAIN_GUN]->enable = gameVar.sv_enableChainGun;
		scene->client->btn_guns[WEAPON_BAZOOKA]->enable = gameVar.sv_enableBazooka;
		scene->client->btn_guns[WEAPON_PHOTON_RIFLE]->enable = gameVar.sv_enablePhotonRifle;
		scene->client->btn_guns[WEAPON_FLAME_THROWER]->enable = gameVar.sv_enableFlameThrower;
		
		if(gameVar.sv_enableSecondary)
		{
			scene->client->btn_meleeguns[WEAPON_KNIVES-WEAPON_KNIVES]->enable = gameVar.sv_enableKnives;
			scene->client->btn_meleeguns[WEAPON_NUCLEAR-WEAPON_KNIVES]->enable = gameVar.sv_enableNuclear;
			scene->client->btn_meleeguns[WEAPON_SHIELD-WEAPON_KNIVES]->enable = gameVar.sv_enableShield;
			scene->client->btn_meleeguns[WEAPON_MINIBOT-WEAPON_KNIVES]->enable = gameVar.sv_enableMinibot;
		}
		else
		{
			scene->client->btn_meleeguns[WEAPON_KNIVES-WEAPON_KNIVES]->enable = false;
			scene->client->btn_meleeguns[WEAPON_NUCLEAR-WEAPON_KNIVES]->enable = false;
			scene->client->btn_meleeguns[WEAPON_SHIELD-WEAPON_KNIVES]->enable = false;
			scene->client->btn_meleeguns[WEAPON_MINIBOT-WEAPON_KNIVES]->enable = false;
		}

	}

	// On update les trails
	for (int i=0;i<(int)trails.size();++i)
	{
		trails[i]->update(delay);
		if (trails[i]->delay >= 1)
		{
			delete trails[i];
			trails.erase(trails.begin()+i);
			i--;
		}
	}

	// On update les floor mark
	for (int i=0;i<MAX_FLOOR_MARK;++i)
	{
		if (floorMarks[i].delay > 0)
		{
			floorMarks[i].update(delay);
		}
		if (drips[i].life > 0)
		{
			drips[i].update(delay);
		}
	}
#endif

	// On update les projectiles
	for (int i=0;i<(int)projectiles.size();++i)
	{
		Projectile * projectile = projectiles[i];
		projectile->update(delay, map);
		projectile->projectileID = (short)i; // On l'update toujours
		if ( projectile->needToBeDeleted )
		{
			if( !projectile->reallyNeedToBeDeleted )
			{
				projectile->reallyNeedToBeDeleted = true;
				continue;
			}
			projectiles.erase(projectiles.begin()+i);
			net_svcl_delete_projectile deleteProjectile;
			deleteProjectile.projectileID = projectile->uniqueID;
			bb_serverSend((char*)&deleteProjectile,sizeof(net_svcl_delete_projectile),NET_SVCL_DELETE_PROJECTILE,0);
			i--;
			delete projectile;
		}

	}

#ifndef CONSOLE

	// On update les projectiles client
	for (int i=0;i<(int)clientProjectiles.size();++i)
	{
		Projectile * projectile = clientProjectiles[i];
		projectile->update(delay, map);
		projectile->projectileID = (short)i; // On l'update toujours
		if (projectile->needToBeDeleted)
		{
			clientProjectiles.erase(projectiles.begin()+i);
			i--;
			delete projectile;
		}
	}

	// On update les douilles
	for (int i=0;i<(int)douilles.size();++i)
	{
		Douille * douille = douilles[i];
		douille->update(delay, map);
		if (douille->delay<=0)
		{
			douilles.erase(douilles.begin()+i);
			i--;
			delete douille;
		}
	}
#endif	

	// Update les particules
//	gameVar.ro_nbParticle = dkpUpdate(delay);
}
Exemplo n.º 25
0
T SparseVectorCompressed<T>::distance(const MyT& rhs) const { return Sqrt(distanceSquared(rhs)); }
Exemplo n.º 26
0
MapCoordVector::size_type MapEditorTool::findHoverPoint(QPointF cursor, const MapWidget* widget, const Object* object, bool include_curve_handles, MapCoordF* out_handle_pos) const
{
	const float click_tolerance_squared = click_tolerance * click_tolerance;
	auto best_index = std::numeric_limits<MapCoordVector::size_type>::max();
	
	if (object->getType() == Object::Point)
	{
		const PointObject* point = reinterpret_cast<const PointObject*>(object);
		if (distanceSquared(widget->mapToViewport(point->getCoordF()), cursor) <= click_tolerance_squared)
		{
			if (out_handle_pos)
				*out_handle_pos = point->getCoordF();
			return 0;
		}
	}
	else if (object->getType() == Object::Text)
	{
		const TextObject* text = reinterpret_cast<const TextObject*>(object);
		std::vector<QPointF> text_handles(text->controlPoints());
		for (std::size_t i = 0; i < text_handles.size(); ++i)
		{
			if (distanceSquared(widget->mapToViewport(text_handles[i]), cursor) <= click_tolerance_squared)
			{
				if (out_handle_pos)
					*out_handle_pos = MapCoordF(text_handles[i]);
				return i;
			}
		}
	}
	else if (object->getType() == Object::Path)
	{
		const PathObject* path = reinterpret_cast<const PathObject*>(object);
		auto size = path->getCoordinateCount();
		
		float best_dist_sq = click_tolerance_squared;
		for (auto i = size - 1; i < size; --i)
		{
			if (!path->getCoordinate(i).isClosePoint())
			{
				float distance_sq = distanceSquared(widget->mapToViewport(path->getCoordinate(i)), cursor);
				bool is_handle = (i >= 1 && path->getCoordinate(i - 1).isCurveStart()) ||
									(i >= 2 && path->getCoordinate(i - 2).isCurveStart());
				if (distance_sq < best_dist_sq || (distance_sq == best_dist_sq && is_handle))
				{
					best_index = i;
					best_dist_sq = distance_sq;
				}
			}
			if (!include_curve_handles && i >= 3 && path->getCoordinate(i - 3).isCurveStart())
				i -= 2;
		}
		
		if (out_handle_pos &&
		    best_index < std::numeric_limits<MapCoordVector::size_type>::max())
		{
			*out_handle_pos = MapCoordF(path->getCoordinate(best_index));
		}
	}
	
	return best_index;
}
Exemplo n.º 27
0
bool LineSegment::intersectsSolidSphere(const class Sphere& s) const {
    return distanceSquared(s.center) <= square(s.radius);
}
Exemplo n.º 28
0
float distance(Vec3 const &a, Vec3 const &b)
{
    return sqrtf(distanceSquared(a, b));
}
Exemplo n.º 29
0
void CMobController::Move()
{
    if (!PMob->PAI->CanFollowPath())
    {
        return;
    }
    float currentDistance = distance(PMob->loc.p, PTarget->loc.p);
    if (PMob->PAI->PathFind->IsFollowingScriptedPath() && PMob->PAI->CanFollowPath())
    {
        PMob->PAI->PathFind->FollowPath();
        return;
    }

    // attempt to teleport
    if (PMob->getMobMod(MOBMOD_TELEPORT_TYPE) == 1)
    {
        if (m_Tick >= m_LastSpecialTime + std::chrono::milliseconds(PMob->getBigMobMod(MOBMOD_TELEPORT_CD)))
        {
            CMobSkill* teleportBegin = battleutils::GetMobSkill(PMob->getMobMod(MOBMOD_TELEPORT_START));

            if (teleportBegin)
            {
                m_LastSpecialTime = m_Tick;
                MobSkill(PMob->targid, teleportBegin->getID());
            }
        }
    }

    bool move = PMob->PAI->PathFind->IsFollowingPath();
    float attack_range = PMob->m_ModelSize;

    if (PMob->getMobMod(MOBMOD_ATTACK_SKILL_LIST) > 0)
    {
        auto skillList {battleutils::GetMobSkillList(PMob->getMobMod(MOBMOD_ATTACK_SKILL_LIST))};

        if (!skillList.empty())
        {
            auto skill {battleutils::GetMobSkill(skillList.front())};
            if (skill)
            {
                attack_range = skill->getDistance();
            }
        }
    }

    if (PMob->getMobMod(MOBMOD_SHARE_POS) > 0)
    {
        CMobEntity* posShare = (CMobEntity*)PMob->GetEntity(PMob->getMobMod(MOBMOD_SHARE_POS) + PMob->targid, TYPE_MOB);
        PMob->loc = posShare->loc;
    }
    else if (((distance(PMob->loc.p, PTarget->loc.p) > attack_range - 0.2f) || move) && PMob->PAI->CanFollowPath())
    {
        //#TODO: can this be moved to scripts entirely?
        if (PMob->getMobMod(MOBMOD_DRAW_IN) > 0)
        {
            if (currentDistance >= PMob->m_ModelSize * 2)
                battleutils::DrawIn(PTarget, PMob, PMob->m_ModelSize - 0.2f);
        }
        if (PMob->speed != 0 && PMob->getMobMod(MOBMOD_NO_MOVE) == 0 && m_Tick >= m_LastSpecialTime)
        {
            // attempt to teleport to target (if in range)
            if (PMob->getMobMod(MOBMOD_TELEPORT_TYPE) == 2)
            {
                CMobSkill* teleportBegin = battleutils::GetMobSkill(PMob->getMobMod(MOBMOD_TELEPORT_START));

                if (teleportBegin && currentDistance <= teleportBegin->getDistance())
                {
                    MobSkill(PMob->targid, teleportBegin->getID());
                    m_LastSpecialTime = m_Tick;
                    return;
                }
            }
            else if (CanMoveForward(currentDistance))
            {
                if (!PMob->PAI->PathFind->IsFollowingPath() || distanceSquared(PMob->PAI->PathFind->GetDestination(), PTarget->loc.p) > 10)
                {
                    //path to the target if we don't have a path already
                    PMob->PAI->PathFind->PathInRange(PTarget->loc.p, attack_range - 0.2f, PATHFLAG_WALLHACK | PATHFLAG_RUN);
                }
                PMob->PAI->PathFind->FollowPath();
                if (!PMob->PAI->PathFind->IsFollowingPath())
                {
                    //arrived at target - move if there is another mob under me
                    if (PTarget->objtype == TYPE_PC)
                    {
                        for (auto PSpawnedMob : static_cast<CCharEntity*>(PTarget)->SpawnMOBList)
                        {
                            if (PSpawnedMob.second != PMob && !PSpawnedMob.second->PAI->PathFind->IsFollowingPath() && distance(PSpawnedMob.second->loc.p, PMob->loc.p) < 1.f)
                            {
                                auto angle = getangle(PMob->loc.p, PTarget->loc.p) + 64;
                                position_t new_pos {0, PMob->loc.p.x - (cosf(rotationToRadian(angle)) * 1.5f),
                                    PTarget->loc.p.y, PMob->loc.p.z + (sinf(rotationToRadian(angle)) * 1.5f), 0};
                                if (PMob->PAI->PathFind->ValidPosition(new_pos))
                                {
                                    PMob->PAI->PathFind->PathTo(new_pos, PATHFLAG_WALLHACK | PATHFLAG_RUN);
                                }
                                break;
                            }
                        }
                    }
                }
            }
            else
            {
                FaceTarget();
            }
        }
    }
    else
    {
        FaceTarget();
    }
}
 float distance(
   const Position6D& pPos1,
   const Position6D& pPos2)
 {
   return sqrtf(distanceSquared(pPos1, pPos2));
 }