Esempio n. 1
0
void GamePadDevice::resetAxisDirection(const int axis,
                                       Input::AxisDirection direction)
{
    // ignore this while in menus
    if (StateManager::get()->getGameState() != GUIEngine::GAME) return;

    AbstractKart* pk = getPlayer()->getKart();
    if (!pk)
    {
        Log::error("Binding", "Trying to reset axis for an unknown player.");
        return;
    }

    for(int n=PA_BEFORE_FIRST+1; n<PA_COUNT; n++)
    {
        const Binding& bind = m_configuration->getBinding(n);
        if(bind.getType() == Input::IT_STICKMOTION &&
           bind.getId() == axis &&
           bind.getDirection()== direction &&
           pk->getController() != NULL)
        {
            ((PlayerController*)(pk->getController()))
                                                  ->action((PlayerAction)n, 0);
            return;
        }
    }

}   // resetAxisDirection
Esempio n. 2
0
// ----------------------------------------------------------------------------
void addAttachment(Attachment::AttachmentType type)
{
    World* world = World::getWorld();
    if (world == NULL) return;
    for (unsigned int i = 0; i < world->getNumKarts(); i++)
    {
        AbstractKart *kart = world->getKart(i);
        if (!kart->getController()->isLocalPlayerController())
            continue;
        if (type == Attachment::ATTACH_ANVIL)
        {
            kart->getAttachment()
                ->set(type, kart->getKartProperties()->getAnvilDuration());
            kart->adjustSpeed(kart->getKartProperties()->getAnvilSpeedFactor());
            kart->updateWeight();
        }
        else if (type == Attachment::ATTACH_PARACHUTE)
        {
            kart->getAttachment()
                ->set(type, kart->getKartProperties()->getParachuteDuration());
        }
        else if (type == Attachment::ATTACH_BOMB)
        {
            kart->getAttachment()
                ->set(type, stk_config->m_bomb_time);
        }
    }

}   // addAttachment
Esempio n. 3
0
/** Sets the kart position and controls to the recorded history value.
 *  \param dt Time step size.
 */
void History::updateReplay(float dt)
{
    m_current++;
    World *world = World::getWorld();
    if(m_current>=(int)m_all_deltas.size())
    {
        Log::info("History", "Replay finished");
        m_current = 0;
        // Note that for physics replay all physics parameters
        // need to be reset, e.g. velocity, ...
        world->reset();
    }
    unsigned int num_karts = world->getNumKarts();
    for(unsigned k=0; k<num_karts; k++)
    {
        AbstractKart *kart = world->getKart(k);
        unsigned int index=m_current*num_karts+k;
        if(m_replay_mode==HISTORY_POSITION)
        {
            kart->setXYZ(m_all_xyz[index]);
            kart->setRotation(m_all_rotations[index]);
        }
        else
        {
            kart->setControls(m_all_controls[index]);
        }
    }
}   // updateReplay
Esempio n. 4
0
/** Creates the explosion physical effect, i.e. pushes the karts and ph
 *  appropriately. The corresponding visual/sfx needs to be added manually!
 *  \param kart_hit If non-NULL a kart that was directly hit.
 *  \param object If non-NULL a physical item that was hit directly.
 *  \param secondary_hits True if items that are not directly hit should
 *         also be affected.
 */
void Flyable::explode(AbstractKart *kart_hit, PhysicalObject *object,
                      bool secondary_hits)
{
    // Apply explosion effect
    // ----------------------
    World *world = World::getWorld();
    for ( unsigned int i = 0 ; i < world->getNumKarts() ; i++ )
    {
        AbstractKart *kart = world->getKart(i);

        // If no secondary hits should be done, only hit the
        // direct hit kart.
        if(!secondary_hits && kart!=kart_hit)
            continue;

        // Handle the actual explosion. The kart that fired a flyable will
        // only be affected if it's a direct hit. This allows karts to use
        // rockets on short distance.
        if( (m_owner!=kart || m_owner==kart_hit) && !kart->getKartAnimation())
        {
            // The explosion animation will register itself with the kart
            // and will free it later.
            ExplosionAnimation::create(kart, getXYZ(), kart==kart_hit);
            if(kart==kart_hit && world->getTrack()->isArena())
            {
                world->kartHit(kart->getWorldKartId());
            }
        }
    }
    world->getTrack()->handleExplosion(getXYZ(), object, secondary_hits);
}   // explode
Esempio n. 5
0
/** Determine the nearest kart or item and update the current target
 *  accordingly.
 */
