示例#1
0
/** Is called when this check structure is triggered. This then can cause
 *  a lap to be counted, animation to be started etc.
 */
void CheckStructure::trigger(unsigned int kart_index)
{    
    World* w = World::getWorld();
    LinearWorld* lw = dynamic_cast<LinearWorld*>(w);
    if (lw != NULL)
    {
        lw->getTrackSector(kart_index).setLastTriggeredCheckline(m_index);
    }
    
    switch(m_check_type)
    {
    case CT_NEW_LAP : 
        World::getWorld()->newLap(kart_index); 
        if(UserConfigParams::m_check_debug)
        {
            printf("CHECK: %s new lap %d triggered\n",
                   World::getWorld()->getKart(kart_index)->getIdent().c_str(),
                   m_index);
        }
        changeStatus(m_check_structures_to_change_state, 
                     kart_index, CS_ACTIVATE);
        break;
    case CT_ACTIVATE: 
        changeStatus(m_check_structures_to_change_state,
                     kart_index, CS_ACTIVATE);
        break;
    case CT_TOGGLE:   
        changeStatus(m_check_structures_to_change_state,
                     kart_index, CS_TOGGLE);
        break;
    default: 
        break;
    }   // switch m_check_type
    changeStatus(m_same_group, kart_index, CS_DEACTIVATE);
}   // trigger
/** Determines the first kart that is still in the race.
 */
void RubberBall::computeTarget()
{
    LinearWorld *world = dynamic_cast<LinearWorld*>(World::getWorld());

    for(unsigned int p = race_manager->getFinishedKarts()+1;
                     p < world->getNumKarts()+1; p++)
    {
        m_target = world->getKartAtPosition(p);
        if(!m_target->isEliminated() && !m_target->hasFinishedRace())
        {
            // If the firing kart itself is the first kart (that is
            // still driving), prepare to remove the rubber ball
            if(m_target==m_owner && m_delete_timer < 0)
            {
#ifdef PRINT_BALL_REMOVE_INFO
                Log::debug("RubberBall",
                           "ball %d removed because owner is target.", m_id);
#endif
                m_delete_timer = m_st_delete_time;
            }
            return;
        }
    }   // for p > num_karts

    // This means it must be the end-animation phase. Now just
    // aim at the owner (the ball is unlikely to hit it), and
    // this will trigger the usage of the delete time in updateAndDelete
#ifdef PRINT_BALL_REMOVE_INFO
    Log::debug("RubberBall" "ball %d removed because no more active target.",
               m_id);
#endif
    m_delete_timer = m_st_delete_time;
    m_target       = m_owner;
}   // computeTarget
/** This function is called each timestep, and it collects most of the
 *  statistics for this kart.
 *  \param dt Time step size.
 */
void KartWithStats::update(int ticks)
{
    Kart::update(ticks);
    if(getSpeed()>m_top_speed        ) m_top_speed = getSpeed();
    float dt = stk_config->ticks2Time(ticks);
    if(getControls().getSkidControl()) m_skidding_time += dt;
    if(getControls().getBrake()      ) m_brake_count ++;
    LinearWorld *world = dynamic_cast<LinearWorld*>(World::getWorld());
    if(world && !world->isOnRoad(getWorldKartId()))
        m_off_track_count ++;
}   // update
/** This function is called each timestep, and it collects most of the 
 *  statistics for this kart.
 *  \param dt Time step size.
 */
void KartWithStats::update(float dt)
{
    Kart::update(dt);
    if(getSpeed()>m_top_speed) m_top_speed = getSpeed();
    if(getControls().m_skid)
        m_skidding_time += dt;
    if(getControls().m_brake)
        m_brake_count ++;
    LinearWorld *world = dynamic_cast<LinearWorld*>(World::getWorld());
    if(world && !world->isOnRoad(getWorldKartId()))
        m_off_track_count ++;
}   // update
示例#5
0
/** Returns true if this (non-GP) challenge is fulfilled.
 */
