Add check trigger to replace item trigger

This commit is contained in:
Benau 2019-02-27 11:31:19 +08:00
parent fe4a9c5406
commit 9b4b283c4c
17 changed files with 191 additions and 123 deletions

View File

@ -211,8 +211,8 @@
<!-- time: How long a switch is being effective. <!-- time: How long a switch is being effective.
items for each item list the index of the item it is switched with. items for each item list the index of the item it is switched with.
Order: giftbox, banana, big-nitro, small-nitro, bubble-gum, nolok-bubble-gum, Order: giftbox, banana, big-nitro, small-nitro, bubble-gum, nolok-bubble-gum,
easter egg, trigger--> easter egg-->
<switch time="5" items="1 0 4 4 2 2 6 7"/> <switch time="5" items="1 0 4 4 2 2 6"/>
<!-- disappear-counter: How often bubblegum gets driven over before it disappears. <!-- disappear-counter: How often bubblegum gets driven over before it disappears.
shield-time: How long the bubblegum shield lasts shield-time: How long the bubblegum shield lasts

View File

@ -195,13 +195,10 @@ Item::Item(ItemType type, const Vec3& xyz, const Vec3& normal,
const AbstractKart *owner) const AbstractKart *owner)
: ItemState(type, owner) : ItemState(type, owner)
{ {
assert(type != ITEM_TRIGGER); // use other constructor for that
m_was_available_previously = true; m_was_available_previously = true;
m_distance_2 = 1.2f; m_distance_2 = 1.2f;
initItem(type, xyz, normal); initItem(type, xyz, normal);
m_graphical_type = getGrahpicalType(); m_graphical_type = getGrahpicalType();
m_listener = NULL;
LODNode* lodnode = LODNode* lodnode =
new LODNode("item", irr_driver->getSceneManager()->getRootSceneNode(), new LODNode("item", irr_driver->getSceneManager()->getRootSceneNode(),
@ -238,23 +235,6 @@ Item::Item(ItemType type, const Vec3& xyz, const Vec3& normal,
m_node->grab(); m_node->grab();
} // Item(type, xyz, normal, mesh, lowres_mesh) } // Item(type, xyz, normal, mesh, lowres_mesh)
//-----------------------------------------------------------------------------
/** \brief Constructor to create a trigger item.
* Trigger items are invisible and can be used to trigger a behavior when
* approaching a point.
*/
Item::Item(const Vec3& xyz, float distance, TriggerItemListener* trigger)
: ItemState(ITEM_TRIGGER)
{
m_distance_2 = distance*distance;
initItem(ITEM_TRIGGER, xyz, /*normal not required*/Vec3(0,1,0));
m_graphical_type = ITEM_TRIGGER;
m_node = NULL;
m_listener = trigger;
m_was_available_previously = true;
} // Item(xyz, distance, trigger)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Initialises the item. Note that m_distance_2 must be defined before calling /** Initialises the item. Note that m_distance_2 must be defined before calling
* this function, since it pre-computes some values based on this. * this function, since it pre-computes some values based on this.

View File

@ -42,19 +42,6 @@ namespace irr
} }
using namespace irr; using namespace irr;
// ============================================================================
/**
* \ingroup items
* \brief Listener class to go with Items of type ITEM_TRIGGER
*/
class TriggerItemListener
{
public:
virtual ~TriggerItemListener() {}
virtual void onTriggerItemApproached() = 0;
};
// ============================================================================ // ============================================================================
/** \ingroup items /** \ingroup items
* Contains the state information of an item, i.e. all non-visual information * Contains the state information of an item, i.e. all non-visual information
@ -83,11 +70,7 @@ public:
/** For easter egg mode only. */ /** For easter egg mode only. */
ITEM_EASTER_EGG, ITEM_EASTER_EGG,
/** An invisible item that can be used to trigger some behavior when ITEM_LAST = ITEM_EASTER_EGG,
* approaching a point
*/
ITEM_TRIGGER,
ITEM_LAST = ITEM_TRIGGER,
ITEM_COUNT, ITEM_COUNT,
ITEM_NONE ITEM_NONE
}; };
@ -235,7 +218,7 @@ public:
virtual void switchTo(ItemType type) virtual void switchTo(ItemType type)
{ {
// triggers and easter eggs should not be switched // triggers and easter eggs should not be switched
if (m_type == ITEM_TRIGGER || m_type == ITEM_EASTER_EGG) return; if (m_type == ITEM_EASTER_EGG) return;
m_original_type = m_type; m_original_type = m_type;
setType(type); setType(type);
return; return;
@ -246,8 +229,6 @@ public:
*/ */
virtual bool switchBack() virtual 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 // 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 // gum is dropped while items are switched - when switching back, this
// bubble gum has no original type. // bubble gum has no original type.
@ -352,9 +333,6 @@ private:
/** Stores if the item was available in the previously rendered frame. */ /** Stores if the item was available in the previously rendered frame. */
bool m_was_available_previously; bool m_was_available_previously;
/** callback used if type == ITEM_TRIGGER */
TriggerItemListener* m_listener;
/** square distance at which item is collected */ /** square distance at which item is collected */
float m_distance_2; float m_distance_2;
@ -378,8 +356,6 @@ public:
Item(ItemType type, const Vec3& xyz, const Vec3& normal, Item(ItemType type, const Vec3& xyz, const Vec3& normal,
scene::IMesh* mesh, scene::IMesh* lowres_mesh, scene::IMesh* mesh, scene::IMesh* lowres_mesh,
const AbstractKart *owner); const AbstractKart *owner);
Item(const Vec3& xyz, float distance,
TriggerItemListener* trigger);
virtual ~Item (); virtual ~Item ();
virtual void updateGraphics(float dt) OVERRIDE; virtual void updateGraphics(float dt) OVERRIDE;
virtual void reset() OVERRIDE; virtual void reset() OVERRIDE;
@ -392,8 +368,6 @@ public:
virtual void collected(const AbstractKart *kart) OVERRIDE virtual void collected(const AbstractKart *kart) OVERRIDE
{ {
ItemState::collected(kart); ItemState::collected(kart);
if (m_listener != NULL)
m_listener->onTriggerItemApproached();
} // isCollected } // isCollected
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
/** Switch backs to the original item. Returns true if the item was not /** Switch backs to the original item. Returns true if the item was not
@ -426,8 +400,7 @@ public:
return lc.length2() < m_distance_2; return lc.length2() < m_distance_2;
} // hitKart } // hitKart
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
bool rotating() const bool rotating() const { return getType() != ITEM_BUBBLEGUM; }
{ return getType() != ITEM_BUBBLEGUM && getType() != ITEM_TRIGGER; }
public: public:
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------

View File

@ -86,7 +86,6 @@ void ItemManager::loadDefaultItemMeshes()
item_names[ItemState::ITEM_BUBBLEGUM ] = "bubblegum"; item_names[ItemState::ITEM_BUBBLEGUM ] = "bubblegum";
item_names[ItemState::ITEM_NITRO_BIG ] = "nitro-big"; item_names[ItemState::ITEM_NITRO_BIG ] = "nitro-big";
item_names[ItemState::ITEM_NITRO_SMALL] = "nitro-small"; 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_BUBBLEGUM_NOLOK] = "bubblegum-nolok";
item_names[ItemState::ITEM_EASTER_EGG ] = "easter-egg"; item_names[ItemState::ITEM_EASTER_EGG ] = "easter-egg";
@ -353,23 +352,6 @@ Item* ItemManager::placeItem(ItemState::ItemType type, const Vec3& xyz,
return item; return item;
} // placeItem } // 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 = new Item(xyz, distance, listener);
insertItem(item);
return item;
} // placeTrigger
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Set an item as collected. /** Set an item as collected.
* This function is called on the server when an item is collected, or on * This function is called on the server when an item is collected, or on

View File

@ -137,8 +137,6 @@ public:
const AbstractKart* parent, const AbstractKart* parent,
const Vec3 *server_xyz = NULL, const Vec3 *server_xyz = NULL,
const Vec3 *normal = NULL); const Vec3 *normal = NULL);
virtual Item* placeTrigger (const Vec3& xyz, float distance,
TriggerItemListener* listener);
void update (int ticks); void update (int ticks);
void updateGraphics (float dt); void updateGraphics (float dt);
void checkItemHit (AbstractKart* kart); void checkItemHit (AbstractKart* kart);

View File

@ -398,9 +398,6 @@ void LocalPlayerController::collectedItem(const ItemState &item_state,
//See Kart::collectedItem() //See Kart::collectedItem()
m_kart->playSound(m_ugh_sound); m_kart->playSound(m_ugh_sound);
break; break;
case Item::ITEM_TRIGGER:
// no default sound for triggers
break;
default: default:
m_kart->playSound(m_grab_sound); m_kart->playSound(m_grab_sound);
break; break;

View File

@ -999,8 +999,6 @@ void SkiddingAI::evaluateItems(const ItemState *item, Vec3 kart_aim_direction,
break; break;
case Item::ITEM_BONUS_BOX: case Item::ITEM_BONUS_BOX:
break; break;
case Item::ITEM_TRIGGER: return; break;
default: assert(false); break; default: assert(false); break;
} // switch } // switch

View File

@ -1074,8 +1074,6 @@ void SkiddingAI::evaluateItems(const ItemState *item, Vec3 kart_aim_direction,
break; break;
case Item::ITEM_BONUS_BOX: case Item::ITEM_BONUS_BOX:
break; break;
case Item::ITEM_TRIGGER: return; break;
default: assert(false); break; default: assert(false); break;
} // switch } // switch

View File

@ -25,13 +25,14 @@
#include "items/item.hpp" #include "items/item.hpp"
#include "modes/world.hpp" #include "modes/world.hpp"
#include "race/race_manager.hpp" #include "race/race_manager.hpp"
#include "tracks/check_manager.hpp"
CheckCylinder::CheckCylinder(const XMLNode &node, unsigned int index, TriggerItemListener* listener) CheckCylinder::CheckCylinder(const XMLNode &node,
: CheckStructure(node, index) std::function<void()> triggering_function)
: CheckStructure(CheckManager::get()->getCheckStructureCount())
{ {
m_radius2 = 1; m_radius2 = 1;
m_height = 0; m_height = 0;
m_listener = listener;
node.get("height", &m_height); node.get("height", &m_height);
node.get("radius", &m_radius2); node.get("radius", &m_radius2);
m_radius2 *= m_radius2; m_radius2 *= m_radius2;
@ -43,6 +44,7 @@ CheckCylinder::CheckCylinder(const XMLNode &node, unsigned int index, TriggerIte
{ {
m_is_inside[i] = false; m_is_inside[i] = false;
} }
m_triggering_function = triggering_function;
} // CheckCylinder } // CheckCylinder
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -57,6 +59,9 @@ CheckCylinder::CheckCylinder(const XMLNode &node, unsigned int index, TriggerIte
bool CheckCylinder::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos, bool CheckCylinder::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
int kart_id) int kart_id)
{ {
// kart_id will be -1 if called by CheckManager::getChecklineTriggering
if (kart_id < 0 || kart_id >= (int)m_is_inside.size())
return false;
// TODO: this is the code for a sphere, rewrite for cylinder // TODO: this is the code for a sphere, rewrite for cylinder
Vec3 old_pos_xz(old_pos.x(), 0.0f, old_pos.z()); Vec3 old_pos_xz(old_pos.x(), 0.0f, old_pos.z());
Vec3 new_pos_xz(new_pos.x(), 0.0f, new_pos.z()); Vec3 new_pos_xz(new_pos.x(), 0.0f, new_pos.z());
@ -70,8 +75,8 @@ bool CheckCylinder::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
bool triggered = (old_dist2>=m_radius2 && new_dist2 < m_radius2) || bool triggered = (old_dist2>=m_radius2 && new_dist2 < m_radius2) ||
(old_dist2< m_radius2 && new_dist2 >=m_radius2); (old_dist2< m_radius2 && new_dist2 >=m_radius2);
if (triggered && m_listener != NULL) if (triggered && m_triggering_function)
m_listener->onTriggerItemApproached(); m_triggering_function();
return triggered; return triggered;
} // isTriggered } // isTriggered

View File

@ -20,6 +20,7 @@
#define HEADER_CHECK_CYLINDER_HPP #define HEADER_CHECK_CYLINDER_HPP
#include "tracks/check_structure.hpp" #include "tracks/check_structure.hpp"
#include <functional>
class XMLNode; class XMLNode;
class CheckManager; class CheckManager;
@ -46,10 +47,11 @@ private:
/** Stores the distance of each kart from the center of this sphere. /** Stores the distance of each kart from the center of this sphere.
* This saves some computations. */ * This saves some computations. */
std::vector<float> m_distance2; std::vector<float> m_distance2;
TriggerItemListener* m_listener; /** Function to call when triggered. */
std::function<void()> m_triggering_function;
public: public:
CheckCylinder(const XMLNode &node, unsigned int index, CheckCylinder(const XMLNode &node,
TriggerItemListener* listener); std::function<void()> triggering_function);
virtual ~CheckCylinder() {}; virtual ~CheckCylinder() {};
virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos, virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
int kart_id); int kart_id);

View File

@ -59,6 +59,9 @@ CheckSphere::CheckSphere(const XMLNode &node, unsigned int index)
bool CheckSphere::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos, bool CheckSphere::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
int kart_id) int kart_id)
{ {
// kart_id will be -1 if called by CheckManager::getChecklineTriggering
if (kart_id < 0 || kart_id >= (int)m_is_inside.size())
return false;
float old_dist2 = (old_pos-m_center_point).length2(); float old_dist2 = (old_pos-m_center_point).length2();
float new_dist2 = (new_pos-m_center_point).length2(); float new_dist2 = (new_pos-m_center_point).length2();
m_is_inside[kart_id] = new_dist2<m_radius2; m_is_inside[kart_id] = new_dist2<m_radius2;

View File

@ -59,13 +59,14 @@ public:
* CANNON: Causes the kart to be shot to a specified point. * CANNON: Causes the kart to be shot to a specified point.
* GOAL: Causes a point to be scored when a soccer ball crosses its line * GOAL: Causes a point to be scored when a soccer ball crosses its line
* AMBIENT_SPHERE: Modifies the ambient color. * AMBIENT_SPHERE: Modifies the ambient color.
* TRIGGER: Run custom trigger function
* A combination of an activate and new_lap line are used to * A combination of an activate and new_lap line are used to
* avoid shortcuts: a new_lap line is deactivated after crossing it, and * avoid shortcuts: a new_lap line is deactivated after crossing it, and
* you have to cross a corresponding activate structure to re-activate it, * you have to cross a corresponding activate structure to re-activate it,
* enabling you to count the lap again. * enabling you to count the lap again.
*/ */
enum CheckType {CT_NEW_LAP, CT_ACTIVATE, CT_TOGGLE, CT_CANNON, enum CheckType {CT_NEW_LAP, CT_ACTIVATE, CT_TOGGLE, CT_CANNON,
CT_GOAL, CT_AMBIENT_SPHERE}; CT_GOAL, CT_AMBIENT_SPHERE, CT_TRIGGER};
protected: protected:
/** Stores the previous position of all karts. This is needed to detect /** Stores the previous position of all karts. This is needed to detect
@ -82,6 +83,9 @@ protected:
* debugging (use --check-debug option). */ * debugging (use --check-debug option). */
unsigned int m_index; unsigned int m_index;
/** For CheckTrigger or CheckCylinder */
CheckStructure(unsigned index) : m_active_at_reset(true), m_index(index),
m_check_type(CT_TRIGGER) {}
private: private:
/** The type of this checkline. */ /** The type of this checkline. */
CheckType m_check_type; CheckType m_check_type;

View File

@ -0,0 +1,56 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2019 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "tracks/check_trigger.hpp"
#include "karts/abstract_kart.hpp"
#include "modes/world.hpp"
#include "tracks/check_manager.hpp"
#include "utils/time.hpp"
/** Constructor for a checksphere.
* \param check_manager Pointer to the check manager, which is needed when
* resetting e.g. new lap counters.
* \param node XML node containing the parameters for this checkline.
*/
CheckTrigger::CheckTrigger(const Vec3& center, float distance,
std::function<void()> triggering_function)
: CheckStructure(CheckManager::get()->getCheckStructureCount()),
m_center(center), m_distance2(distance * distance),
m_triggering_function(triggering_function)
{
m_last_triggered_time = StkTime::getRealTimeMs();
} // CheckSphere
// ----------------------------------------------------------------------------
/** Copied from item state.
*/
bool CheckTrigger::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
int kart_id)
{
// kart_id will be -1 if called by CheckManager::getChecklineTriggering
if (kart_id < 0 || kart_id >= (int)World::getWorld()->getNumKarts())
return false;
if (m_last_triggered_time + 2000 > StkTime::getRealTimeMs())
return false;
AbstractKart* k = World::getWorld()->getKart(kart_id);
if ((k->getXYZ() - m_center).length2() < m_distance2)
{
m_last_triggered_time = StkTime::getRealTimeMs();
return true;
}
return false;
} // isTriggered

View File

@ -0,0 +1,64 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2019 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_CHECK_TRIGGER_HPP
#define HEADER_CHECK_TRIGGER_HPP
#include "tracks/check_structure.hpp"
#include "utils/cpp2011.hpp"
#include "utils/types.hpp"
#include <functional>
/** This class implements a check point like item, but used only for scripting
* or sound trigger.
* \ingroup tracks
*/
class CheckTrigger : public CheckStructure
{
private:
/** Center of the trigger. */
const Vec3 m_center;
/** Squared of the triggering distance. */
const float m_distance2;
/** Function to call when triggered. */
const std::function<void()> m_triggering_function;
/** Time since last trigger, if any triggering between 2 seconds ignored
* (like items). */
uint64_t m_last_triggered_time;
public:
CheckTrigger(const Vec3& center, float distance,
std::function<void()> triggering_function);
// ------------------------------------------------------------------------
virtual ~CheckTrigger() {}
// ------------------------------------------------------------------------
virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
int kart_id) OVERRIDE;
// ------------------------------------------------------------------------
virtual void trigger(unsigned int kart_index) OVERRIDE
{
m_triggering_function();
CheckStructure::trigger(kart_index);
}
}; // CheckSphere
#endif