void Swatter::chooseTarget()
{
    // TODO: for the moment, only handle karts...
    const World*  world         = World::getWorld();
    AbstractKart* closest_kart  = NULL;
    float         min_dist2     = FLT_MAX;

    for(unsigned int i=0; i<world->getNumKarts(); i++)
    {
        AbstractKart *kart = world->getKart(i);
        // TODO: isSwatterReady(), isSquashable()?
        if(kart->isEliminated() || kart==m_kart)
            continue;
        // don't squash an already hurt kart
        if (kart->isInvulnerable() || kart->isSquashed())
            continue;

        float dist2 = (kart->getXYZ()-m_kart->getXYZ()).length2();
        if(dist2<min_dist2)
        {
            min_dist2 = dist2;
            closest_kart = kart;
        }
    }
    m_target = closest_kart;    // may be NULL
}
Esempio n. 6
0
void GamePadDevice::resetAxisDirection(const int axis, 
                                       Input::AxisDirection direction, 
                                       StateManager::ActivePlayer* player)
{
    // ignore this while in menus
    if (StateManager::get()->getGameState() != GUIEngine::GAME) return;

    AbstractKart* pk = player->getKart();
    if (pk == NULL)
    {
        fprintf(stderr, "Error, trying to reset axis for an unknown player\n");
        return;
    }
    
    for(int n=0; n<PA_COUNT; n++)
    {
        Binding& bind = m_configuration->getBinding(n);
        if(bind.getType() == Input::IT_STICKMOTION &&
           bind.getId() == axis &&
           bind.getDirection()== direction)
        {
            ((PlayerController*)(pk->getController()))
                                                  ->action((PlayerAction)n, 0);
            return;
        }
    }

}   // resetAxisDirection
Esempio n. 7
0
/** Called when the check line is triggered. This function  creates a cannon
 *  animation object and attaches it to the kart.
 *  \param kart_index The index of the kart that triggered the check line.
 */
void CheckCannon::trigger(unsigned int kart_index)
{
    Vec3 target(m_target.getMiddle());
    AbstractKart *kart = World::getWorld()->getKart(kart_index);
    if(kart->getKartAnimation()) return;

    new CannonAnimation(kart, m_curve->clone());
}   // CheckCannon
Esempio n. 8
0
        /** Sets the kart's velocity to the specified value. */
        void setVelocity(int idKart, SimpleVec3* position)
        {
            float x = position->getX();
            float y = position->getY();
            float z = position->getZ();

            AbstractKart* kart = World::getWorld()->getKart(idKart);
            kart->setVelocity(btVector3(x, y, z));
        }
Esempio n. 9
0
 /** Teleports the kart to the specified Vec3 location */
 void teleport(int idKart, SimpleVec3* position)
 {
     AbstractKart* kart = World::getWorld()->getKart(idKart);
     Vec3 v(position->getX(), position->getY(), position->getZ());
     kart->setXYZ(v);
     unsigned int index = World::getWorld()->getRescuePositionIndex(kart);
     btTransform s = World::getWorld()->getRescueTransform(index);
     s.setRotation(btQuaternion(btVector3(0.0f, 1.0f, 0.0f), 0.0f));
     World::getWorld()->moveKartTo(kart, s);
 }
Esempio n. 10
0
/** Add powerup selected from debug menu for all player karts */
void addPowerup(PowerupManager::PowerupType powerup)
{
    World* world = World::getWorld();
    if (!world) return;
    for(unsigned int i = 0; i < race_manager->getNumLocalPlayers(); i++)
    {
        AbstractKart* kart = world->getLocalPlayerKart(i);
        kart->setPowerup(powerup, 10000);
    }
}   // addPowerup
Esempio n. 11
0
/** Shows the current soccer result.
 */
