Resolve "Toggle Free Look with Hotkey"
[ryzomcore.git] / ryzom / server / src / ai_service / ais_actions_npc.cpp
blob3367b1cae6cee6d8f538d98b515c719cb1e8509d
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/>.
20 //----------------------------------------------------------------------------
22 #include "stdpch.h"
23 #include "ais_actions.h"
24 #include "states.h"
26 #include "dyn_grp_inline.h"
28 using namespace NLMISC;
29 using namespace NLNET;
30 using namespace std;
31 using namespace CAISActionEnums;
32 using namespace AITYPES;
35 //---------------------------------------------------------------------------------------
36 // Stuff used for management of log messages
38 static bool VerboseLog=false;
39 #define LOG if (!VerboseLog) {} else nlinfo
42 //----------------------------------------------------------------------------
43 // Some handy utilities
44 //----------------------------------------------------------------------------
46 static CGroupNpc *lookupGrpInMgrNpc(uint32 alias)
48 if (!CWorkPtr::mgrNpc())
49 return NULL;
50 return static_cast<CGroupNpc*>(CWorkPtr::mgrNpc()->groups().getChildByAlias(alias));
53 static CAIState *lookupStateInEventReactionContainer(uint32 alias)
55 if (!CWorkPtr::eventReactionContainer())
56 return NULL;
57 return CWorkPtr::eventReactionContainer()->states().getChildByAlias(alias);
60 static CAIEventReaction *lookupEventInEventReactionContainer(uint32 alias)
62 if (!CWorkPtr::eventReactionContainer())
63 return NULL;
64 return NLMISC::safe_cast<CAIEventReaction*>(CWorkPtr::eventReactionContainer()->eventReactions().getChildByAlias(alias));
67 //static CAIStateProfile *lookupProfileInState(uint32 alias)
68 //{
69 // if (!CWorkPtr::stateState())
70 // return NULL;
75 // for (CCont<CAIState>::iterator it=.begin(), itEnd=.end();it!=itEnd;++it)
76 // {
77 // (*it)
78 // }
80 // for (uint i=0;i<CWorkPtr::stateState()->profileCount();++i)
81 // {
82 // CAIStateProfileNpc *profile=static_cast<CAIStateProfileNpc *>(CWorkPtr::stateState()->getProfile(i));
83 // if ( profile
84 // && profile->getAlias()==alias)
85 // return profile;
86 // }
87 // return NULL;
88 //}
92 static CBotNpc *lookupBotInGrpNpc(uint32 alias)
94 if (CWorkPtr::grpNpc()==NULL)
95 return NULL;
97 return ( (CBotNpc*) CWorkPtr::grpNpc()->getBotByAlias (alias) );
99 // for (uint i=0;i<CWorkPtr::grpNpc()->botCount();++i)
100 // if (CWorkPtr::grpNpc()->getBotNpc(i)->getAlias()==alias)
101 // return CWorkPtr::grpNpc()->getBotNpc(i);
102 return NULL;
105 //----------------------------------------------------------------------------
106 // The NPC_MGR context
107 //----------------------------------------------------------------------------
109 DEFINE_ACTION(ContextNpcMgr,GRPNPC)
111 CMgrNpc *mgr=CWorkPtr::mgrNpc();
112 if (!mgr)
113 return;
115 uint32 alias;
116 if (!getArgs(args,name(),alias)) return;
118 LOG("NPC Manager: %s: NPC Group: %u",mgr->getAliasNode()->fullName().c_str(),alias);
120 // set workptr::grp to this grp
121 CWorkPtr::grp(lookupGrpInMgrNpc(alias));
122 if (!CWorkPtr::grpNpc())
124 nlwarning("Failed to select grp %s as not found in manager: %s",
125 LigoConfig.aliasToString(alias).c_str(),
126 CWorkPtr::mgrNpc()->getName().c_str());
127 return;
130 // if all went to plan setup the 'npc group' context
131 CContextStack::setContext(ContextNpcGrp);
134 DEFINE_ACTION(ContextEventContainer,STATE)
136 CStateMachine *container=CWorkPtr::eventReactionContainer();
137 if (!container)
138 return;
140 uint32 alias;
141 if (!getArgs(args,name(),alias))
142 return;
144 // LOG("EventContainer: %s: State (positional): %u",container->getAliasNode()->fullName().c_str(),alias);
146 // set workptr::state to this state
147 CWorkPtr::stateState(lookupStateInEventReactionContainer(alias));
148 if (!CWorkPtr::stateState())
150 nlwarning("Failed to select state %s", LigoConfig.aliasToString(alias).c_str());
151 return;
154 // set workptr state to this state
155 CContextStack::setContext(ContextPositionalState);
158 DEFINE_ACTION(ContextEventContainer,EVENT)
160 CStateMachine *container=CWorkPtr::eventReactionContainer();
161 if (!container)
162 return;
164 uint32 alias;
165 CAIEventDescription::TSmartPtr eventDescription;
166 if (!getArgs(args,name(),alias,eventDescription))
167 return;
169 CAIEventReaction *event=lookupEventInEventReactionContainer(alias);
171 if (!event)
173 nlwarning("Failed to select event %s", LigoConfig.aliasToString(alias).c_str());
174 return;
177 event->processEventDescription(eventDescription,container);
179 // LOG("EventContainer: %s: Event: %u (%s): %s",container->getAliasNode()->fullName().c_str(),alias,event->getName().c_str(),eventDescription->toString().c_str());
180 // LOG("Event: %u (%s): %s",alias,event->getName().c_str(),eventDescription->toString().c_str());
182 // need to extract the entire event from the argument list ...
186 DEFINE_ACTION(ContextEventContainer,SETACTN)
190 uint32 alias;
191 if (!getArgs(args,name(),alias))
192 return;
194 IAILogicAction *action = CWorkPtr::getLogicActionFromAlias(alias);
196 if (!action)
198 nlwarning("Failed to select logic actions", LigoConfig.aliasToString(alias).c_str());
199 CWorkPtr::logicAction(NULL);
200 return;
202 CWorkPtr::logicAction(action);
205 DEFINE_ACTION(ContextEventContainer,CLRACTN)
207 CWorkPtr::logicAction(NULL);
210 DEFINE_ACTION(ContextEventContainer, ENDEVENT)
212 CWorkPtr::clearLogicActionMap();
219 DEFINE_ACTION(ContextEventContainer,PUNCTUAL)
221 CStateMachine *container=CWorkPtr::eventReactionContainer();
222 if (!container)
223 return;
225 uint32 alias;
226 if (!getArgs(args,name(),alias))
227 return;
229 // LOG("EventContainer: %s: Punctual state: %u",container->getAliasNode()->fullName().c_str(),alias);
230 LOG("Punctual state: %u",alias);
232 // set workptr::state to this state
233 CWorkPtr::stateState(lookupStateInEventReactionContainer(alias));
234 if (!CWorkPtr::stateState())
236 nlwarning("Failed to select state %s", LigoConfig.aliasToString(alias).c_str());
237 return;
240 // set workptr state to this state
241 CContextStack::setContext(ContextPunctualState);
245 //----------------------------------------------------------------------------
246 // The NPC_STATE context(s)
247 //----------------------------------------------------------------------------
249 DEFINE_ACTION(BaseContextState,KEYWORDS)
251 if (!CWorkPtr::stateState())
252 return;
254 CWorkPtr::stateState()->keywordsClear();
255 for (uint i=0;i<args.size();++i)
257 std::string s;
258 args[i].get(s);
259 CKeywordMask mask;
260 if (!CAIKeywords::stateMask(s, mask))
262 nlwarning("There are some keyword error in '%s'", CWorkPtr::stateState()->getAliasNode()->fullName().c_str());
264 CWorkPtr::stateState()->keywordsAdd(mask);
266 LOG("State: %s: keywords: %s",CWorkPtr::stateState()->getAliasNode()->fullName().c_str(),s.c_str());
268 LOG("State: %s: => %08x",CWorkPtr::stateState()->getAliasNode()->fullName().c_str(),CWorkPtr::stateState()->getKeywords().asUint());
271 DEFINE_ACTION(BaseContextState,PROFILE)
273 if (!CWorkPtr::stateState())
274 return;
276 uint32 alias;
277 if (!getArgs(args,name(),alias)) return;
279 LOG("State: %s: bot profile: %u",CWorkPtr::stateState()->getAliasNode()->fullName().c_str(),alias);
281 // set workptr::state to this state
282 CWorkPtr::stateProfile(CWorkPtr::stateState()->profiles().getChildByAlias(alias));
284 // CWorkPtr::stateProfile(lookupProfileInState(alias));
285 if (!CWorkPtr::stateProfile())
287 nlwarning("Failed to select state profile %s as not found in state: %s",
288 LigoConfig.aliasToString(alias).c_str(),
289 CWorkPtr::stateState()->getName().c_str());
290 return;
293 // set workptr state to this state
294 CContextStack::setContext(ContextStateProfile);
297 DEFINE_ACTION(BaseContextState,CHAT)
299 if (!CWorkPtr::stateState())
300 return;
302 uint32 alias;
303 if (!getArgs(args,name(),alias)) return;
305 LOG("State: %s: bot chat: %u",CWorkPtr::stateState()->getAliasNode()->fullName().c_str(),alias);
307 // set workptr::state to this state
308 CWorkPtr::stateChat(CWorkPtr::stateState()->chats().getChildByAlias(alias));
310 // CWorkPtr::stateProfile(lookupProfileInState(alias));
311 if (!CWorkPtr::stateChat())
313 nlwarning("Failed to select state chat %s as not found in state: %s",
314 LigoConfig.aliasToString(alias).c_str(),
315 CWorkPtr::stateState()->getName().c_str());
316 return;
319 // set workptr state to this state
320 CContextStack::setContext(ContextStateChat);
323 DEFINE_ACTION(BaseContextState,MOVEPROF)
325 if (!CWorkPtr::stateState())
326 return;
328 string aiMovement;
329 if (!getArgs(args,name(), aiMovement))
330 return;
332 if (aiMovement.empty())
334 // set the default ai_profile
335 aiMovement = "no_change";
338 IAIProfileFactory* aiProfile = lookupAIGrpProfile(aiMovement.c_str());
339 if (!aiProfile)
341 nlwarning("Failed to set move profile to '%s' for state '%s' because no corresponding code module found",aiMovement.c_str(),CWorkPtr::stateState()->getName().c_str());
342 // drop through and assign 'NULL' to pointer anyway
345 LOG("State: %s: move profile: %s",CWorkPtr::stateState()->getAliasNode()->fullName().c_str(),aiMovement.c_str());
346 CWorkPtr::stateState()->setMoveProfile(aiProfile);
349 DEFINE_ACTION(BaseContextState,ACTPROF)
351 if (!CWorkPtr::stateState())
352 return;
354 string aiMovement;
355 if (!getArgs(args,name(),aiMovement))
356 return;
358 if (aiMovement.empty())
360 // set the default ai_profile
361 aiMovement = "no_change";
364 IAIProfileFactory* aiProfile = lookupAIGrpProfile(aiMovement.c_str());
365 if (!aiProfile)
367 nlwarning("Failed to set activity profile to '%s' for state '%s' because no corresponding code module found",aiMovement.c_str(),CWorkPtr::stateState()->getName().c_str());
368 // drop through and assign 'NULL' to pointer anyway
371 LOG("State: %s: activity profile : %s",CWorkPtr::stateState()->getAliasNode()->fullName().c_str(),aiMovement.c_str());
372 CWorkPtr::stateState()->setActivityProfile(aiProfile);
375 DEFINE_ACTION(BaseContextState,PROFPARM)
377 if (!CWorkPtr::stateState())
378 return;
380 vector<string> params;
382 for (uint i=0; i<args.size(); ++i)
384 string s;
385 args[i].get(s);
386 params.push_back(s);
389 LOG("State: %s: profiles parameters : %s%s",CWorkPtr::stateState()->getAliasNode()->fullName().c_str(),
390 !params.empty() ? params[0].c_str() : "no parameter",
391 params.size() > 1 ? "..." : "");
392 CWorkPtr::stateState()->setProfileParameters(params);
396 //----------------------------------------------------------------------------
398 DEFINE_ACTION(ContextPositionalState,VERTPOS)
400 CAIStatePositional *state=dynamic_cast<CAIStatePositional *>(CWorkPtr::stateState());
401 if (state==NULL || args.empty() )
402 return;
403 uint32 verticalPos;
404 getArgs(args, name(), verticalPos);
406 state->shape().setVerticalPos((TVerticalPos)verticalPos);
409 DEFINE_ACTION(ContextPositionalState,PATH)
411 CAIStatePositional *state=dynamic_cast<CAIStatePositional *>(CWorkPtr::stateState());
412 if (state==NULL || args.empty() )
413 return;
414 std::vector <CAIVector> points;
416 LOG("State: %s: set path",state->getAliasNode()->fullName().c_str());
418 for (uint i=1;i<args.size();i+=2)
420 double x,y;
421 args[i-1].get(x);
422 args[i].get(y);
423 points.push_back(CAIVector(x,y));
424 LOG("---- - (%.3f,%.3f)",x,y);
426 if (!state->shape().setPath(state->shape().getVerticalPos(), points))
428 nlwarning("CAIStatePositional: error while placing the points of '%s'",
429 state->getAliasFullName().c_str());
434 DEFINE_ACTION(ContextPositionalState,PATAT)
436 CAIStatePositional *state=dynamic_cast<CAIStatePositional *>(CWorkPtr::stateState());
437 if (state==NULL || args.empty())
438 return;
440 LOG("State: %s: set patat",state->getAliasNode()->fullName().c_str());
441 std::vector <CAIVector> points;
443 for (uint i=1;i<args.size();i+=2)
445 double x,y;
446 args[i-1].get(x);
447 args[i].get(y);
448 points.push_back(CAIVector(x,y));
449 LOG("---- - (%.3f,%.3f)",x,y);
451 if (!state->shape().setPatat(state->shape().getVerticalPos(), points))
453 nlwarning("CAIStatePositional: error while placing the points of '%s'",
454 state->getAliasFullName().c_str());
458 //----------------------------------------------------------------------------
459 // The NPC_STATE_CHAT context
460 //----------------------------------------------------------------------------
462 DEFINE_ACTION(ContextStateChat,BOTKEYS)
464 CAIStateChat *sc=CWorkPtr::stateChat();
465 if (!sc)
466 return;
468 sc->botKeywordFilterClear();
469 for (uint i=0;i<args.size();++i)
471 std::string s;
472 args[i].get(s);
473 sc->botKeywordFilterAdd(s);
474 LOG("State Profile: %s: bot keywords: %s",sc->getAliasNode()->fullName().c_str(),s.c_str());
478 DEFINE_ACTION(ContextStateChat,BOTNAMES)
480 CAIStateChat *sc=CWorkPtr::stateChat();
481 if (!sc)
482 return;
484 sc->botNameFilterClear();
485 for (uint i=0;i<args.size();++i)
487 std::string s;
488 args[i].get(s);
489 sc->botNameFilterAdd(s);
490 LOG("State Profile: %s: bot name: %s",sc->getAliasNode()->fullName().c_str(),s.c_str());
494 DEFINE_ACTION(ContextStateChat,CHAT)
496 CAIStateChat *sc=CWorkPtr::stateChat();
497 if (!sc)
498 return;
500 sc->chatProfile().clear();
501 for (uint i=0;i<args.size();++i)
503 std::string s;
504 args[i].get(s);
505 sc->chatProfile().add(CWorkPtr::aiInstance(), s);
506 LOG("State Profile: %s: chat: %s",sc->getAliasNode()->fullName().c_str(),s.c_str());
511 //----------------------------------------------------------------------------
512 // The NPC_STATE_PROFILE context
513 //----------------------------------------------------------------------------
515 DEFINE_ACTION(ContextStateProfile,GRPKEYS)
517 CAIStateProfile *sp=CWorkPtr::stateProfile();
518 if (!sp)
519 return;
521 sp->grpKeywordFilterClear();
522 for (uint i=0;i<args.size();++i)
524 std::string s;
525 args[i].get(s);
526 sp->grpKeywordFilterAdd(s);
527 LOG("State Profile: %s: grp keywords: %s",sp->getAliasNode()->fullName().c_str(),s.c_str());
531 DEFINE_ACTION(ContextStateProfile,GRPNAMES)
533 CAIStateProfile *sp=CWorkPtr::stateProfile();
534 if (!sp)
535 return;
537 sp->grpNameFilterClear();
538 for (uint i=0;i<args.size();++i)
540 std::string s;
541 args[i].get(s);
542 sp->grpNameFilterAdd(s);
543 LOG("State Profile: %s: grp name: %s",sp->getAliasNode()->fullName().c_str(),s.c_str());
547 DEFINE_ACTION(ContextStateProfile,MOVEPROF)
549 CAIStateProfile *sp=CWorkPtr::stateProfile();
550 if (!sp)
551 return;
553 string type;
554 if (!getArgs(args,name(),type)) return;
556 IAIProfileFactory* profile = lookupAIGrpProfile(type.c_str());
557 if (!profile)
559 nlwarning("Failed to set move profile to '%s' for state '%s' because no corresponding code module found",type.c_str(),sp->getName().c_str());
560 // drop through and assign 'NULL' to pointer anyway
563 sp->setMoveProfile(profile);
565 LOG("State Profile: %s: move profile : %s",sp->getAliasNode()->fullName().c_str(),type.c_str());
568 DEFINE_ACTION(ContextStateProfile,ACTPROF)
570 CAIStateProfile *const sp=CWorkPtr::stateProfile();
571 if (!sp)
572 return;
574 string type;
575 if (!getArgs(args,name(),type))
576 return;
578 IAIProfileFactory* profile = NULL;
579 if (!type.empty())
581 profile = lookupAIGrpProfile(type.c_str());
582 if (!profile)
584 nlwarning("Failed to set activity profile to '%s' for state '%s' because no corresponding code module found",type.c_str(),sp->getName().c_str());
585 // drop through and assign 'NULL' to pointer anyway
589 sp->setActivityProfile(profile);
591 LOG("State Profile: %s: activity profile : %s",sp->getAliasNode()->fullName().c_str(),type.c_str());
594 DEFINE_ACTION(ContextStateProfile,PROFPARM)
596 CAIStateProfile *sp=CWorkPtr::stateProfile();
597 if (!sp)
598 return;
600 vector<string> params;
602 for (uint i=0; i<args.size(); ++i)
604 string s;
605 args[i].get(s);
606 params.push_back(s);
609 LOG("State: %s: profiles parameters : %s%s",sp->getAliasNode()->fullName().c_str(),
610 !params.empty() ? params[0].c_str() : "no parameter",
611 params.size() > 1 ? "..." : "");
612 sp->setProfileParameters(params);
616 //----------------------------------------------------------------------------
617 // The NPC_GRP context
618 //----------------------------------------------------------------------------
620 DEFINE_ACTION(ContextNpcGrp,AUTOSPWN)
622 // set the feed and rest times
623 // args: float time0, float time1
625 if(!CWorkPtr::grpNpc())
626 return;
628 uint32 autoSpawn;
629 if (!getArgs(args, name(), autoSpawn))
630 return;
631 CWorkPtr::grpNpc()->setAutoSpawn(autoSpawn != 0);
632 LOG("AutoSpawn : %s", autoSpawn ? "true" : "false");
636 DEFINE_ACTION(ContextNpcGrp,KEYWORDS)
638 CGroupNpc *grp=CWorkPtr::grpNpc();
639 if (grp==NULL)
640 return;
642 grp->keywordsClear();
643 for (uint i=0;i<args.size();++i)
645 std::string s;
646 args[i].get(s);
647 CKeywordMask mask;
648 if (!CAIKeywords::groupMask(s, mask))
650 nlwarning("There are some keyword error in '%s'", grp->getAliasNode()->fullName().c_str());
652 grp->keywordsAdd(mask);
654 LOG("NPC Group: %s: keywords: %s",grp->getAliasNode()->fullName().c_str(),s.c_str());
658 DEFINE_ACTION(ContextNpcGrp,PARAMETR)
660 CGroupNpc *grp=CWorkPtr::grpNpc();
661 if (grp==NULL)
662 return;
664 grp->clearParameters();
665 for (uint i=0;i<args.size();++i)
667 std::string s;
668 args[i].get(s);
669 grp->addParameter(s);
670 LOG("NPC Group: %s: parameter: %s",grp->getAliasNode()->fullName().c_str(),s.c_str());
674 DEFINE_ACTION(ContextNpcGrp,BOTCOUNT)
676 // this is for the counter of automatically generated bots
677 // if the counter is '0' then only real bots should be here
679 CGroupNpc *grp=CWorkPtr::grpNpc();
680 if (!grp)
681 return;
683 uint32 count;
684 if (!getArgs(args,name(),count))
685 return;
687 if (count==0)
689 grp->setBotsAreNamedFlag();
691 else
693 grp->clrBotsAreNamedFlag();
694 LOG("NPC Group: %s: NPC auto generated bot count: %u",grp->getAliasNode()->fullName().c_str(),count);
696 // clear any unused bots
697 if (grp->bots().size() > count)
698 grp->bots().setChildSize(count);
700 // add any needed bots with a pseudo alias
701 // Todo remove getAlias()+i (wrong), there is other instances of this bug in the code.
702 uint i;
703 for (i=grp->bots().size();i<count;++i)
704 grp->bots().addChild(new CBotNpc(grp, grp->getAlias()+i, grp->getName()));
708 DEFINE_ACTION(ContextNpcGrp,BOTNPC)
711 CGroupNpc *grp=CWorkPtr::grpNpc();
712 if (!grp)
713 return;
715 if (grp->botsAreNamed())
717 uint32 alias;
718 if (!getArgs(args,name(),alias))
719 return;
721 LOG("Named NPC Group: %s: NPC bot: %u",grp->getAliasNode()->fullName().c_str(),alias);
723 // set workptr::bot to this bot
725 CWorkPtr::bot(grp->bots().getChildByAlias(alias)); //lookupBotInGrpNpc(alias));
726 if (!CWorkPtr::botNpc())
728 nlwarning("Failed to select bot %s as not found in group: %s",
729 LigoConfig.aliasToString(alias).c_str(),
730 CWorkPtr::grpNpc()->getName().c_str());
731 return;
735 else
737 uint32 index;
738 if (!getArgs(args,name(),index))
739 return;
741 LOG("NPC Group: %s: NPC bot number : %u",grp->getAliasNode()->fullName().c_str(), index);
743 // set workptr::bot to this bot
744 CWorkPtr::bot(grp->bots()[index]);
745 if (!CWorkPtr::botNpc())
747 nlwarning("Failed to select bot (index:%u) as not found in group: %s", index, CWorkPtr::grpNpc()->getName().c_str());
748 return;
752 if (!(CWorkPtr::botNpc()->getChat().isNull()))
754 CWorkPtr::botNpc()->getChat()->clearMissions();
756 // set workptr state to this state
757 CContextStack::setContext(ContextNpcBot);
760 DEFINE_ACTION(ContextNpcGrp,PROFPARM)
762 CGroupNpc *grp=CWorkPtr::grpNpc();
763 if (grp==NULL)
764 return;
766 vector<string> params;
768 for (uint i=0; i<args.size(); ++i)
770 string s;
771 args[i].get(s);
772 params.push_back(s);
775 LOG("Group: %s: profiles parameters : %s%s", grp->getAliasNode()->fullName().c_str(),
776 !params.empty() ? params[0].c_str() : "no parameter",
777 params.size() > 1 ? "..." : "");
778 grp->setProfileParameters(params);
783 //----------------------------------------------------------------------------
784 // The NPC_BOT context
785 //----------------------------------------------------------------------------
787 DEFINE_ACTION(ContextNpcBot,MISSIONS)
789 CBotNpc *bot=CWorkPtr::botNpc();
790 if (bot==NULL)
791 return;
793 if (args.size() != 2)
795 nlwarning("Action MISSIONS : invalid number of argument, execpted 2, received %u", args.size());
796 return;
799 uint32 alias;
800 std::string name;
801 args[0].get(alias);
802 args[1].get(name);
803 if (bot->getChat().isNull())
805 bot->newChat();
807 bot->getChat()->addMission(alias);
809 CWorkPtr::aiInstance()->addMissionInfo(name, alias);
810 LOG("Bot: %s: mission: %u",bot->getAliasNode()->fullName().c_str(),alias);
813 DEFINE_ACTION(ContextNpcBot,ISSTUCK)
815 CBotNpc *bot=CWorkPtr::botNpc();
816 if (bot==NULL)
817 return;
819 uint32 isStuck;
820 args[0].get(isStuck);
822 bot->setStuck(isStuck!=0);
823 LOG("Bot: %s: is %sstuck",bot->getAliasNode()->fullName().c_str(),(isStuck!=0)?"":"not ");
826 DEFINE_ACTION(ContextNpcBot,BLDNGBOT)
828 CBotNpc *bot=CWorkPtr::botNpc();
829 if (bot==NULL)
830 return;
832 uint32 isBuildingBot;
833 args[0].get(isBuildingBot);
835 bot->setBuildingBot(isBuildingBot!=0);
836 LOG("Bot: %s: is %sbuildingbot",bot->getAliasNode()->fullName().c_str(),(isBuildingBot!=0)?"":"not ");
839 DEFINE_ACTION(ContextNpcBot,KEYWORDS)
841 CBotNpc *bot=CWorkPtr::botNpc();
842 if (bot==NULL)
843 return;
845 bot->keywordsClear();
846 for (uint i=0;i<args.size();++i)
848 std::string s;
849 args[i].get(s);
850 CKeywordMask mask;
851 if (!CAIKeywords::botMask(s, mask))
853 nlwarning("There are some keyword error in '%s'", bot->getAliasNode()->fullName().c_str());
855 bot->keywordsAdd(mask);
856 LOG("Bot: %s: keywords: %s",bot->getAliasNode()->fullName().c_str(),s.c_str());
860 DEFINE_ACTION(ContextNpcBot,EQUIP)
862 CBotNpc *bot=CWorkPtr::botNpc();
863 if (bot==NULL)
864 return;
866 bot->equipmentInit();
867 for (uint i=0;i<args.size();++i)
869 std::string s;
870 args[i].get(s);
871 bot->equipmentAdd(s);
872 LOG("Bot: %s: equipment: %s",bot->getAliasNode()->fullName().c_str(),s.c_str());
876 DEFINE_ACTION(ContextNpcBot,CHAT)
878 CBotNpc *bot=CWorkPtr::botNpc();
879 if (bot==NULL)
880 return;
882 if (!(bot->getChat().isNull()))
884 bot->getChat()->clearShopInfo();
886 else
888 bot->newChat();
891 for (uint i=0;i<args.size();++i)
893 std::string s;
894 args[i].get(s);
895 bot->getChat()->add(bot->getAIInstance(), s);
896 LOG("Bot: %s: chat: %s",bot->getAliasNode()->fullName().c_str(),s.c_str());
900 DEFINE_ACTION(ContextNpcBot,LOOK)
902 CBotNpc*bot=CWorkPtr::botNpc();
903 if (!bot)
904 return;
906 // set client look sheet
907 // args: string sheet
908 std::string sheetName;
909 if (!getArgs(args,name(),sheetName))
910 return;
912 // LOG("Bot: %s: look sheet: %s.creature",bot->getAliasNode()->fullName().c_str(),sheet.c_str());
913 NLMISC::CSheetId sheetId(sheetName+".creature");
914 if (sheetId==CSheetId::Unknown)
916 nlwarning("Parsing npc look: Invalid sheet: '%s' in '%s'",
917 sheetName.c_str(),
918 bot->getAliasFullName().c_str());
919 bot->grp().bots().removeChildByIndex(bot->getChildIndex());
920 CWorkPtr::bot(NULL);
921 return;
923 AISHEETS::ICreatureCPtr c = AISHEETS::CSheets::getInstance()->lookup(sheetId);
924 if (c == NULL)
926 nlwarning("Parsing npc look: can't find creature info for sheetId '%s' in '%s'",
927 sheetId.toString().c_str(),
928 bot->getAliasFullName().c_str());
929 bot->grp().bots().removeChildByIndex(bot->getChildIndex());
930 CWorkPtr::bot(NULL);
931 return;
933 bot->setSheet(c);
936 DEFINE_ACTION(ContextNpcBot,STATS)
938 CBotNpc*bot=CWorkPtr::botNpc();
939 if (bot==NULL)
940 return;
942 bot->initEnergy ((*NLMISC::safe_cast<CGroupNpc*>(bot->getOwner())).getEnergyCoef());
945 DEFINE_ACTION(ContextNpcBot,STARTPOS)
947 CBotNpc *bot=CWorkPtr::botNpc();
948 if (bot==NULL)
949 return;
951 // set the bot's start position
952 // args: int x, y
953 sint32 x,y;
954 float theta;
955 uint32 i;
956 if (!getArgs(args,name(), x, y, theta, i))
957 return;
959 TVerticalPos verticalPos = (TVerticalPos) i;
961 LOG("Bot: %s: startpos: %.3f,%.3f:%s %d",
962 bot->getAliasNode()->fullName().c_str(),
963 double(x)/1000.0,
964 double(y)/1000.0,
965 verticalPosToString(verticalPos).c_str(),
966 uint32(180.0*theta/3.14159265359+0.5)%360);
968 bot->setStartPos(double(x)/1000.0, double(y)/1000.0, theta, TVerticalPos(verticalPos));
972 //---------------------------------------------------------------------------------------
973 // Control over verbose nature of logging
974 //---------------------------------------------------------------------------------------
976 NLMISC_COMMAND(verboseNPCParserLog,"Turn on or off or check the state of verbose .primitive parser logging","")
978 if(args.size()>1)
979 return false;
981 if(args.size()==1)
982 StrToBool (VerboseLog, args[0]);
984 nlinfo("verbose Logging is %s",VerboseLog?"ON":"OFF");
985 return true;
990 DEFINE_ACTION(ContextNpcMgr,GRPKAMI)
992 if (!CWorkPtr::mgrNpc())
993 return;
995 // extract the arguments
996 uint32 alias;
997 if (!getArgs(args,"ContextNpcMgrKami:GRP <persistent id>",alias))
998 return;
1000 CWorkPtr::grp(CWorkPtr::mgrNpc()->groups().getChildByAlias(alias));
1001 CWorkPtr::stateState(CWorkPtr::mgrNpc()->getStateMachine()->states().getChildByAlias(alias));
1003 // setup the KamiGrp context for adding kamis to the group
1004 CContextStack::push(ContextNpcGrp);
1008 DEFINE_ACTION(ContextNpcMgr,DEPOSIT)
1010 if (!CWorkPtr::mgrNpc())
1011 return;
1013 // extract the arguments
1014 uint32 alias;
1015 if (!getArgs(args,"ContextNpcMgrKami:GRP <persistent id>",alias))
1016 return;
1018 CWorkPtr::grp(CWorkPtr::mgrNpc()->groups().getChildByAlias(alias));
1019 CWorkPtr::stateState(CWorkPtr::mgrNpc()->getStateMachine()->states().getChildByAlias(alias));
1021 // setup the KamiGrp context for adding kamis to the group
1022 CContextStack::push(ContextNpcGrp);
1023 CWorkPtr::aiInstance()->registerKamiDeposit(alias,CWorkPtr::grpNpc());
1026 //---------------------------------------------------------------------------------------