示例#1
0
//-----------------------------------------------------------------------------
int SoccerWorld::getAttacker(SoccerTeam team) const
{
    if (team == SOCCER_TEAM_BLUE && m_blue_kdm.size() > 1)
    {
        for (unsigned int i = 1; i < m_blue_kdm.size(); i++)
        {
            // Only AI will do the attack job
            if (getKart(m_blue_kdm[i].m_kart_id)
                ->getController()->isPlayerController())
                continue;
            return m_blue_kdm[i].m_kart_id;
        }
    }
    else if (team == SOCCER_TEAM_RED && m_red_kdm.size() > 1)
    {
        for (unsigned int i = 1; i < m_red_kdm.size(); i++)
        {
            if (getKart(m_red_kdm[i].m_kart_id)
                ->getController()->isPlayerController())
                continue;
            return m_red_kdm[i].m_kart_id;
        }
    }

    // No attacker
    return -1;
}   // getAttacker
/** Localize the ball on the navigation mesh.
 */
void SoccerWorld::updateBallPosition(int ticks)
{
    if (isRaceOver()) return;

    if (!ballNotMoving())
    {
        // Only update heading if the ball is moving
        m_ball_heading = atan2f(m_ball_body->getLinearVelocity().getX(),
            m_ball_body->getLinearVelocity().getZ());
    }

    if (Track::getCurrentTrack()->hasNavMesh())
    {
        m_ball_track_sector
            ->update(getBallPosition(), true/*ignore_vertical*/);
        if (!m_ball_track_sector->isOnRoad() && getPhase() == RACE_PHASE)
        {
            m_ball_invalid_timer += ticks;
            // Reset the ball and karts if out of navmesh after 2 seconds
            if (m_ball_invalid_timer >= stk_config->time2Ticks(2.0f))
            {
                m_ball_invalid_timer = 0;
                m_ball->reset();
                for (unsigned int i = 0; i < m_karts.size(); i++)
                    moveKartAfterRescue(m_karts[i]);
                if (UserConfigParams::m_arena_ai_stats)
                    getKart(8)->flyUp();
            }
        }
        else
            m_ball_invalid_timer = 0;
    }

}   // updateBallPosition
示例#3
0
/** Determine the camera settings for the current frame.
 *  \param above_kart How far above the camera should aim at.
 *  \param cam_angle  Angle above the kart plane for the camera.
 *  \param sideway Sideway movement of the camera.
 *  \param distance Distance from kart.
 */
void CameraDebug::getCameraSettings(float *above_kart, float *cam_angle,
                                    float *sideway, float *distance    )
{
    const KartProperties *kp = getKart()->getKartProperties();

    // Set some default values
    float steering = m_kart->getSteerPercent()
                   * (1.0f + (m_kart->getSkidding()->getSkidFactor()
                              - 1.0f) / 2.3f);
    // quadratically to dampen small variations (but keep sign)
    float dampened_steer = fabsf(steering) * steering;
    *sideway = -m_rotation_range*dampened_steer*0.5f;
    *above_kart = 0;
    *cam_angle  = 0;
    
    switch(m_default_debug_Type)
    {
    case CM_DEBUG_BEHIND_KART:
        *distance   = -0.5f*m_kart->getKartModel()->getLength()-1.0f;
        break;
    case CM_DEBUG_GROUND:
        *distance   = -m_kart->getKartModel()->getLength()-1.0f;
        break;
    case CM_DEBUG_SIDE_OF_KART:
    case CM_DEBUG_TOP_OF_KART:
        *above_kart    = 0.75f;
        *cam_angle     = kp->getCameraForwardUpAngle() * DEGREE_TO_RAD;
        *distance      = -m_distance;
        break;
    }   // switch 

}   // getCameraSettings
/** Remove a kart from the kart manager.
 *  \param id The kart id (i.e. name of the directory) to remove.
 */
