Split Item into two classes: ItemState which contains the non-graphical
and changing properties (e.g. collected,item type etc), and Item (using ItemState as base class) which contains graphical and constant values.
This commit is contained in:
parent
0d1e799b4b
commit
9392354663
@ -361,9 +361,9 @@ void Attachment::hitBanana(Item *item, int new_attachment)
|
||||
// default time. This is necessary to avoid that a kart lands on the
|
||||
// same banana again once the explosion animation is finished, giving
|
||||
// the kart the same penalty twice.
|
||||
int ticks = std::max(item->getDisableTicks(),
|
||||
int ticks = std::max(item->getTicksTillReturn(),
|
||||
stk_config->time2Ticks(kp->getExplosionDuration() + 2.0f));
|
||||
item->setDisableTicks(ticks);
|
||||
item->setTicksTillReturn(ticks);
|
||||
break;
|
||||
}
|
||||
case ATTACH_ANVIL:
|
||||
|
@ -39,8 +39,77 @@
|
||||
#include <IMeshSceneNode.h>
|
||||
#include <ISceneManager.h>
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the disappear counter depending on type. */
|
||||
void ItemState::setDisappearCounter()
|
||||
{
|
||||
switch (m_type)
|
||||
{
|
||||
case ITEM_BUBBLEGUM:
|
||||
m_disappear_counter = stk_config->m_bubblegum_counter; break;
|
||||
case ITEM_EASTER_EGG:
|
||||
m_disappear_counter = -1; break;
|
||||
default:
|
||||
m_disappear_counter = -1;
|
||||
} // switch
|
||||
} // setDisappearCounter
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Update the state of the item, called once per physics frame.
|
||||
* \param ticks Number of ticks to simulate (typically 1).
|
||||
*/
|
||||
void ItemState::update(int ticks)
|
||||
{
|
||||
if (m_deactive_ticks > 0) m_deactive_ticks -= ticks;
|
||||
if (m_collected)
|
||||
{
|
||||
m_ticks_till_return -= ticks;
|
||||
if (m_ticks_till_return<=0) m_collected = false;
|
||||
} // if collected
|
||||
|
||||
} // update
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void ItemState::collected(float t, const AbstractKart *kart)
|
||||
{
|
||||
m_collected = true;
|
||||
if (m_type == ITEM_EASTER_EGG)
|
||||
{
|
||||
m_ticks_till_return = stk_config->time2Ticks(99999);
|
||||
EasterEggHunt *world = dynamic_cast<EasterEggHunt*>(World::getWorld());
|
||||
assert(world);
|
||||
world->collectedEasterEgg(kart);
|
||||
}
|
||||
else if (m_type == ITEM_BUBBLEGUM && m_disappear_counter > 0)
|
||||
{
|
||||
m_disappear_counter--;
|
||||
// Deactivates the item for a certain amount of time. It is used to
|
||||
// prevent bubble gum from hitting a kart over and over again (in each
|
||||
// frame) by giving it time to drive away.
|
||||
m_deactive_ticks = stk_config->time2Ticks(0.5f);
|
||||
// Set the time till reappear to -1 seconds --> the item will
|
||||
// reappear immediately.
|
||||
m_ticks_till_return = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Note if the time is negative, in update the m_collected flag will
|
||||
// be automatically set to false again.
|
||||
m_ticks_till_return = stk_config->time2Ticks(t);
|
||||
}
|
||||
|
||||
if (dynamic_cast<ThreeStrikesBattle*>(World::getWorld()) != NULL)
|
||||
{
|
||||
m_ticks_till_return *= 3;
|
||||
}
|
||||
} // collected
|
||||
|
||||
// ============================================================================
|
||||
|
||||
Item::Item(ItemType type, const Vec3& xyz, const Vec3& normal,
|
||||
scene::IMesh* mesh, scene::IMesh* lowres_mesh)
|
||||
: ItemState(type)
|
||||
{
|
||||
assert(type != ITEM_TRIGGER); // use other constructor for that
|
||||
|
||||
@ -76,7 +145,7 @@ Item::Item(ItemType type, const Vec3& xyz, const Vec3& normal,
|
||||
|
||||
#ifdef DEBUG
|
||||
std::string debug_name("item: ");
|
||||
debug_name += m_type;
|
||||
debug_name += getType();
|
||||
m_node->setName(debug_name.c_str());
|
||||
#endif
|
||||
m_node->setAutomaticCulling(scene::EAC_FRUSTUM_BOX);
|
||||
@ -94,6 +163,7 @@ Item::Item(ItemType type, const Vec3& xyz, const Vec3& normal,
|
||||
* approaching a point.
|
||||
*/
|
||||
Item::Item(const Vec3& xyz, float distance, TriggerItemListener* trigger)
|
||||
: ItemState(ITEM_TRIGGER)
|
||||
{
|
||||
m_distance_2 = distance*distance;
|
||||
initItem(ITEM_TRIGGER, xyz);
|
||||
@ -112,25 +182,12 @@ Item::Item(const Vec3& xyz, float distance, TriggerItemListener* trigger)
|
||||
*/
|
||||
void Item::initItem(ItemType type, const Vec3 &xyz)
|
||||
{
|
||||
m_type = type;
|
||||
ItemState::initItem(type);
|
||||
m_xyz = xyz;
|
||||
m_event_handler = NULL;
|
||||
m_item_id = -1;
|
||||
m_collected = false;
|
||||
m_original_type = ITEM_NONE;
|
||||
m_deactive_ticks = 0;
|
||||
m_ticks_till_return = 0; // not strictly necessary, see isCollected()
|
||||
m_emitter = NULL;
|
||||
m_rotate = (type!=ITEM_BUBBLEGUM) && (type!=ITEM_TRIGGER);
|
||||
switch(m_type)
|
||||
{
|
||||
case ITEM_BUBBLEGUM:
|
||||
m_disappear_counter = stk_config->m_bubblegum_counter; break;
|
||||
case ITEM_EASTER_EGG:
|
||||
m_disappear_counter = -1; break;
|
||||
default:
|
||||
m_disappear_counter = -1;
|
||||
}
|
||||
m_rotate = (getType()!=ITEM_BUBBLEGUM) &&
|
||||
(getType()!=ITEM_TRIGGER );
|
||||
// Now determine in which quad this item is, and its distance
|
||||
// from the center within this quad.
|
||||
m_graph_node = Graph::UNKNOWN_SECTOR;
|
||||
@ -167,7 +224,7 @@ void Item::initItem(ItemType type, const Vec3 &xyz)
|
||||
*/
|
||||
void Item::setType(ItemType type)
|
||||
{
|
||||
m_type = type;
|
||||
ItemState::setType(type);
|
||||
m_rotate = (type!=ITEM_BUBBLEGUM) && (type!=ITEM_TRIGGER);
|
||||
for (auto* node : m_node->getAllNodes())
|
||||
{
|
||||
@ -186,12 +243,8 @@ void Item::setType(ItemType type)
|
||||
*/
|
||||
void Item::switchTo(ItemType type, scene::IMesh *mesh, scene::IMesh *lowmesh)
|
||||
{
|
||||
// triggers and easter eggs should not be switched
|
||||
if (m_type == ITEM_TRIGGER || m_type == ITEM_EASTER_EGG) return;
|
||||
|
||||
m_original_type = m_type;
|
||||
setMesh(mesh, lowmesh);
|
||||
setType(type);
|
||||
ItemState::switchTo(type);
|
||||
} // switchTo
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -199,18 +252,9 @@ void Item::switchTo(ItemType type, scene::IMesh *mesh, scene::IMesh *lowmesh)
|
||||
*/
|
||||
void Item::switchBack()
|
||||
{
|
||||
// triggers should not be switched
|
||||
if (m_type == ITEM_TRIGGER) return;
|
||||
|
||||
// If the item is not switched, do nothing. This can happen if a bubble
|
||||
// gum is dropped while items are switched - when switching back, this
|
||||
// bubble gum has no original type.
|
||||
if(m_original_type==ITEM_NONE)
|
||||
return;
|
||||
if (ItemState::switchBack()) return;
|
||||
|
||||
setMesh(m_original_mesh, m_original_lowmesh);
|
||||
setType(m_original_type);
|
||||
m_original_type = ITEM_NONE;
|
||||
|
||||
Vec3 hpr;
|
||||
hpr.setHPR(m_original_rotation);
|
||||
@ -264,24 +308,7 @@ Item::~Item()
|
||||
*/
|
||||
void Item::reset()
|
||||
{
|
||||
m_collected = false;
|
||||
m_ticks_till_return = 0;
|
||||
m_deactive_ticks = 0;
|
||||
switch(m_type)
|
||||
{
|
||||
case ITEM_BUBBLEGUM:
|
||||
m_disappear_counter = stk_config->m_bubblegum_counter; break;
|
||||
case ITEM_EASTER_EGG:
|
||||
m_disappear_counter = -1; break;
|
||||
default:
|
||||
m_disappear_counter = -1;
|
||||
}
|
||||
if(m_original_type!=ITEM_NONE)
|
||||
{
|
||||
setType(m_original_type);
|
||||
m_original_type = ITEM_NONE;
|
||||
}
|
||||
|
||||
ItemState::reset();
|
||||
if (m_node != NULL)
|
||||
{
|
||||
m_node->setScale(core::vector3df(1,1,1));
|
||||
@ -298,7 +325,7 @@ void Item::setParent(AbstractKart* parent)
|
||||
{
|
||||
m_event_handler = parent;
|
||||
m_emitter = parent;
|
||||
m_deactive_ticks = stk_config->time2Ticks(1.5f);
|
||||
ItemState::setDeactivatedTicks(stk_config->time2Ticks(1.5f));
|
||||
} // setParent
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -308,32 +335,24 @@ void Item::setParent(AbstractKart* parent)
|
||||
*/
|
||||
void Item::update(int ticks)
|
||||
{
|
||||
if(m_deactive_ticks > 0) m_deactive_ticks -= ticks;
|
||||
bool was_collected = !isAvailable();
|
||||
ItemState::update(ticks);
|
||||
|
||||
if(m_collected)
|
||||
if (was_collected && isAvailable() && m_node)
|
||||
{
|
||||
m_ticks_till_return -= ticks;
|
||||
if(m_ticks_till_return<0)
|
||||
{
|
||||
m_collected=false;
|
||||
|
||||
if (m_node != NULL)
|
||||
{
|
||||
m_node->setScale(core::vector3df(1,1,1));
|
||||
}
|
||||
} // time till return <0 --> is fully visible again
|
||||
else if ( m_ticks_till_return <= stk_config->time2Ticks(1.0f) )
|
||||
{
|
||||
if (m_node != NULL)
|
||||
{
|
||||
// Make it visible by scaling it from 0 to 1:
|
||||
m_node->setVisible(true);
|
||||
float t = stk_config->ticks2Time(m_ticks_till_return);
|
||||
m_node->setScale(core::vector3df(1,1,1)*(1-t));
|
||||
}
|
||||
} // time till return < 1
|
||||
} // if collected
|
||||
else
|
||||
// This item is now available again - make sure it is not
|
||||
// scaled anymore.
|
||||
m_node->setScale(core::vector3df(1, 1, 1));
|
||||
}
|
||||
if (!isAvailable() && m_node &&
|
||||
getTicksTillReturn() <= stk_config->time2Ticks(1.0f) )
|
||||
{
|
||||
// Make it visible by scaling it from 0 to 1:
|
||||
m_node->setVisible(true);
|
||||
float t = stk_config->ticks2Time(getTicksTillReturn());
|
||||
m_node->setScale(core::vector3df(1, 1, 1)*(1 - t));
|
||||
}
|
||||
if(isAvailable())
|
||||
{ // not m_collected
|
||||
|
||||
if(!m_rotate || m_node == NULL) return;
|
||||
@ -364,49 +383,17 @@ void Item::update(int ticks)
|
||||
*/
|
||||
void Item::collected(const AbstractKart *kart, float t)
|
||||
{
|
||||
m_collected = true;
|
||||
ItemState::collected(t, kart);
|
||||
m_event_handler = kart;
|
||||
if(m_type==ITEM_EASTER_EGG)
|
||||
if (m_node && (getType() != ITEM_BUBBLEGUM || isUsedUp() ) )
|
||||
{
|
||||
m_ticks_till_return=stk_config->time2Ticks(99999);
|
||||
EasterEggHunt *world = dynamic_cast<EasterEggHunt*>(World::getWorld());
|
||||
assert(world);
|
||||
world->collectedEasterEgg(kart);
|
||||
if (m_node != NULL)
|
||||
{
|
||||
m_node->setVisible(false);
|
||||
}
|
||||
m_node->setVisible(false);
|
||||
}
|
||||
else if(m_type==ITEM_BUBBLEGUM && m_disappear_counter>0)
|
||||
{
|
||||
m_disappear_counter --;
|
||||
// Deactivates the item for a certain amount of time. It is used to
|
||||
// prevent bubble gum from hitting a kart over and over again (in each
|
||||
// frame) by giving it time to drive away.
|
||||
m_deactive_ticks = stk_config->time2Ticks(0.5f);
|
||||
// Set the time till reappear to -1 seconds --> the item will
|
||||
// reappear immediately.
|
||||
m_ticks_till_return = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Note if the time is negative, in update the m_collected flag will
|
||||
// be automatically set to false again.
|
||||
m_ticks_till_return = stk_config->time2Ticks(t);
|
||||
if (m_node != NULL)
|
||||
{
|
||||
m_node->setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (m_listener != NULL)
|
||||
{
|
||||
m_listener->onTriggerItemApproached();
|
||||
}
|
||||
|
||||
if (dynamic_cast<ThreeStrikesBattle*>(World::getWorld()) != NULL)
|
||||
{
|
||||
m_ticks_till_return *= 3;
|
||||
}
|
||||
} // isCollected
|
||||
|
||||
|
@ -42,7 +42,7 @@ namespace irr
|
||||
}
|
||||
using namespace irr;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* \ingroup items
|
||||
@ -55,17 +55,21 @@ public:
|
||||
virtual void onTriggerItemApproached() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* \ingroup items
|
||||
*/
|
||||
class Item : public NoCopy
|
||||
// ============================================================================
|
||||
/** \ingroup items
|
||||
* Contains the state information of an item, i.e. all non-visual information
|
||||
* only, which also can change (e.g. position and AI information is constant
|
||||
* and therefore not stored here). This class is used as a base class for
|
||||
* item and for networking to save item states.
|
||||
*/
|
||||
class ItemState : public NoCopy
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* The list of all items. Important for the switch item function:
|
||||
* bubblegum must be the last item (since bubble gum can't be
|
||||
* switched with any other item, since it's a different objecct).
|
||||
*/
|
||||
* The list of all items. Important for the switch item function:
|
||||
* bubblegum must be the last item (since bubble gum can't be
|
||||
* switched with any other item, since it's a different objecct).
|
||||
*/
|
||||
enum ItemType
|
||||
{
|
||||
ITEM_FIRST,
|
||||
@ -79,8 +83,8 @@ public:
|
||||
/** For easter egg mode only. */
|
||||
ITEM_EASTER_EGG,
|
||||
/** An invisible item that can be used to trigger some behavior when
|
||||
* approaching a point
|
||||
*/
|
||||
* approaching a point
|
||||
*/
|
||||
ITEM_TRIGGER,
|
||||
ITEM_LAST = ITEM_TRIGGER,
|
||||
ITEM_COUNT,
|
||||
@ -88,14 +92,165 @@ public:
|
||||
};
|
||||
|
||||
private:
|
||||
LEAK_CHECK();
|
||||
|
||||
/** Item type. */
|
||||
ItemType m_type;
|
||||
ItemType m_type;
|
||||
|
||||
/** If the item is switched, this contains the original type.
|
||||
* It is ITEM_NONE if the item is not switched. */
|
||||
ItemType m_original_type;
|
||||
* It is ITEM_NONE if the item is not switched. */
|
||||
ItemType m_original_type;
|
||||
|
||||
/** True if item was collected & is not displayed. */
|
||||
bool m_collected;
|
||||
|
||||
/** Time till a collected item reappears. */
|
||||
int m_ticks_till_return;
|
||||
|
||||
/** Index in item_manager field. */
|
||||
unsigned int m_item_id;
|
||||
|
||||
/** Optionally if item was placed by a kart, a timer can be used to
|
||||
* temporarly deactivate collision so a kart is not hit by its own item */
|
||||
int m_deactive_ticks;
|
||||
|
||||
/** Counts how often an item is used before it disappears. Used for
|
||||
* bubble gum to make them disappear after a while. A value >0
|
||||
* indicates that the item still exists, =0 that the item can be
|
||||
* deleted, and <0 that the item will never be deleted. */
|
||||
int m_disappear_counter;
|
||||
|
||||
public:
|
||||
/** Constructor. */
|
||||
ItemState(ItemType type)
|
||||
{
|
||||
m_item_id = -1;
|
||||
setType(type);
|
||||
}
|
||||
void setDisappearCounter();
|
||||
void update(int ticks);
|
||||
void collected(float t, const AbstractKart *kart);
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
void reset()
|
||||
{
|
||||
m_deactive_ticks = 0;
|
||||
m_ticks_till_return = 0;
|
||||
m_collected = false;
|
||||
setDisappearCounter();
|
||||
// If the item was switched:
|
||||
if (m_original_type != ITEM_NONE)
|
||||
{
|
||||
setType(m_original_type);
|
||||
m_original_type = ITEM_NONE;
|
||||
}
|
||||
} // reset
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
/** Initialises an item.
|
||||
/* \param type Type for this item.
|
||||
*/
|
||||
void initItem(ItemType type)
|
||||
{
|
||||
setType(type);
|
||||
m_original_type = ITEM_NONE;
|
||||
m_deactive_ticks = 0;
|
||||
m_ticks_till_return = 0;
|
||||
m_item_id = -1;
|
||||
m_collected = false;
|
||||
setDisappearCounter();
|
||||
} // initItem
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Switches an item to be of a different type. Used for the switch
|
||||
* powerup.
|
||||
* \param type New type for this item.
|
||||
*/
|
||||
void switchTo(ItemType type)
|
||||
{
|
||||
// triggers and easter eggs should not be switched
|
||||
if (m_type == ITEM_TRIGGER || m_type == ITEM_EASTER_EGG) return;
|
||||
m_original_type = m_type;
|
||||
setType(type);
|
||||
} // switchTo
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns true if this item was not actually switched (e.g. trigger etc)
|
||||
*/
|
||||
bool switchBack()
|
||||
{
|
||||
// triggers should not be switched
|
||||
if (m_type == ITEM_TRIGGER) return true;
|
||||
// If the item is not switched, do nothing. This can happen if a bubble
|
||||
// gum is dropped while items are switched - when switching back, this
|
||||
// bubble gum has no original type.
|
||||
if (m_original_type == ITEM_NONE)
|
||||
return true;
|
||||
setType(m_original_type);
|
||||
m_original_type = ITEM_NONE;
|
||||
return false;
|
||||
} // switchBack
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns if this item is negative, i.e. a banana or bubblegum. */
|
||||
bool isNegativeItem() const
|
||||
{
|
||||
return m_type == ITEM_BANANA || m_type == ITEM_BUBBLEGUM ||
|
||||
m_type == ITEM_BUBBLEGUM_NOLOK;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets how long an item should be disabled. While item itself sets
|
||||
* a default, this time is too short in case that a kart that has a bomb
|
||||
* hits a banana: by the time the explosion animation is ended and the
|
||||
* kart is back at its original position, the banana would be back again
|
||||
* and therefore hit the kart again. See Attachment::hitBanana for more
|
||||
* details.
|
||||
* \param f Time till the item can be used again.
|
||||
*/
|
||||
void setTicksTillReturn(int t) { m_ticks_till_return = t; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the time the item is disabled for. */
|
||||
int getTicksTillReturn() const { return m_ticks_till_return; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns true if this item is currently collected. */
|
||||
bool isAvailable() const { return m_ticks_till_return <= 0; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Useless function ;) But it makes some conditionals easier to read. */
|
||||
bool isUnavailable() const { return m_collected; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the type of this item. */
|
||||
ItemType getType() const { return m_type; }
|
||||
// ------------------------------------------------------------------------
|
||||
void setType(ItemType type) { m_type = type; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the index of this item in the item manager list. */
|
||||
void setItemId(unsigned int n) { m_item_id = n; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the index of this item in the item manager list. */
|
||||
unsigned int getItemId() const { return m_item_id; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns true if this item is used up and can be removed. */
|
||||
bool isUsedUp() const { return m_disappear_counter == 0; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns true if this item can be used up, and therefore needs to
|
||||
* be removed when the game is reset. */
|
||||
bool canBeUsedUp() const { return m_disappear_counter>-1; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the number of ticks during which the item is deactivated (i.e.
|
||||
* it was collected). */
|
||||
int getDeactivatedTicks() const { return m_deactive_ticks; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the number of ticks during which the item is deactivated (i.e.
|
||||
* it was collected). */
|
||||
void setDeactivatedTicks(int ticks) { m_deactive_ticks = ticks; }
|
||||
}; // class ItemState
|
||||
|
||||
// ============================================================================
|
||||
/**
|
||||
* \ingroup items
|
||||
*/
|
||||
class Item : public ItemState
|
||||
{
|
||||
|
||||
private:
|
||||
LEAK_CHECK();
|
||||
|
||||
/** Stores the original rotation of an item. This is used in
|
||||
* case of a switch to restore the rotation of a bubble gum
|
||||
@ -107,12 +262,6 @@ private:
|
||||
/** Used when rotating the item */
|
||||
float m_rotation_angle;
|
||||
|
||||
/** True if item was collected & is not displayed. */
|
||||
bool m_collected;
|
||||
|
||||
/** Time till a collected item reappears. */
|
||||
int m_ticks_till_return;
|
||||
|
||||
/** Scene node of this item. */
|
||||
LODNode *m_node;
|
||||
|
||||
@ -124,9 +273,6 @@ private:
|
||||
* and then converting this value to a Vec3. */
|
||||
Vec3 m_xyz;
|
||||
|
||||
/** Index in item_manager field. */
|
||||
unsigned int m_item_id;
|
||||
|
||||
/** Set to false if item should not rotate. */
|
||||
bool m_rotate;
|
||||
|
||||
@ -137,16 +283,6 @@ private:
|
||||
/** Kart that emitted this item if any */
|
||||
const AbstractKart *m_emitter;
|
||||
|
||||
/** Optionally if item was placed by a kart, a timer can be used to
|
||||
* temporarly deactivate collision so a kart is not hit by its own item */
|
||||
int m_deactive_ticks;
|
||||
|
||||
/** Counts how often an item is used before it disappears. Used for
|
||||
* bubble gum to make them disappear after a while. A value >0
|
||||
* indicates that the item still exists, =0 that the item can be
|
||||
* deleted, and <0 that the item will never be deleted. */
|
||||
int m_disappear_counter;
|
||||
|
||||
/** callback used if type == ITEM_TRIGGER */
|
||||
TriggerItemListener* m_listener;
|
||||
|
||||
@ -163,11 +299,10 @@ private:
|
||||
|
||||
/** The closest point to the left and right of this item at which it
|
||||
* would not be collected. Used by the AI to avoid items. */
|
||||
Vec3 *m_avoidance_points[2];
|
||||
Vec3 *m_avoidance_points[2];
|
||||
|
||||
|
||||
void initItem(ItemType type, const Vec3 &xyz);
|
||||
void setType(ItemType type);
|
||||
void initItem(ItemType type, const Vec3 &xyz);
|
||||
void setMesh(scene::IMesh* mesh, scene::IMesh* lowres_mesh);
|
||||
|
||||
public:
|
||||
@ -195,7 +330,7 @@ public:
|
||||
*/
|
||||
bool hitKart(const Vec3 &xyz, const AbstractKart *kart=NULL) const
|
||||
{
|
||||
if (m_event_handler == kart && m_deactive_ticks > 0)
|
||||
if (m_event_handler == kart && getDeactivatedTicks() > 0)
|
||||
return false;
|
||||
Vec3 lc = quatRotate(m_original_rotation, xyz - m_xyz);
|
||||
// Don't be too strict if the kart is a bit above the item
|
||||
@ -216,51 +351,19 @@ protected:
|
||||
bool hitLine(const core::line3df &line,
|
||||
const AbstractKart *kart=NULL) const
|
||||
{
|
||||
if(m_event_handler==kart && m_deactive_ticks >0) return false;
|
||||
if(m_event_handler==kart && getDeactivatedTicks() >0) return false;
|
||||
|
||||
Vec3 closest = line.getClosestPoint(m_xyz.toIrrVector());
|
||||
return hitKart(closest, kart);
|
||||
} // hitLine
|
||||
|
||||
public:
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets the index of this item in the item manager list. */
|
||||
void setItemId(unsigned int n) { m_item_id = n; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the index of this item in the item manager list. */
|
||||
unsigned int getItemId() const { return m_item_id; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the type of this item. */
|
||||
ItemType getType() const { return m_type; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns true if this item is currently collected. */
|
||||
bool wasCollected() const { return m_collected;}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns true if this item is used up and can be removed. */
|
||||
bool isUsedUp() const {return m_disappear_counter==0; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns true if this item can be used up, and therefore needs to
|
||||
* be removed when the game is reset. */
|
||||
bool canBeUsedUp() const {return m_disappear_counter>-1; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets how long an item should be disabled. While item itself sets
|
||||
* a default, this time is too short in case that a kart that has a bomb
|
||||
* hits a banana: by the time the explosion animation is ended and the
|
||||
* kart is back at its original position, the banana would be back again
|
||||
* and therefore hit the kart again. See Attachment::hitBanana for more
|
||||
* details.
|
||||
* \param f Time till the item can be used again.
|
||||
*/
|
||||
void setDisableTicks(int t) { m_ticks_till_return = t; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the time the item is disabled for. */
|
||||
int getDisableTicks() const { return m_ticks_till_return; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the XYZ position of the item. */
|
||||
const Vec3& getXYZ() const { return m_xyz; }
|
||||
const Vec3& getXYZ() const { return m_xyz; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the index of the graph node this item is on. */
|
||||
int getGraphNode() const { return m_graph_node; }
|
||||
int getGraphNode() const { return m_graph_node; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the distance from center: negative means left of center,
|
||||
* positive means right of center. */
|
||||
|
@ -18,10 +18,6 @@
|
||||
|
||||
#include "items/item_manager.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include "config/stk_config.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
@ -41,6 +37,12 @@
|
||||
#include <IMesh.h>
|
||||
#include <IAnimatedMesh.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
|
||||
std::vector<scene::IMesh *> ItemManager::m_item_mesh;
|
||||
std::vector<scene::IMesh *> ItemManager::m_item_lowres_mesh;
|
||||
std::vector<video::SColorf> ItemManager::m_glow_color;
|
||||
@ -69,28 +71,28 @@ void ItemManager::destroy()
|
||||
*/
|
||||
void ItemManager::loadDefaultItemMeshes()
|
||||
{
|
||||
m_item_mesh.resize(Item::ITEM_LAST-Item::ITEM_FIRST+1, NULL);
|
||||
m_glow_color.resize(Item::ITEM_LAST-Item::ITEM_FIRST+1,
|
||||
m_item_mesh.resize(ItemState::ITEM_LAST-ItemState::ITEM_FIRST+1, NULL);
|
||||
m_glow_color.resize(ItemState::ITEM_LAST-ItemState::ITEM_FIRST+1,
|
||||
video::SColorf(255.0f, 255.0f, 255.0f) );
|
||||
|
||||
m_item_lowres_mesh.resize(Item::ITEM_LAST-Item::ITEM_FIRST+1, NULL);
|
||||
m_item_lowres_mesh.resize(ItemState::ITEM_LAST-ItemState::ITEM_FIRST+1, NULL);
|
||||
|
||||
// A temporary mapping of items to names used in the XML file:
|
||||
std::map<Item::ItemType, std::string> item_names;
|
||||
item_names[Item::ITEM_BANANA ] = "banana";
|
||||
item_names[Item::ITEM_BONUS_BOX ] = "bonus-box";
|
||||
item_names[Item::ITEM_BUBBLEGUM ] = "bubblegum";
|
||||
item_names[Item::ITEM_NITRO_BIG ] = "nitro-big";
|
||||
item_names[Item::ITEM_NITRO_SMALL] = "nitro-small";
|
||||
item_names[Item::ITEM_TRIGGER ] = "trigger";
|
||||
item_names[Item::ITEM_BUBBLEGUM_NOLOK] = "bubblegum-nolok";
|
||||
item_names[Item::ITEM_EASTER_EGG ] = "easter-egg";
|
||||
std::map<ItemState::ItemType, std::string> item_names;
|
||||
item_names[ItemState::ITEM_BANANA ] = "banana";
|
||||
item_names[ItemState::ITEM_BONUS_BOX ] = "bonus-box";
|
||||
item_names[ItemState::ITEM_BUBBLEGUM ] = "bubblegum";
|
||||
item_names[ItemState::ITEM_NITRO_BIG ] = "nitro-big";
|
||||
item_names[ItemState::ITEM_NITRO_SMALL] = "nitro-small";
|
||||
item_names[ItemState::ITEM_TRIGGER ] = "trigger";
|
||||
item_names[ItemState::ITEM_BUBBLEGUM_NOLOK] = "bubblegum-nolok";
|
||||
item_names[ItemState::ITEM_EASTER_EGG ] = "easter-egg";
|
||||
|
||||
const std::string file_name = file_manager->getAsset("items.xml");
|
||||
const XMLNode *root = file_manager->createXMLTree(file_name);
|
||||
for(unsigned int i=Item::ITEM_FIRST; i<=Item::ITEM_LAST; i++)
|
||||
for(unsigned int i=ItemState::ITEM_FIRST; i<=ItemState::ITEM_LAST; i++)
|
||||
{
|
||||
const std::string &name = item_names[(Item::ItemType)i];
|
||||
const std::string &name = item_names[(ItemState::ItemType)i];
|
||||
const XMLNode *node = root->getNode(name);
|
||||
if (!node) continue;
|
||||
|
||||
@ -133,7 +135,7 @@ void ItemManager::loadDefaultItemMeshes()
|
||||
*/
|
||||
void ItemManager::removeTextures()
|
||||
{
|
||||
for(unsigned int i=0; i<Item::ITEM_LAST-Item::ITEM_FIRST+1; i++)
|
||||
for(unsigned int i=0; i<ItemState::ITEM_LAST-ItemState::ITEM_FIRST+1; i++)
|
||||
{
|
||||
if(m_item_mesh[i])
|
||||
{
|
||||
@ -162,9 +164,9 @@ ItemManager::ItemManager()
|
||||
// Prepare the switch to array, which stores which item should be
|
||||
// switched to what other item. Initialise it with a mapping that
|
||||
// each item is switched to itself, so basically a no-op.
|
||||
m_switch_to.reserve(Item::ITEM_COUNT);
|
||||
for(unsigned int i=Item::ITEM_FIRST; i<Item::ITEM_COUNT; i++)
|
||||
m_switch_to.push_back((Item::ItemType)i);
|
||||
m_switch_to.reserve(ItemState::ITEM_COUNT);
|
||||
for(unsigned int i=ItemState::ITEM_FIRST; i<ItemState::ITEM_COUNT; i++)
|
||||
m_switch_to.push_back((ItemState::ItemType)i);
|
||||
setSwitchItems(stk_config->m_switch_items);
|
||||
|
||||
if(Graph::get())
|
||||
@ -187,8 +189,8 @@ ItemManager::ItemManager()
|
||||
*/
|
||||
void ItemManager::setSwitchItems(const std::vector<int> &switch_items)
|
||||
{
|
||||
for(unsigned int i=Item::ITEM_FIRST; i<Item::ITEM_COUNT; i++)
|
||||
m_switch_to[i]=(Item::ItemType)stk_config->m_switch_items[i];
|
||||
for(unsigned int i=ItemState::ITEM_FIRST; i<ItemState::ITEM_COUNT; i++)
|
||||
m_switch_to[i]=(ItemState::ItemType)stk_config->m_switch_items[i];
|
||||
} // setSwitchItems
|
||||
|
||||
|
||||
@ -252,13 +254,13 @@ void ItemManager::insertItem(Item *item)
|
||||
* \param parent In case of a dropped item used to avoid that a kart
|
||||
* is affected by its own items.
|
||||
*/
|
||||
Item* ItemManager::newItem(Item::ItemType type, const Vec3& xyz,
|
||||
Item* ItemManager::newItem(ItemState::ItemType type, const Vec3& xyz,
|
||||
const Vec3 &normal, AbstractKart *parent)
|
||||
{
|
||||
Item::ItemType mesh_type = type;
|
||||
if (type == Item::ITEM_BUBBLEGUM && parent->getIdent() == "nolok")
|
||||
ItemState::ItemType mesh_type = type;
|
||||
if (type == ItemState::ITEM_BUBBLEGUM && parent->getIdent() == "nolok")
|
||||
{
|
||||
mesh_type = Item::ITEM_BUBBLEGUM_NOLOK;
|
||||
mesh_type = ItemState::ITEM_BUBBLEGUM_NOLOK;
|
||||
}
|
||||
|
||||
Item* item = new Item(type, xyz, normal, m_item_mesh[mesh_type],
|
||||
@ -268,7 +270,7 @@ Item* ItemManager::newItem(Item::ItemType type, const Vec3& xyz,
|
||||
if(parent != NULL) item->setParent(parent);
|
||||
if(m_switch_ticks>=0)
|
||||
{
|
||||
Item::ItemType new_type = m_switch_to[item->getType()];
|
||||
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]);
|
||||
}
|
||||
@ -298,8 +300,8 @@ void ItemManager::collectedItem(Item *item, AbstractKart *kart, int add_info)
|
||||
assert(item);
|
||||
// Spare tire karts don't collect items
|
||||
if (dynamic_cast<SpareTireAI*>(kart->getController()) != NULL) return;
|
||||
if( (item->getType() == Item::ITEM_BUBBLEGUM ||
|
||||
item->getType() == Item::ITEM_BUBBLEGUM_NOLOK) && kart->isShielded())
|
||||
if( (item->getType() == ItemState::ITEM_BUBBLEGUM ||
|
||||
item->getType() == ItemState::ITEM_BUBBLEGUM_NOLOK) && kart->isShielded())
|
||||
{
|
||||
// shielded karts can simply drive over bubble gums without any effect.
|
||||
return;
|
||||
@ -327,7 +329,7 @@ void ItemManager::checkItemHit(AbstractKart* kart)
|
||||
for(AllItemTypes::iterator i =m_all_items.begin();
|
||||
i!=m_all_items.end(); i++)
|
||||
{
|
||||
if((!*i) || (*i)->wasCollected()) continue;
|
||||
if((!*i) || !(*i)->isAvailable()) continue;
|
||||
// To allow inlining and avoid including kart.hpp in item.hpp,
|
||||
// we pass the kart and the position separately.
|
||||
if((*i)->hitKart(kart->getXYZ(), kart))
|
||||
@ -376,7 +378,7 @@ void ItemManager::reset()
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if((*i)->canBeUsedUp() || (*i)->getType()==Item::ITEM_BUBBLEGUM)
|
||||
if((*i)->canBeUsedUp() || (*i)->getType()==ItemState::ITEM_BUBBLEGUM)
|
||||
{
|
||||
deleteItem( *i );
|
||||
i++;
|
||||
@ -462,7 +464,8 @@ void ItemManager::switchItems()
|
||||
{
|
||||
if(!*i) continue;
|
||||
|
||||
if ((*i)->getType() == Item::ITEM_BUBBLEGUM || (*i)->getType() == Item::ITEM_BUBBLEGUM_NOLOK)
|
||||
if ( (*i)->getType() == ItemState::ITEM_BUBBLEGUM ||
|
||||
(*i)->getType() == ItemState::ITEM_BUBBLEGUM_NOLOK)
|
||||
{
|
||||
if (race_manager->getAISuperPower() == RaceManager::SUPERPOWER_NOLOK_BOSS)
|
||||
{
|
||||
@ -470,7 +473,7 @@ void ItemManager::switchItems()
|
||||
}
|
||||
}
|
||||
|
||||
Item::ItemType new_type = m_switch_to[(*i)->getType()];
|
||||
ItemState::ItemType new_type = m_switch_to[(*i)->getType()];
|
||||
|
||||
if(m_switch_ticks<0)
|
||||
(*i)->switchTo(new_type, m_item_mesh[(int)new_type], m_item_lowres_mesh[(int)new_type]);
|
||||
@ -572,9 +575,9 @@ bool ItemManager::randomItemsForArena(const AlignedArray<btTransform>& pos)
|
||||
for (unsigned int i = 0; i < TOTAL_ITEM; i++)
|
||||
{
|
||||
const int j = random.get(10);
|
||||
Item::ItemType type = (j > BONUS_BOX ? Item::ITEM_BONUS_BOX :
|
||||
j > NITRO_BIG ? Item::ITEM_NITRO_BIG :
|
||||
j > NITRO_SMALL ? Item::ITEM_NITRO_SMALL : Item::ITEM_BANANA);
|
||||
ItemState::ItemType type = (j > BONUS_BOX ? ItemState::ITEM_BONUS_BOX :
|
||||
j > NITRO_BIG ? ItemState::ITEM_NITRO_BIG :
|
||||
j > NITRO_SMALL ? ItemState::ITEM_NITRO_SMALL : ItemState::ITEM_BANANA);
|
||||
|
||||
ArenaNode* an = ag->getNode(used_location[i]);
|
||||
Vec3 loc = an->getCenter();
|
||||
|
@ -60,11 +60,11 @@ public:
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the mesh for a certain item. */
|
||||
static scene::IMesh* getItemModel(Item::ItemType type)
|
||||
static scene::IMesh* getItemModel(ItemState::ItemType type)
|
||||
{ return m_item_mesh[type]; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the glow color for an item. */
|
||||
static video::SColorf& getGlowColor(Item::ItemType type)
|
||||
static video::SColorf& getGlowColor(ItemState::ItemType type)
|
||||
{ return m_glow_color[type]; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Return an instance of the item manager (it does not automatically
|
||||
@ -86,7 +86,7 @@ private:
|
||||
std::vector< AllItemTypes > *m_items_in_quads;
|
||||
|
||||
/** What item this item is switched to. */
|
||||
std::vector<Item::ItemType> m_switch_to;
|
||||
std::vector<ItemState::ItemType> m_switch_to;
|
||||
|
||||
/** Remaining time that items should remain switched. If the
|
||||
* value is <0, it indicates that the items are not switched atm. */
|
||||
@ -101,7 +101,7 @@ private:
|
||||
void setSwitchItems(const std::vector<int> &switch_items);
|
||||
|
||||
public:
|
||||
Item* newItem (Item::ItemType type, const Vec3& xyz,
|
||||
Item* newItem (ItemState::ItemType type, const Vec3& xyz,
|
||||
const Vec3 &normal,
|
||||
AbstractKart* parent=NULL);
|
||||
Item* newItem (const Vec3& xyz, float distance,
|
||||
|
@ -581,10 +581,7 @@ void ArenaAI::tryCollectItem(Vec3* aim_point, int* target_node) const
|
||||
ItemManager::get()->getFirstItemInQuad(*target_node));
|
||||
|
||||
// Don't look for a new item unless it's collected or swapped
|
||||
if (selected && !(selected->wasCollected() ||
|
||||
selected->getType() == Item::ITEM_BANANA ||
|
||||
selected->getType() == Item::ITEM_BUBBLEGUM ||
|
||||
selected->getType() == Item::ITEM_BUBBLEGUM_NOLOK))
|
||||
if (selected && selected->isAvailable() && !selected->isNegativeItem())
|
||||
{
|
||||
*aim_point = selected->getXYZ();
|
||||
return;
|
||||
@ -594,10 +591,7 @@ void ArenaAI::tryCollectItem(Vec3* aim_point, int* target_node) const
|
||||
{
|
||||
Item* cur_item = ItemManager::get()->getFirstItemInQuad(i);
|
||||
if (cur_item == NULL) continue;
|
||||
if (cur_item->wasCollected() ||
|
||||
cur_item->getType() == Item::ITEM_BANANA ||
|
||||
cur_item->getType() == Item::ITEM_BUBBLEGUM ||
|
||||
cur_item->getType() == Item::ITEM_BUBBLEGUM_NOLOK)
|
||||
if (!cur_item->isAvailable() || cur_item->isNegativeItem())
|
||||
continue;
|
||||
|
||||
if ((cur_item->getType() == Item::ITEM_NITRO_BIG ||
|
||||
@ -667,10 +661,7 @@ void ArenaAI::determinePath(int forward, std::vector<int>* path)
|
||||
const int node = (*path)[i];
|
||||
Item* selected = ItemManager::get()->getFirstItemInQuad(node);
|
||||
|
||||
if (selected && !selected->wasCollected() &&
|
||||
(selected->getType() == Item::ITEM_BANANA ||
|
||||
selected->getType() == Item::ITEM_BUBBLEGUM ||
|
||||
selected->getType() == Item::ITEM_BUBBLEGUM_NOLOK))
|
||||
if (selected && selected->isAvailable() && selected->isNegativeItem())
|
||||
{
|
||||
bad_item_nodes.push_back(node);
|
||||
}
|
||||
|
@ -852,7 +852,7 @@ bool SkiddingAI::handleSelectedItem(Vec3 kart_aim_direction, Vec3 *aim_point)
|
||||
// If the item is unavailable keep on testing. It is not necessary
|
||||
// to test if an item has turned bad, this was tested before this
|
||||
// function is called.
|
||||
if(m_item_to_collect->getDisableTicks()>0)
|
||||
if(!m_item_to_collect->isAvailable())
|
||||
return false;
|
||||
|
||||
const Vec3 &xyz = m_item_to_collect->getXYZ();
|
||||
@ -1042,7 +1042,7 @@ void SkiddingAI::evaluateItems(const Item *item, Vec3 kart_aim_direction,
|
||||
const KartProperties *kp = m_kart->getKartProperties();
|
||||
|
||||
// Ignore items that are currently disabled
|
||||
if(item->getDisableTicks()>0) return;
|
||||
if(!item->isAvailable()) return;
|
||||
|
||||
// If the item type is not handled here, ignore it
|
||||
Item::ItemType type = item->getType();
|
||||
|
@ -856,7 +856,7 @@ bool SkiddingAI::handleSelectedItem(Vec3 kart_aim_direction, Vec3 *aim_point)
|
||||
// If the item is unavailable keep on testing. It is not necessary
|
||||
// to test if an item has turned bad, this was tested before this
|
||||
// function is called.
|
||||
if(m_item_to_collect->getDisableTicks()>0)
|
||||
if(!m_item_to_collect->isAvailable())
|
||||
return false;
|
||||
|
||||
const Vec3 &xyz = m_item_to_collect->getXYZ();
|
||||
@ -1046,7 +1046,7 @@ void SkiddingAI::evaluateItems(const Item *item, Vec3 kart_aim_direction,
|
||||
const KartProperties *kp = m_kart->getKartProperties();
|
||||
|
||||
// Ignore items that are currently disabled
|
||||
if(item->getDisableTicks()>0) return;
|
||||
if(!item->isAvailable()) return;
|
||||
|
||||
// If the item type is not handled here, ignore it
|
||||
Item::ItemType type = item->getType();
|
||||
|
Loading…
Reference in New Issue
Block a user