/** Called at the end of a race. Checks if the current times are worth a new * score, if so it notifies the HighscoreManager so the new score is added * and saved. */ void World::updateHighscores(int* best_highscore_rank, int* best_finish_time, std::string* highscore_who, StateManager::ActivePlayer** best_player) { *best_highscore_rank = -1; *best_player = NULL; if(!m_use_highscores) return; // Add times to highscore list. First compute the order of karts, // so that the timing of the fastest kart is added first (otherwise // someone might get into the highscore list, only to be kicked out // again by a faster kart in the same race), which might be confusing // if we ever decide to display a message (e.g. during a race) unsigned int *index = new unsigned int[m_karts.size()]; const unsigned int kart_amount = m_karts.size(); for (unsigned int i=0; i<kart_amount; i++ ) { index[i] = 999; // first reset the contents of the array } for (unsigned int i=0; i<kart_amount; i++ ) { const int pos = m_karts[i]->getPosition()-1; if(pos < 0 || pos >= (int)kart_amount) continue; // wrong position index[pos] = i; } for (unsigned int pos=0; pos<kart_amount; pos++) { if(index[pos] == 999) { // no kart claimed to be in this position, most likely means // the kart location data is wrong #ifdef DEBUG fprintf(stderr, "Error, incorrect kart positions:\n"); for (unsigned int i=0; i<m_karts.size(); i++ ) { fprintf(stderr, "i=%d position %d\n",i, m_karts[i]->getPosition()); } #endif continue; } // Only record times for player karts and only if // they finished the race if(!m_karts[index[pos]]->getController()->isPlayerController()) continue; if (!m_karts[index[pos]]->hasFinishedRace()) continue; assert(index[pos] >= 0); assert(index[pos] < m_karts.size()); Kart *k = (Kart*)m_karts[index[pos]]; Highscores* highscores = getHighscores(); PlayerController *controller = (PlayerController*)(k->getController()); int highscore_rank = highscores->addData(k->getIdent(), controller->getPlayer()->getProfile()->getName(), k->getFinishTime()); if (highscore_rank > 0) { if (*best_highscore_rank == -1 || highscore_rank < *best_highscore_rank) { *best_highscore_rank = highscore_rank; *best_finish_time = (int)(k->getFinishTime()); *best_player = controller->getPlayer(); *highscore_who = k->getIdent(); } highscore_manager->saveHighscores(); } } // next position delete []index; } // updateHighscores
void Tool::draw(sf::RenderTarget &render, const PlayerController &event) const { drawRect(render, getPos(), m_dim, sf::Color::Black, 1, m_selected ? getPlayer()->getBaseColor() : (isInside(event.mousePos()) ? sf::Color(150, 150, 150, 255) : sf::Color(100, 100, 100, 255))); }
void GroupCamera::Move(void) { GamePlayer *gp = nullptr; PlayerController *cont = nullptr; Node *node = nullptr; Point3D loc; int numPlayers = 0; float sumX = 0; float xPos = 0; //float sumY = 0; float yPos = 0; float min = 0; float max = 0; float offset=0; //find center of mass, min, and max Player *p = TheMessageMgr->GetFirstPlayer(); if (p) { gp = static_cast<GamePlayer *>(p); cont = gp->GetController(); if (cont) { node = cont->GetTargetNode(); loc = node->GetWorldPosition(); sumX = sumX + loc.x; yPos = loc.y; min = sumX; max = sumX; numPlayers++; } p = p->Next(); } while (p) { gp = static_cast<GamePlayer *>(p); cont = gp->GetController(); if (cont) { node = cont->GetTargetNode(); loc = node->GetWorldPosition(); sumX = sumX + loc.x; if (loc.y < yPos) { yPos = loc.y; } if (loc.x < min){ min = loc.x; } else if (loc.x > max) { max = loc.x; } numPlayers++; } p = p->Next(); } xPos = sumX / numPlayers; offset = max - min; if (offset < 8.0F){ offset = 8.0F; } SetNodePosition(Point3D(xPos, yPos - offset, 4.5F)); LookAtPoint(Point3D(xPos, yPos, 0.0F)); }
/** Updates the physics simulation and handles all collisions. * \param dt Time step. */ void Physics::update(float dt) { PROFILER_PUSH_CPU_MARKER("Physics", 0, 0, 0); m_physics_loop_active = true; // Bullet can report the same collision more than once (up to 4 // contact points per collision). Additionally, more than one internal // substep might be taken, resulting in potentially even more // duplicates. To handle this, all collisions (i.e. pair of objects) // are stored in a vector, but only one entry per collision pair // of objects. m_all_collisions.clear(); // Maximum of three substeps. This will work for framerate down to // 20 FPS (bullet default frequency is 60 HZ). m_dynamics_world->stepSimulation(dt, 3); // Now handle the actual collision. Note: flyables can not be removed // inside of this loop, since the same flyables might hit more than one // other object. So only a flag is set in the flyables, the actual // clean up is then done later in the projectile manager. std::vector<CollisionPair>::iterator p; for(p=m_all_collisions.begin(); p!=m_all_collisions.end(); ++p) { // Kart-kart collision // -------------------- if(p->getUserPointer(0)->is(UserPointer::UP_KART)) { KartKartCollision(p->getUserPointer(0)->getPointerKart(), p->getContactPointCS(0), p->getUserPointer(1)->getPointerKart(), p->getContactPointCS(1) ); Scripting::ScriptEngine* script_engine = World::getWorld()->getScriptEngine(); int kartid1 = p->getUserPointer(0)->getPointerKart()->getWorldKartId(); int kartid2 = p->getUserPointer(1)->getPointerKart()->getWorldKartId(); script_engine->runFunction("void onKartKartCollision(int, int)", [=](asIScriptContext* ctx) { ctx->SetArgDWord(0, kartid1); ctx->SetArgDWord(1, kartid2); }); continue; } // if kart-kart collision if(p->getUserPointer(0)->is(UserPointer::UP_PHYSICAL_OBJECT)) { // Kart hits physical object // ------------------------- Scripting::ScriptEngine* script_engine = World::getWorld()->getScriptEngine(); AbstractKart *kart = p->getUserPointer(1)->getPointerKart(); int kartId = kart->getWorldKartId(); PhysicalObject* obj = p->getUserPointer(0)->getPointerPhysicalObject(); std::string obj_id = obj->getID(); std::string scripting_function = obj->getOnKartCollisionFunction(); if (scripting_function.size() > 0) { script_engine->runFunction("void " + scripting_function + "(int, const string)", [&](asIScriptContext* ctx) { ctx->SetArgDWord(0, kartId); ctx->SetArgObject(1, &obj_id); }); } if (obj->isCrashReset()) { new RescueAnimation(kart); } else if (obj->isExplodeKartObject()) { ExplosionAnimation::create(kart); } else if (obj->isFlattenKartObject()) { const KartProperties* kp = kart->getKartProperties(); kart->setSquash(kp->getSquashDuration() * kart->getPlayerDifficulty()->getSquashDuration(), kp->getSquashSlowdown() * kart->getPlayerDifficulty()->getSquashSlowdown()); } else if(obj->isSoccerBall() && race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER) { SoccerWorld* soccerWorld = (SoccerWorld*)World::getWorld(); soccerWorld->setLastKartTohitBall(kartId); } continue; } if (p->getUserPointer(0)->is(UserPointer::UP_ANIMATION)) { // Kart hits animation ThreeDAnimation *anim=p->getUserPointer(0)->getPointerAnimation(); if(anim->isCrashReset()) { AbstractKart *kart = p->getUserPointer(1)->getPointerKart(); new RescueAnimation(kart); } else if (anim->isExplodeKartObject()) { AbstractKart *kart = p->getUserPointer(1)->getPointerKart(); ExplosionAnimation::create(kart); } else if (anim->isFlattenKartObject()) { AbstractKart *kart = p->getUserPointer(1)->getPointerKart(); const KartProperties* kp = kart->getKartProperties(); kart->setSquash(kp->getSquashDuration() * kart->getPlayerDifficulty()->getSquashDuration(), kp->getSquashSlowdown() * kart->getPlayerDifficulty()->getSquashSlowdown()); } continue; } // now the first object must be a projectile // ========================================= if(p->getUserPointer(1)->is(UserPointer::UP_TRACK)) { // Projectile hits track // --------------------- p->getUserPointer(0)->getPointerFlyable()->hitTrack(); } else if(p->getUserPointer(1)->is(UserPointer::UP_PHYSICAL_OBJECT)) { // Projectile hits physical object // ------------------------------- Scripting::ScriptEngine* script_engine = World::getWorld()->getScriptEngine(); Flyable* flyable = p->getUserPointer(0)->getPointerFlyable(); PhysicalObject* obj = p->getUserPointer(1)->getPointerPhysicalObject(); std::string obj_id = obj->getID(); std::string scripting_function = obj->getOnItemCollisionFunction(); if (scripting_function.size() > 0) { script_engine->runFunction("void " + scripting_function + "(int, int, const string)", [&](asIScriptContext* ctx) { ctx->SetArgDWord(0, (int)flyable->getType()); ctx->SetArgDWord(1, flyable->getOwnerId()); ctx->SetArgObject(2, &obj_id); }); } flyable->hit(NULL, obj); if (obj->isSoccerBall() && race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER) { int kartId = p->getUserPointer(0)->getPointerFlyable()->getOwnerId(); SoccerWorld* soccerWorld = (SoccerWorld*)World::getWorld(); soccerWorld->setLastKartTohitBall(kartId); } } else if(p->getUserPointer(1)->is(UserPointer::UP_KART)) { // Projectile hits kart // -------------------- // Only explode a bowling ball if the target is // not invulnerable AbstractKart* target_kart = p->getUserPointer(1)->getPointerKart(); PowerupManager::PowerupType type = p->getUserPointer(0)->getPointerFlyable()->getType(); if(type != PowerupManager::POWERUP_BOWLING || !target_kart->isInvulnerable()) { Flyable *f = p->getUserPointer(0)->getPointerFlyable(); f->hit(target_kart); // Check for achievements AbstractKart * kart = World::getWorld()->getKart(f->getOwnerId()); PlayerController *c = dynamic_cast<PlayerController*>(kart->getController()); // Check that it's not a kart hitting itself (this can // happen at the time a flyable is shot - release too close // to the kart, and it's the current player. At this stage // only the current player can get achievements. if (target_kart != kart && c && c->getPlayer()->getConstProfile() == PlayerManager::getCurrentPlayer()) { // Compare the current value of hits with the 'hit' goal value // (otherwise it would be compared with the kart id goal value, // which doesn't exist. PlayerManager::increaseAchievement(AchievementInfo::ACHIEVE_ARCH_ENEMY, target_kart->getIdent(), 1, "hit"); if (type == PowerupManager::POWERUP_BOWLING) { PlayerManager::increaseAchievement(AchievementInfo::ACHIEVE_STRIKE, "ball", 1); } // is bowling ball } // if target_kart != kart && is a player kart and is current player } } else { // Projectile hits projectile // -------------------------- p->getUserPointer(0)->getPointerFlyable()->hit(NULL); p->getUserPointer(1)->getPointerFlyable()->hit(NULL); } } // for all p in m_all_collisions m_physics_loop_active = false; // Now remove the karts that were removed while the above loop // was active. Now we can safely call removeKart, since the loop // is finished and m_physics_world_active is not set anymore. for(unsigned int i=0; i<m_karts_to_delete.size(); i++) removeKart(m_karts_to_delete[i]); m_karts_to_delete.clear(); PROFILER_POP_CPU_MARKER(); } // update
void GroupCamera2::Move(void) { GamePlayer *gp = nullptr; PlayerController *cont = nullptr; Node *node = nullptr; Point3D loc; int numPlayers = 0; float sumX = 0; float xPos = 0; float min = 0; float max = 0; //find center of mass, min, and max Player *p = TheMessageMgr->GetFirstPlayer(); if (p) { gp = static_cast<GamePlayer *>(p); cont = gp->GetController(); if (cont) { node = cont->GetTargetNode(); loc = node->GetWorldPosition(); sumX = sumX + loc.x; min = sumX; max = sumX; numPlayers++; } p = p->Next(); } while (p) { gp = static_cast<GamePlayer *>(p); cont = gp->GetController(); if (cont) { node = cont->GetTargetNode(); loc = node->GetWorldPosition(); sumX = sumX + loc.x; if (loc.x < min){ min = loc.x; } else if (loc.x > max) { max = loc.x; } numPlayers++; } p = p->Next(); } xPos = sumX / numPlayers; //float offset = -5.0F; float yPos = 4.0F; float y = 0; //find center of mass, min, and max p = TheMessageMgr->GetFirstPlayer(); while (p) { gp = static_cast<GamePlayer *>(p); cont = gp->GetController(); if (cont) { node = cont->GetTargetNode(); loc = node->GetWorldPosition(); if (loc.x > xPos) { //use y = 2x y = 2.0F*(loc.x - xPos); } else { //use y = -2x y = 2.0F*(xPos - loc.x); } //get distance y to loc.y y = y - loc.y; //check is y is minimum value (negative) if (yPos < y){ yPos = y; } } p = p->Next(); } SetNodePosition(Point3D(xPos, -4.5F - yPos, 3.5F)); LookAtPoint(Point3D(xPos, 0.0, 0.0F)); }
void GuiCommandButton::actionPerformed(const PlayerController &event, Vec pos, Vec dim, Gui* gui) { if(event.pressed(0)) m_commands++; }
/** * Handle the player interacting with the Rotator */ void RotatorController::HandleInteractionEvent(InteractionEventType type, const Point3D *position, Node *activator) { PlayerController* sc = TheGame->GetPlayerController(); sc->SetPlayerAzimuth(sc->GetPlayerAzimuth() + K::pi_over_2); }
void GuiButton::update(const PlayerController &controller, Vec pos, Vec dim) { m_hovered = controller.mousePos().insideRect(pos, dim); }
GameObject* ScriptArguments::getPlayerCharacter(unsigned int player) const { auto playerId = parameters->at(player).integerValue(); PlayerController* controller = getWorld()->players.at(playerId); RW_CHECK(controller != nullptr, "No controller for player " << player); return controller->getCharacter(); }