bool ChallengeData::isChallengeFulfilled() const
{
    // GP's use the grandPrixFinished() function,
    // so they can't be fulfilled here.
    if(m_mode==CM_GRAND_PRIX) return false;

    // Single races
    // ------------
    World *world = World::getWorld();
    std::string track_name = world->getTrack()->getIdent();

    int d = race_manager->getDifficulty();

    AbstractKart* kart = world->getPlayerKart(0);

    if (kart->isEliminated()                                    ) return false;
    if (track_name != m_track_id                                ) return false;
    if ((int)world->getNumKarts() < m_num_karts[d]              ) return false;
    if (m_energy[d] > 0   && kart->getEnergy() < m_energy[d]    ) return false;
    if (m_position[d] > 0 && kart->getPosition() > m_position[d]) return false;

    // Follow the leader
    // -----------------
    if(m_minor==RaceManager::MINOR_MODE_FOLLOW_LEADER)
    {
        // All possible conditions were already checked, so:
        // must have been successful
        return true;
    }
    // Quickrace / Timetrial
    // ---------------------
    // FIXME - encapsulate this better, each race mode needs to be able
    // to specify its own challenges and deal with them
    LinearWorld* lworld = dynamic_cast<LinearWorld*>(world);
    if(lworld != NULL)
    {
        // wrong number of laps
        if(lworld->getLapForKart( kart->getWorldKartId() ) != m_num_laps)
            return false;
    }
    // too slow
    if (m_time[d] > 0.0f && kart->getFinishTime() > m_time[d]) return false;

    if (m_ai_superpower[d] != RaceManager::SUPERPOWER_NONE &&
        race_manager->getAISuperPower() != m_ai_superpower[d])
    {
        return false;
    }

    return true;
}   // isChallengeFulfilled
// ----------------------------------------------------------------------------
bool GameEventsProtocol::notifyEvent(Event* event)
{
    // Avoid crash in case that we still receive race events when
    // the race is actually over.
    if (event->getType() != EVENT_TYPE_MESSAGE || !World::getWorld())
        return true;
    NetworkString &data = event->data();
    if (data.size() < 1) // for type
    {
        Log::warn("GameEventsProtocol", "Too short message.");
        return true;
    }
    uint8_t type = data.getUInt8();
    CaptureTheFlag* ctf = dynamic_cast<CaptureTheFlag*>(World::getWorld());
    FreeForAll* ffa = dynamic_cast<FreeForAll*>(World::getWorld());
    SoccerWorld* sw = dynamic_cast<SoccerWorld*>(World::getWorld());
    LinearWorld* lw = dynamic_cast<LinearWorld*>(World::getWorld());
    switch (type)
    {
    case GE_KART_FINISHED_RACE:
        kartFinishedRace(data);     break;
    case GE_RESET_BALL:
    {
        if (!sw)
            throw std::invalid_argument("No soccer world");
        sw->handleResetBallFromServer(data);
        break;
    }
    case GE_PLAYER_GOAL:
    {
        if (!sw)
            throw std::invalid_argument("No soccer world");
        sw->handlePlayerGoalFromServer(data);
        break;
    }
    case GE_BATTLE_KART_SCORE:
    {
        if (!ffa)
            throw std::invalid_argument("No free-for-all world");
        ffa->setKartScoreFromServer(data);
        break;
    }
    case GE_CTF_SCORED:
    {
        if (!ctf)
            throw std::invalid_argument("No CTF world");
        uint8_t kart_id = data.getUInt8();
        bool red_team_scored = data.getUInt8() == 1;
        int16_t new_kart_scores = data.getUInt16();
        int new_red_scores = data.getUInt8();
        int new_blue_scores = data.getUInt8();
        ctf->ctfScored(kart_id, red_team_scored, new_kart_scores,
            new_red_scores, new_blue_scores);
        break;
    }
    case GE_STARTUP_BOOST:
    {
        if (NetworkConfig::get()->isServer())
        {
            uint8_t kart_id = data.getUInt8();
            if (!event->getPeer()->availableKartID(kart_id))
            {
                Log::warn("GameProtocol", "Wrong kart id %d from %s.",
                    kart_id, event->getPeer()->getAddress().toString().c_str());
                return true;
            }
            float f = LobbyProtocol::get<ServerLobby>()
                ->getStartupBoostOrPenaltyForKart(
                event->getPeer()->getAveragePing(), kart_id);
            NetworkString *ns = getNetworkString();
            ns->setSynchronous(true);
            ns->addUInt8(GE_STARTUP_BOOST).addUInt8(kart_id).addFloat(f);
            sendMessageToPeers(ns, true);
            delete ns;
        }
        else
        {
            uint8_t kart_id = data.getUInt8();
            float boost = data.getFloat();
            AbstractKart* k = World::getWorld()->getKart(kart_id);
            if (boost < 0.0f)
            {
                PlayerController* pc =
                    dynamic_cast<PlayerController*>(k->getController());
                pc->displayPenaltyWarning();
            }
            else
                k->setStartupBoost(boost);
        }
        break;
    }
    case GE_CHECK_LINE:
    {
        if (!lw)
            throw std::invalid_argument("No linear world");
        if (NetworkConfig::get()->isClient())
            lw->updateCheckLinesClient(data);
        break;
    }
    default:
        Log::warn("GameEventsProtocol", "Unkown message type.");
        break;
    }
    return true;
}   // notifyEvent
示例#7
0
/** True if going from old_pos to new_pos crosses this checkline. This function
 *  is called from update (of the checkline structure).
 *  \param old_pos  Position in previous frame.
 *  \param new_pos  Position in current frame.
 *  \param indx     Index of the kart, can be used to store kart specific
 *                  additional data.
 */
