diff --git a/src/items/item.cpp b/src/items/item.cpp index 389154e2a..8f3eb7d07 100644 --- a/src/items/item.cpp +++ b/src/items/item.cpp @@ -43,10 +43,7 @@ Item::Item(ItemType type, const Vec3& xyz, const Vec3& normal, m_distance_2 = 1.2f; initItem(type, xyz); - Vec3 axis = -normal.cross(Vec3(0, 1, 0)); - if (axis.length() == 0) - axis = Vec3(0, 0, 1); - m_original_rotation = btQuaternion(axis, normal.angle(Vec3(0, 1, 0))); + m_original_rotation = Track::createRotationFromNormal(normal); m_rotation_angle = 0.0f; m_original_mesh = mesh; m_original_lowmesh = lowres_mesh; diff --git a/src/items/item.hpp b/src/items/item.hpp index 99b1b3abf..763b3008c 100644 --- a/src/items/item.hpp +++ b/src/items/item.hpp @@ -276,9 +276,6 @@ public: { return (scene::ISceneNode *) m_node; } - // ------------------------------------------------------------------------ - const btQuaternion& getRotation() const { return m_original_rotation; } - }; // class Item #endif diff --git a/src/modes/three_strikes_battle.cpp b/src/modes/three_strikes_battle.cpp index af07cd973..f5c06d996 100644 --- a/src/modes/three_strikes_battle.cpp +++ b/src/modes/three_strikes_battle.cpp @@ -23,7 +23,6 @@ #include "graphics/camera.hpp" #include "graphics/irr_driver.hpp" #include "io/file_manager.hpp" -#include "items/item_manager.hpp" #include "karts/kart.hpp" #include "karts/controller/spare_tire_ai.hpp" #include "karts/kart_model.hpp" @@ -32,10 +31,12 @@ #include "physics/physics.hpp" #include "states_screens/race_gui_base.hpp" #include "tracks/arena_graph.hpp" +#include "tracks/arena_node.hpp" #include "tracks/track.hpp" #include "tracks/track_object_manager.hpp" #include "utils/constants.hpp" +#include #include #include @@ -675,27 +676,44 @@ void ThreeStrikesBattle::spawnSpareTireKarts() //----------------------------------------------------------------------------- void ThreeStrikesBattle::loadCustomModels() { - // Pre-add spare tire karts - if (ArenaGraph::get()) + // Pre-add spare tire karts if there are more than certain number of karts + ArenaGraph* ag = ArenaGraph::get(); + if (ag && m_karts.size() > 4) { // Spare tire karts only added with large arena - const int all_nodes = ArenaGraph::get()->getNumNodes(); - if (all_nodes > 200) + const int all_nodes = ag->getNumNodes(); + if (all_nodes > 500) { + // Don't create too many spare tire karts const unsigned int max_sta_num = unsigned(m_karts.size() * 0.8f); unsigned int pos_created = 0; + std::vector used; std::vector pos; - for (int i = 0; i < all_nodes; i++) + + // Fill all current starting position into used first + for (unsigned int i = 0; i < getNumberOfRescuePositions(); i++) { - // Pre-spawn the spare tire karts on the item position, - // preven affecting current karts - Item* item = ItemManager::get()->getFirstItemInQuad(i); - if (item == NULL) continue; + int node = -1; + ag->findRoadSector(getRescueTransform(i).getOrigin(), &node, + NULL, true); + assert(node != -1); + used.push_back(node); + } + + // Find random nodes to pre-spawn spare tire karts + RandomGenerator random; + while (true) + { + const int node = random.get(all_nodes); + if (std::find(used.begin(), used.end(), node) != used.end()) + continue; + const ArenaNode* n = ag->getNode(node); btTransform t; - t.setOrigin(item->getXYZ()); - t.setRotation(item->getRotation()); + t.setOrigin(n->getCenter()); + t.setRotation(Track::createRotationFromNormal(n->getNormal())); pos.push_back(t); pos_created++; + used.push_back(node); if (pos_created >= max_sta_num) break; } @@ -715,16 +733,17 @@ void ThreeStrikesBattle::loadCustomModels() sta->setController(new SpareTireAI(sta)); m_karts.push_back(sta); - race_manager->addSpareTireKartStatus(sta_list[i]); + race_manager->addSpareTireKart(sta_list[i]); m_track->adjustForFog(sta->getNode()); // Copy STA pointer to m_spare_tire_karts array, allowing them // to respawn easily m_spare_tire_karts.push_back(sta); } - race_manager->setNumKarts(m_karts.size()); - assert(m_spare_tire_karts.size() == - race_manager->getNumSpareTireKarts()); + unsigned int sta_num = race_manager->getNumSpareTireKarts(); + assert(m_spare_tire_karts.size() == sta_num); + Log::info("ThreeStrikesBattle","%d spare tire kart(s) created.", + sta_num); } } } // loadCustomModels diff --git a/src/race/race_manager.hpp b/src/race/race_manager.hpp index 46326887f..7be0e8227 100644 --- a/src/race/race_manager.hpp +++ b/src/race/race_manager.hpp @@ -754,12 +754,13 @@ public: return m_watching_replay; } // isWatchingReplay // ------------------------------------------------------------------------ - void addSpareTireKartStatus(const std::string& name) + void addSpareTireKart(const std::string& name) { m_kart_status.push_back(KartStatus(name, 0, -1, -1, -1, KT_SPARE_TIRE, PLAYER_DIFFICULTY_NORMAL)); m_num_spare_tire_karts++; - } // addSpareTireKartStatus + m_num_karts++; + } // addSpareTireKart // ------------------------------------------------------------------------ void setSpareTireKartNum(unsigned int i) { diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index a24d79a6b..dce9fe474 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -702,11 +702,7 @@ btQuaternion Track::getArenaStartRotation(const Vec3& xyz, float heading) } const Vec3& normal = Graph::get()->getQuad(node)->getNormal(); - Vec3 axis = -normal.cross(Vec3(0, 1, 0)); - if (axis.length() == 0) - axis = Vec3(0, 0, 1); - - btQuaternion q(axis, normal.angle(Vec3(0, 1, 0))); + btQuaternion q = createRotationFromNormal(normal); btMatrix3x3 m; m.setRotation(q); return btQuaternion(m.getColumn(1), heading * DEGREE_TO_RAD) * q; diff --git a/src/tracks/track.hpp b/src/tracks/track.hpp index 03e4972f4..8f9bcd05a 100644 --- a/src/tracks/track.hpp +++ b/src/tracks/track.hpp @@ -397,6 +397,14 @@ public: static const float NOHIT; + static btQuaternion createRotationFromNormal(const Vec3& normal) + { + Vec3 axis = -normal.cross(Vec3(0, 1, 0)); + if (axis.length() == 0) + axis = Vec3(0, 0, 1); + return btQuaternion(axis, normal.angle(Vec3(0, 1, 0))); + } // createRotationFromNormal + Track (const std::string &filename); ~Track (); void cleanup ();