void RaceGUI::drawScores()
{
    SoccerWorld* soccerWorld = (SoccerWorld*)World::getWorld();
    int offsetY = 5;
    int offsetX = 5;
    gui::ScalableFont* font = GUIEngine::getFont();
    static video::SColor color = video::SColor(255,255,255,255);

    //Draw kart icons above score(denoting teams)
    irr::video::ITexture *red_team = irr_driver->getTexture(FileManager::GUI,
                                                            "soccer_ball_red.png");
    irr::video::ITexture *blue_team = irr_driver->getTexture(FileManager::GUI,
                                                             "soccer_ball_blue.png");
    irr::video::ITexture *team_icon;

    int numLeader = 1;
    for(unsigned int i=0; i<soccerWorld->getNumKarts(); i++)
    {
        int j = soccerWorld->getTeamLeader(i);
        if(j < 0) break;

        AbstractKart* kart = soccerWorld->getKart(i);
        video::ITexture* icon = kart->getKartProperties()->getMinimapIcon();
        core::rect<s32> source(core::position2di(0, 0), icon->getSize());
        core::recti position(offsetX, offsetY,
            offsetX + 2*m_minimap_player_size, offsetY + 2*m_minimap_player_size);
        draw2DImage(icon, position, source,
            NULL, NULL, true);
        core::stringw score = StringUtils::toWString(soccerWorld->getScore(i));
        int string_height =
            GUIEngine::getFont()->getDimension(score.c_str()).Height;
        core::recti pos(position.UpperLeftCorner.X + 5,
                        position.LowerRightCorner.Y + offsetY,
                        position.LowerRightCorner.X,
                        position.LowerRightCorner.Y + string_height);

        font->draw(score.c_str(),pos,color);
        
        switch(numLeader)
        {
            case 1: team_icon = red_team; break;
            case 2: team_icon = blue_team; break;
            default: break;
        }
        core::rect<s32> indicatorPos(offsetX, offsetY,
                                     offsetX + (int)(m_minimap_player_size/1.25f),
                                     offsetY + (int)(m_minimap_player_size/1.25f));
        core::rect<s32> sourceRect(core::position2d<s32>(0,0),
                                                   team_icon->getOriginalSize());
        draw2DImage(team_icon,indicatorPos,sourceRect,
            NULL,NULL,true);
        numLeader++;
        offsetX += position.LowerRightCorner.X;
    }
}   // drawScores
Esempio n. 12
0
void IrrDebugDrawer::setDebugMode(DebugModeType mode)
{
    m_debug_mode = mode;
    World *world = World::getWorld();
    unsigned int num_karts = world->getNumKarts();
    for(unsigned int i=0; i<num_karts; i++)
    {
        AbstractKart *kart = world->getKart(i);
        if(kart->isEliminated()) continue;
        kart->getNode()->setVisible(!(m_debug_mode & DM_NO_KARTS_GRAPHICS));
    }
}   // nextDebugMode
/** Activates the next debug mode, or switches the mode off again.
 */
void IrrDebugDrawer::nextDebugMode()
{
    // Go to next debug mode. Note that debug mode 3 (
    m_debug_mode = (DebugModeType) ((m_debug_mode+1) % 3);
    World *world = World::getWorld();
    unsigned int num_karts = world->getNumKarts();
    for(unsigned int i=0; i<num_karts; i++)
    {
        AbstractKart *kart = world->getKart(i);
        if(kart->isEliminated()) continue;
        kart->getNode()->setVisible(!(m_debug_mode & DM_NO_KARTS_GRAPHICS));
    }
}   // nextDebugMode
/** De-serialises a race result message and sets the appropriate results in 
 *  the kart and the race manager.
 *  \param pkt The enet message paket.
 */
RaceResultMessage::RaceResultMessage(ENetPacket* pkt) 
                 : Message(pkt, MT_RACE_RESULT)
{
    World *world = World::getWorld();
    const unsigned int num_karts = world->getNumKarts();
    for(unsigned int i=0; i<num_karts; i++)
    {
        AbstractKart *kart = world->getKart(i);
        float time  = getFloat();
        char position = getChar();
        kart->setPosition(position);
        kart->finishedRace(time);
    }
}   // RaceResultMessage
Esempio n. 15
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
Esempio n. 16
0
/** Copied from item state.
 */
