Allow random items number and type for arena with navmesh.

Number and types are hard-coded for now.
This commit is contained in:
Benau 2016-03-17 01:27:24 +08:00
parent 6f5d36f479
commit d2509baf5c
5 changed files with 135 additions and 18 deletions

View File

@ -32,6 +32,7 @@
#include "network/network_config.hpp"
#include "network/race_event_manager.hpp"
#include "tracks/quad_graph.hpp"
#include "tracks/battle_graph.hpp"
#include "tracks/track.hpp"
#include "utils/string_utils.hpp"
@ -473,3 +474,96 @@ void ItemManager::switchItems()
m_switch_time = m_switch_time < 0 ? stk_config->m_item_switch_time : -1;
} // switchItems
//-----------------------------------------------------------------------------
bool ItemManager::randomItemsForArena(const AlignedArray<btTransform>& pos,
unsigned int bonus, unsigned int big_nitro,
unsigned int small_nitro, unsigned int banana)
{
if (!BattleGraph::get()) return false;
if (bonus == 0 && big_nitro == 0 && small_nitro == 0 && banana == 0)
return false;
std::vector<int> used_location;
std::vector<int> invalid_location;
std::vector<int> final_location;
for (unsigned int i = 0; i < pos.size(); i++)
{
// Load all starting positions of arena, so no items will be near them
int node = BattleGraph::get()->pointToNode(/*cur_node*/-1,
Vec3(pos[i].getOrigin()), /*ignore_vertical*/true);
assert(node != -1);
used_location.push_back(node);
invalid_location.push_back(node);
}
const unsigned int total_item = bonus + big_nitro + small_nitro + banana;
for (unsigned int i = 0; i < total_item; i++)
{
int chosen_node = -1;
const unsigned int total_node = BattleGraph::get()->getNumNodes();
while(true)
{
if (final_location.size() + invalid_location.size() == total_node)
{
Log::warn("[ItemManager]","Can't place more random items! "
"Use default item location.");
return false;
}
RandomGenerator random;
const int node = random.get(total_node);
// Check if tried
std::vector<int>::iterator it = std::find(invalid_location.begin(),
invalid_location.end(), node);
if (it != invalid_location.end())
continue;
// Check if near edge
if (BattleGraph::get()->isNearEdge(node))
{
invalid_location.push_back(node);
continue;
}
// Check if too close
bool found = true;
for (unsigned int j = 0; j < used_location.size(); j++)
{
if (!found) continue;
Vec3 d = BattleGraph::get()
->getPolyOfNode(used_location[j]).getCenter() -
BattleGraph::get()->getPolyOfNode(node).getCenter();
found = d.length_2d() > 20.0f;
}
if (found)
{
chosen_node = node;
invalid_location.push_back(node);
break;
}
else
invalid_location.push_back(node);
}
assert(chosen_node != -1);
used_location.push_back(chosen_node);
final_location.push_back(chosen_node);
}
assert (final_location.size() == total_item);
for (unsigned int i = 0; i < total_item; i++)
{
Item::ItemType type = (i < bonus ? Item::ITEM_BONUS_BOX :
i < bonus + big_nitro ? Item::ITEM_NITRO_BIG :
i < bonus + big_nitro + small_nitro ? Item::ITEM_NITRO_SMALL :
Item::ITEM_BANANA);
Vec3 loc = BattleGraph::get()
->getPolyOfNode(final_location[i]).getCenter();
Item* item = newItem(type, loc, Vec3(0, 1, 0));
BattleGraph::get()->insertItems(item, final_location[i]);
}
return true;
} // randomItemsForArena

View File

@ -19,7 +19,10 @@
#ifndef HEADER_ITEMMANAGER_HPP
#define HEADER_ITEMMANAGER_HPP
#include "LinearMath/btTransform.h"
#include "items/item.hpp"
#include "utils/aligned_array.hpp"
#include "utils/no_copy.hpp"
#include <SColor.h>
@ -110,6 +113,10 @@ public:
int add_info=-1);
void switchItems ();
// ------------------------------------------------------------------------
bool randomItemsForArena(const AlignedArray<btTransform>& pos,
unsigned int bonus, unsigned int big_nitro,
unsigned int small_nitro, unsigned int banana);
// ------------------------------------------------------------------------
/** Returns the number of items. */
unsigned int getNumberOfItems() const { return (unsigned int) m_all_items.size(); }
// ------------------------------------------------------------------------

