Resolve "Toggle Free Look with Hotkey"
[ryzomcore.git] / ryzom / server / src / ai_service / states.cpp
blob94fa79b17c657c8ca551c4c1df406737d1bab73f
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "stdpch.h"
21 #include "states.h"
22 #include "event_reaction_container.h"
23 #include "state_profil.h"
24 #include "world_container.h"
25 #include "ai.h"
26 #include "ai_instance.h"
27 #include "state_instance.h"
29 extern NLMISC::CVariable<bool> LogAcceptablePos;
31 using namespace AITYPES;
33 std::string CAIState::getIndexString () const
35 return getOwner()->getIndexString()+NLMISC::toString(":%u", getChildIndex());
38 void CAIState::updateDependencies (const CAIAliasDescriptionNode &aliasTree, CAliasTreeOwner *aliasTreeOwner)
40 switch(aliasTree.getType())
42 case AITypeGrp:
44 CGroup *const group=NLMISC::safe_cast<CGroup*>(aliasTreeOwner);
45 nlassert(group);
46 group->getPersistentStateInstance()->setStartState(getOwner()->states().getChildByAlias(getAlias()));
48 break;
50 case AITypeEvent:
52 CAIEventReaction*const eventPtr=NLMISC::safe_cast<CAIEventReaction*>(getOwner()->eventReactions().getAliasChildByAlias(aliasTree.getAlias()));
53 nlassert(eventPtr);
54 if (!eventPtr)
55 break;
56 eventPtr->setState (getAlias());
57 eventPtr->setType (CAIEventReaction::FixedState);
59 break;
64 IAliasCont* CAIState::getAliasCont(TAIType type)
66 switch(type)
68 case AITypeNpcStateProfile:
69 return &_Profiles;
70 case AITypeNpcStateChat:
71 return &_Chats;
72 default:
73 return NULL;
78 CAliasTreeOwner* CAIState::createChild(IAliasCont *cont, CAIAliasDescriptionNode *aliasTree)
80 CAliasTreeOwner* child = NULL;
82 switch(aliasTree->getType())
84 case AITypeNpcStateProfile:
85 child = new CAIStateProfile(this, aliasTree);
86 break;
87 case AITypeNpcStateChat:
88 child = new CAIStateChat(this, aliasTree);
89 break;
92 if (child)
93 cont->addAliasChild(child);
94 return child;
98 CAIState *CStateInstance::getCAIState ()
100 return _state;
103 bool CShape::setPath(TVerticalPos verticalPos, const std::vector <CAIVector> &points)
105 bool ret = true;
107 _VerticalPos = verticalPos;
109 _Geometry.clear ();
110 _Geometry.reserve(points.size());
112 for (uint32 ind=0;ind<points.size();ind++)
114 RYAI_MAP_CRUNCH::CWorldPosition newpos;
115 CWorldContainer::calcNearestWPosFromPosAnRadius(_VerticalPos, newpos, points[ind], 0, 1, CWorldContainer::CPosValidatorDefault());
117 if ( !newpos.isValid()
118 && !_AcceptInvalidPos )
120 CWorldContainer::calcNearestWPosFromPosAnRadius(_VerticalPos, newpos, points[ind], 6, 100, CWorldContainer::CPosValidatorDefault());
121 //#ifdef NL_DEBUG
122 if (newpos.isValid())
124 if (LogAcceptablePos)
125 nlinfo("StatePositionnal 'ss'(uu): Path pos Error at position %s, an acceptable position could be %s (in 'ss')",
126 /*getAliasFullName().c_str(), getAlias(),*/
127 points[ind].toString().c_str(), newpos.toString().c_str()/*, getAliasFullName().c_str()*/);
129 else
131 nlwarning("StatePositionel 'ss'(uu): Path pos Error at position %s, no acceptable position found around (in 'ss')",
132 /*getAliasFullName().c_str(), getAlias(),*/
133 points[ind].toString().c_str()/*, getAliasFullName().c_str()*/);
134 ret = false;
136 //#endif
138 _Geometry.push_back(newpos);
140 _GeometryType=PATH;
142 return ret;
145 bool CShape::contains (const CAIVector &pos) const
147 // Point or line can't contains !
148 if (_Geometry.size() < 3)
149 return false;
151 // Check with the bounding rectangle of the zone
152 if ( (pos.x() < _VMin.x())
153 || (pos.y() < _VMin.y())
154 || (pos.x() > _VMax.x())
155 || (pos.y() > _VMax.y()) )
156 return false;
158 uint32 nNbIntersection = 0;
159 for (uint32 i = 0; i<_Geometry.size(); ++i)
161 const CAIVector p1 = _Geometry[i];
162 const CAIVector p2 = _Geometry[(i+1)%_Geometry.size()];
164 if ( (p1.y() <= pos.y())
165 && (p2.y() <= pos.y()) )
166 continue;
167 if ( (p1.y() > pos.y())
168 && (p2.y() > pos.y()) )
169 continue;
171 const double deltaX=p2.x()-p1.x();
172 const double deltaY=p2.y()-p1.y();
173 const double deltaYPos=pos.y()-p1.y();
175 const double xinter = (double)p1.x() + deltaX*(deltaYPos/deltaY);
176 if (xinter > pos.x())
177 ++nNbIntersection;
179 return ((nNbIntersection&1)==1); // odd intersections so the vertex is inside
182 bool CShape::setPatat(TVerticalPos verticalPos, const std::vector <CAIVector> &points)
184 bool ret = true;
185 _VerticalPos = verticalPos;
186 // _Geometry=points;
187 _GeometryType=PATAT;
188 _Geometry.clear();
189 _Geometry.reserve(points.size());
191 // create a list of valid position inside the patat
193 CAIVector vMin, vMax;
195 // Point or line can't contains !
196 if (points.size() < 3)
197 return true;
199 // Get the bounding rectangle of the zone
200 vMax = vMin = points[0];
201 for (uint i = 0; i < points.size(); ++i)
203 if (vMin.x() > points[i].x())
204 vMin.setX(points[i].x());
205 if (vMin.y() > points[i].y())
206 vMin.setY(points[i].y());
208 if (vMax.x() < points[i].x())
209 vMax.setX(points[i].x());
210 if (vMax.y() < points[i].y())
211 vMax.setY(points[i].y());
214 _VMin = vMin;
215 _VMax = vMax;
217 // fill the geometry vector with invalid word pos
218 for (uint i=0; i<points.size(); ++i)
220 _Geometry.push_back(TPosition(sint(points[i].x().asDouble()), sint(points[i].y().asDouble())));
222 // find a valid position for every geometric
224 RYAI_MAP_CRUNCH::CWorldPosition worldPos;
225 if (!CWorldContainer::calcNearestWPosFromPosAnRadius (_VerticalPos, worldPos, points[0], float((vMax-vMin).quickNorm()), 1000, CWorldContainer::CPosValidatorDefault()))
227 // nlwarning("Can't find valid pos for state position '%s'(%u)", getAliasFullName().c_str(), getAlias());
228 if (!_AcceptInvalidPos)
230 nlwarning("Can't find valid pos for state at position %s", points[0].toString().c_str());
231 ret = false;
234 else
236 buildRandomPos(worldPos, float((vMax-vMin).quickNorm()));
239 // build the valid pos for each patat point
240 _Geometry.clear();
241 _Geometry.reserve(points.size());
242 for (uint32 ind=0;ind<points.size();ind++)
244 RYAI_MAP_CRUNCH::CWorldPosition newpos;
245 CWorldContainer::calcNearestWPosFromPosAnRadius(_VerticalPos, newpos, points[ind], 0, 1, CWorldContainer::CPosValidatorDefault());
246 if ( !newpos.isValid()
247 && !_AcceptInvalidPos)
250 CWorldContainer::calcNearestWPosFromPosAnRadius(_VerticalPos, newpos, points[ind], 6, 100, CWorldContainer::CPosValidatorDefault());
251 //#ifdef NL_DEBUG
252 if (newpos.isValid())
254 if (LogAcceptablePos)
255 nlinfo("Path pos Error at position %s, an acceptable position could be %s",
256 points[ind].toString().c_str(),
257 newpos.toString().c_str());
259 // nlinfo("StatePrositionnal '%s'(%u): Path pos Error at position %s, an acceptable position could be %s (in '%s')",
260 // getAliasFullName().c_str(),
261 // getAlias(),
262 // points[ind].toString().c_str(),
263 // newpos.toString().c_str(),
264 // getAliasFullName().c_str());
266 else
268 nlwarning("Path pos Error at position %s, no acceptable position found around",
269 points[ind].toString().c_str());
270 ret = false;
272 //#endif
274 _Geometry.push_back(newpos);
277 return ret;
280 bool CShape::calcRandomPos(CAIPos &pos) const
282 CAIVector v(
283 (double(_VMin.x()) + CAIS::rand32(_VMax.x() - _VMin.x()))/CAICoord::UNITS_PER_METER,
284 (double(_VMin.y()) + CAIS::rand32(_VMax.y() - _VMin.y()))/CAICoord::UNITS_PER_METER);
285 if ((v.x() < _VMin.x()) || (v.y() < _VMin.y()) || (v.x() > _VMax.x()) || (v.y() > _VMax.y()))
286 return false;
288 uint32 nNbIntersection = 0;
289 for (uint k = 0; k < _Geometry.size(); ++k)
291 const CAIVector &p1 = _Geometry[k];
292 const CAIVector &p2 = _Geometry[(k+1)%_Geometry.size()];
294 if (((p1.y()-v.y()) < 0.0)&&((p2.y()-v.y()) < 0.0))
295 continue;
296 if (((p1.y()-v.y()) > 0.0)&&((p2.y()-v.y()) > 0.0))
297 continue;
298 if ((p2.y()-p1.y()) == 0)
299 continue;
301 const float delta = (v.y()-p1.y()).asInt()/float(p2.y()-p1.y());
302 const float xinter = (float)(p1.x().asInt() + (p2.x()-p1.x()).asInt() * delta);
303 if (xinter > v.x())
304 ++nNbIntersection;
306 if ((nNbIntersection&1) == 1) // odd intersections so the vertex is inside
308 pos = CAIPos(v, 0, 0);
309 return true;
312 return false;