bool CheckTrigger::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
                               int kart_id)
{
    // kart_id will be -1 if called by CheckManager::getChecklineTriggering
    if (kart_id < 0 || kart_id >= (int)World::getWorld()->getNumKarts())
        return false;
    if (m_last_triggered_time + 2000 > StkTime::getRealTimeMs())
        return false;
    AbstractKart* k = World::getWorld()->getKart(kart_id);
    if ((k->getXYZ() - m_center).length2() < m_distance2)
    {
        m_last_triggered_time = StkTime::getRealTimeMs();
        return true;
    }
    return false;
}   // isTriggered
/** Receives a kart control message. 
 *  \param kart_id_offset is the global id of the first kart on the host from 
 *         which this packet was received.
 */
KartControlMessage::KartControlMessage(ENetPacket* pkt, int kart_id_offset,
                                       int num_local_players)
                  : Message(pkt, MT_KART_CONTROL)
{
    // FIXME: This probably does not work anymore - it assume that
    // num_local_Players is the number of all local karts, while it might
    // only be the number of all network karts.
    for(int i=kart_id_offset; i<kart_id_offset+num_local_players; i++)
    {
        KartControl kc(this);
        AbstractKart *kart = World::getWorld()->getKart(i);
        if(kart->getController()->isNetworkController())
        {
            ((NetworkKart*)kart)->setControl(kc);
        }
    }
};   // KartControlMessage
Esempio n. 18
0
void addAttachment(Attachment::AttachmentType type)
{
    World* world = World::getWorld();
        if (world == NULL) return;
        for(unsigned int i = 0; i < world->getNumKarts(); i++)
        {
        AbstractKart *kart = world->getKart(i);
        if (kart->getController()->isPlayerController()) {
            if (type == Attachment::ATTACH_ANVIL)
            {
                kart->getAttachment()
                    ->set(type, stk_config->m_anvil_time);
                kart->adjustSpeed(stk_config->m_anvil_speed_factor);
                kart->updateWeight();
            }
            else if (type == Attachment::ATTACH_PARACHUTE)
            {
                kart->getAttachment()
                        ->set(type, stk_config->m_parachute_time);
            }
            else if (type == Attachment::ATTACH_BOMB)
            {
                kart->getAttachment()
                        ->set(type, stk_config->m_bomb_time);
            }
        }
        }

}
/** Checks if the kart was overtaken, and if so plays a sound
*/
void NetworkPlayerController::setPosition(int p)
{
    if(m_kart->getPosition()<p)
    {
        World *world = World::getWorld();
        //have the kart that did the passing beep.
        //I'm not sure if this method of finding the passing kart is fail-safe.
        for(unsigned int i = 0 ; i < world->getNumKarts(); i++ )
        {
            AbstractKart *kart = world->getKart(i);
            if(kart->getPosition() == p + 1)
            {
                kart->beep();
                break;
            }
        }
    }
}   // setPosition
Esempio n. 20
0
// ----------------------------------------------------------------------------
void changeCameraTarget(u32 num)
{
    World* world = World::getWorld();
    Camera *cam = Camera::getActiveCamera();
    if (world == NULL || cam == NULL) return;

    if (num < (world->getNumKarts() + 1))
    {
        AbstractKart* kart = world->getKart(num - 1);
        if (kart == NULL) return;
        if (kart->isEliminated()) return;
        cam->setMode(Camera::CM_NORMAL);
        cam->setKart(kart);
    }
    else
        return;

}   // changeCameraTarget
Esempio n. 21
0
/** Remove (eliminate) a kart from the race */
void World::eliminateKart(int kart_id, bool notify_of_elimination)
{
    AbstractKart *kart = m_karts[kart_id];
    if (kart->isGhostKart()) return;

    // Display a message about the eliminated kart in the race guia
    if (notify_of_elimination)
    {
        for(unsigned int i=0; i<Camera::getNumCameras(); i++)
        {
            Camera *camera = Camera::getCamera(i);
            if(camera->getKart()==kart)
                m_race_gui->addMessage(_("You have been eliminated!"), kart,
                                       2.0f);
            else
                m_race_gui->addMessage(_("'%s' has been eliminated.",
                                       kart->getName()),
                                       camera->getKart(),
                                       2.0f);
        }  // for i < number of cameras
    }   // if notify_of_elimination

    if(kart->getController()->isLocalPlayerController())
    {
        for(unsigned int i=0; i<Camera::getNumCameras(); i++)
        {
            // Change the camera so that it will be attached to the leader
            // and facing backwards.
            Camera *camera = Camera::getCamera(i);
            if(camera->getKart()==kart)
                camera->setMode(Camera::CM_LEADER_MODE);
        }
        m_eliminated_players++;
    }

    // The kart can't be really removed from the m_kart array, since otherwise
    // a race can't be restarted. So it's only marked to be eliminated (and
    // ignored in all loops). Important:world->getCurrentNumKarts() returns
    // the number of karts still racing. This value can not be used for loops
    // over all karts, use race_manager->getNumKarts() instead!
    kart->eliminate();
    m_eliminated_karts++;

}   // eliminateKart
Esempio n. 22
0
/** Ends the race early and places still active player karts at the back.
 *  The race immediately goes to the result stage, estimating the time for the
 *  karts still in the race. Still active player karts get a penalty in time
 *  as well as being placed at the back. Players that already finished keep
 *  their position.
 *
 *  End time for the punished players is calculated as follows
 *  end_time = current_time + (estimated_time - current_time)
 *                          + (estimated_time_for_last - current_time)
 *           = estimated_time + estimated_time_for_last - current_time
 *  This will put them at the end at all times. The further you (and the last in
 *  the race) are from the finish line, the harsher the punishment will be.
 */