void KartPropertiesManager::removeKart(const std::string &ident)
{
    // Remove the kart properties from the vector of all kart properties
    int index = getKartId(ident);
    const KartProperties *kp = getKart(ident);  // must be done before remove
    m_karts_properties.remove(index);
    m_all_kart_dirs.erase(m_all_kart_dirs.begin()+index);
    m_kart_available.erase(m_kart_available.begin()+index);

    // Remove the just removed kart from the 'group-name to kart property
    // index' mapping. If a group is now empty (i.e. the removed kart was
    // the only member of this group), remove the group
    const std::vector<std::string> &groups = kp->getGroups();

    for (unsigned int i=0; i<groups.size(); i++)
    {
        std::vector<int> ::iterator it;
        it = std::find(m_groups_2_indices[groups[i]].begin(),
                       m_groups_2_indices[groups[i]].end(),   index);
        // Since we are iterating over all groups the kart belongs to,
        // there must be an entry found
        assert(it!=m_groups_2_indices[groups[i]].end());

        m_groups_2_indices[groups[i]].erase(it);

        // Check if the last kart of a group was removed
        if(m_groups_2_indices[groups[i]].size()==0)
        {
            m_groups_2_indices.erase(groups[i]);
            std::vector<std::string>::iterator its;
            its = std::find(m_all_groups.begin(), m_all_groups.end(),
                            groups[i]);
            assert(its!=m_all_groups.end());
            m_all_groups.erase(its);
        }   // if m_groups_2_indices[groups[i]].size()==0)
    }   // for i in all groups the kart belongs to


    // Adjust the indices of all kart properties in the 'group name to
    // kart property index' mapping: all kart properties with an index
    // greater than index were moved one position further to the beginning
    std::map<std::string, std::vector<int> >::iterator it_gr;
    for(it_gr=m_groups_2_indices.begin(); it_gr != m_groups_2_indices.end();
        it_gr++)
    {
        for(unsigned int i=0; i<(*it_gr).second.size(); i++)
        {
            if( (*it_gr).second[i]>index)
                (*it_gr).second[i]--;
        }
    }

    delete kp;

    // Only used for networking and it is safe to just clear it.
    // If a networking game is started it will be initialised properly.
    m_selected_karts.clear();
}   // removeKart
示例#5
0
/** General update function called once per frame.
 *  \param dt Time step size.
 */
void OverWorld::update(float dt)
{
    // Skip annoying waiting without a purpose
    // Make sure to do all things that would normally happen in the
    // update() method of the base classes.
    if (getPhase() < GO_PHASE)
    {
        setPhase(RACE_PHASE);
        // Normally done in WorldStatus::update(), during phase SET_PHASE,
        // so we have to start music 'manually', since we skip all phases.
        World::getWorld()->getTrack()->startMusic();

        if (music_manager->getCurrentMusic() != NULL &&
            UserConfigParams::m_music)
            music_manager->getCurrentMusic()->startMusic();
        m_karts[0]->startEngineSFX();
    }
    WorldWithRank::update(dt);
    WorldWithRank::updateTrack(dt);
    const unsigned int kart_amount  = m_karts.size();

    // isn't it cool, on the overworld nitro is free!
    for(unsigned int n=0; n<kart_amount; n++)
    {
        m_karts[n]->setEnergy(100.0f);
    }

    TrackObjectManager* tom = getTrack()->getTrackObjectManager();
    PtrVector<TrackObject>& objects = tom->getObjects();
    for(unsigned int i=0; i<objects.size(); i++)
    {
        TrackObject* obj = objects.get(i);
        if(!obj->isGarage())
            continue;

        float m_distance = obj->getDistance();
        Vec3 m_garage_pos = obj->getPosition();
        Vec3 m_kart_pos = getKart(0)->getXYZ();

        if ((m_garage_pos-m_kart_pos).length_2d() > m_distance)
        {
            obj->reset();
        }
    }

    if (m_return_to_garage)
    {
        m_return_to_garage = false;
        delayedSelfDestruct();
        race_manager->exitRace(false);
        KartSelectionScreen* s = OfflineKartSelectionScreen::getInstance();
        s->setMultiplayer(false);
        s->setFromOverworld(true);
        StateManager::get()->resetAndGoToScreen(s);
    }
}   // update
示例#6
0
void OverWorld::onFirePressed(Controller* who)
{
    const std::vector<OverworldChallenge>& challenges =
                                  Track::getCurrentTrack()->getChallengeList();

    AbstractKart* k = getKart(0);
    Vec3 kart_xyz = k->getXYZ();
    if (dynamic_cast<RescueAnimation*>(k->getKartAnimation()) != NULL)
    {
        // you can't start a race while being rescued
        return;
    }

    for (unsigned int n=0; n<challenges.size(); n++)
    {
        if ( (kart_xyz - Vec3(challenges[n].m_position)).length2_2d()
              < CHALLENGE_DISTANCE_SQUARED)
        {
            if (challenges[n].m_challenge_id == "tutorial")
            {
                scheduleTutorial();
                return;
            }
            else
            {
                const ChallengeData* challenge = unlock_manager->getChallengeData(challenges[n].m_challenge_id);
                if (challenge == NULL)
                {
                    Log::error("track", "Cannot find challenge named '%s'\n",
                        challenges[n].m_challenge_id.c_str());
                    continue;
                }

                const unsigned int val = challenge->getNumTrophies();
                bool unlocked = (PlayerManager::getCurrentPlayer()->getPoints() >= val);
                
                if (UserConfigParams::m_everything_unlocked)
                    unlocked = true;

                if (unlocked)
                {
                    race_manager->setKartLastPositionOnOverworld(kart_xyz);
                    new SelectChallengeDialog(0.8f, 0.8f,
                        challenges[n].m_challenge_id);
                }
            }
        } // end if
    } // end for
}   // onFirePressed
/** Called when a soccer game is restarted.
 */