bool CheckLine::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
    unsigned int kart_index)
{
    World* w = World::getWorld();
    core::vector2df p=new_pos.toIrrVector2d();
    bool sign = m_line.getPointOrientation(p)>=0;
    bool result;

    bool previous_sign;

    if (kart_index == -1)
    {
        core::vector2df p = old_pos.toIrrVector2d();
        previous_sign = (m_line.getPointOrientation(p) >= 0);
    }
    else
    {
        previous_sign = m_previous_sign[kart_index];
    }

    // If the sign has changed, i.e. the infinite line was crossed somewhere,
    // check if the finite line was actually crossed:
    if (sign != previous_sign &&
        m_line.intersectWith(core::line2df(old_pos.toIrrVector2d(),
                                           new_pos.toIrrVector2d()),
                             m_cross_point) )
    {
        // Now check the minimum height: the kart position must be within a
        // reasonable distance in the Z axis - 'reasonable' for now to be
        // between -1 and 4 units (negative numbers are unlikely, but help
        // in case that the kart is 'somewhat' inside of the track, or the
        // checklines are a bit off in Z direction.
        result = new_pos.getY()-m_min_height<m_over_min_height   &&
                 new_pos.getY()-m_min_height>-m_under_min_height;
        if(UserConfigParams::m_check_debug && !result)
        {
            if(World::getWorld()->getNumKarts()>0)
                Log::info("CheckLine", "Kart %s crosses line, but wrong height "
                          "(%f vs %f).",
                          World::getWorld()->getKart(kart_index)->getIdent().c_str(),
                          new_pos.getY(), m_min_height);
            else
                Log::info("CheckLine", "Kart %d crosses line, but wrong height "
                          "(%f vs %f).",
                          kart_index, new_pos.getY(), m_min_height);

        }
    }
    else
        result = false;

    if (kart_index != -1)
        m_previous_sign[kart_index] = sign;

    if (result && kart_index != -1)
    {
        LinearWorld* lw = dynamic_cast<LinearWorld*>(w);
        if (lw != NULL)
            lw->setLastTriggeredCheckline(kart_index, m_index);
    }
    return result;
}   // isTriggered