void StandardRace::endRaceEarly()
{
    const unsigned int kart_amount = (unsigned int)m_karts.size();
    std::vector<int> active_players;
    // Required for debugging purposes
    beginSetKartPositions();
    for (unsigned int i = 1; i <= kart_amount; i++)
    {
        int kartid = m_position_index[i-1];
        AbstractKart* kart = m_karts[kartid];
        if (kart->hasFinishedRace())
        {
            // Have to do this to keep endSetKartPosition happy
            setKartPosition(kartid, kart->getPosition());
            continue;
        }

        if (kart->getController()->isPlayerController())
        {
            // Keep active players apart for now
            active_players.push_back(kartid);
        }
        else
        {
            // AI karts finish
            setKartPosition(kartid, i - (unsigned int) active_players.size());
            kart->finishedRace(estimateFinishTimeForKart(kart));
        }
    } // i <= kart_amount
    // Now make the active players finish
    for (unsigned int i = 0; i < active_players.size(); i++)
    {
        int kartid = active_players[i];
        int position = getNumKarts() - (int) active_players.size() + 1 + i;
        setKartPosition(kartid, position);
        m_karts[kartid]->eliminate();
    } // Finish the active players
    endSetKartPositions();
    setPhase(RESULT_DISPLAY_PHASE);
    if (!isNetworkWorld() || NetworkConfig::get()->isServer())
        terminateRace();
} // endRaceEarly
Esempio n. 23
0
/** Squash karts or items that are around the end position (determined using
 *  a joint) of the swatter.
 */
