Added ai command setEquipment
[ryzomcore.git] / ryzom / server / src / ai_service / ai_outpost_actions.cpp
blob64b0d9720461fa3cbe921d84b87d93fc1ec45e22
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 //
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/>.
23 //----------------------------------------------------------------------------
25 #include "stdpch.h"
26 #include "ais_actions.h"
27 #include "ai_outpost.h"
28 #include "continent.h"
29 #include "continent_inline.h"
32 using namespace NLMISC;
33 using namespace NLNET;
34 using namespace std;
35 using namespace CAISActionEnums;
38 extern CAIInstance *currentInstance;
40 DEFINE_ACTION(ContextGlobal,SQD_TMPL)
42 nlassertex(currentInstance != NULL, ("No AIInstance created !"));
43 CWorkPtr::aiInstance(currentInstance);
44 CAIInstance *aii = CWorkPtr::aiInstance();
46 CAIAliasDescriptionNode *aliasTree;
47 string filename;
48 if (!getArgs(args, name(), aliasTree, filename))
49 return;
51 CContextStack::setContext(ContextSquadTemplate);
54 DEFINE_ACTION(ContextSquadTemplate,SQD_T_V)
56 string templateName, variantTag;
57 if ( !getArgs(args, name(), templateName, variantTag))
58 return;
60 CAIInstance *aii = CWorkPtr::aiInstance();
61 CWorkPtr::squadVariantName(templateName + ":" + variantTag);
63 CContextStack::setContext(ContextSquadTemplateVariant);
66 DEFINE_ACTION(ContextOutpostGroupDesc,IDTREE_F)
68 // IDTREE "flat": instead of browsing nodes, we build tree from the argument vector
70 if (!CWorkPtr::groupDesc())
71 return;
73 // read the bot sheet vector from the argument list
74 vector<string> botSheets( args.size() );
75 for ( uint i=0; i!=args.size(); ++i )
77 args[i].get( botSheets[i] );
79 // Remove .creature suffix if present
80 string::size_type p = botSheets[i].find( ".creature" );
81 if ( p != string::npos )
82 botSheets[i].erase( p );
84 if ( botSheets.empty() )
86 OUTPOST_WRN( "No bot sheets specified in %s => no squad", CWorkPtr::groupDesc()->getFullName().c_str() );
87 return;
90 // build the bot nodes
91 CAliasTreeOwner *owner = dynamic_cast<CAliasTreeOwner *>(CWorkPtr::groupDesc());
92 if ( ! owner )
94 OUTPOST_WRN( "Invalid squad group desc %s", CWorkPtr::groupDesc()->getFullName().c_str() );
95 return;
98 owner->pushCurrentOwnerList();
99 for ( uint j=0; j!=botSheets.size(); ++j )
101 CAliasTreeOwner* childOwner = NULL;
102 IAliasCont* cont = NULL;
104 // we try to get a valid IAliasCont for this type
105 if ( ! owner->getCont( childOwner, cont, AITYPES::AITypeSquadTemplateMember ) )
106 break;
108 // create a bot desc object (with alias 0)
109 CAliasTreeOwner* child = NULL;
110 CSmartPtr<CAIAliasDescriptionNode> fakeNode = new CAIAliasDescriptionNode( /*NLMISC::toString( "tm%u", j )*/botSheets[j], 0, AITYPES::AITypeSquadTemplateMember, NULL );
111 child = childOwner->createChild( cont, fakeNode );
112 if ( ! child )
114 OUTPOST_WRN( "Can't create child %s of squad template variant %s", botSheets[j].c_str(), owner->getName().c_str() );
116 else
118 CBotDesc<COutpostSquadFamily>* botDesc = dynamic_cast< CBotDesc<COutpostSquadFamily>* >(child);
119 nlassert( botDesc );
120 botDesc->setSheet( botSheets[j] );
121 botDesc->setUseSheetBotName(true);
124 owner->popCurrentOwnerList();
127 DEFINE_ACTION(ContextGlobal,OUTPOST)
129 nlassertex(currentInstance != NULL, ("No AIInstance created !"));
130 CWorkPtr::aiInstance(currentInstance);
131 CAIInstance *aii = CWorkPtr::aiInstance();
133 CAIAliasDescriptionNode *aliasTree;
134 string contName, mapName, filename, familyName;
135 if (!getArgs(args, name(), aliasTree, contName, filename, familyName))
136 return;
138 if (!CWorkPtr::continent())
139 return;
141 // see whether the region is already created
142 COutpost *outpost = CWorkPtr::continent()->outposts().getChildByAlias(aliasTree->getAlias());
144 // not found so create it
145 if (!outpost)
147 outpost = new COutpost(CWorkPtr::continent(), aliasTree->getAlias(), aliasTree->getName(), filename);
149 CWorkPtr::continent()->outposts().addAliasChild(outpost);
150 CWorkPtr::outpost(outpost);
152 else
154 outpost->registerForFile(filename);
157 // set the owner tribe
158 CWorkPtr::outpost()->setTribe(familyName);
160 CContextStack::setContext(ContextOutpost);
164 DEFINE_ACTION(ContextOutpost,OUTP_SQD)
166 CAIInstance *aii = CWorkPtr::aiInstance();
167 COutpost *outpost = CWorkPtr::outpost();
168 if (!outpost)
169 return;
171 set<string> squads;
172 string variantTag;
174 // read the variant tag (first element of vector)
175 nlassert( ! args.empty() );
176 args[0].get( variantTag );
178 // read the squads (skip first element of vector; avoid duplicates)
179 for ( uint i=1; i!=args.size(); ++i )
181 string s;
182 args[i].get( s );
183 squads.insert( s );
186 // link outpost to squads
187 for ( set<string>::const_iterator its=squads.begin(); its!=squads.end(); ++its )
189 string variantName = (*its);
190 if ( variantName.find( ':' ) == string::npos ) // the leveldesigner can specify which variant he wants
191 variantName += ":" + variantTag;
192 CGroupDesc<COutpostSquadFamily> *groupDesc = aii->getSquadByVariantName( variantName );
193 if ( groupDesc )
194 outpost->addSquadLink( groupDesc->getAlias(), groupDesc );
195 else
196 OUTPOST_WRN( "Can't find squad %s for outpost %s", variantName.c_str(), outpost->getName().c_str() );
200 DEFINE_ACTION(ContextOutpost,IDTREE)
202 // set the id tree for the region (results in creation or update of region's object tree)
203 // args: aliasTree
205 if (!CWorkPtr::outpost())
206 return;
208 // read the alias tree from the argument list
209 CAIAliasDescriptionNode *aliasTree;
210 if (!getArgs(args, name(),aliasTree))
211 return;
214 // have the manager update it's structure from the id tree
215 nlinfo("ACTION IDTREE: Applying new tree to outpost[%u]: '%s'%s in continent '%s'",
216 CWorkPtr::outpost()->getChildIndex(),
217 CWorkPtr::outpost()->getName().c_str(),
218 CWorkPtr::outpost()->getAliasString().c_str(),
219 CWorkPtr::outpost()->getOwner()->getName().c_str()
222 if (aliasTree && CWorkPtr::outpost())
223 CWorkPtr::outpost()->updateAliasTree(*aliasTree);
226 DEFINE_ACTION(ContextOutpost,OUTPOGEO)
228 COutpost* outpost = CWorkPtr::outpost();
229 if (!outpost)
230 return;
232 std::vector <CAIVector> points;
233 for (uint i=0; i<(args.size()-1); i+=2)
235 double x, y;
236 args[i].get(x);
237 args[i+1].get(y);
238 points.push_back(CAIVector(x, y));
240 NLMISC::CSmartPtr<CAIPlaceOutpost> shape = NLMISC::CSmartPtr<CAIPlaceOutpost>(new CAIPlaceOutpost(outpost));
241 shape->setPatat(AITYPES::vp_auto, points);
242 shape->setOutpostAlias(outpost->getAlias());
243 outpost->setShape(shape);
246 DEFINE_ACTION(ContextOutpost,SPWNZONE)
248 COutpost* outpost = CWorkPtr::outpost();
249 if (!outpost)
250 return;
252 float x, y, r;
253 uint32 verticalPos;
254 // read the alias tree from the argument list
255 CAIAliasDescriptionNode* aliasTree;
256 if (!getArgs(args, name(), aliasTree, x, y, r, verticalPos))
257 return;
259 // see whether the region is already loaded
260 COutpostSpawnZone* spawnZone = outpost->spawnZones().getChildByAlias(aliasTree->getAlias());
261 if (!spawnZone)
262 return;
264 spawnZone->setPosAndRadius((AITYPES::TVerticalPos)verticalPos, CAIPos(x, y, 0, 0.f), uint32(r*1000));
267 DEFINE_ACTION(ContextOutpost,BUILDING)
269 /****************************************************************************/
271 COutpost* outpost = CWorkPtr::outpost();
272 if (!outpost)
273 return;
275 float x, y, theta;
276 uint32 verticalPos;
277 // read the alias tree from the argument list
278 CAIAliasDescriptionNode* aliasTree;
279 if (!getArgs(args, name(), aliasTree, x, y, theta, verticalPos))
280 return;
282 // see whether the region is already loaded
283 COutpostSpawnZone* spawnZone = outpost->spawnZones().getChildByAlias(aliasTree->getAlias());
284 if (!spawnZone)
285 return;
287 spawnZone->setPosAndRadius((AITYPES::TVerticalPos)verticalPos, CAIPos(x, y, 0, 0.f), uint32(r*1000));
289 /****************************************************************************/
290 COutpost* outpost = CWorkPtr::outpost();
291 if (!outpost)
292 return;
293 CGroup* grp = outpost->getBuildingGroup();
294 if (!grp)
295 return;
297 uint32 alias;
298 if (!getArgs(args, name(), alias))
299 return;
301 // LOG("Outpost Building: group: %s, bot: %u", grp->getFullName().c_str(), alias);
303 // set workptr::bot to this bot
304 CWorkPtr::bot(grp->bots().getChildByAlias(alias)); //lookupBotInGrpNpc(alias));
305 if (!CWorkPtr::botNpc())
307 nlwarning("Failed to select bot %s as not found in group: %s",
308 LigoConfig.aliasToString(alias).c_str(),
309 CWorkPtr::grpNpc()->getName().c_str());
310 return;
313 if (!(CWorkPtr::botNpc()->getChat().isNull()))
315 CWorkPtr::botNpc()->getChat()->clearMissions();
318 // set workptr state to this state
319 CContextStack::setContext(ContextNpcBot);
322 DEFINE_ACTION(ContextOutpost,PLACE)
324 COutpost *outpost = CWorkPtr::outpost();
325 if (!outpost)
326 return;
328 float x,y;
330 if (!getArgs(args,name(), x, y))
331 return;
333 outpost->setPosition(CAIVector(x, y));
337 DEFINE_ACTION(ContextOutpost,CHARGE)
339 COutpost *outpost = CWorkPtr::outpost();
340 if (!outpost)
341 return;
343 // read the alias tree from the argument list
344 CAIAliasDescriptionNode *aliasTree;
345 string civilisation;
346 if (!getArgs(args, name(), aliasTree, civilisation))
347 return;
349 // see whether the outpost charge is already loaded
350 COutpostCharge *charge = outpost->charges().getChildByAlias(aliasTree->getAlias());
351 if (!charge)
352 return;
354 charge->setCivilisation(civilisation);
356 CWorkPtr::outpostCharge(charge);
357 CContextStack::setContext(ContextOutpostCharge);
361 DEFINE_ACTION(ContextOutpost,CHGPARM)
363 COutpostCharge *charge = CWorkPtr::outpostCharge();
364 if (!charge)
365 return;
367 vector<string> params;
368 for (uint i=0; args.size(); ++i)
370 string s;
371 args[i].get(s);
372 params.push_back(s);
375 charge->setParams(params);
378 /*DEFINE_ACTION(ContextOutpost,SQUADFAM)
380 COutpost *outpost = CWorkPtr::outpost();
381 if (!outpost)
382 return;
384 CAIAliasDescriptionNode *aliasTree;
385 if (!getArgs(args, name(), aliasTree))
386 return;
388 COutpostSquadFamily* squadFamily = outpost->squadFamilies().getChildByAlias(aliasTree->getAlias());
389 if (!squadFamily)
390 return;
392 CWorkPtr::outpostSquadFamily(squadFamily);
393 CContextStack::setContext(ContextOutpostSquadFamily);
396 static void DoMgrAction(
397 std::vector <CAIActions::CArg> const& args,
398 AITYPES::TMgrType type,
399 CAISActionEnums::TContext context)
401 // nlassertex(currentInstance != NULL, ("No AIInstance created !"));
402 // CAIInstance* aiInstance = currentInstance;
403 // CWorkPtr::aiInstance(aiInstance); // set the current AIInstance.
404 COutpost* outpost = CWorkPtr::outpost();
406 // get hold of the manager's slot id - note that managers are identified by slot and not by alias!
407 uint32 alias;
408 std::string name, mapName, filename;
409 bool manualSpawn = true;
410 if (type==AITYPES::MgrTypeOutpost)
412 if (!getArgs(args, "MANAGER", alias, name, mapName, filename, manualSpawn))
413 return;
415 else
417 if (!getArgs(args, "MANAGER", alias, name, mapName, filename))
418 return;
421 // see whether the manager is already loaded
422 COutpostManager* mgr = static_cast<COutpostManager*>(outpost->managers().getChildByAlias(alias));
424 // not found so look for a free slot
425 nlassert(mgr);
426 // outpost->newMgr(type, alias, name, mapName, filename);
427 mgr->registerForFile(filename);
428 mgr->setAutoSpawn(!manualSpawn);
430 mgr = outpost->managers().getChildByAlias(alias);
432 // setup the working manager pointer and exit
433 CWorkPtr::mgr(mgr);
434 if (mgr)
435 CWorkPtr::eventReactionContainer(mgr->getStateMachine());
436 else
437 CWorkPtr::eventReactionContainer(NULL);
439 // push the manager context onto the context stack
440 CContextStack::setContext(context);
444 DEFINE_ACTION(ContextOutpost,MGRNPC)
446 DoMgrAction(args, AITYPES::MgrTypeNpc, CAISActionEnums::ContextNpcMgr);
449 DEFINE_ACTION(ContextOutpost,MGROUTPO)
451 DoMgrAction(args, AITYPES::MgrTypeOutpost, CAISActionEnums::ContextNpcMgr);
455 DEFINE_ACTION(ContextOutpostSquadFamily,IDTREE)
457 // set the id tree for the region (results in creation or update of region's object tree)
458 // args: aliasTree
460 if (!CWorkPtr::outpostSquadFamily())
461 return;
463 // read the alias tree from the argument list
464 CAIAliasDescriptionNode *aliasTree;
465 if (!getArgs(args, name(),aliasTree))
466 return;
469 // have the manager update it's structure from the id tree
470 nlinfo("ACTION IDTREE: Applying new tree to outpost[%u]: '%s'%s in continent '%s'",
471 CWorkPtr::outpostSquadFamily()->getChildIndex(),
472 CWorkPtr::outpostSquadFamily()->getName().c_str(),
473 CWorkPtr::outpostSquadFamily()->getAliasString().c_str(),
474 CWorkPtr::outpostSquadFamily()->getOwner()->getName().c_str()
477 if (aliasTree && CWorkPtr::outpostSquadFamily())
478 CWorkPtr::outpostSquadFamily()->updateAliasTree(*aliasTree);
481 DEFINE_ACTION(ContextSquadTemplateVariant,GRPTMPL)
483 CAIInstance *aii = CWorkPtr::aiInstance();
484 COutpostSquadFamily* const squadFamily = aii->getSquadFamily();
485 if (!squadFamily)
486 return;
488 string grpFamily; // Ignored
489 uint32 botCount;
490 bool countMultipliedBySheet;
491 bool multiLevel;
493 // read the alias tree from the argument list
494 CAIAliasDescriptionNode* aliasTree;
495 if (!getArgs(args, name(), aliasTree, grpFamily, botCount, countMultipliedBySheet, multiLevel))
496 return;
498 IAliasCont *aliasCont = squadFamily->getAliasCont( AITYPES::AITypeGroupTemplate );
499 CAliasTreeOwner *child = squadFamily->createChild( aliasCont, aliasTree );
500 CGroupDesc<COutpostSquadFamily> *groupDesc = (dynamic_cast<CGroupDesc<COutpostSquadFamily>*>(child));
501 if (!groupDesc)
502 return;
504 aii->registerSquadVariant( CWorkPtr::squadVariantName(), groupDesc );
505 CWorkPtr::groupDesc( groupDesc );
507 groupDesc->setBaseBotCount(botCount);
508 groupDesc->setCountMultiplierFlag(countMultipliedBySheet);
509 groupDesc->setMultiLevel(multiLevel);
511 CContextStack::setContext(ContextOutpostGroupDesc);
514 //////////////////////////////////////////////////////////////////////////////
515 // ContextGroupDesc actions instances //
516 //////////////////////////////////////////////////////////////////////////////
519 //////////////////////////////////////////////////////////////////////////////
520 // ContextGroupDesc actions //
521 //////////////////////////////////////////////////////////////////////////////
523 /// :KLUDGE: This code is copied from continent_inline.h. Update both if you
524 /// make a modification.
525 DEFINE_ACTION_TEMPLATE1(ContextOutpostGroupDesc,GT_SHEE,FamilyT)
527 CGroupDesc<FamilyT>* groupDesc = static_cast<CGroupDesc<FamilyT>*>(CWorkPtr::groupDesc());
528 if (!groupDesc)
529 return;
531 string lookSheet;
533 if (!getArgs(args,name(), lookSheet))
534 return;
536 if (!groupDesc->setSheet(lookSheet))
538 groupDesc->getOwner()->groupDescs().removeChildByIndex(groupDesc->getChildIndex());
539 CWorkPtr::groupDesc(NULL);
540 return;
544 /// :KLUDGE: This code is copied from continent_inline.h. Update both if you
545 /// make a modification.
546 DEFINE_ACTION_TEMPLATE1(ContextOutpostGroupDesc,GT_LVLD,FamilyT)
548 CGroupDesc<FamilyT>* groupDesc = static_cast<CGroupDesc<FamilyT>*>(CWorkPtr::groupDesc());
549 if (!groupDesc)
550 return;
552 sint32 levelDelta;
554 if (!getArgs(args,name(), levelDelta))
555 return;
557 groupDesc->setLevelDelta(levelDelta);
560 /// :KLUDGE: This code is copied from continent_inline.h. Update both if you
561 /// make a modification.
562 DEFINE_ACTION_TEMPLATE1(ContextOutpostGroupDesc,GT_SEAS,FamilyT)
564 CGroupDesc<FamilyT>* groupDesc = static_cast<CGroupDesc<FamilyT>*>(CWorkPtr::groupDesc());
565 if (!groupDesc)
566 return;
568 bool seasons[4];
570 if (!getArgs(args,name(), seasons[0], seasons[1], seasons[2], seasons[3]))
571 return;
573 groupDesc->setSeasonFlags(seasons);
576 /// :KLUDGE: This code is copied from continent_inline.h. Update both if you
577 /// make a modification.
578 DEFINE_ACTION_TEMPLATE1(ContextOutpostGroupDesc,GT_ACT,FamilyT)
580 CGroupDesc<FamilyT>* groupDesc = static_cast<CGroupDesc<FamilyT>*>(CWorkPtr::groupDesc());
581 if (!groupDesc)
582 return;
584 uint32 spawnType;
585 if (!getArgs(args, name(), spawnType))
586 return;
588 groupDesc->setSpawnType((AITYPES::TSpawnType)spawnType);
591 /// :KLUDGE: This code is copied from continent_inline.h. Update both if you
592 /// make a modification.
593 DEFINE_ACTION_TEMPLATE1(ContextOutpostGroupDesc,GT_APRM,FamilyT)
595 CGroupDesc<FamilyT>* groupDesc = static_cast<CGroupDesc<FamilyT>*>(CWorkPtr::groupDesc());
596 if (!groupDesc)
597 return;
599 for (size_t i=0; i<args.size(); ++i)
601 string property;
602 args[i].get(property);
603 groupDesc->properties().addProperty(AITYPES::CPropertyId::create(property));
607 /// :KLUDGE: This code is copied from continent_inline.h. Update both if you
608 /// make a modification.
609 DEFINE_ACTION_TEMPLATE1(ContextOutpostGroupDesc,GT_NRG,FamilyT)
611 CGroupDesc<FamilyT>* groupDesc = static_cast<CGroupDesc<FamilyT>*>(CWorkPtr::groupDesc());
612 if (!groupDesc)
613 return;
615 uint32 weight[4];
617 if (!getArgs(args,name(), weight[0], weight[1], weight[2], weight[3]))
618 return;
620 groupDesc->setWeightLevels(weight);
623 /// :KLUDGE: This code is copied from continent_inline.h. Update both if you
624 /// make a modification.
625 DEFINE_ACTION_TEMPLATE1(ContextOutpostGroupDesc,GT_EQUI,FamilyT)
627 CGroupDesc<FamilyT>* groupDesc = static_cast<CGroupDesc<FamilyT>*>(CWorkPtr::groupDesc());
628 if (!groupDesc)
629 return;
631 groupDesc->botEquipment().clear();
633 for (size_t i=0; i<args.size(); ++i)
635 string equip;
636 args[i].get(equip);
637 groupDesc->botEquipment().push_back(equip);
641 /// :KLUDGE: This code is copied from continent_inline.h. Update both if you
642 /// make a modification.
643 DEFINE_ACTION_TEMPLATE1(ContextOutpostGroupDesc,GT_GPRM,FamilyT)
645 CGroupDesc<FamilyT>* groupDesc = static_cast<CGroupDesc<FamilyT>*>(CWorkPtr::groupDesc());
646 if (!groupDesc)
647 return;
649 for (size_t i=0; i<args.size(); ++i)
651 string param;
652 args[i].get(param);
654 param = NLMISC::toLowerAscii(param);
656 if ( param == "contact camp"
657 || param == "contact outpost"
658 || param == "contact city"
659 || param == "boss" )
660 groupDesc->properties().addProperty(param);
661 else // unreconized param, leace it for the group instance
662 groupDesc->grpParameters().push_back(param);
666 /// :KLUDGE: This code is copied from continent_inline.h. Update both if you
667 /// make a modification.
668 DEFINE_ACTION_TEMPLATE1(ContextOutpostGroupDesc,BOTTMPL,FamilyT)
670 CGroupDesc<FamilyT>* groupDesc = static_cast<CGroupDesc<FamilyT>*>(CWorkPtr::groupDesc());
671 if (!groupDesc)
672 return;
674 string lookSheet;
675 bool multiLevel;
677 // read the alias tree from the argument list
678 CAIAliasDescriptionNode* aliasTree;
679 if (!getArgs(args, name(), aliasTree, lookSheet, multiLevel))
680 return;
682 // see whether the region is already loaded
683 CBotDesc<FamilyT>* botDesc = groupDesc->botDescs().getChildByAlias(aliasTree->getAlias());
684 if (!botDesc)
685 return;
687 botDesc->setMultiLevel(multiLevel);
688 botDesc->setSheet(lookSheet);
690 CWorkPtr::botDesc(botDesc);
691 CContextStack::setContext(ContextOutpostBotDesc);
694 /// :KLUDGE: This code is copied from continent_inline.h. Update both if you
695 /// make a modification.
696 DEFINE_ACTION_TEMPLATE1(ContextOutpostBotDesc,BT_EQUI,FamilyT)
698 CBotDesc<FamilyT>* botDesc = static_cast<CBotDesc<FamilyT>*>(CWorkPtr::botDesc());
699 if (!botDesc)
700 return;
702 for (size_t i=0; i<args.size(); ++i)
704 string equip;
705 args[i].get(equip);
706 botDesc->equipement().push_back(equip);
710 /// :KLUDGE: This code is copied from continent_inline.h. Update both if you
711 /// make a modification.
712 DEFINE_ACTION_TEMPLATE1(ContextOutpostBotDesc,BT_LVLD,FamilyT)
714 CBotDesc<FamilyT>* botDesc = static_cast<CBotDesc<FamilyT>*>(CWorkPtr::botDesc());
715 if (!botDesc)
716 return;
718 sint32 levelDelta;
720 if (!getArgs(args,name(), levelDelta))
721 return;
723 botDesc->setLevelDelta(levelDelta);
727 /// :KLUDGE: This code is copied from continent_inline.h. Update both if you
728 /// make a modification.
729 DEFINE_ACTION_TEMPLATE1(ContextOutpostGroupDesc,GT_GNRJ,FamilyT)
731 CGroupDesc<FamilyT>* groupDesc = static_cast<CGroupDesc<FamilyT>*>(CWorkPtr::groupDesc());
732 if (!groupDesc)
733 return;
735 uint32 energyValue;
737 if (!getArgs(args,name(), energyValue))
738 return;
741 /// :KLUDGE: This code is copied from continent_inline.h. Update both if you
742 /// make a modification.
743 DEFINE_ACTION_TEMPLATE1(ContextOutpostGroupDesc,POPVER,FamilyT)
745 // add a population version for a group
746 // args: uint32 alias, string spawn_type, uint weight, (string sheet, uint32 count)+
748 if(!CWorkPtr::groupDesc())
749 return;
751 const uint32 fixedArgsCount = 0;
752 if (args.size()<fixedArgsCount+2 || ((args.size()-fixedArgsCount)&1)==1)
754 nlwarning("POPVER action FAILED due to bad number of arguments (%d)", args.size());
755 return;
758 // get hold of the parameters and check their validity
759 for (size_t i=fixedArgsCount; i+1<args.size(); i+=2)
761 std::string sheet;
762 uint32 count;
764 if ( !args[i].get(sheet)
765 || !args[i+1].get(count))
767 nlwarning("POPVER Add Record FAILED due to bad arguments");
768 continue;
771 CSheetId sheetId(sheet);
772 if (sheetId==CSheetId::Unknown)
774 nlwarning("POPVER Add Record Invalid sheet: %s", sheet.c_str());
775 continue;
778 AISHEETS::ICreatureCPtr sheetPtr = AISHEETS::CSheets::getInstance()->lookup(sheetId);
779 if (!sheetPtr)
781 nlwarning("POPVER Add Record Invalid sheet: %s", sheet.c_str());
782 continue;
784 static_cast<CGroupDesc<FamilyT>*>(CWorkPtr::groupDesc())->populationRecords().push_back(CPopulationRecord(sheetPtr, count));
789 /// :KLUDGE: This code is copied from continent_inline.h. Update both if you
790 /// make a modification.
791 // scales bot energy .. to match with group's one.
792 DEFINE_ACTION_TEMPLATE1(ContextOutpostGroupDesc,GT_END,FamilyT)
794 CGroupDesc<FamilyT>* groupDesc = static_cast<CGroupDesc<FamilyT>*>(CWorkPtr::groupDesc());
795 if (!groupDesc)
796 return;
798 if (!groupDesc->isMultiLevel())
800 uint32 totalEnergyValue = groupDesc->calcTotalEnergyValue();
801 if (totalEnergyValue)
803 double coef = (double)groupDesc->groupEnergyValue()/(double)totalEnergyValue;
804 groupDesc->setGroupEnergyCoef((float)coef);
806 else
808 nlwarning("exists some empty template groups");
813 // O for outpost
814 DEFINE_ACTION_TEMPLATE1_INSTANCE(ContextOutpostGroupDesc,GT_SHEE,O,COutpostSquadFamily);
815 DEFINE_ACTION_TEMPLATE1_INSTANCE(ContextOutpostGroupDesc,GT_LVLD,O,COutpostSquadFamily);
816 DEFINE_ACTION_TEMPLATE1_INSTANCE(ContextOutpostGroupDesc,GT_SEAS,O,COutpostSquadFamily);
817 DEFINE_ACTION_TEMPLATE1_INSTANCE(ContextOutpostGroupDesc,GT_ACT, O,COutpostSquadFamily);
818 DEFINE_ACTION_TEMPLATE1_INSTANCE(ContextOutpostGroupDesc,GT_APRM,O,COutpostSquadFamily);
819 DEFINE_ACTION_TEMPLATE1_INSTANCE(ContextOutpostGroupDesc,GT_NRG, O,COutpostSquadFamily);
820 DEFINE_ACTION_TEMPLATE1_INSTANCE(ContextOutpostGroupDesc,GT_EQUI,O,COutpostSquadFamily);
821 DEFINE_ACTION_TEMPLATE1_INSTANCE(ContextOutpostGroupDesc,GT_GPRM,O,COutpostSquadFamily);
822 DEFINE_ACTION_TEMPLATE1_INSTANCE(ContextOutpostGroupDesc,BOTTMPL,O,COutpostSquadFamily);
823 DEFINE_ACTION_TEMPLATE1_INSTANCE(ContextOutpostBotDesc,BT_EQUI,O,COutpostSquadFamily);
824 DEFINE_ACTION_TEMPLATE1_INSTANCE(ContextOutpostBotDesc,BT_LVLD,O,COutpostSquadFamily);
825 DEFINE_ACTION_TEMPLATE1_INSTANCE(ContextOutpostGroupDesc,GT_GNRJ,O,COutpostSquadFamily);
826 DEFINE_ACTION_TEMPLATE1_INSTANCE(ContextOutpostGroupDesc,POPVER, O,COutpostSquadFamily);
827 DEFINE_ACTION_TEMPLATE1_INSTANCE(ContextOutpostGroupDesc,GT_END, O,COutpostSquadFamily);