View File

@ -44,7 +44,7 @@
#include "states_screens/dialogs/tutorial_message_dialog.hpp" #include "states_screens/dialogs/tutorial_message_dialog.hpp"
#include "tracks/check_cylinder.hpp" #include "tracks/check_cylinder.hpp"
#include "tracks/check_manager.hpp" #include "tracks/check_manager.hpp"
#include "tracks/check_sphere.hpp" #include "tracks/check_trigger.hpp"
#include "tracks/model_definition_loader.hpp" #include "tracks/model_definition_loader.hpp"
#include "tracks/track.hpp" #include "tracks/track.hpp"
#include "tracks/track_manager.hpp" #include "tracks/track_manager.hpp"
@ -683,7 +683,10 @@ TrackObjectPresentationSound::TrackObjectPresentationSound(
if (trigger_when_near) if (trigger_when_near)
{ {
ItemManager::get()->placeTrigger(m_init_xyz, trigger_distance, this); CheckManager::get()->add(
new CheckTrigger(m_init_xyz, trigger_distance, std::bind(
&TrackObjectPresentationSound::onTriggerItemApproached,
this)));
} }
if (disable_for_multiplayer) if (disable_for_multiplayer)
@ -1067,7 +1070,7 @@ TrackObjectPresentationActionTrigger::TrackObjectPresentationActionTrigger(
} }
m_xml_reenable_timeout = 999999.9f; m_xml_reenable_timeout = 999999.9f;
xml_node.get("reenable-timeout", &m_xml_reenable_timeout); xml_node.get("reenable-timeout", &m_xml_reenable_timeout);
m_reenable_timeout = 0.0f; setReenableTimeout(0.0f);
if (m_action.empty()) if (m_action.empty())
{ {
@ -1098,17 +1101,16 @@ TrackObjectPresentationActionTrigger::TrackObjectPresentationActionTrigger(
if (m_type == TRIGGER_TYPE_POINT) if (m_type == TRIGGER_TYPE_POINT)
{ {
// TODO: rewrite as a sphere check structure? CheckManager::get()->add(
ItemManager::get()->placeTrigger(m_init_xyz, trigger_distance, this); new CheckTrigger(m_init_xyz, trigger_distance, std::bind(
// 0 is the index, and is mostly used for debugging (i.e. to identify which check &TrackObjectPresentationActionTrigger::onTriggerItemApproached,
// structure information is printed about) - not sure how to best use this 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) else if (m_type == TRIGGER_TYPE_CYLINDER)
{ {
CheckManager::get()->add(new CheckCylinder(xml_node, 0 /* TODO what is this? */, this)); CheckManager::get()->add(new CheckCylinder(xml_node, std::bind(
&TrackObjectPresentationActionTrigger::onTriggerItemApproached,
this)));
} }
else else
{ {
@ -1129,19 +1131,22 @@ TrackObjectPresentationActionTrigger::TrackObjectPresentationActionTrigger(
float trigger_distance = distance; float trigger_distance = distance;
m_action = script_name; m_action = script_name;
m_xml_reenable_timeout = 999999.9f; m_xml_reenable_timeout = 999999.9f;
m_reenable_timeout = 0.0f; setReenableTimeout(0.0f);
m_type = TRIGGER_TYPE_POINT; m_type = TRIGGER_TYPE_POINT;
ItemManager::get()->placeTrigger(m_init_xyz, trigger_distance, this); CheckManager::get()->add(
new CheckTrigger(m_init_xyz, trigger_distance, std::bind(
&TrackObjectPresentationActionTrigger::onTriggerItemApproached,
this)));
} // TrackObjectPresentationActionTrigger } // TrackObjectPresentationActionTrigger
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void TrackObjectPresentationActionTrigger::onTriggerItemApproached() void TrackObjectPresentationActionTrigger::onTriggerItemApproached()
{ {
if (m_reenable_timeout > 0.0f) if (m_reenable_timeout > StkTime::getRealTimeMs())
{ {
return; return;
} }
m_reenable_timeout = m_xml_reenable_timeout; setReenableTimeout(m_xml_reenable_timeout);
int kart_id = 0; int kart_id = 0;
Camera* camera = Camera::getActiveCamera(); Camera* camera = Camera::getActiveCamera();

View File

@ -21,16 +21,18 @@
#define HEADER_TRACK_OBJECT_PRESENTATION_HPP #define HEADER_TRACK_OBJECT_PRESENTATION_HPP
#include "graphics/lod_node.hpp" #include "graphics/lod_node.hpp"
#include "items/item.hpp"
#include "utils/cpp2011.hpp" #include "utils/cpp2011.hpp"
#include "utils/no_copy.hpp" #include "utils/no_copy.hpp"
#include "utils/log.hpp" #include "utils/log.hpp"
#include "utils/leak_check.hpp"
#include "utils/time.hpp"
#include "utils/vec3.hpp" #include "utils/vec3.hpp"
#include <vector3d.h> #include <vector3d.h>
#include <IAnimatedMeshSceneNode.h> #include <IAnimatedMeshSceneNode.h>
#include <memory> #include <memory>
#include <limits>
#include <string> #include <string>
class SFXBase; class SFXBase;
@ -268,8 +270,7 @@ public:
/** \ingroup tracks /** \ingroup tracks
* A track object representation that consists of a sound emitter * A track object representation that consists of a sound emitter
*/ */
class TrackObjectPresentationSound : public TrackObjectPresentation, class TrackObjectPresentationSound : public TrackObjectPresentation
public TriggerItemListener
{ {
private: private:
@ -290,7 +291,7 @@ public:
scene::ISceneNode* parent, scene::ISceneNode* parent,
bool disable_for_multiplayer); bool disable_for_multiplayer);
virtual ~TrackObjectPresentationSound(); virtual ~TrackObjectPresentationSound();
virtual void onTriggerItemApproached() OVERRIDE; void onTriggerItemApproached();
virtual void updateGraphics(float dt) OVERRIDE; virtual void updateGraphics(float dt) OVERRIDE;
virtual void move(const core::vector3df& xyz, const core::vector3df& hpr, virtual void move(const core::vector3df& xyz, const core::vector3df& hpr,
const core::vector3df& scale, bool isAbsoluteCoord) OVERRIDE; const core::vector3df& scale, bool isAbsoluteCoord) OVERRIDE;
@ -383,14 +384,15 @@ enum ActionTriggerType
/** \ingroup tracks /** \ingroup tracks
* A track object representation that consists of an action trigger * A track object representation that consists of an action trigger
*/ */
class TrackObjectPresentationActionTrigger : public TrackObjectPresentation, class TrackObjectPresentationActionTrigger : public TrackObjectPresentation
public TriggerItemListener
{ {
private: private:
/** For action trigger objects */ /** For action trigger objects */
std::string m_action, m_library_id, m_triggered_object, m_library_name; std::string m_action, m_library_id, m_triggered_object, m_library_name;
float m_xml_reenable_timeout, m_reenable_timeout; float m_xml_reenable_timeout;
uint64_t m_reenable_timeout;
ActionTriggerType m_type; ActionTriggerType m_type;
@ -403,24 +405,25 @@ public:
virtual ~TrackObjectPresentationActionTrigger() {} virtual ~TrackObjectPresentationActionTrigger() {}
virtual void onTriggerItemApproached() OVERRIDE; void onTriggerItemApproached();
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Reset the trigger (i.e. sets it to active again). */ /** Reset the trigger (i.e. sets it to active again). */
virtual void reset() OVERRIDE { m_reenable_timeout = 0.0f; } virtual void reset() OVERRIDE
{ m_reenable_timeout = StkTime::getRealTimeMs(); }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
virtual void update(float dt) OVERRIDE /** Sets the trigger to be enabled or disabled. getRealTimeMs is used to
{ * to avoid called update which duplicated in network rewinding. */
if (m_reenable_timeout < 900000.0f)
{
m_reenable_timeout -= dt;
}
}
// ------------------------------------------------------------------------
/** Sets the trigger to be enabled or disabled. */
virtual void setEnable(bool status) OVERRIDE virtual void setEnable(bool status) OVERRIDE
{ m_reenable_timeout = status ? 0.0f : 999999.9f; } {
m_reenable_timeout = status ? StkTime::getRealTimeMs() :
std::numeric_limits<uint64_t>::max();
}
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void setReenableTimeout(float time) { m_reenable_timeout = time; } void setReenableTimeout(float time)
{
m_reenable_timeout =
StkTime::getRealTimeMs() + (uint64_t)(time * 1000.0f);
}
}; // class TrackObjectPresentationActionTrigger }; // class TrackObjectPresentationActionTrigger