1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2011 Matt RAYKOWSKI (sfb) <matt.raykowski@gmail.com>
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "mission_compiler.h"
23 #include "nel/misc/factory.h"
27 using namespace NLMISC
;
28 using namespace NLLIGO
;
35 IStep
*IStep::createStep(CMissionData
&md
, IPrimitive
*prim
)
38 if (!prim
->getPropertyByName("class", c
))
39 throw EParseException(prim
, "Can't find property 'class' on primitive");
41 IStep
*ret
= CFactoryIndirect
<IStepFactory
, string
>::instance().getFactory(*c
)->createStep(md
, prim
);
47 IStep::IStep(CMissionData
&md
, NLLIGO::IPrimitive
*prim
)
55 prim
->getPropertyByName("class", _StepType
);
56 prim
->getPropertyByName("name", _StepName
);
58 // parse the sub prim to create action & objectives;
60 // parse the preactions
62 TPrimitiveClassAndNamePredicate
pred("actions", "pre_actions");
63 child
= getPrimitiveChild(prim
, pred
);
68 for (uint i
=0; i
<child
->getNumChildren(); ++i
)
71 child
->getChild(subChild
, i
);
75 IStepContent
*sc
= IStepContent::createStepContent(md
, subChild
);
77 _PreActions
.push_back(sc
);
81 // parse the objectives
83 TPrimitiveClassAndNamePredicate
pred("mission_objectives", "objectives");
84 child
= getPrimitiveChild(prim
, pred
);
88 for (uint i
=0; i
<child
->getNumChildren(); ++i
)
91 child
->getChild(subChild
, i
);
95 IStepContent
*sc
= IStepContent::createStepContent(md
, subChild
);
97 _Objectives
.push_back(sc
);
101 // parse the post actions
103 TPrimitiveClassAndNamePredicate
pred("actions", "post_actions");
104 child
= getPrimitiveChild(prim
, pred
);
108 for (uint i
=0; i
<child
->getNumChildren(); ++i
)
110 IPrimitive
*subChild
;
111 child
->getChild(subChild
, i
);
115 IStepContent
*sc
= IStepContent::createStepContent(md
, subChild
);
117 _PostActions
.push_back(sc
);
123 void IStep::fillStepJump(CMissionData
&md
, std::set
<TJumpInfo
> &jumpPoints
)
126 // extract step content jump points
127 for (i
=0; i
<_PreActions
.size(); ++i
)
129 _PreActions
[i
]->fillJump(md
, jumpPoints
);
131 for (i
=0; i
<_Objectives
.size(); ++i
)
133 _Objectives
[i
]->fillJump(md
, jumpPoints
);
135 for (i
=0; i
<_PostActions
.size(); ++i
)
137 _PostActions
[i
]->fillJump(md
, jumpPoints
);
140 fillJump(md
, jumpPoints
);
142 for (i
= 0; i
< _SubSteps
.size(); ++i
)
143 if (_SubSteps
[i
] != NULL
)
144 _SubSteps
[i
]->fillStepJump(md
, jumpPoints
);
148 void IStep::fillJump(CMissionData
&md
, std::set
<TJumpInfo
> &jumpPoints
)
150 // jump to the next step
151 IStep
*next
= md
.getNextStep(this);
153 if (!EndOfBranch
&& next
)
155 TJumpInfo
ji(next
->getStepName());
156 jumpPoints
.insert(ji
);
160 TJumpInfo
ji("__end__");
161 jumpPoints
.insert(ji
);
165 std::string
IStep::genCode(CMissionData
&md
)
169 ret
+= genCodePreActions(md
);
170 ret
+= genCodeObjectives(md
);
171 ret
+= genCodePostActions(md
);
176 std::string
IStep::genCodePreActions(CMissionData
&md
)
179 // generate code for pre actions
180 for (uint i
=0; i
<_PreActions
.size(); ++i
)
182 ret
+= _PreActions
[i
]->genStepContentCode(md
);
187 std::string
IStep::genCodeObjectives(CMissionData
&md
)
190 // generate code for objectives
191 for (uint i
=0; i
<_Objectives
.size(); ++i
)
193 ret
+= _Objectives
[i
]->genStepContentCode(md
);
198 std::string
IStep::genCodePostActions(CMissionData
&md
)
201 //generate code for post actions
202 for (uint i
=0; i
<_PostActions
.size(); ++i
)
204 ret
+= _PostActions
[i
]->genStepContentCode(md
);
210 std::string
IStep::genPhrase()
213 // generate code for pre actions
214 for (uint i
=0; i
<_PreActions
.size(); ++i
)
216 ret
+= _PreActions
[i
]->genStepContentPhrase();
218 // generate code for objectives
219 for (uint i
=0; i
<_Objectives
.size(); ++i
)
221 ret
+= _Objectives
[i
]->genStepContentPhrase();
223 //generate code for post actions
224 for (uint i
=0; i
<_PostActions
.size(); ++i
)
226 ret
+= _PostActions
[i
]->genStepContentPhrase();
228 //generate code for sub steps
229 for (uint i
=0; i
<_SubSteps
.size(); ++i
)
231 ret
+= _SubSteps
[i
]->genPhrase();
238 class CStep
: public IStep
241 CStep(CMissionData
&md
, IPrimitive
*prim
)
244 // nothing special to do
248 REGISTER_STEP_INDIRECT(CStep
, "step");
250 class CStepObjective
: public CStep
253 virtual void getPredefParam(uint32
&numEntry
, CPhrase::TPredefParams
&predef
)
259 CStepObjective(CMissionData
&md
, IPrimitive
*prim
, const std::string
&prefix
= "")
266 void init(CMissionData
&md
, IPrimitive
*prim
)
268 _HideObj
= md
.getProperty(prim
, _Prefix
+ "hide_obj", true, false) == "true";
269 _OverloadObj
= md
.getPropertyArray(prim
, _Prefix
+ "overload_objective", false, false);
270 _RoleplayObj
= md
.getPropertyArray(prim
, _Prefix
+ "roleplay_objective", false, false);
272 CPhrase::TPredefParams params
;
273 // ask derived class for predefined params
274 getPredefParam(numEntry
, params
);
275 _OverloadPhrase
.initPhrase(md
, prim
, _OverloadObj
, numEntry
, params
);
276 _RoleplayPhrase
.initPhrase(md
, prim
, _RoleplayObj
, numEntry
, params
);
279 virtual bool isAction() { return true; }
281 string
genCode(CMissionData
&md
)
285 ret
= "hide_obj" + NL
;
286 if (!_OverloadObj
.empty())
288 ret
+= "set_obj : " + _OverloadPhrase
.genScript(md
) + NL
;
290 if (!_RoleplayObj
.empty())
292 ret
+= "set_obj_rp : " + _RoleplayPhrase
.genScript(md
) + NL
;
301 ret
+= _OverloadPhrase
.genPhrase();
302 ret
+= _RoleplayPhrase
.genPhrase();
304 ret
+= IStep::genPhrase();
312 vector
<string
> _OverloadObj
;
313 CPhrase _OverloadPhrase
;
314 vector
<string
> _RoleplayObj
;
315 CPhrase _RoleplayPhrase
;
318 class CStepDynChatTalkTo
: public CStepObjective
320 // string _BotNameVar;
322 TCompilerVarName _BotName
;
325 void getPredefParam(uint32
&numEntry
, CPhrase::TPredefParams
&predef
)
330 predef
[0][0] = _BotName
.getParamInfo();
331 // if (_BotNameVar.empty())
332 // predef[0][0] = CPhrase::TParamInfo("npc", STRING_MANAGER::bot);
334 // predef[0][0] = CPhrase::TParamInfo(_BotNameVar, STRING_MANAGER::bot);
337 CStepDynChatTalkTo(CMissionData
&md
, IPrimitive
*prim
, const std::string
&prefix
= "")
338 : CStepObjective(md
, prim
, prefix
)
342 void init(CMissionData
&md
, IPrimitive
*prim
)
344 _BotName
.init("npc", STRING_MANAGER::bot
, md
, prim
, "npc_name");
345 // _BotNameVar = md.getProperty(prim, "npc_name", false, false);
346 // remove the variable tag if any
347 // untagVar(_BotNameVar);
349 // _BotName = md.getProperty(prim, "npc_name", true, false);
351 vs
= md
.getPropertyArray(prim
, "talk_to_menu", false, false);
352 CPhrase::TPredefParams
pp(1);
353 pp
[0].push_back(_BotName
.getParamInfo());
354 // if (_BotNameVar.empty())
355 // pp[0].push_back(CPhrase::TParamInfo("npc", STRING_MANAGER::bot));
357 // pp[0].push_back(CPhrase::TParamInfo(_BotNameVar, STRING_MANAGER::bot));
358 _Phrase
.initPhrase(md
, prim
, vs
, 0, pp
);
360 // _Phrase.initPhrase(md, prim, vs);
362 // if (_Phrase.asAdditionnalParams())
364 // // we need to remove the default 'npc' parameter if add params are found
366 // temp.initPhrase(md, prim, vs);
370 CStepObjective::init(md
, prim
);
373 string
genCode(CMissionData
&md
)
376 ret
= CStepObjective::genCode(md
);
378 ret
+= "talk_to : "+_BotName
._VarValue
;
380 if (!_Phrase
.isEmpty())
381 ret
+= " : "+_Phrase
.genScript(md
);
390 ret
= CStepObjective::genPhrase();
391 ret
+= _Phrase
.genPhrase();
397 class CStepJump
: public IStep
400 CStepJump(CMissionData
&md
, IPrimitive
*prim
)
403 _StepName
= md
.getProperty(prim
, "target", true, false);
406 void fillJump(CMissionData
&md
, set
<TJumpInfo
> &jumpPoints
)
408 jumpPoints
.insert(TJumpInfo(_StepName
, "", false));
411 string
genCode(CMissionData
&md
)
415 ret
+= "jump : " + _StepName
+ NL
;
427 REGISTER_STEP_INDIRECT(CStepJump
, "jump_to");
429 /// pseudo step used in step parsing
430 class CStepEnd
: public IStep
433 CStepEnd(CMissionData
&md
, IPrimitive
*prim
)
438 string
genCode(CMissionData
&md
)
447 bool isEnd() { return true; }
450 REGISTER_STEP_INDIRECT(CStepEnd
, "end");
452 class CStepFailure
: public IStep
454 // Optional jump at end of failure
457 CStepFailure(CMissionData
&md
, IPrimitive
*prim
)
460 // parse the sub prim to create action & objectives;
462 // parse the pre-actions
464 TPrimitiveClassAndNamePredicate
pred("actions", "actions");
465 child
= getPrimitiveChild(prim
, pred
);
469 for (uint i
=0; i
<child
->getNumChildren(); ++i
)
471 IPrimitive
*subChild
;
472 child
->getChild(subChild
, i
);
476 IStepContent
*sc
= IStepContent::createStepContent(md
, subChild
);
478 _PreActions
.push_back(sc
);
482 // look for an optional jump
484 TPrimitiveClassPredicate
pred("jump_to");
485 child
= getPrimitiveChild(prim
, pred
);
489 // ok, we have a jump at end of fail step
490 _JumpTo
= md
.getProperty(child
, "target", true, false);
494 string
genCode(CMissionData
&md
)
498 ret
= "failure" + NL
;
500 string tmp
= IStep::genCode(md
);
501 tabulateLine(tmp
, 1);
505 if (!_JumpTo
.empty())
507 ret
+= "\tjump : "+_JumpTo
+ NL
;
510 ret
+= "/failure"+NL
;
515 void fillJump(CMissionData
&md
, set
<TJumpInfo
> &jumpPoints
)
517 IStep::fillJump(md
, jumpPoints
);
518 if (!_JumpTo
.empty())
519 jumpPoints
.insert(TJumpInfo(_JumpTo
));
523 REGISTER_STEP_INDIRECT(CStepFailure
, "step_failure");
525 class CStepCrash
: public IStep
527 // Optional jump at end of failure
529 vector
<string
> _AiInstances
;
531 CStepCrash(CMissionData
&md
, IPrimitive
*prim
)
534 // parse the sub prim to create action & objectives;
536 // parse the pre-actions
538 TPrimitiveClassAndNamePredicate
pred("actions", "actions");
539 child
= getPrimitiveChild(prim
, pred
);
543 for (uint i
=0; i
<child
->getNumChildren(); ++i
)
545 IPrimitive
*subChild
;
546 child
->getChild(subChild
, i
);
550 IStepContent
*sc
= IStepContent::createStepContent(md
, subChild
);
552 _PreActions
.push_back(sc
);
557 // parse ai instance list
558 vector
<string
> vs
= md
.getPropertyArray(prim
, "ai_instances", true, false);
561 string err = toString("crash block need at least one ai instance !");
562 throw EParseException(prim, err.c_str());
565 for (uint i
=0; i
<vs
.size(); ++i
)
567 _AiInstances
.push_back(vs
[i
]);
570 // look for an optional jump
572 TPrimitiveClassPredicate
pred("jump_to");
573 child
= getPrimitiveChild(prim
, pred
);
577 // ok, we have a jump at end of fail step
578 _JumpTo
= md
.getProperty(child
, "target", true, false);
582 string
genCode(CMissionData
&md
)
588 if (!_AiInstances
.empty())
591 for (uint i
=0; i
<_AiInstances
.size(); ++i
)
593 ret
+= string(" ")+_AiInstances
[i
];
599 string tmp
= IStep::genCode(md
);
600 tabulateLine(tmp
, 1);
604 if (!_JumpTo
.empty())
606 ret
+= "\tjump : "+_JumpTo
+ NL
;
614 void fillJump(CMissionData
&md
, set
<TJumpInfo
> &jumpPoints
)
616 IStep::fillJump(md
, jumpPoints
);
617 if (!_JumpTo
.empty())
618 jumpPoints
.insert(TJumpInfo(_JumpTo
));
622 REGISTER_STEP_INDIRECT(CStepCrash
, "step_crash");
624 // ///////////////////// //
625 // STEP PLAYER RECONNECT //
626 // ///////////////////// //
628 // ***************************************************************************
629 CStepPlayerReconnect::CStepPlayerReconnect(CMissionData
&md
, IPrimitive
*prim
) : IStep(md
, prim
)
631 // parse the sub prim to create action & objectives;
636 TPrimitivePropertyPredicate
pred("step_tag", "true");
637 filterPrimitiveChilds(prim
, pred
, resp
);
639 for (uint i
=0; i
<resp
.size(); ++i
)
641 _SubBranchs
.push_back(resp
[i
]);
644 // look for an optional jump
646 TPrimitiveClassPredicate
pred("jump_to");
647 child
= getPrimitiveChild(prim
, pred
);
651 // ok, we have a jump at end of fail step
652 _JumpTo
= md
.getProperty(child
, "target", true, false);
656 // ***************************************************************************
657 TPrimitiveSet
CStepPlayerReconnect::getSubBranchs()
662 // ***************************************************************************
663 string
CStepPlayerReconnect::genCode(CMissionData
&md
)
667 ret
= "player_reconnect"+NL
;
669 string tmp
= IStep::genCode(md
);
670 tabulateLine(tmp
, 1);
673 for (uint i
= 0; i
< _SubSteps
.size(); ++i
)
675 if ( md
.isThereAJumpTo(_SubSteps
[i
]->getStepName()) )
677 // insert a jump point
678 ret
+= "jump_point : " + _SubSteps
[i
]->getStepName() + NL
;
681 ret
+= _SubSteps
[i
]->genCode(md
);
684 if (!_JumpTo
.empty())
686 ret
+= "\tjump : "+_JumpTo
+ NL
;
689 ret
+= "/player_reconnect"+NL
;
694 // ***************************************************************************
695 void CStepPlayerReconnect::fillJump(CMissionData
&md
, set
<TJumpInfo
> &jumpPoints
)
697 IStep::fillJump(md
, jumpPoints
);
698 if (!_JumpTo
.empty())
699 jumpPoints
.insert(TJumpInfo(_JumpTo
));
702 REGISTER_STEP_INDIRECT(CStepPlayerReconnect
, "step_player_reconnect");
704 // //////////////////////////// //
705 // END OF STEP PLAYER RECONNECT //
706 // //////////////////////////// //
708 // ***************************************************************************
709 // get the jump point of a node. NB: if the node is itself a jump, then directly jump to its target
710 static std::string
*getJumpTarget(IPrimitive
*child
)
715 // default: jump to the node
717 child
->getPropertyByName("name", s
);
719 // if the node is a jump itself
720 string
*className
= NULL
;
721 child
->getPropertyByName("class", className
);
722 if (className
&& *className
== "jump_to")
724 // generate jump to the step jump target
725 child
->getPropertyByName("target", s
);
732 // ***************************************************************************
733 class CStepDynChat
: public IStep
736 CStepDynChat(CMissionData
&md
, IPrimitive
*prim
)
739 _BotName
= md
.getProperty(prim
, "npc_name", true, false);
740 vector
<string
> temp
= md
.getPropertyArray(prim
, "phrase", false, false);
741 _Phrase
.initPhrase(md
, prim
, temp
);
743 temp
= md
.getPropertyArray(prim
, "talk_to_menu", false, false);
744 // _TalkToMenu.initPhrase(md, prim, temp);
746 _TalkToObjective
= NULL
;
747 CUniquePtr
<CStepDynChatTalkTo
> talkToObjective
; // next calls could throw exceptions, so take care...
750 talkToObjective
.reset(new CStepDynChatTalkTo(md
, prim
, "talk_to_"));
751 talkToObjective
->init(md
, prim
);
754 // build the sub branch list
757 TPrimitiveClassPredicate
pred("no_answer");
758 noResp
= getPrimitiveChild(prim
, pred
);
761 _SubBranchs
.push_back(noResp
);
765 TPrimitiveClassPredicate
pred("dyn_answer");
766 filterPrimitiveChilds(prim
, pred
, resp
);
768 _Responses
.resize(resp
.size());
769 for (uint i
=0; i
<resp
.size(); ++i
)
771 _SubBranchs
.push_back(resp
[i
]);
772 if (resp
[i
]->getNumChildren() == 0)
773 throw EParseException(prim
, "missing step under 'dyn_answer' node for response");
775 vector
<string
> temp
= md
.getPropertyArray(resp
[i
], "phrase_answer", false, false);
776 _Responses
[i
].initPhrase(md
, resp
[i
], temp
);
778 _TalkToObjective
= talkToObjective
.release(); // commit result
782 delete _TalkToObjective
;
785 TPrimitiveSet
getSubBranchs()
787 TPrimitiveSet vStepsToReturn
;
788 for (uint i
= 0; i
< _SubBranchs
.size(); ++i
)
790 TPrimitiveSet childs
;
792 TPrimitivePropertyPredicate
pred("step_tag", "true");
793 filterPrimitiveChilds(_SubBranchs
[i
], pred
, childs
);
795 for (uint j
= 0; j
< childs
.size(); ++j
)
796 vStepsToReturn
.push_back(childs
[j
]);
798 return vStepsToReturn
;
801 void fillJump(CMissionData
&md
, set
<TJumpInfo
> &jumpPoints
)
803 for (uint i
=0; i
<_SubBranchs
.size(); ++i
)
806 IPrimitive
*firstStep
;
807 if (!_SubBranchs
[i
]->getChild(firstStep
, 0))
808 throw EParseException(_Primitive
, toString("Can't find child in %uth sub branch", i
+1).c_str());
810 bool ret
= firstStep
->getPropertyByName("name", s
);
812 throw EParseException(_Primitive
, toString("Can't find property 'name' in %uth sub branch", i
+1).c_str());
815 _SubBranchs
[i
]->getPropertyByName("name", label
);
816 jumpPoints
.insert(TJumpInfo(*s
, label
));
820 string
genCode(CMissionData
&md
)
824 // if there's a talk_to menu, add it
825 // if (!_TalkToMenu.isEmpty())
826 if (_TalkToObjective
!= NULL
)
828 ret
+= _TalkToObjective
->genCode(md
);
829 // ret += "talk_to : "+_BotName;
830 // ret += " : " + _TalkToMenu.genScript(md);
835 ret
+= "dyn_chat : " + _BotName
+ " : " + _Phrase
.genScript(md
);
837 for (uint i
=1; i
<_SubBranchs
.size(); ++i
)
840 _SubBranchs
[i
]->getChild(child
, 0);
842 // get the jump target
843 string
*s
= getJumpTarget(child
);
845 ret
+= " : " + *s
+ " " + _Responses
[i
-1].genScript(md
);
855 string ret
; /* = CStepObjective::genPhrase();*/
857 // if (!_TalkToMenu.isEmpty())
858 if (_TalkToObjective
!= NULL
)
860 ret
+= _TalkToObjective
->genPhrase();
861 // ret += _TalkToMenu.genPhrase();
864 ret
+= _Phrase
.genPhrase();
866 for (uint i
=0; i
<_Responses
.size(); ++i
)
868 ret
+= _Responses
[i
].genPhrase();
873 /// the list of sub branch for the dyn chat.
874 TPrimitiveSet _SubBranchs
;
875 // phrase for the main text
877 // list of phrase for each response
878 vector
<CPhrase
> _Responses
;
883 // CPhrase _TalkToMenu;
884 CStepDynChatTalkTo
*_TalkToObjective
;
887 REGISTER_STEP_INDIRECT(CStepDynChat
, "step_dyn_chat");
889 class CLinearDynChat
: public IStep
908 CLinearDynChat(CMissionData
&md
, IPrimitive
*prim
)
911 _BotName
= md
.getProperty(prim
, "npc_name", true, false);
912 vector
<string
> temp
= md
.getPropertyArray(prim
, "phrase", false, false);
913 _Phrase
.initPhrase(md
, prim
, temp
);
915 // set the linear mode
917 prim
->getPropertyByName("class", className
);
919 if (className
== "linear_dyn_chat_fail")
921 else if (className
== "linear_dyn_chat_retry")
923 else if (className
== "linear_dyn_chat_continue")
924 _Mode
= mode_continue
;
927 string err
= toString("Unknow class '%s' for dyn chat !", className
.c_str());
928 throw EParseException(prim
, err
.c_str());
931 // read the response phrase
932 vector
<string
> phraseYes
;
933 phraseYes
= md
.getPropertyArray(prim
, "phrase_yes", false, false);
934 _PhraseYes
.initPhrase(md
, prim
, phraseYes
);
937 string
genCode(CMissionData
&md
)
944 ret
= "dyn_chat : "+_BotName
+" : "+_Phrase
.genScript(md
)+" : "+_StepName
+"_resp "+_PhraseYes
.genScript(md
)+NL
;
946 ret
+= "jump_point : " +_StepName
+"_resp"+NL
;
949 ret
+= "jump_point : " +_StepName
+"_retry"+NL
;
950 ret
+= "dyn_chat : "+_BotName
+" : "+_Phrase
.genScript(md
)+" : "+_StepName
+"_resp "+_PhraseYes
.genScript(md
)+NL
;
951 ret
+= "jump : "+_StepName
+"_retry"+NL
;
952 ret
+= "jump_point : " +_StepName
+"_resp"+NL
;
955 ret
= "dyn_chat : "+_BotName
+" : "+_Phrase
.genScript(md
)+" : "+_StepName
+"_resp "+_PhraseYes
.genScript(md
)+NL
;
956 ret
+= "jump_point : " +_StepName
+"_resp"+NL
;
966 // ret = CStepObjective::genPhrase();
967 ret
+= _Phrase
.genPhrase();
968 ret
+= _PhraseYes
.genPhrase();
974 typedef CLinearDynChat TLinearDynChatFail
;
975 REGISTER_STEP_INDIRECT(TLinearDynChatFail
, "linear_dyn_chat_fail");
976 typedef CLinearDynChat TLinearDynChatRetry
;
977 REGISTER_STEP_INDIRECT(TLinearDynChatRetry
, "linear_dyn_chat_retry");
978 typedef CLinearDynChat TLinearDynChatContinue
;
979 REGISTER_STEP_INDIRECT(TLinearDynChatContinue
, "linear_dyn_chat_continue");
985 CStepIf::CStepIf(CMissionData
&md
, IPrimitive
*prim
) : IStep(md
, prim
)
987 if (prim
->getNumChildren() != 2)
988 throw EParseException(prim
, toString("step_if need two child primitive for 'not_ok' and 'ok' clause, found %u child", prim
->getNumChildren()).c_str());
990 IPrimitive
*notOk
= const_cast<IPrimitive
*>(prim
->getPrimitive("result_no"));
991 //prim->getChild(notOk, 0);
992 IPrimitive
*ok
= const_cast<IPrimitive
*>(prim
->getPrimitive("result_yes"));
993 //prim->getChild(ok, 1);
996 throw EParseException(prim
, "Can't find 'not ok' step branch");
998 throw EParseException(prim
, "Can't find 'ok' step branch");
1001 notOk
->getPropertyByName("class", name
);
1002 if (name
!= "result_no")
1003 throw EParseException(prim
, toString("first child must be of class 'result_no', found '%s' instead", name
.c_str()).c_str());
1004 ok
->getPropertyByName("class", name
);
1005 if (name
!= "result_yes")
1006 throw EParseException(prim
, toString("second child must be of class 'result_yes', found '%s' instead", name
.c_str()).c_str());
1008 // push in order : not ok, then ok
1009 _SubBranchs
.push_back(notOk
);
1010 _SubBranchs
.push_back(ok
);
1013 string s
= md
.getProperty(prim
, "condition_type", true, false);
1014 if (s
== "test_missions_done")
1015 _IfType
= it_mission_done
;
1016 else if (s
== "test_skills_level")
1017 _IfType
= it_skills
;
1018 else if (s
== "test_bricks_known")
1019 _IfType
= it_bricks
;
1020 else if (s
== "test_sdb")
1022 else if (s
== "test_race")
1024 else if (s
== "test_cult")
1026 else if (s
== "test_civ")
1028 else if (s
== "test_faction_point")
1029 _IfType
= it_faction_point
;
1030 else if (s
== "test_guild_civ")
1031 _IfType
= it_guild_civ
;
1032 else if (s
== "test_guild_cult")
1033 _IfType
= it_guild_cult
;
1034 else if (s
== "test_guild_fame")
1035 _IfType
= it_guild_fame
;
1036 else if (s
== "test_no_trial")
1037 _IfType
= it_no_trial
;
1038 else if (s
== "test_item_in_inv")
1039 _IfType
= it_item_in_inv
;
1041 throw EParseException(prim
, "Unknow test type !");
1043 _IfParams
= md
.getPropertyArray(prim
, "test_parameters", true, false);
1046 TPrimitiveSet
CStepIf::getSubBranchs()
1048 TPrimitiveSet vStepsToReturn
;
1049 for (uint i
= 0; i
< _SubBranchs
.size(); ++i
)
1051 TPrimitiveSet childs
;
1053 TPrimitivePropertyPredicate
pred("step_tag", "true");
1054 filterPrimitiveChilds(_SubBranchs
[i
], pred
, childs
);
1056 for (uint j
= 0; j
< childs
.size(); ++j
)
1057 vStepsToReturn
.push_back(childs
[j
]);
1059 return vStepsToReturn
;
1062 void CStepIf::fillJump(CMissionData
&md
, set
<TJumpInfo
> &jumpPoints
)
1065 TPrimitiveSet childs;
1068 filterPrimitiveChilds(_SubBranchs[1], TPrimitivePropertyPredicate("step_tag", "true"), childs);
1069 if (!childs.empty())
1071 ret = childs[0]->getPropertyByName("name", s);
1073 throw EParseException(childs[0], "Can't find property 'name' in first step of 'ok' sub branch");
1075 jumpPoints.insert(TJumpInfo(*s, "yes"));
1078 // insert link to 'no' step
1080 filterPrimitiveChilds(_SubBranchs[0], TPrimitivePropertyPredicate("step_tag", "true"), childs);
1081 if (!childs.empty())
1083 ret = childs[0]->getPropertyByName("name", s);
1085 throw EParseException(childs[0], "Can't find property 'name' in first step of 'not ok' sub branch");
1087 jumpPoints.insert(TJumpInfo(*s, "no"));
1091 string
CStepIf::genCode(CMissionData
&md
)
1097 TPrimitiveSet childs
;
1098 vector
<IStep
*> yesSteps
;
1099 vector
<IStep
*> noSteps
;
1101 // Get the 'yes branch' jump point
1103 TPrimitivePropertyPredicate
pred("step_tag", "true");
1104 filterPrimitiveChilds(_SubBranchs
[1], pred
, childs
);
1106 if (!childs
.empty())
1108 for (i
= 0; i
< _SubSteps
.size(); ++i
)
1109 if (std::find(childs
.begin(), childs
.end(), _SubSteps
[i
]->getPrimitive()) != childs
.end())
1110 yesSteps
.push_back(_SubSteps
[i
]);
1112 if (yesSteps
.empty())
1114 string err
= toString("In step '%s', can't find sub step in 'yes' sub branch", getStepName().c_str());
1115 throw EParseException(_SubBranchs
[1]->getParent(), err
.c_str());
1119 // Get the 'no branch' jump point
1122 TPrimitivePropertyPredicate
pred("step_tag", "true");
1123 filterPrimitiveChilds(_SubBranchs
[0], pred
, childs
);
1125 if (!childs
.empty())
1127 for (i
= 0; i
< _SubSteps
.size(); ++i
)
1128 if (std::find(childs
.begin(), childs
.end(), _SubSteps
[i
]->getPrimitive()) != childs
.end())
1129 noSteps
.push_back(_SubSteps
[i
]);
1131 if (noSteps
.empty())
1133 string err
= toString("In step '%s', can't find sub step in 'no' sub branch", getStepName().c_str());
1134 throw EParseException(_SubBranchs
[0]->getParent(), err
.c_str());
1138 if ((yesSteps
.empty()) && (noSteps
.empty()))
1140 string err
= toString("In step '%s', no yes-branch and no no-branch", getStepName().c_str());
1141 throw EParseException(_SubBranchs
[0]->getParent(), err
.c_str());
1145 if (!yesSteps
.empty())
1146 jumpToYes
= yesSteps
[0]->getStepName();
1148 jumpToYes
= getStepName() + "_endif";
1154 case it_mission_done
:
1155 if (_IfParams
.empty())
1156 throw EParseException(_Primitive
, "if_mission_done need at least one mission to test");
1157 for (uint i
=0; i
<_IfParams
.size(); ++i
)
1158 ret
+= "if_mission_done : " + _IfParams
[i
] + " : " + jumpToYes
+ NL
;
1161 if (_IfParams
.empty())
1162 throw EParseException(_Primitive
, "if_skills need at least one <skill level> to test");
1163 ret
= "if_skills : ";
1164 for (uint i
=0; i
<_IfParams
.size(); ++i
)
1166 ret
+= _IfParams
[i
];
1167 if (i
< _IfParams
.size()-1)
1170 ret
+= " : " + jumpToYes
+ NL
;
1173 if (_IfParams
.empty())
1174 throw EParseException(_Primitive
, "if_bricks need at least one sbrick to test");
1175 ret
= "if_bricks : ";
1176 for (uint i
=0; i
<_IfParams
.size(); ++i
)
1178 ret
+= _IfParams
[i
];
1179 if (i
< _IfParams
.size()-1)
1182 ret
+= " : " + jumpToYes
+ NL
;
1185 if (_IfParams
.empty())
1186 throw EParseException(_Primitive
, "if_sdb need an expression to test");
1188 for (uint i
=0; i
<_IfParams
.size(); ++i
)
1190 ret
+= _IfParams
[i
];
1191 if (i
< _IfParams
.size()-1)
1194 ret
+= " : " + jumpToYes
+ NL
;
1197 if (_IfParams
.empty())
1198 throw EParseException(_Primitive
, "if_race need an expression to test");
1200 for (uint i
=0; i
<_IfParams
.size(); ++i
)
1202 ret
+= _IfParams
[i
];
1203 if (i
< _IfParams
.size()-1)
1206 ret
+= " : " + jumpToYes
+ NL
;
1209 if (_IfParams
.empty())
1210 throw EParseException(_Primitive
, "if_cult need an expression to test");
1212 for (uint i
=0; i
<_IfParams
.size(); ++i
)
1214 ret
+= _IfParams
[i
];
1215 if (i
< _IfParams
.size()-1)
1218 ret
+= " : " + jumpToYes
+ NL
;
1221 if (_IfParams
.empty())
1222 throw EParseException(_Primitive
, "if_civ need an expression to test");
1224 for (uint i
=0; i
<_IfParams
.size(); ++i
)
1226 ret
+= _IfParams
[i
];
1227 if (i
< _IfParams
.size()-1)
1230 ret
+= " : " + jumpToYes
+ NL
;
1232 case it_faction_point
:
1233 if (_IfParams
.empty())
1234 throw EParseException(_Primitive
, "if_faction_point need an expression to test");
1235 ret
= "if_faction_point : ";
1236 for (uint i
=0; i
<_IfParams
.size(); ++i
)
1238 ret
+= _IfParams
[i
];
1239 if (i
< _IfParams
.size()-1)
1242 ret
+= " : " + jumpToYes
+ NL
;
1245 if (_IfParams
.empty())
1246 throw EParseException(_Primitive
, "it_guild_civ need an expression to test");
1247 ret
= "if_guild_civ : ";
1248 for (uint i
=0; i
<_IfParams
.size(); ++i
)
1250 ret
+= _IfParams
[i
];
1251 if (i
< _IfParams
.size()-1)
1254 ret
+= " : " + jumpToYes
+ NL
;
1257 if (_IfParams
.empty())
1258 throw EParseException(_Primitive
, "it_guild_cult need an expression to test");
1259 ret
= "if_guild_cult : ";
1260 for (uint i
=0; i
<_IfParams
.size(); ++i
)
1262 ret
+= _IfParams
[i
];
1263 if (i
< _IfParams
.size()-1)
1266 ret
+= " : " + jumpToYes
+ NL
;
1269 if (_IfParams
.empty())
1270 throw EParseException(_Primitive
, "it_guild_fame need an expression to test");
1271 ret
= "if_guild_fame : ";
1272 for (uint i
=0; i
<_IfParams
.size(); ++i
)
1274 ret
+= _IfParams
[i
];
1275 if (i
< _IfParams
.size()-1)
1278 ret
+= " : " + jumpToYes
+ NL
;
1281 ret
= "if_no_trial : " + jumpToYes
+ NL
;
1283 case it_item_in_inv
:
1284 if (_IfParams
.empty())
1285 throw EParseException(_Primitive
, "if_item_in_inv need at least one mission to test");
1286 for (uint i
=0; i
<_IfParams
.size(); ++i
)
1287 ret
+= "if_item_in_inv : " + _IfParams
[i
] + " : " + jumpToYes
+ NL
;
1291 // Generate the 'no branch'
1293 if (!noSteps
.empty())
1295 ret
+= "# no: " + noSteps
[0]->getStepName() + NL
;
1296 for (uint i
= 0; i
< noSteps
.size(); ++i
)
1298 if ( md
.isThereAJumpTo(noSteps
[i
]->getStepName()) )
1300 // insert a jump point
1301 ret
+= "jump_point : " + noSteps
[i
]->getStepName() + NL
;
1304 ret
+= noSteps
[i
]->genCode(md
);
1308 // Generate the 'yes branch'
1310 if (!yesSteps
.empty())
1312 ret
+= "jump : " + getStepName() + "_endif" + NL
;
1313 ret
+= "# yes: " + yesSteps
[0]->getStepName() + NL
;
1315 for (uint i
= 0; i
< yesSteps
.size(); ++i
)
1317 if ((i
== 0) || md
.isThereAJumpTo(yesSteps
[i
]->getStepName()) )
1319 // insert a jump point
1320 ret
+= "jump_point : " + yesSteps
[i
]->getStepName() + NL
;
1323 ret
+= yesSteps
[i
]->genCode(md
);
1327 // Generate ending jump point
1329 ret
+= "jump_point : " + getStepName() + "_endif" + NL
;
1334 REGISTER_STEP_INDIRECT(CStepIf
, "step_if");
1336 // ////////////// //
1337 // END OF STEP IF //
1338 // ////////////// //
1340 class CStepOOO
: public CStepObjective
1343 CStepOOO(CMissionData
&md
, IPrimitive
*prim
)
1344 : CStepObjective(md
, prim
)
1349 string
genCode(CMissionData
&md
)
1353 ret
+= CStepObjective::genCode(md
);
1355 ret
+= IStep::genCodePreActions(md
);
1359 string tmp
= IStep::genCodeObjectives(md
);
1360 tabulateLine(tmp
, 1);
1365 ret
+= genCodePostActions(md
);
1371 REGISTER_STEP_INDIRECT(CStepOOO
, "step_ooo");
1373 class CStepAny
: public CStepObjective
1376 CStepAny(CMissionData
&md
, IPrimitive
*prim
)
1377 : CStepObjective(md
, prim
)
1381 string
genCode(CMissionData
&md
)
1385 ret
+= CStepObjective::genCode(md
);
1387 ret
+= IStep::genCodePreActions(md
);
1391 string tmp
= IStep::genCodeObjectives(md
);
1392 tabulateLine(tmp
, 1);
1398 ret
+= genCodePostActions(md
);
1404 REGISTER_STEP_INDIRECT(CStepAny
, "step_any");