View File

@ -116,7 +116,11 @@ public:
const NavPoly& getPolyOfNode(int i) const
{ return NavMesh::get()->getNavPoly(i); }
// ----------------------------------------------------------------------
// ------------------------------------------------------------------------
/** Returns true if the NavPoly lies near the edge. */
bool isNearEdge(int i) const
{ return NavMesh::get()->getNavPoly(i).isPolyNearEdge(); }
// ------------------------------------------------------------------------
/** Returns the next polygon on the shortest path from i to j.
* Note: m_parent_poly[j][i] contains the parent of i on path from j to i,
* which is the next node on the path from i to j (undirected graph) */
@ -124,9 +128,12 @@ public:
const std::vector < std::pair<const Item*, int> >& getItemList()
{ return m_items_on_graph; }
// ------------------------------------------------------------------------
void insertItems(Item* item, int polygon)
{ m_items_on_graph.push_back(std::make_pair(item, polygon)); }
// ------------------------------------------------------------------------
void findItemsOnGraphNodes();
// ----------------------------------------------------------------------
// ------------------------------------------------------------------------
int pointToNode(const int cur_node,
const Vec3& cur_point,
bool ignore_vertical) const;

View File

@ -45,11 +45,11 @@ public:
// ------------------------------------------------------------------------
/** Returns the center point of a polygon. */
const Vec3& getCenter() const {return m_center;}
const Vec3& getCenter() const { return m_center; }
// ------------------------------------------------------------------------
/** Returns the adjacent polygons of a polygon. */
const std::vector<int>& getAdjacents() const {return m_adjacents;}
const std::vector<int>& getAdjacents() const { return m_adjacents; }
// ------------------------------------------------------------------------
/** Returns the vertices(Vec3) of this polygon. */
@ -57,13 +57,17 @@ public:
// ------------------------------------------------------------------------
/** Returns the indices of the vertices of this polygon */
const std::vector<int> getVerticesIndex() const {return m_vertices;}
const std::vector<int> getVerticesIndex() const
{ return m_vertices; }
// ------------------------------------------------------------------------
/** Returns true if a given point lies in this polygon. */
bool pointInPoly(const Vec3& p,
bool ignore_vertical) const;
// ------------------------------------------------------------------------
/** Returns true if this polygon lies near the edge. */
bool isPolyNearEdge() const
{ return m_adjacents.size() < 4; }
// ------------------------------------------------------------------------
const Vec3& operator[](int i) const ;
}; // class NavPoly

View File

@ -1862,22 +1862,27 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
createPhysicsModel(main_track_count);
const bool arena_random_item = (m_has_navmesh && ItemManager::get()
->randomItemsForArena(m_start_transforms,5,2,2,1));
for (unsigned int i=0; i<root->getNumNodes(); i++)
if (!arena_random_item)
{
const XMLNode *node = root->getNode(i);
const std::string &name = node->getName();
if (name=="banana" || name=="item" ||
name=="small-nitro" || name=="big-nitro" ||
name=="easter-egg" )
for (unsigned int i=0; i<root->getNumNodes(); i++)
{
itemCommand(node);
}
} // for i<root->getNumNodes()
const XMLNode *node = root->getNode(i);
const std::string &name = node->getName();
if (name=="banana" || name=="item" ||
name=="small-nitro" || name=="big-nitro" ||
name=="easter-egg" )
{
itemCommand(node);
}
} // for i<root->getNumNodes()
}
delete root;
if ((m_is_arena || m_is_soccer) && !m_is_cutscene && m_has_navmesh)
if ((m_is_arena || m_is_soccer) && !m_is_cutscene && m_has_navmesh && !arena_random_item)
BattleGraph::get()->findItemsOnGraphNodes();
if (UserConfigParams::m_track_debug &&