void SoccerWorld::reset()
{
    WorldWithRank::reset();
    if (race_manager->hasTimeTarget())
    {
        WorldStatus::setClockMode(WorldStatus::CLOCK_COUNTDOWN,
            race_manager->getTimeTarget());
    }
    else
    {
        WorldStatus::setClockMode(CLOCK_CHRONO);
    }

    m_count_down_reached_zero = false;
    m_red_scorers.clear();
    m_red_score_times.clear();
    m_blue_scorers.clear();
    m_blue_score_times.clear();
    m_ball_hitter = -1;
    m_red_kdm.clear();
    m_blue_kdm.clear();
    m_ball_heading = 0.0f;
    m_ball_invalid_timer = 0;

    if (m_goal_sound != NULL &&
        m_goal_sound->getStatus() == SFXBase::SFX_PLAYING)
    {
        m_goal_sound->stop();
    }

    if (Track::getCurrentTrack()->hasNavMesh())
    {
        m_ball_track_sector->reset();
    }

    initKartList();
    m_ball->reset();
    m_bgd.reset();

    // Make the player kart in profiling mode up
    // ie make this kart less likely to affect gaming result
    if (UserConfigParams::m_arena_ai_stats)
        getKart(8)->flyUp();

}   // reset
示例#8
0
/** Update the world and the track.
 *  \param dt Time step size.
 */
void SoccerWorld::update(float dt)
{
    updateBallPosition(dt);
    if (m_track->hasNavMesh())
    {
        updateKartNodes();
        updateAIData();
    }

    WorldWithRank::update(dt);
    WorldWithRank::updateTrack(dt);

    if (getPhase() == World::GOAL_PHASE)
    {
        if (m_goal_timer == 0.0f)
        {
            // Stop all karts
            for (unsigned int i = 0; i < m_karts.size(); i++)
                m_karts[i]->setVelocity(btVector3(0, 0, 0));
        }
        m_goal_timer += dt;

        if (m_goal_timer > 3.0f)
        {
            setPhase(WorldStatus::RACE_PHASE);
            m_goal_timer = 0.0f;
            if (!isRaceOver())
            {
                // Reset all karts
                for (unsigned int i = 0; i < m_karts.size(); i++)
                    moveKartAfterRescue(m_karts[i]);
                if (UserConfigParams::m_arena_ai_stats)
                    getKart(8)->flyUp();
            }
        }
    }
    if (UserConfigParams::m_arena_ai_stats)
        m_frame_count++;

}   // update
/** Update the world and the track.
 *  \param ticks Physics time steps - should be 1.
 */
void SoccerWorld::update(int ticks)
{
    updateBallPosition(ticks);
    if (Track::getCurrentTrack()->hasNavMesh())
    {
        updateSectorForKarts();
        updateAIData();
    }

    WorldWithRank::update(ticks);
    WorldWithRank::updateTrack(ticks);

    if (getPhase() == World::GOAL_PHASE)
    {
        if (m_goal_timer == 0)
        {
            // Stop all karts
            for (unsigned int i = 0; i < m_karts.size(); i++)
                m_karts[i]->setVelocity(btVector3(0, 0, 0));
        }
        m_goal_timer += ticks;

        if (m_goal_timer > stk_config->time2Ticks(3.0f))
        {
            setPhase(WorldStatus::RACE_PHASE);
            m_goal_timer = 0;
            if (!isRaceOver())
            {
                // Reset all karts
                for (unsigned int i = 0; i < m_karts.size(); i++)
                    moveKartAfterRescue(m_karts[i]);
                if (UserConfigParams::m_arena_ai_stats)
                    getKart(8)->flyUp();
            }
        }
    }
    if (UserConfigParams::m_arena_ai_stats)
        m_frame_count++;

}   // update
示例#10
0
unsigned int WorldWithRank::getRescuePositionIndex(AbstractKart *kart)
{
    const int start_spots_amount = getTrack()->getNumberOfStartPositions();
    assert(start_spots_amount > 0);

    float largest_accumulated_distance_found = -1;
    int   furthest_id_found                  = -1;

    for(int n=0; n<start_spots_amount; n++)
    {
        const btTransform &s = getStartTransform(n);
        const Vec3 &v=s.getOrigin();
        float accumulated_distance = .0f;
        bool spawn_point_clear = true;

        for(unsigned int k=0; k<getCurrentNumKarts(); k++)
        {
            if(kart->getWorldKartId()==k) continue;
            float abs_distance2 = (getKart(k)->getXYZ()-v).length2();
            const float CLEAR_SPAWN_RANGE2 = 5*5;
            if( abs_distance2 < CLEAR_SPAWN_RANGE2)
            {
                spawn_point_clear = false;
                break;
            }
            accumulated_distance += sqrt(abs_distance2);
        }

        if(accumulated_distance > largest_accumulated_distance_found &&
            spawn_point_clear)
        {
            furthest_id_found = n;
            largest_accumulated_distance_found = accumulated_distance;
        }
    }

    assert(furthest_id_found != -1);
    return furthest_id_found;
}   // getRescuePositionIndex
示例#11
0
/** Called when a mouse click happens. If the click happened while the mouse
 *  was hovering on top of a challenge, the kart will be teleported to
 *  the challenge.
 *  \param x,y Mouse coordinates.
 */
