Change Encyclo button name and macros icon
[ryzomcore.git] / nel / src / logic / logic_state.cpp
blob9e943c7ce5749430a1fd45acbf86353b4867103d
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
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/>.
18 #include "stdlogic.h"
19 #include "nel/logic/logic_state.h"
20 #include "nel/logic/logic_state_machine.h"
23 using namespace std;
24 using namespace NLMISC;
25 using namespace NLNET;
27 namespace NLLOGIC
30 //---------------------------------------------------
31 // CLogicState
33 //---------------------------------------------------
34 CLogicState::CLogicState()
36 _StateName = "no_state";
37 _LogicStateMachine = 0;
39 } // CLogicState //
42 //---------------------------------------------------
43 // setLogicStateMachine
45 //---------------------------------------------------
46 void CLogicState::setLogicStateMachine( CLogicStateMachine * logicStateMachine )
48 if( logicStateMachine == 0 )
50 nlwarning("(LOGIC)<CLogicCondition::setLogicStateMachine> The state machine is null");
52 else
54 // init the logic state machine for this state
55 _LogicStateMachine = logicStateMachine;
57 // init the logic state machine in each event
58 vector<CLogicEvent>::iterator itEvent;
59 for( itEvent = _Events.begin(); itEvent != _Events.end(); ++itEvent )
61 (*itEvent).setLogicStateMachine( logicStateMachine );
65 } // setLogicStateMachine //
69 //---------------------------------------------------
70 // addEvent :
72 //---------------------------------------------------
73 void CLogicState::addEvent( CLogicEvent event )
75 event.setLogicStateMachine( _LogicStateMachine );
76 _Events.push_back( event );
78 } // addEvent //
82 //---------------------------------------------------
83 // addSIdMap :
85 // looks in all the messages of the state if the
86 // destination names can be associated with a sid.
87 //---------------------------------------------------
88 void CLogicState::addSIdMap( const TSIdMap& sIdMap )
90 vector<CLogicEventMessage>::iterator itMsg;
92 /// entry messages
93 for( itMsg = _EntryMessages.begin(); itMsg != _EntryMessages.end(); ++itMsg )
95 TSIdMap::const_iterator itId = sIdMap.find( (*itMsg).Destination );
96 // if message destination exists in the map we associate the sid with the message
97 if( itId != sIdMap.end() )
99 (*itMsg).DestinationId = (*itId).second;
102 /// send the entry messages that can be sent
103 trySendEntryMessages();
106 // event messages
107 vector<CLogicEvent>::iterator itEvt;
108 for( itEvt = _Events.begin(); itEvt != _Events.end(); ++itEvt )
110 string dest = (*itEvt).EventAction.EventMessage.Destination;
111 TSIdMap::const_iterator itId = sIdMap.find( dest );
112 // if message destination exists in the map we associate the sid with the message
113 if( itId != sIdMap.end() )
115 (*itEvt).EventAction.EventMessage.DestinationId = (*itId).second;
118 /// send the event messages that can be sent
119 trySendEventMessages();
122 /// exit messages
123 for( itMsg = _ExitMessages.begin(); itMsg != _ExitMessages.end(); ++itMsg )
125 TSIdMap::const_iterator itId = sIdMap.find( (*itMsg).Destination );
126 // if message destination exists in the map we associate the sid with the message
127 if( itId != sIdMap.end() )
129 (*itMsg).DestinationId = (*itId).second;
133 } // addSIdMap //
136 //---------------------------------------------------
137 // processLogic :
139 //---------------------------------------------------
140 void CLogicState::processLogic()
142 // test all conditions managed by this state
143 vector<CLogicEvent>::iterator itEvent;
144 for( itEvent = _Events.begin(); itEvent != _Events.end(); ++itEvent )
146 if( (*itEvent).testCondition() )
148 //nlinfo("The condition %s is valid",(*itEvent).ConditionName.c_str());
149 if( (*itEvent).EventAction.IsStateChange )
151 _LogicStateMachine->setCurrentState( (*itEvent).EventAction.StateChange );
153 else
155 // this message will be sent as soon as the dest id will be given
156 (*itEvent).EventAction.enableSendMessage();
158 /// send the event messages that must and can be sent
159 trySendEventMessages();
162 else
164 // reset message send status here to be able to send messages several times in the logic state
165 // --> this has to be done if we want messages to be sent every time the condition becomes verified
169 } // processLogic //
172 //---------------------------------------------------
173 // enterState :
175 //---------------------------------------------------
176 void CLogicState::enterState()
178 /// send the entry messages that can be sent
179 trySendEntryMessages();
181 } // enterState //
184 //---------------------------------------------------
185 // exitState :
187 //---------------------------------------------------
188 void CLogicState::exitState()
190 vector<CLogicEventMessage>::iterator itMsg;
191 for( itMsg = _ExitMessages.begin(); itMsg != _ExitMessages.end(); ++itMsg )
193 if( (*itMsg).DestinationId != CEntityId() )
195 CMessage msgOut( (*itMsg).MessageId );
196 msgOut.serial( (*itMsg).Arguments );
198 _MessagesToSend.insert( make_pair((*itMsg).DestinationId,msgOut) );
202 // reset the entry messages send status
203 for( itMsg = _EntryMessages.begin(); itMsg != _EntryMessages.end(); ++itMsg )
205 (*itMsg).ToSend = false;
206 (*itMsg).Sent = false;
209 // reset all events
210 vector<CLogicEvent>::iterator itEvent;
211 for( itEvent = _Events.begin(); itEvent != _Events.end(); ++itEvent )
213 (*itEvent).reset();
216 // reset the exit messages send status
217 for( itMsg = _ExitMessages.begin(); itMsg != _ExitMessages.end(); ++itMsg )
219 (*itMsg).ToSend = false;
220 (*itMsg).Sent = false;
223 } // exitState //
227 //---------------------------------------------------
228 // trySendEntryMessages :
230 //---------------------------------------------------
231 void CLogicState::trySendEntryMessages()
233 /// send the entry messages that can be sent
234 vector<CLogicEventMessage>::iterator itMsg;
235 for( itMsg = _EntryMessages.begin(); itMsg != _EntryMessages.end(); ++itMsg )
237 if( !(*itMsg).Sent && (*itMsg).DestinationId.getType() != 0xfe )
239 CMessage msgOut( (*itMsg).MessageId );
240 msgOut.serial( (*itMsg).Arguments );
242 _MessagesToSend.insert( make_pair((*itMsg).DestinationId,msgOut) );
244 (*itMsg).ToSend = false;
245 (*itMsg).Sent = true;
249 } // trySendEntryMessages //
253 //---------------------------------------------------
254 // trySendEventMessages :
256 //---------------------------------------------------
257 void CLogicState::trySendEventMessages()
259 // test all conditions managed by this state
260 vector<CLogicEvent>::iterator itEvent;
261 for( itEvent = _Events.begin(); itEvent != _Events.end(); ++itEvent )
263 if( (*itEvent).EventAction.EventMessage.ToSend == true )
265 if( (*itEvent).EventAction.EventMessage.Sent == false )
267 if( (*itEvent).EventAction.EventMessage.DestinationId.getType() != 0xfe )
269 CMessage msgOut( (*itEvent).EventAction.EventMessage.MessageId );
270 msgOut.serial( (*itEvent).EventAction.EventMessage.Arguments );
272 _MessagesToSend.insert( make_pair((*itEvent).EventAction.EventMessage.DestinationId,msgOut) );
274 (*itEvent).EventAction.EventMessage.ToSend = false;
275 (*itEvent).EventAction.EventMessage.Sent = true;
281 } // trySendEventMessages //
284 //---------------------------------------------------
285 // getMessagesToSend :
287 //---------------------------------------------------
288 void CLogicState::getMessagesToSend( multimap<CEntityId,CMessage>& msgs )
290 multimap<CEntityId,CMessage>::iterator itMsg;
291 for( itMsg = _MessagesToSend.begin(); itMsg != _MessagesToSend.end(); ++itMsg )
293 msgs.insert( *itMsg );
296 // erase all the messages
297 _MessagesToSend.clear();
299 } // getMessagesToSend //
303 //---------------------------------------------------
304 // fillVarMap :
306 //---------------------------------------------------
307 void CLogicState::fillVarMap( multimap<CEntityId,string >& stateMachineVariables )
309 // events
310 vector<CLogicEvent>::iterator itEvt;
311 for( itEvt = _Events.begin(); itEvt != _Events.end(); ++itEvt )
313 // get the condition used in the event
314 CLogicCondition condition;
315 if( _LogicStateMachine->getCondition((*itEvt).ConditionName,condition) )
317 // get vars used in the conditions
318 set<string> condVars;
319 condition.fillVarSet( condVars );
321 // add var with related service
322 set<string>::iterator itCV;
323 for( itCV = condVars.begin(); itCV != condVars.end(); ++itCV )
325 stateMachineVariables.insert( make_pair((*itEvt).EventAction.EventMessage.DestinationId,*itCV) );
330 } // fillVarMap //
334 //---------------------------------------------------
335 // serial :
337 //---------------------------------------------------
338 /*void CLogicState::serial( IStream &f )
340 f.xmlPush( "STATE");
342 f.serial( _StateName );
343 f.serialCont( _EntryMessages );
344 f.serialCont( _ExitMessages );
345 f.serialCont( _Events );
347 f.xmlPop();
349 } // serial //*/
351 void CLogicState::write (xmlNodePtr node) const
353 xmlNodePtr elmPtr = xmlNewChild ( node, NULL, (const xmlChar*)"STATE", NULL);
354 xmlSetProp (elmPtr, (const xmlChar*)"Name", (const xmlChar*)_StateName.c_str());
356 uint i;
357 for (i = 0; i < _EntryMessages.size(); i++)
359 _EntryMessages[i].write(elmPtr, "ENTRY_");
361 for (i = 0; i < _ExitMessages.size(); i++)
363 _ExitMessages[i].write(elmPtr, "EXIT_");
365 for (i = 0; i < _Events.size(); i++)
367 _Events[i].write(elmPtr);
371 void CLogicState::read (xmlNodePtr node)
373 xmlCheckNodeName (node, "STATE");
375 _StateName = getXMLProp (node, "Name");
378 // Count the parent
379 uint nb = CIXml::countChildren (node, "ENTRY_EVENT_MESSAGE");
380 uint i = 0;
381 xmlNodePtr parent = CIXml::getFirstChildNode (node, "ENTRY_EVENT_MESSAGE");
382 while (i<nb)
384 CLogicEventMessage v;
385 v.read(parent);
386 _EntryMessages.push_back(v);
388 // Next parent
389 parent = CIXml::getNextChildNode (parent, "ENTRY_EVENT_MESSAGE");
390 i++;
395 // Count the parent
396 uint nb = CIXml::countChildren (node, "EXIT_EVENT_MESSAGE");
397 uint i = 0;
398 xmlNodePtr parent = CIXml::getFirstChildNode (node, "EXIT_EVENT_MESSAGE");
399 while (i<nb)
401 CLogicEventMessage v;
402 v.read(parent);
403 _ExitMessages.push_back(v);
405 // Next parent
406 parent = CIXml::getNextChildNode (parent, "EXIT_EVENT_MESSAGE");
407 i++;
412 // Count the parent
413 uint nb = CIXml::countChildren (node, "EVENT");
414 uint i = 0;
415 xmlNodePtr parent = CIXml::getFirstChildNode (node, "EVENT");
416 while (i<nb)
418 CLogicEvent v;
419 v.read(parent);
420 _Events.push_back(v);
422 // Next parent
423 parent = CIXml::getNextChildNode (parent, "EVENT");
424 i++;
431 } // NLLOGIC