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) 2013 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
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/>.
20 #include "mission_compiler.h"
23 using namespace NLMISC
;
24 using namespace NLLIGO
;
30 virtual IVar
*createVar(CMissionData
&md
, IPrimitive
*prim
) = 0;
34 template <class VarClass
>
35 class CVarFactory
: public IVarFactory
37 IVar
*createVar(CMissionData
&md
, IPrimitive
*prim
)
39 return new VarClass(md
, prim
);
43 #define REGISTER_VAR_INDIRECT(varClass, key) typedef CVarFactory<varClass> TVarFactory##varClass; \
44 NLMISC_REGISTER_OBJECT_INDIRECT(IVarFactory, TVarFactory##varClass, string, string(key));
47 //#define REGISTER_VARIABLE(className, varName) NLMISC_REGISTER_OBJECT(IVar, className, std::string, string(varName));
49 /* Class for npc variable */
50 class CVarNpc
: public IVar
53 CVarNpc(CMissionData
&md
, IPrimitive
*prim
)
56 _NpcLabel
= getPrimProperty(prim
, "npc_name");
57 _NpcFunction
= getPrimProperty(prim
, "npc_function");
58 if (!_NpcFunction
.empty())
60 _NpcFunction
= "$"+_NpcFunction
+"$";
63 IVar
*nameVar
= CFactoryIndirect
<IVarFactory
, string
>::instance().getFactory("var_npc_name")->createVar(md
, prim
);
64 md
.addVariable(prim
, nameVar
);
67 const std::string
getNpcLabel()
71 const std::string
getNpcFunction()
75 const std::string
getNpcFullName()
77 return _NpcLabel
+_NpcFunction
;
80 string
evalVar(const string
&subPart
)
82 if (subPart
== "fullname")
83 return getNpcFullName();
84 else if (subPart
== "function")
86 else if (subPart
.empty())
89 throw EParseException(NULL
, toString("var_npc don't have a subpart '%s'", subPart
.c_str()).c_str());
92 STRING_MANAGER::TParamType
getStringManagerType()
94 return STRING_MANAGER::bot
;
97 string
genDecl(CMissionData
&md
)
99 return "decl : bot : "+evalVar("")+NL
;
106 REGISTER_VAR_INDIRECT(CVarNpc
, "var_npc");
108 /** Var for npc name (aka bot_name)
109 * This class is implicitly instancied by
112 class CVarNpcName
: public IVar
115 CVarNpcName(CMissionData
&md
, IPrimitive
*prim
)
118 // Change the var name
120 _NpcLabel
= getPrimProperty(prim
, "npc_name");
121 _NpcFunction
= getPrimProperty(prim
, "npc_function");
122 if (!_NpcFunction
.empty())
124 _NpcFunction
= "$"+_NpcFunction
+"$";
128 const std::string
getNpcLabel()
132 const std::string
getNpcFunction()
136 const std::string
getNpcFullName()
138 return _NpcLabel
+_NpcFunction
;
141 string
evalVar(const string
&subPart
)
144 return string("\"")+_NpcLabel
+"\"";
146 throw EParseException(NULL
, toString("var_npc_name don't have a subpart '%s'", subPart
.c_str()).c_str());
149 STRING_MANAGER::TParamType
getStringManagerType()
151 return STRING_MANAGER::bot_name
;
154 string
genDecl(CMissionData
&md
)
163 REGISTER_VAR_INDIRECT(CVarNpcName
, "var_npc_name");
165 /* Class for npc variable */
166 class CVarGroup
: public IVar
169 CVarGroup(CMissionData
&md
, IPrimitive
*prim
)
172 _GroupName
= getPrimProperty(prim
, "group_name");
175 string
evalVar(const string
&subPart
)
179 else if (subPart
== "quoted")
180 return string("\"")+_GroupName
+"\"";
186 STRING_MANAGER::TParamType
getStringManagerType()
188 return STRING_MANAGER::bot_name
;
191 string
genDecl(CMissionData
&md
)
193 // return "decl : bot : "+evalVar("no_quote")+NL;
194 return "decl : bot : "+evalVar("")+NL
;
200 REGISTER_VAR_INDIRECT(CVarGroup
, "var_group");
201 //NLMISC_REGISTER_OBJECT(IVar, CVarGroup, std::string, string("var_group"));
205 class CVarItem
: public IVar
208 CVarItem(CMissionData
&md
, IPrimitive
*prim
)
209 : IVar(vt_item
, prim
)
211 _ItemSheet
= getPrimProperty(prim
, "item_sheet");
214 const std::string
getItemSheet()
219 string
evalVar(const string
&subPart
)
221 nlassert(subPart
.empty());
225 STRING_MANAGER::TParamType
getStringManagerType()
227 return STRING_MANAGER::item
;
230 string
genDecl(CMissionData
&md
)
232 return "decl : item : "+evalVar("")+NL
;
238 REGISTER_VAR_INDIRECT(CVarItem
, "var_item");
239 //NLMISC_REGISTER_OBJECT(IVar, CVarItem, std::string, string("var_item"));
243 class CVarRace
: public IVar
246 CVarRace(CMissionData
&md
, IPrimitive
*prim
)
247 : IVar(vt_item
, prim
)
249 _Race
= getPrimProperty(prim
, "race");
252 string
evalVar(const string
&subPart
)
254 nlassert(subPart
.empty());
258 STRING_MANAGER::TParamType
getStringManagerType()
260 return STRING_MANAGER::race
;
263 string
genDecl(CMissionData
&md
)
265 return "decl : race : "+evalVar("")+NL
;
271 REGISTER_VAR_INDIRECT(CVarRace
, "var_race");
273 /* Class for sphrase */
274 class CVarSPhrase
: public IVar
277 CVarSPhrase(CMissionData
&md
, IPrimitive
*prim
)
278 : IVar(vt_item
, prim
)
280 _SPhrase
= getPrimProperty(prim
, "sphrase_sheet");
283 string
evalVar(const string
&subPart
)
285 nlassert(subPart
.empty());
289 STRING_MANAGER::TParamType
getStringManagerType()
291 return STRING_MANAGER::sphrase
;
294 string
genDecl(CMissionData
&md
)
296 return "decl : sphrase : "+evalVar("")+NL
;
302 REGISTER_VAR_INDIRECT(CVarSPhrase
, "var_sphrase");
304 /* Class for sbrick */
305 class CVarSBrick
: public IVar
308 CVarSBrick(CMissionData
&md
, IPrimitive
*prim
)
309 : IVar(vt_item
, prim
)
311 _SBrick
= getPrimProperty(prim
, "sbrick_sheet");
314 string
evalVar(const string
&subPart
)
316 nlassert(subPart
.empty());
320 STRING_MANAGER::TParamType
getStringManagerType()
322 return STRING_MANAGER::sbrick
;
325 string
genDecl(CMissionData
&md
)
327 return "decl : sbrick : "+evalVar("")+NL
;
333 REGISTER_VAR_INDIRECT(CVarSBrick
, "var_sbrick");
336 /* for special item */
337 const char *SpecialItemProp
[] =
347 "AdversaryDodgeModifier",
348 "AdversaryParryModifier",
350 "MaxSlashingProtection",
351 "MaxBluntProtection",
352 "MaxPiercingProtection",
365 /* Class for special item */
366 class CVarSpecialItem
: public IVar
369 CVarSpecialItem(CMissionData
&md
, IPrimitive
*prim
)
370 : IVar(vt_item
, prim
)
372 static bool init
= false;
373 static set
<string
> propertyNames
;
377 for (uint i
=0; i
<sizeof(SpecialItemProp
)/sizeof(char*); ++i
)
378 propertyNames
.insert(SpecialItemProp
[i
]);
383 _ItemSheet
= getPrimProperty(prim
, "item_sheet");
384 _ReqSkill
= getPrimProperty(prim
, "req_skill_level");
386 vs
= getPrimPropertyArray(prim
, "properties/values");
387 // parse the strings vector
388 for (uint i
=0; i
<vs
.size(); ++i
)
390 vector
<string
> parts
;
391 explode(vs
[i
], string(" "), parts
, true);
392 if (!parts
.empty() && parts
.size() != 2)
394 string s
= toString("Invalid special item property at line %u", i
+1);
395 throw EParseException(prim
, s
.c_str());
398 if (parts
.size() == 2)
401 ip
.PropName
= parts
[0];
402 ip
.PropValue
= parts
[1];
404 if (propertyNames
.find(ip
.PropName
) == propertyNames
.end())
406 string s
= toString("Invalid property name '%s'", ip
.PropName
.c_str());
407 throw EParseException(prim
, s
.c_str());
410 _Properties
.push_back(ip
);
413 _Action
= getPrimProperty(prim
, "item_action");
415 vs
= getPrimPropertyArray(prim
, "phrase_item_name");
416 _ItemPhrase
.initPhrase(md
, prim
, vs
);
419 s
= getPrimProperty(prim
, "no_drop");
420 _NoDrop
= (s
== "true");
423 // const std::string getItemSheet()
425 // return _ItemSheet;
428 string
evalVar(const string
&subPart
)
430 nlassert(subPart
.empty());
434 STRING_MANAGER::TParamType
getStringManagerType()
436 return STRING_MANAGER::item
;
439 string
genDecl(CMissionData
&md
)
441 string ret
= string("decl_item : ")+_VarName
+" : "+_ItemSheet
+" : "+_ReqSkill
;
442 if (!_Properties
.empty() ||!_Action
.empty())
444 for (uint i
=0; i
<_Properties
.size(); ++i
)
446 TItemProperty
&ip
= _Properties
[i
];
447 ret
+= ip
.PropName
+" "+ip
.PropValue
;
448 if (i
< _Properties
.size()-1 || !_Action
.empty())
452 if (!_Action
.empty())
455 ret
+= " : "+_ItemPhrase
.genScript(md
);
465 std::string
genPhrase()
467 return _ItemPhrase
.genPhrase();
472 /// the item sheet used as base for this special item
474 /// The skill required to use the item
476 /// The list of properties
477 vector
<TItemProperty
> _Properties
;
478 // Optional action (enchantement)
489 REGISTER_VAR_INDIRECT(CVarSpecialItem
, "var_special_item");
490 //NLMISC_REGISTER_OBJECT(IVar, CVarSpecialItem, std::string, string("var_special_item"));
492 /* Class for place variable */
493 class CVarPlace
: public IVar
496 CVarPlace(CMissionData
&md
, IPrimitive
*prim
)
499 _PlaceLabel
= getPrimProperty(prim
, "place_name");
502 /* const std::string getPlaceLabel()
507 string
evalVar(const string
&subPart
)
509 nlassert(subPart
.empty());
513 STRING_MANAGER::TParamType
getStringManagerType()
515 return STRING_MANAGER::place
;
518 string
genDecl(CMissionData
&md
)
520 return "decl : place : "+evalVar("")+NL
;
526 REGISTER_VAR_INDIRECT(CVarPlace
, "var_place");
527 //NLMISC_REGISTER_OBJECT(IVar, CVarPlace, std::string, string("var_place"));
529 /* Class for integer variable */
530 class CVarInteger
: public IVar
533 CVarInteger(CMissionData
&md
, IPrimitive
*prim
)
534 : IVar(vt_integer
, prim
)
536 if (prim
->checkProperty("value"))
537 _Value
= getPrimProperty(prim
, "value");
538 else if (prim
->checkProperty("quantity"))
539 _Value
= getPrimProperty(prim
, "quantity");
540 else if (prim
->checkProperty("quality"))
541 _Value
= getPrimProperty(prim
, "quality");
544 string err
= toString("Can't find a valid property for integer variable");
545 throw EParseException(prim
, err
.c_str());
549 const std::string
getIntegerValue()
554 string
evalVar(const string
&subPart
)
556 nlassert(subPart
.empty());
560 STRING_MANAGER::TParamType
getStringManagerType()
562 return STRING_MANAGER::integer
;
565 string
genDecl(CMissionData
&md
)
567 // nothing to declare for this pseudo var
573 REGISTER_VAR_INDIRECT(CVarInteger
, "var_integer");
574 //NLMISC_REGISTER_OBJECT(IVar, CVarInteger, std::string, string("var_integer"));
575 typedef CVarInteger CVarQuantity
;
576 REGISTER_VAR_INDIRECT(CVarQuantity
, "var_quantity");
577 //NLMISC_REGISTER_OBJECT(IVar, CVarQuantity, std::string, string("var_quantity"));
578 typedef CVarInteger CVarQuality
;
579 REGISTER_VAR_INDIRECT(CVarQuality
, "var_quality");
580 //NLMISC_REGISTER_OBJECT(IVar, CVarQuality, std::string, string("var_quality"));
583 /* Class for text var */
584 class CVarText
: public IVar
587 CVarText(CMissionData
&md
, IPrimitive
*prim
)
588 : IVar(vt_item
, prim
)
590 _TextValue
= getPrimPropertyArray(prim
, "text");
593 const vector
<std::string
> &getText()
598 string
evalVar(const string
&subPart
)
600 nlassert(subPart
.empty());
602 return std::accumulate(_TextValue
.begin(), _TextValue
.end(), string(""));
606 STRING_MANAGER::TParamType
getStringManagerType()
609 return STRING_MANAGER::NB_PARAM_TYPES
;
612 string
genDecl(CMissionData
&md
)
614 // nothing to declare for this one
618 vector
<string
> _TextValue
;
620 REGISTER_VAR_INDIRECT(CVarText
, "var_text");
621 //NLMISC_REGISTER_OBJECT(IVar, CVarText, std::string, string("var_text"));
623 /* Class for creature var */
624 class CVarCreature
: public IVar
627 CVarCreature(CMissionData
&md
, IPrimitive
*prim
)
628 : IVar(vt_item
, prim
)
630 _CreatureSheet
= getPrimProperty(prim
, "creature_sheet");
633 string
evalVar(const string
&subPart
)
635 nlassert(subPart
.empty());
636 return _CreatureSheet
;
639 STRING_MANAGER::TParamType
getStringManagerType()
641 // return STRING_MANAGER::creature;
642 return STRING_MANAGER::creature_model
;
645 string
genDecl(CMissionData
&md
)
647 // declare a creature sheet
648 // return "decl : creature : "+_CreatureSheet+NL;
649 return "decl : creature_model : "+_CreatureSheet
+NL
;
652 string _CreatureSheet
;
654 REGISTER_VAR_INDIRECT(CVarCreature
, "var_creature");
655 //NLMISC_REGISTER_OBJECT(IVar, CVarCreature, std::string, string("var_creature"));
657 /* Class for faction var */
658 class CVarFaction
: public IVar
661 CVarFaction(CMissionData
&md
, IPrimitive
*prim
)
662 : IVar(vt_item
, prim
)
664 _FactionName
= getPrimProperty(prim
, "faction_name");
667 string
evalVar(const string
&subPart
)
669 nlassert(subPart
.empty());
673 STRING_MANAGER::TParamType
getStringManagerType()
675 return STRING_MANAGER::faction
;
678 string
genDecl(CMissionData
&md
)
680 // declare a creature sheet
681 return "decl : faction : "+_FactionName
+NL
;
686 REGISTER_VAR_INDIRECT(CVarFaction
, "var_faction");
687 //NLMISC_REGISTER_OBJECT(IVar, CVarFaction, std::string, string("var_faction"));
690 IVar
*IVar::createVar(CMissionData
&md
, IPrimitive
*prim
)
693 if (!prim
->getPropertyByName("class", c
))
694 throw EParseException(prim
, "Can't find property 'class' on primitive");
696 return CFactoryIndirect
<IVarFactory
, string
>::instance().getFactory(*c
)->createVar(md
, prim
);
700 //IVar *IVar::createVar(CMissionData &md, IPrimitive *prim)
702 // string *className;
703 // if (!prim->getPropertyByName("class", className))
704 // throw EParseException(prim, "Can't find property 'class' in primitive");
706 // IVar *ret = NLMISC_GET_FACTORY_INDIRECT(IVar, std::string).createObject(md, *className, prim);