Renamed and split the two newItem () functions into three functions:
placeItem(), placeTrigger(), dropNewItem(). Started to add support for networked bubble gum (though that's not working, i.e. will crash atm ;) ).
This commit is contained in:
@@ -609,25 +609,7 @@ void Attachment::update(int ticks)
|
||||
m_bubble_explode_sound->setPosition(m_kart->getXYZ());
|
||||
m_bubble_explode_sound->play();
|
||||
|
||||
// drop a small bubble gum
|
||||
Vec3 hit_point;
|
||||
Vec3 normal;
|
||||
const Material* material_hit;
|
||||
|
||||
Track::getCurrentTrack()->getTriangleMesh().castRay(m_kart->getXYZ(),
|
||||
m_kart->getTrans().getBasis() * Vec3(0, -10000, 0),
|
||||
&hit_point,&material_hit, &normal );
|
||||
// This can happen if the kart is 'over nothing' when dropping
|
||||
// the bubble gum
|
||||
if(material_hit)
|
||||
{
|
||||
normal.normalize();
|
||||
|
||||
Vec3 pos = hit_point + m_kart->getTrans().getBasis()
|
||||
* Vec3(0, -0.05f, 0);
|
||||
ItemManager::get()->newItem(Item::ITEM_BUBBLEGUM, pos,
|
||||
normal, m_kart );
|
||||
}
|
||||
ItemManager::get()->dropNewItem(Item::ITEM_BUBBLEGUM, m_kart);
|
||||
}
|
||||
break;
|
||||
} // switch
|
||||
|
||||
@@ -217,8 +217,10 @@ ItemManager::~ItemManager()
|
||||
/** Inserts the new item into the items management data structures, if possible
|
||||
* reusing an existing, unused entry (e.g. due to a removed bubble gum). Then
|
||||
* the item is also added to the quad-wise list of items.
|
||||
* \param item The item to be added.
|
||||
* \return Index of the newly added item in the list of all items.
|
||||
*/
|
||||
void ItemManager::insertItem(Item *item)
|
||||
unsigned int ItemManager::insertItem(Item *item)
|
||||
{
|
||||
// Find where the item can be stored in the index list: either in a
|
||||
// previously deleted entry, otherwise at the end.
|
||||
@@ -246,30 +248,46 @@ void ItemManager::insertItem(Item *item)
|
||||
else // otherwise store it in the 'outside' index
|
||||
(*m_items_in_quads)[m_items_in_quads->size()-1].push_back(item);
|
||||
} // if m_items_in_quads
|
||||
return index;
|
||||
} // insertItem
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Creates a new item.
|
||||
/** Creates a new item at the location of the kart (e.g. kart drops a
|
||||
* bubblegum).
|
||||
* \param type Type of the item.
|
||||
* \param xyz Position of the item.
|
||||
* \param normal The normal of the terrain to set roll and pitch.
|
||||
* \param parent In case of a dropped item used to avoid that a kart
|
||||
* is affected by its own items.
|
||||
* \param kart The kart that drops the new item.
|
||||
*/
|
||||
Item* ItemManager::newItem(ItemState::ItemType type, const Vec3& xyz,
|
||||
const Vec3 &normal, AbstractKart *parent)
|
||||
Item* ItemManager::dropNewItem(ItemState::ItemType type, AbstractKart *kart)
|
||||
{
|
||||
Vec3 hit_point;
|
||||
Vec3 normal;
|
||||
const Material* material_hit;
|
||||
Vec3 pos = kart->getXYZ();
|
||||
Vec3 to = pos + kart->getTrans().getBasis() * Vec3(0, -10000, 0);
|
||||
Track::getCurrentTrack()->getTriangleMesh().castRay(pos, to,
|
||||
&hit_point,
|
||||
&material_hit,
|
||||
&normal);
|
||||
// This can happen if the kart is 'over nothing' when dropping
|
||||
// the bubble gum
|
||||
if (!material_hit) return NULL;
|
||||
|
||||
normal.normalize();
|
||||
|
||||
pos = hit_point + kart->getTrans().getBasis() * Vec3(0, -0.05f, 0);
|
||||
|
||||
|
||||
ItemState::ItemType mesh_type = type;
|
||||
if (type == ItemState::ITEM_BUBBLEGUM && parent->getIdent() == "nolok")
|
||||
if (type == ItemState::ITEM_BUBBLEGUM && kart->getIdent() == "nolok")
|
||||
{
|
||||
mesh_type = ItemState::ITEM_BUBBLEGUM_NOLOK;
|
||||
}
|
||||
|
||||
Item* item = new Item(type, xyz, normal, m_item_mesh[mesh_type],
|
||||
Item* item = new Item(type, pos, normal, m_item_mesh[mesh_type],
|
||||
m_item_lowres_mesh[mesh_type]);
|
||||
|
||||
insertItem(item);
|
||||
if(parent != NULL) item->setParent(parent);
|
||||
if(kart != NULL) item->setParent(kart);
|
||||
if(m_switch_ticks>=0)
|
||||
{
|
||||
ItemState::ItemType new_type = m_switch_to[item->getType()];
|
||||
@@ -277,21 +295,55 @@ Item* ItemManager::newItem(ItemState::ItemType type, const Vec3& xyz,
|
||||
m_item_lowres_mesh[(int)new_type]);
|
||||
}
|
||||
return item;
|
||||
} // newItem
|
||||
} // dropNewItem
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Creates a new trigger item.
|
||||
/** Places a new item on the track/arena. It is used for the initial placement
|
||||
* of the items - either according to the scene.xml file, or random item
|
||||
* placement.
|
||||
* \param type Type of the item.
|
||||
* \param xyz Position of the item.
|
||||
* \param normal The normal of the terrain to set roll and pitch.
|
||||
*/
|
||||
Item* ItemManager::newItem(const Vec3& xyz, float distance,
|
||||
TriggerItemListener* listener)
|
||||
Item* ItemManager::placeItem(ItemState::ItemType type, const Vec3& xyz,
|
||||
const Vec3 &normal)
|
||||
{
|
||||
// Make sure this subroutine is not used otherwise (since networking
|
||||
// needs to be aware of items added to the track, so this would need
|
||||
// to be added).
|
||||
assert(World::getWorld()->getPhase() == WorldStatus::SETUP_PHASE);
|
||||
ItemState::ItemType mesh_type = type;
|
||||
|
||||
Item* item = new Item(type, xyz, normal, m_item_mesh[mesh_type],
|
||||
m_item_lowres_mesh[mesh_type]);
|
||||
|
||||
insertItem(item);
|
||||
if (m_switch_ticks >= 0)
|
||||
{
|
||||
ItemState::ItemType new_type = m_switch_to[item->getType()];
|
||||
item->switchTo(new_type, m_item_mesh[(int)new_type],
|
||||
m_item_lowres_mesh[(int)new_type]);
|
||||
}
|
||||
return item;
|
||||
} // placeItem
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Creates a new trigger item. This is not synched between client and
|
||||
* server, since the triggers are created at startup only and should
|
||||
* therefore always be in sync.
|
||||
* \param xyz Position of the item.
|
||||
* \param listener The listener object that gets called when a kart
|
||||
* triggers this trigger.
|
||||
*/
|
||||
Item* ItemManager::placeTrigger(const Vec3& xyz, float distance,
|
||||
TriggerItemListener* listener)
|
||||
{
|
||||
Item* item;
|
||||
item = new Item(xyz, distance, listener);
|
||||
insertItem(item);
|
||||
|
||||
return item;
|
||||
} // newItem
|
||||
} // placeTrigger
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Set an item as collected.
|
||||
@@ -605,17 +657,17 @@ bool ItemManager::randomItemsForArena(const AlignedArray<btTransform>& pos)
|
||||
Vec3 hit_point;
|
||||
const TriangleMesh& tm = Track::getCurrentTrack()->getTriangleMesh();
|
||||
bool success = tm.castRay(loc, an->getCenter() + (-10000*quad_normal),
|
||||
&hit_point, &m, &normal);
|
||||
&hit_point, &m, &normal);
|
||||
|
||||
if (success)
|
||||
{
|
||||
newItem(type, hit_point, normal);
|
||||
placeItem(type, hit_point, normal);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::warn("[ItemManager]","Raycast to surface failed"
|
||||
"from node %d", used_location[i]);
|
||||
newItem(type, an->getCenter(), quad_normal);
|
||||
placeItem(type, an->getCenter(), quad_normal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "items/item.hpp"
|
||||
#include "utils/aligned_array.hpp"
|
||||
#include "utils/no_copy.hpp"
|
||||
#include "utils/vec3.hpp"
|
||||
|
||||
#include <SColor.h>
|
||||
|
||||
@@ -104,20 +105,21 @@ private:
|
||||
* value is <0, it indicates that the items are not switched atm. */
|
||||
int m_switch_ticks;
|
||||
|
||||
void insertItem(Item *item);
|
||||
void deleteItem(Item *item);
|
||||
|
||||
public:
|
||||
// Make those private so only create/destroy functions can call them.
|
||||
ItemManager();
|
||||
virtual ~ItemManager();
|
||||
void setSwitchItems(const std::vector<int> &switch_items);
|
||||
protected:
|
||||
virtual unsigned int insertItem(Item *item);
|
||||
void setSwitchItems(const std::vector<int> &switch_items);
|
||||
ItemManager();
|
||||
virtual ~ItemManager();
|
||||
|
||||
public:
|
||||
Item* newItem (ItemState::ItemType type, const Vec3& xyz,
|
||||
const Vec3 &normal,
|
||||
AbstractKart* parent=NULL);
|
||||
Item* newItem (const Vec3& xyz, float distance,
|
||||
|
||||
virtual Item* placeItem (ItemState::ItemType type, const Vec3& xyz,
|
||||
const Vec3 &normal);
|
||||
virtual Item* dropNewItem (ItemState::ItemType type,
|
||||
AbstractKart* parent);
|
||||
virtual Item* placeTrigger (const Vec3& xyz, float distance,
|
||||
TriggerItemListener* listener);
|
||||
void update (int ticks);
|
||||
void updateGraphics (float dt);
|
||||
|
||||
@@ -79,6 +79,26 @@ void NetworkItemManager::saveInitialState()
|
||||
}
|
||||
} // saveInitialState
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Called when an item is inserted. It makes sure the vector for the
|
||||
* confirmed state has the right size.
|
||||
* \param item The item to be added.
|
||||
* \returns Index of the newly inserted item.
|
||||
*/
|
||||
unsigned int NetworkItemManager::insertItem(Item *item)
|
||||
{
|
||||
unsigned int index = ItemManager::insertItem(item);
|
||||
if(index>=m_confirmed_state.size())
|
||||
{
|
||||
m_confirmed_state.push_back(NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
*m_confirmed_state[index] = *m_all_items[index];
|
||||
}
|
||||
return index;
|
||||
} // insertItem
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Called when a kart collects an item. In network games only the server
|
||||
* acts on this event.
|
||||
@@ -105,7 +125,27 @@ void NetworkItemManager::collectedItem(Item *item, AbstractKart *kart)
|
||||
}
|
||||
} // collectedItem
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Called when a new item is created, e.g. bubble gum.
|
||||
* \param type Type of the item.
|
||||
* \param parent In case of a dropped item used to avoid that a kart
|
||||
* is affected by its own items.
|
||||
*/
|
||||
Item* NetworkItemManager::dropNewItem(ItemState::ItemType type,
|
||||
AbstractKart *kart)
|
||||
{
|
||||
Item *item = ItemManager::dropNewItem(type, kart);
|
||||
if(!item) return NULL;
|
||||
|
||||
m_item_events.lock();
|
||||
m_item_events.getData().emplace_back(World::getWorld()->getTimeTicks(), type,
|
||||
item->getItemId(),
|
||||
kart->getXYZ() );
|
||||
m_item_events.unlock();
|
||||
return item;
|
||||
} // newItem
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Called by the GameProtocol when a confirmation for an item event is
|
||||
* received by a host. Once all hosts have confirmed an event, it can be
|
||||
* deleted and won't be send to any clients again.
|
||||
@@ -267,7 +307,8 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count)
|
||||
{
|
||||
Item *item = m_all_items[i];
|
||||
const ItemState *is = m_confirmed_state[i];
|
||||
*(ItemState*)item = *is;
|
||||
if(is)
|
||||
*(ItemState*)item = *is;
|
||||
}
|
||||
|
||||
// Now we save the current local
|
||||
|
||||
@@ -72,6 +72,9 @@ private:
|
||||
* otherwise undefined. */
|
||||
int m_kart_id;
|
||||
|
||||
/** In case of new items the position of the new item. */
|
||||
Vec3 m_xyz;
|
||||
|
||||
/** Constructor for collecting an existing item.
|
||||
* \param ticks Time of the event.
|
||||
* \param item_id The index of the item that was collected.
|
||||
@@ -85,9 +88,12 @@ private:
|
||||
// --------------------------------------------------------------------
|
||||
/** Constructor for creating a new item (i.e. a bubble gum is dropped).
|
||||
*/
|
||||
ItemEventInfo(int ticks, ItemState::ItemType type, int item_id,
|
||||
Vec3 xyz)
|
||||
{
|
||||
ItemEventInfo(int ticks, ItemState::ItemType type, int index,
|
||||
const Vec3 &xyz)
|
||||
{
|
||||
m_ticks = ticks;
|
||||
m_index = index;
|
||||
m_xyz = xyz;
|
||||
} // ItemEventInfo(new item)
|
||||
// --------------------------------------------------------------------
|
||||
/** Constructor for switching items. */
|
||||
@@ -103,6 +109,7 @@ private:
|
||||
Synchronised< std::vector<ItemEventInfo> > m_item_events;
|
||||
|
||||
void forwardTime(int ticks);
|
||||
virtual unsigned int insertItem(Item *item) OVERRIDE;
|
||||
|
||||
NetworkItemManager();
|
||||
virtual ~NetworkItemManager();
|
||||
@@ -117,6 +124,8 @@ public:
|
||||
virtual void reset();
|
||||
virtual void setItemConfirmationTime(int host_id, int ticks) OVERRIDE;
|
||||
virtual void collectedItem(Item *item, AbstractKart *kart) OVERRIDE;
|
||||
virtual Item* dropNewItem(ItemState::ItemType type,
|
||||
AbstractKart *kart) OVERRIDE;
|
||||
virtual BareNetworkString* saveState() OVERRIDE;
|
||||
virtual void restoreState(BareNetworkString *buffer, int count) OVERRIDE;
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
@@ -234,8 +234,6 @@ void Powerup::use()
|
||||
// FIXME - for some collectibles, set() is never called
|
||||
if(m_sound_use == NULL)
|
||||
{
|
||||
//if (m_type == POWERUP_SWITCH) m_sound_use = SFXManager::get()->newSFX(SFXManager::SOUND_SWAP);
|
||||
//else
|
||||
m_sound_use = SFXManager::get()->createSoundSource("shoot");
|
||||
}
|
||||
|
||||
@@ -275,26 +273,14 @@ void Powerup::use()
|
||||
// use the bubble gum the traditional way, if the kart is looking back
|
||||
if (m_kart->getControls().getLookBack())
|
||||
{
|
||||
Vec3 hit_point;
|
||||
Vec3 normal;
|
||||
const Material* material_hit;
|
||||
Vec3 pos = m_kart->getXYZ();
|
||||
Vec3 to = pos+ m_kart->getTrans().getBasis() * Vec3(0, -10000, 0);
|
||||
Track::getCurrentTrack()->getTriangleMesh().castRay(pos, to,
|
||||
&hit_point,
|
||||
&material_hit,
|
||||
&normal);
|
||||
// This can happen if the kart is 'over nothing' when dropping
|
||||
// the bubble gum
|
||||
if(!material_hit)
|
||||
return;
|
||||
normal.normalize();
|
||||
Item *new_item =
|
||||
ItemManager::get()->dropNewItem(Item::ITEM_BUBBLEGUM, m_kart);
|
||||
|
||||
// E.g. ground not found in raycast.
|
||||
if(!new_item) return;
|
||||
|
||||
Powerup::adjustSound();
|
||||
m_sound_use->play();
|
||||
|
||||
pos = hit_point + m_kart->getTrans().getBasis() * Vec3(0, -0.05f, 0);
|
||||
ItemManager::get()->newItem(Item::ITEM_BUBBLEGUM, pos, normal, m_kart);
|
||||
}
|
||||
else // if the kart is looking forward, use the bubblegum as a shield
|
||||
{
|
||||
|
||||
@@ -40,6 +40,7 @@ WorldStatus::WorldStatus()
|
||||
{
|
||||
main_loop->setFrameBeforeLoadingWorld();
|
||||
m_clock_mode = CLOCK_CHRONO;
|
||||
m_phase = SETUP_PHASE;
|
||||
|
||||
m_prestart_sound = SFXManager::get()->createSoundSource("pre_start_race");
|
||||
m_start_sound = SFXManager::get()->createSoundSource("start_race");
|
||||
|
||||
@@ -2448,7 +2448,7 @@ void Track::itemCommand(const XMLNode *node)
|
||||
#endif
|
||||
}
|
||||
|
||||
ItemManager::get()->newItem(type, drop ? hit_point : loc, normal);
|
||||
ItemManager::get()->placeItem(type, drop ? hit_point : loc, normal);
|
||||
} // itemCommand
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -710,7 +710,7 @@ TrackObjectPresentationSound::TrackObjectPresentationSound(
|
||||
|
||||
if (trigger_when_near)
|
||||
{
|
||||
ItemManager::get()->newItem(m_init_xyz, trigger_distance, this);
|
||||
ItemManager::get()->placeTrigger(m_init_xyz, trigger_distance, this);
|
||||
}
|
||||
} // TrackObjectPresentationSound
|
||||
|
||||
@@ -1095,7 +1095,11 @@ TrackObjectPresentationActionTrigger::TrackObjectPresentationActionTrigger(
|
||||
if (m_type == TRIGGER_TYPE_POINT)
|
||||
{
|
||||
// TODO: rewrite as a sphere check structure?
|
||||
ItemManager::get()->newItem(m_init_xyz, trigger_distance, this);
|
||||
ItemManager::get()->placeTrigger(m_init_xyz, trigger_distance, this);
|
||||
// 0 is the index, and is mostly used for debugging (i.e. to identify which check
|
||||
// structure information is printed about) - not sure how to best use this
|
||||
// with items added outside of the checkline manager. Best option would be to
|
||||
// change CheckManager::add() to create the object?
|
||||
// CheckManager::get()->add(new CheckSphere(xml_node, 0 /* TODO what is this? */));
|
||||
}
|
||||
else if (m_type == TRIGGER_TYPE_CYLINDER)
|
||||
@@ -1123,7 +1127,7 @@ TrackObjectPresentationActionTrigger::TrackObjectPresentationActionTrigger(
|
||||
m_xml_reenable_timeout = 999999.9f;
|
||||
m_reenable_timeout = 0.0f;
|
||||
m_type = TRIGGER_TYPE_POINT;
|
||||
ItemManager::get()->newItem(m_init_xyz, trigger_distance, this);
|
||||
ItemManager::get()->placeTrigger(m_init_xyz, trigger_distance, this);
|
||||
} // TrackObjectPresentationActionTrigger
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user