// Ryzom - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero 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 Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #include "stdpch.h" #include "states.h" #include "event_reaction_container.h" #include "state_profil.h" #include "world_container.h" #include "ai.h" #include "ai_instance.h" #include "state_instance.h" extern NLMISC::CVariable LogAcceptablePos; using namespace AITYPES; std::string CAIState::getIndexString () const { return getOwner()->getIndexString()+NLMISC::toString(":%u", getChildIndex()); } void CAIState::updateDependencies (const CAIAliasDescriptionNode &aliasTree, CAliasTreeOwner *aliasTreeOwner) { switch(aliasTree.getType()) { case AITypeGrp: { CGroup *const group=NLMISC::safe_cast(aliasTreeOwner); nlassert(group); group->getPersistentStateInstance()->setStartState(getOwner()->states().getChildByAlias(getAlias())); } break; case AITypeEvent: { CAIEventReaction*const eventPtr=NLMISC::safe_cast(getOwner()->eventReactions().getAliasChildByAlias(aliasTree.getAlias())); nlassert(eventPtr); if (!eventPtr) break; eventPtr->setState (getAlias()); eventPtr->setType (CAIEventReaction::FixedState); } break; } } IAliasCont* CAIState::getAliasCont(TAIType type) { switch(type) { case AITypeNpcStateProfile: return &_Profiles; case AITypeNpcStateChat: return &_Chats; default: return NULL; } } CAliasTreeOwner* CAIState::createChild(IAliasCont *cont, CAIAliasDescriptionNode *aliasTree) { CAliasTreeOwner* child = NULL; switch(aliasTree->getType()) { case AITypeNpcStateProfile: child = new CAIStateProfile(this, aliasTree); break; case AITypeNpcStateChat: child = new CAIStateChat(this, aliasTree); break; } if (child) cont->addAliasChild(child); return child; } CAIState *CStateInstance::getCAIState () { return _state; } bool CShape::setPath(TVerticalPos verticalPos, const std::vector &points) { bool ret = true; _VerticalPos = verticalPos; _Geometry.clear (); _Geometry.reserve(points.size()); for (uint32 ind=0;ind _VMax.x()) || (pos.y() > _VMax.y()) ) return false; uint32 nNbIntersection = 0; for (uint32 i = 0; i<_Geometry.size(); ++i) { const CAIVector p1 = _Geometry[i]; const CAIVector p2 = _Geometry[(i+1)%_Geometry.size()]; if ( (p1.y() <= pos.y()) && (p2.y() <= pos.y()) ) continue; if ( (p1.y() > pos.y()) && (p2.y() > pos.y()) ) continue; const double deltaX=p2.x()-p1.x(); const double deltaY=p2.y()-p1.y(); const double deltaYPos=pos.y()-p1.y(); const double xinter = (double)p1.x() + deltaX*(deltaYPos/deltaY); if (xinter > pos.x()) ++nNbIntersection; } return ((nNbIntersection&1)==1); // odd intersections so the vertex is inside } bool CShape::setPatat(TVerticalPos verticalPos, const std::vector &points) { bool ret = true; _VerticalPos = verticalPos; // _Geometry=points; _GeometryType=PATAT; _Geometry.clear(); _Geometry.reserve(points.size()); // create a list of valid position inside the patat CAIVector vMin, vMax; // Point or line can't contains ! if (points.size() < 3) return true; // Get the bounding rectangle of the zone vMax = vMin = points[0]; for (uint i = 0; i < points.size(); ++i) { if (vMin.x() > points[i].x()) vMin.setX(points[i].x()); if (vMin.y() > points[i].y()) vMin.setY(points[i].y()); if (vMax.x() < points[i].x()) vMax.setX(points[i].x()); if (vMax.y() < points[i].y()) vMax.setY(points[i].y()); } _VMin = vMin; _VMax = vMax; // fill the geometry vector with invalid word pos for (uint i=0; i _VMax.x()) || (v.y() > _VMax.y())) return false; uint32 nNbIntersection = 0; for (uint k = 0; k < _Geometry.size(); ++k) { const CAIVector &p1 = _Geometry[k]; const CAIVector &p2 = _Geometry[(k+1)%_Geometry.size()]; if (((p1.y()-v.y()) < 0.0)&&((p2.y()-v.y()) < 0.0)) continue; if (((p1.y()-v.y()) > 0.0)&&((p2.y()-v.y()) > 0.0)) continue; if ((p2.y()-p1.y()) == 0) continue; const float delta = (v.y()-p1.y()).asInt()/float(p2.y()-p1.y()); const float xinter = (float)(p1.x().asInt() + (p2.x()-p1.x()).asInt() * delta); if (xinter > v.x()) ++nNbIntersection; } if ((nNbIntersection&1) == 1) // odd intersections so the vertex is inside { pos = CAIPos(v, 0, 0); return true; }; return false; }