#include "PortalEndPoint.h" #include "core/XMLPort.h" #include "objects/triggers/MultiTriggerContainer.h" #include "portals/PortalLink.h" #include "worldentities/MobileEntity.h" namespace orxonox { CreateFactory(PortalEndPoint); /*static*/ const std::string PortalEndPoint::EVENTFUNCTIONNAME = "execute"; std::map PortalEndPoint::idMap_s; PortalEndPoint::PortalEndPoint(BaseObject* creator) : StaticEntity(creator), id_(0), trigger_(new DistanceMultiTrigger(this)), reenterDelay_(0) { RegisterObject(PortalEndPoint); this->trigger_->setName("portal"); this->attach(trigger_); } PortalEndPoint::~PortalEndPoint() { } void PortalEndPoint::XMLPort(Element& xmlelement, XMLPort::Mode mode) { SUPER(PortalEndPoint, XMLPort, xmlelement, mode); XMLPortParam(PortalEndPoint, "id", setID, getID, xmlelement, mode); XMLPortParam(PortalEndPoint, "design", setTemplate, getTemplate, xmlelement, mode); XMLPortParam(PortalEndPoint, "reenterDelay", setReenterDelay, getReenterDelay, xmlelement, mode); XMLPortParamExtern(PortalEndPoint, DistanceMultiTrigger, this->trigger_, "distance", setDistance, getDistance, xmlelement, mode); XMLPortParamLoadOnly(PortalEndPoint, "target", setTarget, xmlelement, mode).defaultValues("Pawn"); // Add the DistanceMultiTrigger as event source. this->addEventSource(this->trigger_, EVENTFUNCTIONNAME); if(mode == XMLPort::LoadObject) { PortalEndPoint::idMap_s[this->id_] = this; } } void PortalEndPoint::XMLEventPort(Element& xmlelement, XMLPort::Mode mode) { SUPER(PortalEndPoint, XMLEventPort, xmlelement, mode); XMLPortEventSink(PortalEndPoint, BaseObject, EVENTFUNCTIONNAME, execute, xmlelement, mode); } bool PortalEndPoint::execute(bool bTriggered, BaseObject* trigger) { if(!this->isActive()) return true; MultiTriggerContainer * cont = orxonox_cast(trigger); if(cont == 0) return true; DistanceMultiTrigger * originatingTrigger = orxonox_cast(cont->getOriginator()); if(originatingTrigger == 0) { // COUT(1) << "originator no DistanceMultiTrigger\n" << std::endl; return true; } MobileEntity * entity = orxonox_cast(cont->getData()); if(entity == 0) return true; if(bTriggered) { if(this->letsEnter(entity)) // only enter the portal if not just (this very moment) jumped out of it, or if the reenterDelay expired { PortalLink::use(entity, this); } } else { this->recentlyJumpedOut_.erase(entity); } return true; } bool PortalEndPoint::letsEnter(MobileEntity* entity) { // not allowed to enter if reenterDelay hasn't expired yet std::map::const_iterator time = this->jumpOutTimes_.find(entity); if(time != this->jumpOutTimes_.end() && std::difftime(std::time(0),time->second) < this->reenterDelay_) return false; // not allowed to enter if jumped out of this portal and not left its activation radius yet std::set::const_iterator recent = this->recentlyJumpedOut_.find(entity); if(recent != this->recentlyJumpedOut_.end()) return false; return true; } void PortalEndPoint::jumpOut(MobileEntity* entity) { this->jumpOutTimes_[entity] = std::time(0); this->recentlyJumpedOut_.insert(entity); entity->setPosition(this->getWorldPosition()); entity->rotate(this->getWorldOrientation()); entity->setVelocity(this->getWorldOrientation() * entity->getVelocity()); entity->setVelocity(entity->getVelocity() * 1.5); } }