void OverWorld::onMouseClick(int x, int y)
{
    const OverworldChallenge *challenge =
        ((RaceGUIOverworld*)getRaceGUI())->getCurrentChallenge();

    if(challenge)
    {
        // Use the 'get closest start point' rescue function
        // from WorldWithRank by setting the kart's position to
        // be the location of the challenge bubble.
        AbstractKart* kart = getKart(0);
        kart->setXYZ(challenge->m_position);

        unsigned int index   = getRescuePositionIndex(kart);
        btTransform s        = getRescueTransform(index);
        const btVector3 &xyz = s.getOrigin();
        float angle          = atan2(challenge->m_position.X - xyz[0],
                                     challenge->m_position.Z - xyz[2]);
        s.setRotation( btQuaternion(btVector3(0.0f, 1.0f, 0.0f), angle) );
        moveKartTo(kart, s);
        return;
    }
}  // onMouseClick
示例#12
0
void OverWorld::onFirePressed(Controller* who)
{
    const std::vector<OverworldChallenge>& challenges =
                                                  m_track->getChallengeList();

    AbstractKart* k = getKart(0);
    Vec3 kart_xyz = k->getXYZ();
    if (dynamic_cast<RescueAnimation*>(k->getKartAnimation()) != NULL)
    {
        // you can't start a race while being rescued
        return;
    }

    for (unsigned int n=0; n<challenges.size(); n++)
    {
        if ( challenges[n].isForceFieldSet() &&
             challenges[n].getForceField().m_is_locked )
            continue;

        if ( (kart_xyz - Vec3(challenges[n].m_position)).length2_2d()
              < CHALLENGE_DISTANCE_SQUARED)
        {
            if (challenges[n].m_challenge_id == "tutorial")
            {
                scheduleTutorial();
                return;
            }
            else
            {
                race_manager->setKartLastPositionOnOverworld(kart_xyz);
                new SelectChallengeDialog(0.8f, 0.8f,
                                          challenges[n].m_challenge_id);
            }
        } // end if
    } // end for
}   // onFirePressed
示例#13
0
/** Localize the ball on the navigation mesh.
 */
void SoccerWorld::updateBallPosition(float dt)
{
    if (isRaceOver()) return;

    if (!ballNotMoving())
    {
        // Only update heading if the ball is moving
        m_ball_heading = atan2f(m_ball_body->getLinearVelocity().getX(),
            m_ball_body->getLinearVelocity().getZ());
    }

    if (m_track->hasNavMesh())
    {
        m_ball_on_node  = BattleGraph::get()->pointToNode(m_ball_on_node,
                          getBallPosition(), true/*ignore_vertical*/);

        if (m_ball_on_node == BattleGraph::UNKNOWN_POLY &&
            getPhase() == RACE_PHASE)
        {
            m_ball_invalid_timer += dt;
            // Reset the ball and karts if out of navmesh after 2 seconds
            if (m_ball_invalid_timer >= 2.0f)
            {
                m_ball_invalid_timer = 0.0f;
                m_ball->reset();
                for (unsigned int i = 0; i < m_karts.size(); i++)
                    moveKartAfterRescue(m_karts[i]);
                if (UserConfigParams::m_arena_ai_stats)
                    getKart(8)->flyUp();
            }
        }
        else
            m_ball_invalid_timer = 0.0f;
    }

}   // updateBallPosition
示例#14
0
//-----------------------------------------------------------------------------
OverWorld::~OverWorld()
{
    Vec3 kart_xyz = getKart(0)->getXYZ();
    race_manager->setKartLastPositionOnOverworld(kart_xyz);
}   // ~OverWorld
示例#15
0
/** Called when a kart must be eliminated.
 */
