[Orxonox-commit 2084] r6800 - in code/trunk/src: libraries/core modules/objects modules/objects/eventsystem modules/objects/triggers modules/questsystem
dafrick at orxonox.net
dafrick at orxonox.net
Thu Apr 29 13:16:17 CEST 2010
Author: dafrick
Date: 2010-04-29 13:16:16 +0200 (Thu, 29 Apr 2010)
New Revision: 6800
Added:
code/trunk/src/modules/objects/triggers/DistanceMultiTrigger.cc
code/trunk/src/modules/objects/triggers/DistanceMultiTrigger.h
code/trunk/src/modules/objects/triggers/MultiTrigger.cc
code/trunk/src/modules/objects/triggers/MultiTrigger.h
code/trunk/src/modules/objects/triggers/MultiTriggerContainer.cc
code/trunk/src/modules/objects/triggers/MultiTriggerContainer.h
Modified:
code/trunk/src/libraries/core/BaseObject.cc
code/trunk/src/libraries/core/BaseObject.h
code/trunk/src/libraries/core/Event.cc
code/trunk/src/libraries/core/Event.h
code/trunk/src/libraries/core/EventIncludes.h
code/trunk/src/modules/objects/ObjectsPrereqs.h
code/trunk/src/modules/objects/eventsystem/EventListener.cc
code/trunk/src/modules/objects/triggers/CMakeLists.txt
code/trunk/src/modules/questsystem/CMakeLists.txt
code/trunk/src/modules/questsystem/QuestEffectBeacon.cc
code/trunk/src/modules/questsystem/QuestEffectBeacon.h
Log:
Created a new class of triggers called Multitriggers.
MultiTriggers are triggers which (as opposed to normal triggers) have a state for each object triggering the MultiTrigger, that means, that a MultiTrigger can be triggered for two different Players, while not being triggered for a third.
To go with this MultiTrigger I created a data structure (MultitriggerContainer), which helps relaying important information to the objects, that receive the Events of the trigger.
Also there is a MultiDistanceTrigger, which is just the DistanceTrigger as a MultiTrigger.
To make this work I had to make some adjustements to the eventsystem, namely an EventState can now be either an EventState (as it was before) or an EventSink, which means that every efent arriving at the EventState is processed as opposed to just the ones which change the state.
There is a new makro (XMLPortEventSink) to create an EventState with sink behaviour. It can be used exacly as the XMLPortEventState makro.
Modified: code/trunk/src/libraries/core/BaseObject.cc
===================================================================
--- code/trunk/src/libraries/core/BaseObject.cc 2010-04-29 10:57:23 UTC (rev 6799)
+++ code/trunk/src/libraries/core/BaseObject.cc 2010-04-29 11:16:16 UTC (rev 6800)
@@ -102,6 +102,13 @@
delete it->second;
}
}
+
+ /** @brief Adds an object which listens to the events of this object. */
+ void BaseObject::registerEventListener(BaseObject* object)
+ {
+ COUT(4) << "New EventListener: " << object->getIdentifier()->getName() << " &(" << object << ")." << std::endl;
+ this->eventListeners_.insert(object);
+ }
/**
@brief XML loading and saving.
@@ -355,6 +362,8 @@
void BaseObject::processEvent(Event& event)
{
this->registerEventStates();
+
+ COUT(4) << this->getIdentifier()->getName() << " (&" << this << ") processing event. originator: " << event.originator_->getIdentifier()->getName() << " (&" << event.originator_ << "), activate: " << event.activate_ << ", name: " << event.name_ << ", statename: " << event.statename_ << "." << std::endl;
std::map<std::string, EventState*>::const_iterator it = this->eventStates_.find(event.statename_);
if (it != this->eventStates_.end())
Modified: code/trunk/src/libraries/core/BaseObject.h
===================================================================
--- code/trunk/src/libraries/core/BaseObject.h 2010-04-29 10:57:23 UTC (rev 6799)
+++ code/trunk/src/libraries/core/BaseObject.h 2010-04-29 11:16:16 UTC (rev 6800)
@@ -187,8 +187,7 @@
private:
/** @brief Adds an object which listens to the events of this object. */
- inline void registerEventListener(BaseObject* object)
- { this->eventListeners_.insert(object); }
+ void registerEventListener(BaseObject* object);
/** @brief Removes an event listener from this object. */
inline void unregisterEventListener(BaseObject* object)
{ this->eventListeners_.erase(object); }
Modified: code/trunk/src/libraries/core/Event.cc
===================================================================
--- code/trunk/src/libraries/core/Event.cc 2010-04-29 10:57:23 UTC (rev 6799)
+++ code/trunk/src/libraries/core/Event.cc 2010-04-29 11:16:16 UTC (rev 6800)
@@ -58,18 +58,24 @@
this->bProcessingEvent_ = true;
+ COUT(4) << "Processing event (EventState) : originator: " << event.originator_->getIdentifier()->getName() << " (&" << event.originator_ << "), activate: " << event.activate_ << ", name: " << event.name_ << ", statename: " << event.statename_ << ", object: " << object->getIdentifier()->getName() << " (&" << object << ")" << ", subclass: " << this->subclass_->getName() << ", (?): " << event.originator_->isA(this->subclass_) << "." << std::endl;
+
// check if the originator is an instance of the requested class
if (event.originator_->isA(this->subclass_))
{
+ // If the EventState doesn't act as an EventSink.
// actualize the activationcounter
- if (event.activate_)
- ++this->activeEvents_;
- else
+ if(!this->bSink_)
{
- --this->activeEvents_;
+ if (event.activate_)
+ ++this->activeEvents_;
+ else
+ {
+ --this->activeEvents_;
- if (this->activeEvents_ < 0)
- this->activeEvents_ = 0;
+ if (this->activeEvents_ < 0)
+ this->activeEvents_ = 0;
+ }
}
if (this->statefunction_->getParamCount() == 0 && event.activate_)
@@ -77,13 +83,13 @@
// if the eventfunction doesn't have a state, just call it whenever an activation-event comes in
(*this->statefunction_)();
}
- else if ((this->activeEvents_ == 1 && event.activate_) || (this->activeEvents_ == 0 && !event.activate_))
+ else if (this->bSink_ || (!this->bSink_ && ((this->activeEvents_ == 1 && event.activate_) || (this->activeEvents_ == 0 && !event.activate_)) ) )
{
// if the eventfunction needs a state, we just call the function if the state changed from 0 to 1 (state = true) or from 1 to 0 (state = false) [but not if activeEvents_ is > 1]
if (this->statefunction_->getParamCount() == 1)
{
// one argument: just the eventstate
- (*this->statefunction_)(this->activeEvents_);
+ (*this->statefunction_)(event.activate_);
}
else if (this->statefunction_->getParamCount() >= 2)
{
@@ -91,13 +97,13 @@
if (this->subclass_->isExactlyA(ClassIdentifier<BaseObject>::getIdentifier()))
{
// if the subclass is BaseObject, we don't have to cast the pointer
- (*this->statefunction_)(this->activeEvents_, event.originator_);
+ (*this->statefunction_)(event.activate_, event.originator_);
}
else
{
// else cast the pointer to the desired class
void* castedOriginator = event.originator_->getDerivedPointer(this->subclass_->getClassID());
- (*this->statefunction_)(this->activeEvents_, castedOriginator);
+ (*this->statefunction_)(event.activate_, castedOriginator);
}
}
}
Modified: code/trunk/src/libraries/core/Event.h
===================================================================
--- code/trunk/src/libraries/core/Event.h 2010-04-29 10:57:23 UTC (rev 6799)
+++ code/trunk/src/libraries/core/Event.h 2010-04-29 11:16:16 UTC (rev 6800)
@@ -45,6 +45,7 @@
std::string statename_; //!< The name of the state this event affects
BaseObject* originator_; //!< The object which triggered this event
std::string name_; //!< The name of this event
+
};
/**
@@ -65,7 +66,7 @@
class _CoreExport EventState
{
public:
- EventState(Functor* statefunction, Identifier* subclass) : bProcessingEvent_(false), activeEvents_(0), statefunction_(statefunction), subclass_(subclass) {}
+ EventState(Functor* statefunction, Identifier* subclass, bool bSink = false) : bProcessingEvent_(false), activeEvents_(0), statefunction_(statefunction), subclass_(subclass), bSink_(bSink) {}
virtual ~EventState();
void process(const Event& event, BaseObject* object);
@@ -78,6 +79,7 @@
int activeEvents_; //!< The number of events which affect this state and are currently active
Functor* statefunction_; //!< A functor to set the state
Identifier* subclass_; //!< Originators must be an instance of this class (usually BaseObject, but some statefunctions allow a second argument with an originator of a specific class)
+ bool bSink_; //!< Determines whether the EventState acts as an EventSink forwarding any Event (even if the state didn't change) or in the normal manner, only processing Events that change the state.
};
}
Modified: code/trunk/src/libraries/core/EventIncludes.h
===================================================================
--- code/trunk/src/libraries/core/EventIncludes.h 2010-04-29 10:57:23 UTC (rev 6799)
+++ code/trunk/src/libraries/core/EventIncludes.h 2010-04-29 11:16:16 UTC (rev 6800)
@@ -51,9 +51,19 @@
this->addEventState(statename, containername##function); \
} \
XMLPortEventStateIntern(xmlportevent##function, classname, statename, xmlelement, mode)
+
+#define XMLPortEventSink(classname, subclassname, statename, function, xmlelement, mode) \
+ orxonox::EventState* containername##function = this->getEventState(statename); \
+ if (!containername##function) \
+ { \
+ containername##function = new orxonox::EventState(orxonox::createFunctor(&classname::function, this), orxonox::ClassIdentifier<subclassname>::getIdentifier(), true); \
+ this->addEventState(statename, containername##function); \
+ } \
+ XMLPortEventStateIntern(xmlportevent##function, classname, statename, xmlelement, mode)
/**
- @brief Like XMLPortEventState but with additional template arguments to identify the function of the state (if ambiguous).
+ @brief Like XMLPortEventState but creates an event sink instead of an event state.
+ The most important destinction between an EventState and an EventSink is, that an EventState only processes event which change the state of the EventState, where as an EventSink is an EventState that processes any Event that reaches it.
*/
#define XMLPortEventStateTemplate(classname, subclassname, statename, function, xmlelement, mode, ...) \
orxonox::EventState* containername##function = this->getEventState(statename); \
Modified: code/trunk/src/modules/objects/ObjectsPrereqs.h
===================================================================
--- code/trunk/src/modules/objects/ObjectsPrereqs.h 2010-04-29 10:57:23 UTC (rev 6799)
+++ code/trunk/src/modules/objects/ObjectsPrereqs.h 2010-04-29 11:16:16 UTC (rev 6800)
@@ -84,8 +84,11 @@
// triggers
class CheckPoint;
+ class DistanceMultiTrigger;
class DistanceTrigger;
class EventTrigger;
+ class MultiTrigger;
+ class MultiTriggerContainer;
class Trigger;
}
Modified: code/trunk/src/modules/objects/eventsystem/EventListener.cc
===================================================================
--- code/trunk/src/modules/objects/eventsystem/EventListener.cc 2010-04-29 10:57:23 UTC (rev 6799)
+++ code/trunk/src/modules/objects/eventsystem/EventListener.cc 2010-04-29 11:16:16 UTC (rev 6800)
@@ -60,6 +60,8 @@
COUT(2) << "Warning: Detected Event loop in EventListener \"" << this->getName() << '"' << std::endl;
return;
}
+
+ COUT(4) << "EventListener: Processing event: originator: " << event.originator_->getIdentifier()->getName() << " (&" << event.originator_ << ")" << ", activate: " << event.activate_ << ", name: " << event.name_ << std::endl;
this->bActive_ = true;
this->fireEvent(event.activate_, event.originator_, event.name_);
Modified: code/trunk/src/modules/objects/triggers/CMakeLists.txt
===================================================================
--- code/trunk/src/modules/objects/triggers/CMakeLists.txt 2010-04-29 10:57:23 UTC (rev 6799)
+++ code/trunk/src/modules/objects/triggers/CMakeLists.txt 2010-04-29 11:16:16 UTC (rev 6800)
@@ -1,6 +1,9 @@
ADD_SOURCE_FILES(OBJECTS_SRC_FILES
- Trigger.cc
+ CheckPoint.cc
+ DistanceMultiTrigger.cc
DistanceTrigger.cc
EventTrigger.cc
- CheckPoint.cc
+ MultiTrigger.cc
+ MultiTriggerContainer.cc
+ Trigger.cc
)
Added: code/trunk/src/modules/objects/triggers/DistanceMultiTrigger.cc
===================================================================
--- code/trunk/src/modules/objects/triggers/DistanceMultiTrigger.cc (rev 0)
+++ code/trunk/src/modules/objects/triggers/DistanceMultiTrigger.cc 2010-04-29 11:16:16 UTC (rev 6800)
@@ -0,0 +1,109 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * 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 2
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Damian 'Mozork' Frick
+ * Co-authors:
+ * ...
+ *
+*/
+
+#include "DistanceMultiTrigger.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+namespace orxonox
+{
+
+ CreateFactory(DistanceMultiTrigger);
+
+ DistanceMultiTrigger::DistanceMultiTrigger(BaseObject* creator) : MultiTrigger(creator)
+ {
+ RegisterObject(DistanceMultiTrigger);
+
+ this->distance_ = 100.0f;
+ }
+
+ DistanceMultiTrigger::~DistanceMultiTrigger()
+ {
+
+ }
+
+ void DistanceMultiTrigger::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+ {
+ SUPER(DistanceMultiTrigger, XMLPort, xmlelement, mode);
+
+ XMLPortParam(DistanceMultiTrigger, "distance", setDistance, getDistance, xmlelement, mode).defaultValues(100.0f);
+ }
+
+ std::queue<MultiTriggerState*>* DistanceMultiTrigger::letTrigger(void)
+ {
+ ClassTreeMask targetMask = this->getTargetMask();
+
+ std::queue<MultiTriggerState*>* queue = NULL;
+ // Check for new objects that are in range
+ for(ClassTreeMaskObjectIterator it = targetMask.begin(); it != targetMask.end(); ++it)
+ {
+ WorldEntity* entity = orxonox_cast<WorldEntity*>(*it);
+ if (entity == NULL || this->inRange(entity)) //If the object is no WorldEntity or is already in range.
+ continue;
+
+ Vector3 distanceVec = entity->getWorldPosition() - this->getWorldPosition();
+ if (distanceVec.length() < this->distance_)
+ {
+ if(!this->addToRange(entity))
+ continue;
+
+ if(queue == NULL)
+ {
+ queue = new std::queue<MultiTriggerState*>();
+ }
+ MultiTriggerState* state = new MultiTriggerState;
+ state->bTriggered = true;
+ state->originator = entity;
+ queue->push(state);
+ }
+ }
+
+ for(std::set<WorldEntity*>::iterator it = this->range_.begin(); it != this->range_.end(); it++)
+ {
+ Vector3 distanceVec = (*it)->getWorldPosition() - this->getWorldPosition();
+ if (distanceVec.length() >= this->distance_)
+ {
+ if(!this->removeFromRange(*it))
+ continue;
+
+ if(queue == NULL)
+ {
+ queue = new std::queue<MultiTriggerState*>();
+ }
+ MultiTriggerState* state = new MultiTriggerState;
+ state->bTriggered = false;
+ state->originator = *it;
+ queue->push(state);
+ }
+ }
+
+ return queue;
+ }
+
+}
Added: code/trunk/src/modules/objects/triggers/DistanceMultiTrigger.h
===================================================================
--- code/trunk/src/modules/objects/triggers/DistanceMultiTrigger.h (rev 0)
+++ code/trunk/src/modules/objects/triggers/DistanceMultiTrigger.h 2010-04-29 11:16:16 UTC (rev 6800)
@@ -0,0 +1,74 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * 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 2
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Damian 'Mozork' Frick
+ * Co-authors:
+ * ...
+ *
+*/
+
+#ifndef _DistanceMultiTrigger_H__
+#define _DistanceMultiTrigger_H__
+
+#include "objects/ObjectsPrereqs.h"
+
+#include "worldentities/WorldEntity.h"
+#include <set>
+
+#include "MultiTrigger.h"
+
+namespace orxonox
+{
+
+ class _ObjectsExport DistanceMultiTrigger : public MultiTrigger
+ {
+
+ public:
+ DistanceMultiTrigger(BaseObject* creator);
+ ~DistanceMultiTrigger();
+
+ void XMLPort(Element& xmlelement, XMLPort::Mode mode);
+
+ inline void setDistance(float distance)
+ { this->distance_ = distance; }
+ inline float getDistance() const
+ { return this->distance_; }
+
+ protected:
+ virtual std::queue<MultiTriggerState*>* letTrigger(void);
+
+ inline bool inRange(WorldEntity* entity)
+ { return this->range_.find(entity) != this->range_.end(); }
+ bool addToRange(WorldEntity* entity)
+ { std::pair<std::set<WorldEntity*>::iterator, bool> pair = this->range_.insert(entity); return pair.second; }
+ bool removeFromRange(WorldEntity* entity)
+ { return this->range_.erase(entity) > 0; }
+
+ private:
+ float distance_;
+ std::set<WorldEntity*> range_;
+
+ };
+
+}
+
+#endif // _DistanceMultiTrigger_H__
Added: code/trunk/src/modules/objects/triggers/MultiTrigger.cc
===================================================================
--- code/trunk/src/modules/objects/triggers/MultiTrigger.cc (rev 0)
+++ code/trunk/src/modules/objects/triggers/MultiTrigger.cc 2010-04-29 11:16:16 UTC (rev 6800)
@@ -0,0 +1,412 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * 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 2
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Damian 'Mozork' Frick
+ * Co-authors:
+ * Benjamin Knecht
+ *
+*/
+
+#include "MultiTrigger.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "MultiTriggerContainer.h"
+
+namespace orxonox
+{
+
+ /*static*/ const int MultiTrigger::INF_s = -1;
+ /*static*/ const std::string MultiTrigger::or_s = "or";
+ /*static*/ const std::string MultiTrigger::and_s = "and";
+ /*static*/ const std::string MultiTrigger::xor_s = "xor";
+
+ CreateFactory(MultiTrigger);
+
+ //TODO: Clean up.
+ MultiTrigger::MultiTrigger(BaseObject* creator) : StaticEntity(creator)
+ {
+ RegisterObject(MultiTrigger);
+
+ this->mode_ = MultiTriggerMode::EventTriggerAND;
+
+ this->bFirstTick_ = true;
+
+ this->bInvertMode_ = false;
+ this->bSwitch_ = false;
+ this->bStayActive_ = false;
+ this->delay_ = 0.0f;
+ this->remainingActivations_ = INF_s;
+ this->maxNumSimultaniousTriggerers_ = INF_s;
+
+ this->targetMask_.exclude(Class(BaseObject));
+
+ this->setSyncMode(0x0);
+
+ }
+
+ //TODO: Document
+ MultiTrigger::~MultiTrigger()
+ {
+ COUT(4) << "Destorying MultiTrigger &" << this << ". " << this->stateQueue_.size() << " states still in queue. Deleting." << std::endl;
+ while(this->stateQueue_.size() > 0)
+ {
+ MultiTriggerState* state = this->stateQueue_.front().second;
+ this->stateQueue_.pop_front();
+ delete state;
+ }
+ }
+
+ //TODO: Clean up?
+ void MultiTrigger::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+ {
+ SUPER(MultiTrigger, XMLPort, xmlelement, mode);
+
+ XMLPortParam(MultiTrigger, "delay", setDelay, getDelay, xmlelement, mode).defaultValues(0.0f);
+ XMLPortParam(MultiTrigger, "switch", setSwitch, getSwitch, xmlelement, mode).defaultValues(false);
+ XMLPortParam(MultiTrigger, "stayactive", setStayActive, getStayActive, xmlelement, mode).defaultValues(false);
+ XMLPortParam(MultiTrigger, "activations", setActivations, getActivations, xmlelement, mode).defaultValues(INF_s);
+ XMLPortParam(MultiTrigger, "invert", setInvert, getInvert, xmlelement, mode).defaultValues(false);
+ XMLPortParam(MultiTrigger, "simultaniousTriggerers", setSimultaniousTriggerers, getSimultaniousTriggerers, xmlelement, mode).defaultValues(INF_s);
+ XMLPortParamTemplate(MultiTrigger, "mode", setMode, getModeString, xmlelement, mode, const std::string&).defaultValues(MultiTrigger::and_s);
+ XMLPortParamLoadOnly(MultiTrigger, "target", addTargets, xmlelement, mode).defaultValues("ControllableEntity"); //TODO: Remove load only
+
+ XMLPortObject(MultiTrigger, MultiTrigger, "", addTrigger, getTrigger, xmlelement, mode);
+
+ COUT(4) << "MultiTrigger &" << this << " created." << std::endl;
+ }
+
+ //TODO: Document
+ void MultiTrigger::tick(float dt)
+ {
+ if(this->bFirstTick_) // If this is the first tick.
+ {
+ this->bFirstTick_ = false;
+ this->fire(false); //TODO: Does this work? Resp. Is it correct?
+ }
+
+ // Check if the object is active (this is NOT Trigger::isActive()!)
+ if (!this->BaseObject::isActive())
+ return;
+
+ SUPER(MultiTrigger, tick, dt);
+
+ std::queue<MultiTriggerState*>* queue = this->letTrigger();
+ if(queue != NULL)
+ COUT(4) << "MultiTrigger &" << this << ": " << queue->size() << " new states to state queue." << std::endl;
+ while(queue != NULL && queue->size() > 0)
+ {
+ //TODO: Be more efficient, Don't delete a state and create a new one immediately after that. Reuse!
+ MultiTriggerState* state = queue->front();
+ this->addState(state->bTriggered & this->isModeTriggered(state->originator), state->originator);
+ queue->pop();
+ delete state;
+ }
+ delete queue;
+
+ if (this->stateQueue_.size() > 0)
+ {
+ MultiTriggerState* state;
+ float timeRemaining;
+ for(int size = this->stateQueue_.size(); size >= 1; size--)
+ {
+ timeRemaining = this->stateQueue_.front().first;
+ state = this->stateQueue_.front().second;
+ if(timeRemaining <= dt)
+ {
+ if(this->maxNumSimultaniousTriggerers_ == INF_s || this->triggered_.size() < (unsigned int)this->maxNumSimultaniousTriggerers_)
+ {
+ // Add the originator to the objects triggering this MultiTrigger.
+ if(state->bTriggered == true)
+ {
+ this->triggered_.insert(state->originator);
+ }
+ // Remove the originator from the objects triggering this MultiTrigger.
+ else
+ {
+ this->triggered_.erase(state->originator);
+ }
+
+ // Add the originator to the objects activating this MultiTrigger.
+ if(state->bActive == true)
+ {
+ this->active_.insert(state->originator);
+ }
+ // Remove the originator from the objects activating this MultiTrigger.
+ else
+ {
+ this->active_.erase(state->originator);
+ }
+
+ // Fire the event.
+ this->fire(state->bActive, state->originator);
+ }
+
+ // Remove the state from the state queue.
+ this->stateQueue_.pop_front();
+ COUT(4) << "MultiTrigger &" << this << ": State processed, removing from state queue. originator: " << state->originator->getIdentifier()->getName() << " (&" << state->originator << "), active: " << state->bActive << "|" << this->isActive(state->originator) << ", triggered: " << state->bTriggered << "|" << this->isTriggered(state->originator) << "." << std::endl;
+ delete state;
+ size -= 1;
+ }
+ else
+ {
+ this->stateQueue_.push_back(std::pair<float, MultiTriggerState*>(timeRemaining-dt, state));
+ this->stateQueue_.pop_front();
+ COUT(4) << "MultiTrigger &" << this << ": State processed, decreasing time remaining. originator: " << state->originator->getIdentifier()->getName() << " (&" << state->originator << "), active: " << state->bActive << ", triggered: " << state->bTriggered << ", time remaining: " << timeRemaining-dt << "." << std::endl;
+ }
+ }
+ }
+ }
+
+ //TODO: Document
+ bool MultiTrigger::isModeTriggered(BaseObject* triggerer)
+ {
+ if (this->children_.size() != 0)
+ {
+ bool returnVal = false;
+
+ switch (this->mode_)
+ {
+ case MultiTriggerMode::EventTriggerAND:
+ returnVal = checkAnd(triggerer);
+ break;
+ case MultiTriggerMode::EventTriggerOR:
+ returnVal = checkOr(triggerer);
+ break;
+ case MultiTriggerMode::EventTriggerXOR:
+ returnVal = checkXor(triggerer);
+ break;
+ default:
+ returnVal = false;
+ break;
+ }
+
+ return returnVal;
+ }
+
+ return true;
+ }
+
+ //TODO: Document
+ std::queue<MultiTriggerState*>* MultiTrigger::letTrigger(void)
+ {
+ std::queue<MultiTriggerState*>* queue = new std::queue<MultiTriggerState*>();
+ MultiTriggerState* state = new MultiTriggerState;
+ state->bTriggered = true;
+ state->originator = NULL;
+ queue->push(state);
+ return queue;
+ }
+
+ //TODO: Document
+ bool MultiTrigger::isTriggered(BaseObject* triggerer)
+ {
+ std::set<BaseObject*>::iterator it = this->triggered_.find(triggerer);
+ if(it == this->triggered_.end())
+ return false;
+ return true;
+ }
+
+ //TODO: Document
+ bool MultiTrigger::checkAnd(BaseObject* triggerer)
+ {
+ std::set<MultiTrigger*>::iterator it;
+ for(it = this->children_.begin(); it != this->children_.end(); ++it)
+ {
+ if (!(*it)->isActive(triggerer))
+ return false;
+ }
+ return true;
+ }
+
+ //TODO: Document
+ bool MultiTrigger::checkOr(BaseObject* triggerer)
+ {
+ std::set<MultiTrigger*>::iterator it;
+ for(it = this->children_.begin(); it != this->children_.end(); ++it)
+ {
+ if ((*it)->isActive(triggerer))
+ return true;
+ }
+ return false;
+ }
+
+ //TODO: Document
+ bool MultiTrigger::checkXor(BaseObject* triggerer)
+ {
+ std::set<MultiTrigger*>::iterator it;
+ bool test = false;
+ for(it = this->children_.begin(); it != this->children_.end(); ++it)
+ {
+ if (test && (*it)->isActive(triggerer))
+ return false;
+ if ((*it)->isActive(triggerer))
+ test = true;
+ }
+ return test;
+ }
+
+ //TODO: Document
+ bool MultiTrigger::addState(bool bTriggered, BaseObject* originator)
+ {
+ if(!this->isTarget(originator))
+ return false;
+
+ bTriggered ^= this->bInvertMode_;
+ // If the state doesn't change.
+ if(this->isTriggered() && bTriggered)
+ return false;
+
+ bool bActive = !this->isActive(originator);
+
+ // If the MultiTrigger is in switch mode.
+ if(this->bSwitch_ && !bTriggered)
+ return false;
+
+ // If the state changes to active.
+ if(this->remainingActivations_ != INF_s && bActive)
+ {
+ if(this->remainingActivations_ == 0)
+ return false;
+ this->remainingActivations_--;
+ }
+ else
+ {
+ // If the MultiTrigger should stay active and there are no more remaining activations.
+ if(this->bStayActive_ && this->remainingActivations_ == 0)
+ return false;
+ }
+
+ COUT(4) << "MultiTrigger &" << this << ": State added to state queue. originator: " << originator->getIdentifier()->getName() << " (&" << originator << "), active: " << bActive << "|" << this->isActive(originator) << ", triggered: " << bTriggered << "|" << this->isTriggered(originator) << "." << std::endl;
+
+ // Create state.
+ MultiTriggerState* state = new MultiTriggerState;
+ state->bActive = bActive;
+ state->bTriggered = bTriggered;
+ state->originator = originator;
+ this->stateQueue_.push_back(std::pair<float, MultiTriggerState*>(this->delay_, state));
+
+ return true;
+ }
+
+ //TODO: Document
+ void MultiTrigger::setMode(const std::string& modeName)
+ {
+ if (modeName == MultiTrigger::and_s)
+ this->setMode(MultiTriggerMode::EventTriggerAND);
+ else if (modeName == MultiTrigger::or_s)
+ this->setMode(MultiTriggerMode::EventTriggerOR);
+ else if (modeName == MultiTrigger::xor_s)
+ this->setMode(MultiTriggerMode::EventTriggerXOR);
+ }
+
+ //TODO: Document
+ const std::string& MultiTrigger::getModeString() const
+ {
+ if (this->mode_ == MultiTriggerMode::EventTriggerAND)
+ return MultiTrigger::and_s;
+ else if (this->mode_ == MultiTriggerMode::EventTriggerOR)
+ return MultiTrigger::or_s;
+ else if (this->mode_ == MultiTriggerMode::EventTriggerXOR)
+ return MultiTrigger::xor_s;
+ else
+ return MultiTrigger::and_s;
+ }
+
+ //TODO: Document
+ bool MultiTrigger::isActive(BaseObject* triggerer)
+ {
+ std::set<BaseObject*>::iterator it = this->active_.find(triggerer);
+ if(it == this->active_.end())
+ return false;
+ return true;
+ }
+
+ //TODO: Document
+ void MultiTrigger::addTrigger(MultiTrigger* trigger)
+ {
+ if (this != trigger && trigger != NULL)
+ this->children_.insert(trigger);
+ }
+
+ //TODO: Document
+ const MultiTrigger* MultiTrigger::getTrigger(unsigned int index) const
+ {
+ if (this->children_.size() <= index)
+ return NULL;
+
+ std::set<MultiTrigger*>::const_iterator it;
+ it = this->children_.begin();
+
+ for (unsigned int i = 0; i != index; ++i)
+ ++it;
+
+ return (*it);
+ }
+
+ //TODO: Document
+ void MultiTrigger::fire(bool status, BaseObject* originator)
+ {
+ if(originator == NULL)
+ {
+ this->fireEvent(status);
+ return;
+ }
+ MultiTriggerContainer* container = new MultiTriggerContainer(this, this, originator);
+ this->fireEvent(status, container);
+ COUT(4) << "MultiTrigger &" << this << ": Fired event. originator: " << originator->getIdentifier()->getName() << " (&" << originator << "), status: " << status << "." << std::endl;
+ delete container;
+ }
+
+ //TODO: Document
+ void MultiTrigger::addTargets(const std::string& targets)
+ {
+ Identifier* target = ClassByString(targets);
+
+ if (target == NULL)
+ {
+ COUT(1) << "Error: \"" << targets << "\" is not a valid class name to include in ClassTreeMask (in " << this->getName() << ", class " << this->getIdentifier()->getName() << ')' << std::endl;
+ return;
+ }
+
+ this->targetMask_.include(target);
+
+ // trigger shouldn't react on itself or other triggers
+ this->targetMask_.exclude(Class(MultiTrigger), true);
+
+ // we only want WorldEntities
+ ClassTreeMask WEMask;
+ WEMask.include(Class(WorldEntity));
+ this->targetMask_ *= WEMask;
+
+ this->notifyMaskUpdate();
+ }
+
+ //TODO: Document
+ void MultiTrigger::removeTargets(const std::string& targets)
+ {
+ Identifier* target = ClassByString(targets);
+ this->targetMask_.exclude(target);
+ }
+
+}
Added: code/trunk/src/modules/objects/triggers/MultiTrigger.h
===================================================================
--- code/trunk/src/modules/objects/triggers/MultiTrigger.h (rev 0)
+++ code/trunk/src/modules/objects/triggers/MultiTrigger.h 2010-04-29 11:16:16 UTC (rev 6800)
@@ -0,0 +1,164 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * 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 2
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * Damian 'Mozork' Frick
+ * Co-authors:
+ * Benjamin Knecht
+ *
+*/
+
+#ifndef _MultiTrigger_H__
+#define _MultiTrigger_H__
+
+#include "objects/ObjectsPrereqs.h"
+
+#include "core/BaseObject.h"
+#include "core/ClassTreeMask.h"
+
+#include <set>
+#include <deque>
+
+#include "tools/interfaces/Tickable.h"
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{
+
+ namespace MultiTriggerMode
+ {
+ enum Value
+ {
+ EventTriggerAND,
+ EventTriggerOR,
+ EventTriggerXOR,
+ };
+ }
+
+ struct MultiTriggerState
+ {
+ BaseObject* originator;
+ bool bActive;
+ bool bTriggered;
+ };
+
+ class _ObjectsExport MultiTrigger : public StaticEntity, public Tickable
+ {
+ public:
+ MultiTrigger(BaseObject* creator);
+ ~MultiTrigger();
+
+ virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
+ virtual void tick(float dt);
+
+ bool isActive(BaseObject* triggerer = NULL);
+ void addTrigger(MultiTrigger* trigger);
+ const MultiTrigger* getTrigger(unsigned int index) const;
+
+ void addTargets(const std::string& targets);
+ void removeTargets(const std::string& targets);
+ inline bool isTarget(BaseObject* target)
+ { return targetMask_.isIncluded(target->getIdentifier()); }
+
+ void setMode(const std::string& modeName);
+ const std::string& getModeString(void) const;
+ inline void setMode(MultiTriggerMode::Value mode)
+ { this->mode_ = mode; }
+ inline MultiTriggerMode::Value getMode() const
+ { return mode_; }
+
+ inline void setInvert(bool bInvert)
+ { this->bInvertMode_ = bInvert; }
+ inline bool getInvert() const
+ { return this->bInvertMode_; }
+
+ inline void setSwitch(bool bSwitch)
+ { this->bSwitch_ = bSwitch; }
+ inline bool getSwitch() const
+ { return this->bSwitch_; }
+
+ inline void setStayActive(bool bStayActive)
+ { this->bStayActive_ = bStayActive; }
+ inline bool getStayActive() const
+ { return this->bStayActive_; }
+
+ inline void setActivations(int activations)
+ { this->remainingActivations_ = activations; }
+ inline int getActivations() const
+ { return this->remainingActivations_; }
+
+ inline void setSimultaniousTriggerers(int triggerers)
+ { this->maxNumSimultaniousTriggerers_ = triggerers; }
+ inline int getSimultaniousTriggerers(void)
+ { return this->maxNumSimultaniousTriggerers_; }
+
+ inline void setDelay(float delay)
+ { this->delay_= delay; }
+ inline float getDelay() const
+ { return this->delay_; }
+
+ protected:
+ void fire(bool status, BaseObject* originator = NULL);
+
+ bool isModeTriggered(BaseObject* triggerer = NULL);
+ bool isTriggered(BaseObject* triggerer = NULL);
+
+ virtual std::queue<MultiTriggerState*>* letTrigger(void);
+
+ inline ClassTreeMask& getTargetMask(void)
+ { return this->targetMask_; }
+ virtual void notifyMaskUpdate(void) {}
+
+ private:
+ static const int INF_s;
+ static const std::string or_s;
+ static const std::string and_s;
+ static const std::string xor_s;
+
+ bool addState(bool bTriggered, BaseObject* originator = NULL);
+
+ bool checkAnd(BaseObject* triggerer);
+ bool checkOr(BaseObject* triggerer);
+ bool checkXor(BaseObject* triggerer);
+
+ bool bFirstTick_;
+
+ MultiTriggerMode::Value mode_;
+ bool bInvertMode_;
+ bool bSwitch_;
+ bool bStayActive_;
+ float delay_;
+ int remainingActivations_;
+ int maxNumSimultaniousTriggerers_;
+
+ std::set<BaseObject*> active_;
+ std::set<BaseObject*> triggered_;
+
+ std::set<MultiTrigger*> children_;
+ std::deque<std::pair<float, MultiTriggerState*> > stateQueue_;
+
+ ClassTreeMask targetMask_;
+
+ };
+
+}
+
+#endif // _MultiTrigger_H__
Added: code/trunk/src/modules/objects/triggers/MultiTriggerContainer.cc
===================================================================
--- code/trunk/src/modules/objects/triggers/MultiTriggerContainer.cc (rev 0)
+++ code/trunk/src/modules/objects/triggers/MultiTriggerContainer.cc 2010-04-29 11:16:16 UTC (rev 6800)
@@ -0,0 +1,56 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * 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 2
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * ...
+ * Co-authors:
+ * ...
+ *
+*/
+
+#include "MultiTriggerContainer.h"
+
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+
+ CreateFactory(MultiTriggerContainer);
+
+ MultiTriggerContainer::MultiTriggerContainer(BaseObject* creator) : BaseObject(creator), originator_(NULL), data_(NULL)
+ {
+ RegisterObject(MultiTriggerContainer);
+
+ }
+
+ MultiTriggerContainer::MultiTriggerContainer(BaseObject* creator, MultiTrigger* originator, BaseObject* data) : BaseObject(creator), originator_(originator), data_(data)
+ {
+ RegisterObject(MultiTriggerContainer);
+
+ }
+
+ MultiTriggerContainer::~MultiTriggerContainer()
+ {
+
+ }
+
+
+}
Added: code/trunk/src/modules/objects/triggers/MultiTriggerContainer.h
===================================================================
--- code/trunk/src/modules/objects/triggers/MultiTriggerContainer.h (rev 0)
+++ code/trunk/src/modules/objects/triggers/MultiTriggerContainer.h 2010-04-29 11:16:16 UTC (rev 6800)
@@ -0,0 +1,59 @@
+/*
+ * ORXONOX - the hottest 3D action shooter ever to exist
+ * > www.orxonox.net <
+ *
+ *
+ * License notice:
+ *
+ * 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 2
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Author:
+ * ...
+ * Co-authors:
+ * ...
+ *
+*/
+
+#ifndef _MultiTriggerContainer_H__
+#define _MultiTriggerContainer_H__
+
+#include "objects/ObjectsPrereqs.h"
+
+#include "core/BaseObject.h"
+
+namespace orxonox
+{
+
+ class _ObjectsExport MultiTriggerContainer : public BaseObject
+ {
+ public:
+
+ MultiTriggerContainer(BaseObject* creator);
+ MultiTriggerContainer(BaseObject* creator, MultiTrigger* originator, BaseObject* data);
+ ~MultiTriggerContainer();
+
+ inline MultiTrigger* getOriginator(void)
+ { return this->originator_; }
+ inline BaseObject* getData(void)
+ { return this->data_; }
+
+ private:
+ MultiTrigger* originator_;
+ BaseObject* data_;
+ };
+
+}
+
+#endif // _MultiTriggerContainer_H__
Modified: code/trunk/src/modules/questsystem/CMakeLists.txt
===================================================================
--- code/trunk/src/modules/questsystem/CMakeLists.txt 2010-04-29 10:57:23 UTC (rev 6799)
+++ code/trunk/src/modules/questsystem/CMakeLists.txt 2010-04-29 11:16:16 UTC (rev 6800)
@@ -33,6 +33,7 @@
QuestsystemPrecompiledHeaders.h
LINK_LIBRARIES
orxonox
+ objects
overlays
SOURCE_FILES ${QUESTSYSTEM_SRC_FILES}
)
Modified: code/trunk/src/modules/questsystem/QuestEffectBeacon.cc
===================================================================
--- code/trunk/src/modules/questsystem/QuestEffectBeacon.cc 2010-04-29 10:57:23 UTC (rev 6799)
+++ code/trunk/src/modules/questsystem/QuestEffectBeacon.cc 2010-04-29 11:16:16 UTC (rev 6800)
@@ -38,6 +38,7 @@
#include "core/EventIncludes.h"
#include "worldentities/pawns/Pawn.h"
#include "interfaces/PlayerTrigger.h"
+#include "objects/triggers/MultiTriggerContainer.h"
#include "QuestEffect.h"
namespace orxonox
@@ -74,7 +75,7 @@
XMLPortParam(QuestEffectBeacon, "times", setTimes, getTimes, xmlelement, mode);
XMLPortObject(QuestEffectBeacon, QuestEffect, "effects", addEffect, getEffect, xmlelement, mode);
- XMLPortEventState(QuestEffectBeacon, PlayerTrigger, "execute", execute, xmlelement, mode);
+ XMLPortEventState(QuestEffectBeacon, BaseObject, "execute", execute, xmlelement, mode); //TODO: Change BaseObject to MultiTrigger as soon as MultiTrigger is the base of all triggers.
COUT(3) << "New QuestEffectBeacon created." << std::endl;
}
@@ -83,7 +84,7 @@
{
SUPER(QuestEffectBeacon, XMLEventPort, xmlelement, mode);
- XMLPortEventState(QuestEffectBeacon, PlayerTrigger, "execute", execute, xmlelement, mode);
+ XMLPortEventSink(QuestEffectBeacon, BaseObject, "execute", execute, xmlelement, mode);
}
/**
@@ -91,12 +92,15 @@
Executes the QuestEffectBeacon.
This means extracting the Pawn from the PlayerTrigger, provided by the Event causing the execution, and the extracting the PlayerInfo from the received Pawn and invoking the QuestEffectbeacon's QuestEffects on the received PlayerInfo.
@param trigger
- Apointer to the PlayerTrigger that threw the Event.
+ A pointer to the PlayerTrigger that threw the Event.
@return
Returns true if successfully executed, false if not.
*/
- bool QuestEffectBeacon::execute(bool b, PlayerTrigger* trigger)
+ bool QuestEffectBeacon::execute(bool b, BaseObject* trigger)
{
+ //TODO: Remove debug output.
+ COUT(1) << "Debug: Calling execute on QuestEffectBeacon." << std::endl;
+
if(!b)
{
return false;
@@ -107,14 +111,29 @@
return false;
}
- if(!trigger->isForPlayer()) //!< The PlayerTrigger is not exclusively for Pawns which means we cannot extract one.
+ PlayerTrigger* pTrigger = orxonox_cast<PlayerTrigger*>(trigger);
+ MultiTriggerContainer* mTrigger = orxonox_cast<MultiTriggerContainer*>(trigger);
+ Pawn* pawn = NULL;
+
+ //! If the trigger is neither a Playertrigger nor a MultiTrigger (i.e. a MultitriggerContainer) we can do anything with it.
+ if(pTrigger == NULL && mTrigger == NULL)
+ return false;
+
+ // If the trigger is a PlayerTrigger.
+ if(pTrigger != NULL)
{
- return false;
+ if(!pTrigger->isForPlayer()) //!< The PlayerTrigger is not exclusively for Pawns which means we cannot extract one.
+ return false;
+ else
+ pawn = pTrigger->getTriggeringPlayer();
}
+
+ // If the trigger is a MultiTrigger (i.e. a MultiTriggerContainer)
+ if(mTrigger != NULL)
+ {
+ pawn = orxonox_cast<Pawn*>(mTrigger->getData());
+ }
- //! Extracting the Pawn from the PlayerTrigger.
- Pawn* pawn = trigger->getTriggeringPlayer();
-
if(pawn == NULL)
{
COUT(2) << "The QuestEffectBeacon was triggered by an entity other than a Pawn." << std::endl;
Modified: code/trunk/src/modules/questsystem/QuestEffectBeacon.h
===================================================================
--- code/trunk/src/modules/questsystem/QuestEffectBeacon.h 2010-04-29 10:57:23 UTC (rev 6799)
+++ code/trunk/src/modules/questsystem/QuestEffectBeacon.h 2010-04-29 11:16:16 UTC (rev 6800)
@@ -87,7 +87,7 @@
virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode); //!< Method for creating a QuestEffectBeacon object through XML.
virtual void XMLEventPort(Element& xmlelement, XMLPort::Mode mode);
- bool execute(bool b, PlayerTrigger* trigger); //!< Executes the QuestEffects of the QuestEffectBeacon.
+ bool execute(bool b, BaseObject* trigger); //!< Executes the QuestEffects of the QuestEffectBeacon.
/**
@brief Tests whether the QuestEffectBeacon is active.
More information about the Orxonox-commit
mailing list