void Swatter::squashThingsAround()
{
    const KartProperties*  kp           = m_kart->getKartProperties();
    // Square of the minimum distance
    float                  min_dist2    = kp->getSwatterDistance2();
    const World*           world        = World::getWorld();

    // Get the node corresponding to the joint at the center of the swatter
    // (by swatter, I mean the thing hold in the hand, not the whole thing)
    scene::ISceneNode* swatter_node = m_scene_node->getJointNode("Swatter");
    assert(swatter_node);
    Vec3 swatter_pos = swatter_node->getAbsolutePosition();

    m_swat_sound->setPosition(swatter_pos);
    m_swat_sound->play();

    // Squash karts around
    for(unsigned int i=0; i<world->getNumKarts(); i++)
    {
        AbstractKart *kart = world->getKart(i);
        // TODO: isSwatterReady()
        if(kart->isEliminated() || kart==m_kart)
            continue;
        // don't swat an already hurt kart
        if (kart->isInvulnerable() || kart->isSquashed())
            continue;

        float dist2 = (kart->getXYZ()-swatter_pos).length2();

        if(dist2 >= min_dist2) continue;   // too far away, ignore this kart

        kart->setSquash(kp->getSquashDuration(), kp->getSquashSlowdown());

        if (kart->getAttachment()->getType()==Attachment::ATTACH_BOMB)
        {   // make bomb explode
            kart->getAttachment()->update(10000);
            HitEffect *he = new Explosion(m_kart->getXYZ(),  "explosion", "explosion.xml");
            if(m_kart->getController()->isPlayerController())
                he->setPlayerKartHit();
            projectile_manager->addHitEffect(he);
            ExplosionAnimation::create(kart);
        }   // if kart has bomb attached
        World::getWorld()->kartHit(kart->getWorldKartId());
    }   // for i < num_kartrs

    // TODO: squash items
}   // squashThingsAround
/** Remove (eliminate) a kart from the race */
void World::eliminateKart(int kart_number, bool notify_of_elimination)
{
    AbstractKart *kart = m_karts[kart_number];
    
    // Display a message about the eliminated kart in the race gui
    if (notify_of_elimination)
    {
        for (KartList::iterator i = m_karts.begin(); i != m_karts.end();  i++ )
        {
            if(!(*i)->getCamera()) continue;
            if(*i==kart)
            {
                m_race_gui->addMessage(_("You have been eliminated!"), *i, 
                                       2.0f);
            }
            else
            {
                m_race_gui->addMessage(_("'%s' has been eliminated.",
                                       core::stringw(kart->getName())), *i, 
                                       2.0f);
            }
        }   // for i in kart
    }
    
    if(kart->getController()->isPlayerController())
    {
        // Change the camera so that it will be attached to the leader
        // and facing backwards.
        Camera* camera=kart->getCamera();
        camera->setMode(Camera::CM_LEADER_MODE);
        m_eliminated_players++;
    }

    // The kart can't be really removed from the m_kart array, since otherwise
    // a race can't be restarted. So it's only marked to be eliminated (and
    // ignored in all loops). Important:world->getCurrentNumKarts() returns
    // the number of karts still racing. This value can not be used for loops
    // over all karts, use race_manager->getNumKarts() instead!
    kart->eliminate();
    m_eliminated_karts++;

}   // eliminateKart
Esempio n. 25
0
void Flyable::getClosestKart(const AbstractKart **minKart,
                             float *minDistSquared, Vec3 *minDelta,
                             const AbstractKart* inFrontOf,
                             const bool backwards) const
{
    btTransform trans_projectile = (inFrontOf != NULL ? inFrontOf->getTrans()
                                                      : getTrans());

    *minDistSquared = 999999.9f;
    *minKart = NULL;

    World *world = World::getWorld();
    for(unsigned int i=0 ; i<world->getNumKarts(); i++ )
    {
        AbstractKart *kart = world->getKart(i);
        // If a kart has star effect shown, the kart is immune, so
        // it is not considered a target anymore.
        if(kart->isEliminated() || kart == m_owner ||
            kart->isInvulnerable()                 ||
            kart->getKartAnimation()                   ) continue;
        btTransform t=kart->getTrans();

        Vec3 delta      = t.getOrigin()-trans_projectile.getOrigin();
        // the Y distance is added again because karts above or below should//
        // not be prioritized when aiming
        float distance2 = delta.length2() + std::abs(t.getOrigin().getY()
                        - trans_projectile.getOrigin().getY())*2;

        if(inFrontOf != NULL)
        {
            // Ignore karts behind the current one
            Vec3 to_target       = kart->getXYZ() - inFrontOf->getXYZ();
            const float distance = to_target.length();
            if(distance > 50) continue; // kart too far, don't aim at it

            btTransform trans = inFrontOf->getTrans();
            // get heading=trans.getBasis*(0,0,1) ... so save the multiplication:
            Vec3 direction(trans.getBasis().getColumn(2));
            // Originally it used angle = to_target.angle( backwards ? -direction : direction );
            // but sometimes due to rounding errors we get an acos(x) with x>1, causing
            // an assertion failure. So we remove the whole acos() test here and copy the
            // code from to_target.angle(...)
            Vec3  v = backwards ? -direction : direction;
            float s = sqrt(v.length2() * to_target.length2());
            float c = to_target.dot(v)/s;
            // Original test was: fabsf(acos(c))>1,  which is the same as
            // c<cos(1) (acos returns values in [0, pi] anyway)
            if(c<0.54) continue;
        }

        if(distance2 < *minDistSquared)
        {
            *minDistSquared = distance2;
            *minKart  = kart;
            *minDelta = delta;
        }
    }  // for i<getNumKarts

}   // getClosestKart
Esempio n. 26
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
Esempio n. 27
0
/** Sets the kart position and controls to the recorded history value.
 *  \param dt Time step size.
 */