void FollowTheLeaderRace::countdownReachedZero()
{
    if(m_leader_intervals.size()>1)
        m_leader_intervals.erase(m_leader_intervals.begin());
    WorldStatus::setTime(m_leader_intervals[0]);

    // If the leader kart is not the first kart, remove the first
    // kart, otherwise remove the last kart.
    int position_to_remove = m_karts[0]->getPosition()==1
                           ? getCurrentNumKarts() : 1;
    AbstractKart *kart = getKartAtPosition(position_to_remove);
    if(!kart || kart->isEliminated())
    {
        fprintf(stderr,"Problem with removing leader: position %d not found\n",
                position_to_remove);
        for(unsigned int i=0; i<m_karts.size(); i++)
        {
            fprintf(stderr,"kart %d: eliminated %d position %d\n",
                    i,m_karts[i]->isEliminated(), m_karts[i]->getPosition());
        }   // for i
    }  //
    else
    {
        if(UserConfigParams::m_ftl_debug)
        {
            printf("[ftl] Eliminiating kart '%s' at position %d.\n",
                kart->getIdent().c_str(), position_to_remove);
        }
        eliminateKart(kart->getWorldKartId());

        // In case that the kart on position 1 was removed, we have
        // to set the correct position (which equals the remaining
        // number of karts) for the removed kart, as well as recompute
        // the position for all other karts
        if(position_to_remove==1)
        {
            // We have to add 1 to the number of karts to get the correct
            // position, since the eliminated kart was already removed
            // from the value returned by getCurrentNumKarts (and we have
            // to remove the kart before we can call updateRacePosition).
            // Note that we can not call WorldWithRank::setKartPosition
            // here, since it would not properly support debugging kart
            // ranks (since this kart would get its position set again
            // in updateRacePosition). We only set the rank of the eliminated
            // kart, and updateRacePosition will then call setKartPosition
            // for the now eliminated kart.
            kart->setPosition(getCurrentNumKarts()+1);
            updateRacePosition();
        }
        // Time doesn't make any sense in FTL (and it is not displayed)
        kart->finishedRace(-1.0f);

        // Move any camera for this kart to the leader, facing backwards,
        // so that the eliminated player has something to watch.
        if (race_manager->getNumPlayers() > 1)
        {
            for(unsigned int i=0; i<Camera::getNumCameras(); i++)
            {
                Camera *camera = Camera::getCamera(i);
                if(camera->getKart()==kart)
                {
                    camera->setMode(Camera::CM_LEADER_MODE);
                    camera->setKart(getKart(0));
                }
            }   // for i<number of cameras
        }
    }   // if kart to eliminate exists

    // almost over, use fast music
    if(getCurrentNumKarts()==3)
    {
        music_manager->switchToFastMusic();
    }

    if (isRaceOver())
    {
        // Handle special FTL situation: the leader is kart number 3 when
        // the last kart gets eliminated. In this case kart on position 1
        // is eliminated, and the kart formerly on position 2 is on
        // position 1, the leader now position 2. In this case the kart
        // on position 1 would get more points for this victory. So if
        // this is the case, change the position
        if(m_karts[0]->getPosition()!=1)
        {
            // Adjust the position of all still driving karts that
            // are ahead of the leader by +1, and move the leader
            // to position 1.
            for (unsigned int i=1; i<m_karts.size(); i++)
            {
                if(!m_karts[i]->hasFinishedRace() &&
                    !m_karts[i]->isEliminated()   &&
                    m_karts[i]->getPosition()<m_karts[0]->getPosition())
                {
                        m_karts[i]->setPosition(m_karts[i]->getPosition()+1);
                }
            }
            m_karts[0]->setPosition(1);
        }

        // Mark all still racing karts to be finished.
        for (unsigned int n=0; n<m_karts.size(); n++)
        {
            if (!m_karts[n]->isEliminated() &&
                !m_karts[n]->hasFinishedRace())
            {
                m_karts[n]->finishedRace(getTime());
            }
        }
    }
    // End of race is detected from World::updateWorld()

}   // countdownReachedZero
示例#16
0
/** Called immediately after the constructor. Here functions that use
 *  World::getWorld() as well as overridden functions.
 */
void FollowTheLeaderRace::init()
{
    LinearWorld::init();
    getKart(0)->setOnScreenText(_("Leader"));
}