float History::updateReplayAndGetDT()
{
    m_current++;
    World *world = World::getWorld();
    if(m_current>=(int)m_all_deltas.size())
    {
        Log::info("History", "Replay finished");
        m_current = 0;
        // This is useful to use a reproducable rewind problem:
        // replay it with history, for debugging only
#undef DO_REWIND_AT_END_OF_HISTORY
#ifdef DO_REWIND_AT_END_OF_HISTORY
        RewindManager::get()->rewindTo(5.0f);
        exit(-1);
#else
        // Note that for physics replay all physics parameters
        // need to be reset, e.g. velocity, ...
        world->reset();
#endif
    }
    unsigned int num_karts = world->getNumKarts();
    for(unsigned k=0; k<num_karts; k++)
    {
        AbstractKart *kart = world->getKart(k);
        unsigned int index=m_current*num_karts+k;
        if(m_replay_mode==HISTORY_POSITION)
        {
            kart->setXYZ(m_all_xyz[index]);
            kart->setRotation(m_all_rotations[index]);
        }
        else
        {
            kart->getControls().set(m_all_controls[index]);
        }
    }
    return m_all_deltas[m_current];
}   // updateReplayAndGetDT
Esempio n. 28
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
Esempio n. 29
0
/** Creates the explosion physical effect, i.e. pushes the karts and ph
 *  appropriately. The corresponding visual/sfx needs to be added manually!
 *  \param kart_hit If non-NULL a kart that was directly hit.
 *  \param object If non-NULL a physical item that was hit directly.
 *  \param secondary_hits True if items that are not directly hit should
 *         also be affected.
 */
void Flyable::explode(AbstractKart *kart_hit, PhysicalObject *object,
                      bool secondary_hits)
{
    // Apply explosion effect
    // ----------------------
    World *world = World::getWorld();
    for ( unsigned int i = 0 ; i < world->getNumKarts() ; i++ )
    {
        AbstractKart *kart = world->getKart(i);
        // Don't explode teammates in team world
        if (world->hasTeam() &&
            world->getKartTeam(kart->getWorldKartId()) ==
            world->getKartTeam(m_owner->getWorldKartId()))
            continue;

        if (kart->isGhostKart()) continue;

        // If no secondary hits should be done, only hit the
        // direct hit kart.
        if(!secondary_hits && kart!=kart_hit)
            continue;

        // Handle the actual explosion. The kart that fired a flyable will
        // only be affected if it's a direct hit. This allows karts to use
        // rockets on short distance.
        if( (m_owner!=kart || m_owner==kart_hit) && !kart->getKartAnimation())
        {
            // The explosion animation will register itself with the kart
            // and will free it later.
            ExplosionAnimation::create(kart, getXYZ(), kart==kart_hit);
            if (kart == kart_hit)
            {
                world->kartHit(kart->getWorldKartId(),
                    m_owner->getWorldKartId());

                if (m_owner->getController()->canGetAchievements())
                {
                    if (m_owner->getWorldKartId() != kart->getWorldKartId())
                        PlayerManager::addKartHit(kart->getWorldKartId());
                    PlayerManager::increaseAchievement(AchievementsStatus::ALL_HITS, 1);
                    if (race_manager->isLinearRaceMode())
                        PlayerManager::increaseAchievement(AchievementsStatus::ALL_HITS_1RACE, 1);
                }
            }
        }
    }
    Track::getCurrentTrack()->handleExplosion(getXYZ(), object,secondary_hits);
}   // explode
Esempio n. 30
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