1027 lines
25 KiB
C++
1027 lines
25 KiB
C++
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
|
|
// Copyright (C) 2010 Winch Gate Property Limited
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as
|
|
// published by the Free Software Foundation, either version 3 of the
|
|
// License, or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "stdpch.h"
|
|
#include "ais_actions.h"
|
|
#include "states.h"
|
|
|
|
#include "dyn_grp_inline.h"
|
|
|
|
using namespace NLMISC;
|
|
using namespace NLNET;
|
|
using namespace std;
|
|
using namespace CAISActionEnums;
|
|
using namespace AITYPES;
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
// Stuff used for management of log messages
|
|
|
|
static bool VerboseLog=false;
|
|
#define LOG if (!VerboseLog) {} else nlinfo
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Some handy utilities
|
|
//----------------------------------------------------------------------------
|
|
|
|
static CGroupNpc *lookupGrpInMgrNpc(uint32 alias)
|
|
{
|
|
if (!CWorkPtr::mgrNpc())
|
|
return NULL;
|
|
return static_cast<CGroupNpc*>(CWorkPtr::mgrNpc()->groups().getChildByAlias(alias));
|
|
}
|
|
|
|
static CAIState *lookupStateInEventReactionContainer(uint32 alias)
|
|
{
|
|
if (!CWorkPtr::eventReactionContainer())
|
|
return NULL;
|
|
return CWorkPtr::eventReactionContainer()->states().getChildByAlias(alias);
|
|
}
|
|
|
|
static CAIEventReaction *lookupEventInEventReactionContainer(uint32 alias)
|
|
{
|
|
if (!CWorkPtr::eventReactionContainer())
|
|
return NULL;
|
|
return NLMISC::safe_cast<CAIEventReaction*>(CWorkPtr::eventReactionContainer()->eventReactions().getChildByAlias(alias));
|
|
}
|
|
|
|
//static CAIStateProfile *lookupProfileInState(uint32 alias)
|
|
//{
|
|
// if (!CWorkPtr::stateState())
|
|
// return NULL;
|
|
//
|
|
//
|
|
//
|
|
//
|
|
// for (CCont<CAIState>::iterator it=.begin(), itEnd=.end();it!=itEnd;++it)
|
|
// {
|
|
// (*it)
|
|
// }
|
|
//
|
|
// for (uint i=0;i<CWorkPtr::stateState()->profileCount();++i)
|
|
// {
|
|
// CAIStateProfileNpc *profile=static_cast<CAIStateProfileNpc *>(CWorkPtr::stateState()->getProfile(i));
|
|
// if ( profile
|
|
// && profile->getAlias()==alias)
|
|
// return profile;
|
|
// }
|
|
// return NULL;
|
|
//}
|
|
|
|
|
|
/*
|
|
static CBotNpc *lookupBotInGrpNpc(uint32 alias)
|
|
{
|
|
if (CWorkPtr::grpNpc()==NULL)
|
|
return NULL;
|
|
|
|
return ( (CBotNpc*) CWorkPtr::grpNpc()->getBotByAlias (alias) );
|
|
|
|
// for (uint i=0;i<CWorkPtr::grpNpc()->botCount();++i)
|
|
// if (CWorkPtr::grpNpc()->getBotNpc(i)->getAlias()==alias)
|
|
// return CWorkPtr::grpNpc()->getBotNpc(i);
|
|
return NULL;
|
|
}
|
|
*/
|
|
//----------------------------------------------------------------------------
|
|
// The NPC_MGR context
|
|
//----------------------------------------------------------------------------
|
|
|
|
DEFINE_ACTION(ContextNpcMgr,GRPNPC)
|
|
{
|
|
CMgrNpc *mgr=CWorkPtr::mgrNpc();
|
|
if (!mgr)
|
|
return;
|
|
|
|
uint32 alias;
|
|
if (!getArgs(args,name(),alias)) return;
|
|
|
|
LOG("NPC Manager: %s: NPC Group: %u",mgr->getAliasNode()->fullName().c_str(),alias);
|
|
|
|
// set workptr::grp to this grp
|
|
CWorkPtr::grp(lookupGrpInMgrNpc(alias));
|
|
if (!CWorkPtr::grpNpc())
|
|
{
|
|
nlwarning("Failed to select grp %s as not found in manager: %s",
|
|
LigoConfig.aliasToString(alias).c_str(),
|
|
CWorkPtr::mgrNpc()->getName().c_str());
|
|
return;
|
|
}
|
|
|
|
// if all went to plan setup the 'npc group' context
|
|
CContextStack::setContext(ContextNpcGrp);
|
|
}
|
|
|
|
DEFINE_ACTION(ContextEventContainer,STATE)
|
|
{
|
|
CStateMachine *container=CWorkPtr::eventReactionContainer();
|
|
if (!container)
|
|
return;
|
|
|
|
uint32 alias;
|
|
if (!getArgs(args,name(),alias))
|
|
return;
|
|
|
|
// LOG("EventContainer: %s: State (positional): %u",container->getAliasNode()->fullName().c_str(),alias);
|
|
|
|
// set workptr::state to this state
|
|
CWorkPtr::stateState(lookupStateInEventReactionContainer(alias));
|
|
if (!CWorkPtr::stateState())
|
|
{
|
|
nlwarning("Failed to select state %s", LigoConfig.aliasToString(alias).c_str());
|
|
return;
|
|
}
|
|
|
|
// set workptr state to this state
|
|
CContextStack::setContext(ContextPositionalState);
|
|
}
|
|
|
|
DEFINE_ACTION(ContextEventContainer,EVENT)
|
|
{
|
|
CStateMachine *container=CWorkPtr::eventReactionContainer();
|
|
if (!container)
|
|
return;
|
|
|
|
uint32 alias;
|
|
CAIEventDescription::TSmartPtr eventDescription;
|
|
if (!getArgs(args,name(),alias,eventDescription))
|
|
return;
|
|
|
|
CAIEventReaction *event=lookupEventInEventReactionContainer(alias);
|
|
|
|
if (!event)
|
|
{
|
|
nlwarning("Failed to select event %s", LigoConfig.aliasToString(alias).c_str());
|
|
return;
|
|
}
|
|
|
|
event->processEventDescription(eventDescription,container);
|
|
|
|
// LOG("EventContainer: %s: Event: %u (%s): %s",container->getAliasNode()->fullName().c_str(),alias,event->getName().c_str(),eventDescription->toString().c_str());
|
|
// LOG("Event: %u (%s): %s",alias,event->getName().c_str(),eventDescription->toString().c_str());
|
|
|
|
// need to extract the entire event from the argument list ...
|
|
}
|
|
|
|
|
|
DEFINE_ACTION(ContextEventContainer,SETACTN)
|
|
{
|
|
|
|
|
|
uint32 alias;
|
|
if (!getArgs(args,name(),alias))
|
|
return;
|
|
|
|
IAILogicAction *action = CWorkPtr::getLogicActionFromAlias(alias);
|
|
|
|
if (!action)
|
|
{
|
|
nlwarning("Failed to select logic actions", LigoConfig.aliasToString(alias).c_str());
|
|
CWorkPtr::logicAction(NULL);
|
|
return;
|
|
}
|
|
CWorkPtr::logicAction(action);
|
|
}
|
|
|
|
DEFINE_ACTION(ContextEventContainer,CLRACTN)
|
|
{
|
|
CWorkPtr::logicAction(NULL);
|
|
}
|
|
|
|
DEFINE_ACTION(ContextEventContainer, ENDEVENT)
|
|
{
|
|
CWorkPtr::clearLogicActionMap();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DEFINE_ACTION(ContextEventContainer,PUNCTUAL)
|
|
{
|
|
CStateMachine *container=CWorkPtr::eventReactionContainer();
|
|
if (!container)
|
|
return;
|
|
|
|
uint32 alias;
|
|
if (!getArgs(args,name(),alias))
|
|
return;
|
|
|
|
// LOG("EventContainer: %s: Punctual state: %u",container->getAliasNode()->fullName().c_str(),alias);
|
|
LOG("Punctual state: %u",alias);
|
|
|
|
// set workptr::state to this state
|
|
CWorkPtr::stateState(lookupStateInEventReactionContainer(alias));
|
|
if (!CWorkPtr::stateState())
|
|
{
|
|
nlwarning("Failed to select state %s", LigoConfig.aliasToString(alias).c_str());
|
|
return;
|
|
}
|
|
|
|
// set workptr state to this state
|
|
CContextStack::setContext(ContextPunctualState);
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// The NPC_STATE context(s)
|
|
//----------------------------------------------------------------------------
|
|
|
|
DEFINE_ACTION(BaseContextState,KEYWORDS)
|
|
{
|
|
if (!CWorkPtr::stateState())
|
|
return;
|
|
|
|
CWorkPtr::stateState()->keywordsClear();
|
|
for (uint i=0;i<args.size();++i)
|
|
{
|
|
std::string s;
|
|
args[i].get(s);
|
|
CKeywordMask mask;
|
|
if (!CAIKeywords::stateMask(s, mask))
|
|
{
|
|
nlwarning("There are some keyword error in '%s'", CWorkPtr::stateState()->getAliasNode()->fullName().c_str());
|
|
}
|
|
CWorkPtr::stateState()->keywordsAdd(mask);
|
|
|
|
LOG("State: %s: keywords: %s",CWorkPtr::stateState()->getAliasNode()->fullName().c_str(),s.c_str());
|
|
}
|
|
LOG("State: %s: => %08x",CWorkPtr::stateState()->getAliasNode()->fullName().c_str(),CWorkPtr::stateState()->getKeywords().asUint());
|
|
}
|
|
|
|
DEFINE_ACTION(BaseContextState,PROFILE)
|
|
{
|
|
if (!CWorkPtr::stateState())
|
|
return;
|
|
|
|
uint32 alias;
|
|
if (!getArgs(args,name(),alias)) return;
|
|
|
|
LOG("State: %s: bot profile: %u",CWorkPtr::stateState()->getAliasNode()->fullName().c_str(),alias);
|
|
|
|
// set workptr::state to this state
|
|
CWorkPtr::stateProfile(CWorkPtr::stateState()->profiles().getChildByAlias(alias));
|
|
|
|
// CWorkPtr::stateProfile(lookupProfileInState(alias));
|
|
if (!CWorkPtr::stateProfile())
|
|
{
|
|
nlwarning("Failed to select state profile %s as not found in state: %s",
|
|
LigoConfig.aliasToString(alias).c_str(),
|
|
CWorkPtr::stateState()->getName().c_str());
|
|
return;
|
|
}
|
|
|
|
// set workptr state to this state
|
|
CContextStack::setContext(ContextStateProfile);
|
|
}
|
|
|
|
DEFINE_ACTION(BaseContextState,CHAT)
|
|
{
|
|
if (!CWorkPtr::stateState())
|
|
return;
|
|
|
|
uint32 alias;
|
|
if (!getArgs(args,name(),alias)) return;
|
|
|
|
LOG("State: %s: bot chat: %u",CWorkPtr::stateState()->getAliasNode()->fullName().c_str(),alias);
|
|
|
|
// set workptr::state to this state
|
|
CWorkPtr::stateChat(CWorkPtr::stateState()->chats().getChildByAlias(alias));
|
|
|
|
// CWorkPtr::stateProfile(lookupProfileInState(alias));
|
|
if (!CWorkPtr::stateChat())
|
|
{
|
|
nlwarning("Failed to select state chat %s as not found in state: %s",
|
|
LigoConfig.aliasToString(alias).c_str(),
|
|
CWorkPtr::stateState()->getName().c_str());
|
|
return;
|
|
}
|
|
|
|
// set workptr state to this state
|
|
CContextStack::setContext(ContextStateChat);
|
|
}
|
|
|
|
DEFINE_ACTION(BaseContextState,MOVEPROF)
|
|
{
|
|
if (!CWorkPtr::stateState())
|
|
return;
|
|
|
|
string aiMovement;
|
|
if (!getArgs(args,name(), aiMovement))
|
|
return;
|
|
|
|
if (aiMovement.empty())
|
|
{
|
|
// set the default ai_profile
|
|
aiMovement = "no_change";
|
|
}
|
|
|
|
IAIProfileFactory* aiProfile = lookupAIGrpProfile(aiMovement.c_str());
|
|
if (!aiProfile)
|
|
{
|
|
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());
|
|
// drop through and assign 'NULL' to pointer anyway
|
|
}
|
|
|
|
LOG("State: %s: move profile: %s",CWorkPtr::stateState()->getAliasNode()->fullName().c_str(),aiMovement.c_str());
|
|
CWorkPtr::stateState()->setMoveProfile(aiProfile);
|
|
}
|
|
|
|
DEFINE_ACTION(BaseContextState,ACTPROF)
|
|
{
|
|
if (!CWorkPtr::stateState())
|
|
return;
|
|
|
|
string aiMovement;
|
|
if (!getArgs(args,name(),aiMovement))
|
|
return;
|
|
|
|
if (aiMovement.empty())
|
|
{
|
|
// set the default ai_profile
|
|
aiMovement = "no_change";
|
|
}
|
|
|
|
IAIProfileFactory* aiProfile = lookupAIGrpProfile(aiMovement.c_str());
|
|
if (!aiProfile)
|
|
{
|
|
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());
|
|
// drop through and assign 'NULL' to pointer anyway
|
|
}
|
|
|
|
LOG("State: %s: activity profile : %s",CWorkPtr::stateState()->getAliasNode()->fullName().c_str(),aiMovement.c_str());
|
|
CWorkPtr::stateState()->setActivityProfile(aiProfile);
|
|
}
|
|
|
|
DEFINE_ACTION(BaseContextState,PROFPARM)
|
|
{
|
|
if (!CWorkPtr::stateState())
|
|
return;
|
|
|
|
vector<string> params;
|
|
|
|
for (uint i=0; i<args.size(); ++i)
|
|
{
|
|
string s;
|
|
args[i].get(s);
|
|
params.push_back(s);
|
|
}
|
|
|
|
LOG("State: %s: profiles parameters : %s%s",CWorkPtr::stateState()->getAliasNode()->fullName().c_str(),
|
|
!params.empty() ? params[0].c_str() : "no parameter",
|
|
params.size() > 1 ? "..." : "");
|
|
CWorkPtr::stateState()->setProfileParameters(params);
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
DEFINE_ACTION(ContextPositionalState,VERTPOS)
|
|
{
|
|
CAIStatePositional *state=dynamic_cast<CAIStatePositional *>(CWorkPtr::stateState());
|
|
if (state==NULL || args.empty() )
|
|
return;
|
|
uint32 verticalPos;
|
|
getArgs(args, name(), verticalPos);
|
|
|
|
state->shape().setVerticalPos((TVerticalPos)verticalPos);
|
|
}
|
|
|
|
DEFINE_ACTION(ContextPositionalState,PATH)
|
|
{
|
|
CAIStatePositional *state=dynamic_cast<CAIStatePositional *>(CWorkPtr::stateState());
|
|
if (state==NULL || args.empty() )
|
|
return;
|
|
std::vector <CAIVector> points;
|
|
|
|
LOG("State: %s: set path",state->getAliasNode()->fullName().c_str());
|
|
|
|
for (uint i=1;i<args.size();i+=2)
|
|
{
|
|
double x,y;
|
|
args[i-1].get(x);
|
|
args[i].get(y);
|
|
points.push_back(CAIVector(x,y));
|
|
LOG("---- - (%.3f,%.3f)",x,y);
|
|
}
|
|
if (!state->shape().setPath(state->shape().getVerticalPos(), points))
|
|
{
|
|
nlwarning("CAIStatePositional: error while placing the points of '%s'",
|
|
state->getAliasFullName().c_str());
|
|
|
|
}
|
|
}
|
|
|
|
DEFINE_ACTION(ContextPositionalState,PATAT)
|
|
{
|
|
CAIStatePositional *state=dynamic_cast<CAIStatePositional *>(CWorkPtr::stateState());
|
|
if (state==NULL || args.empty())
|
|
return;
|
|
|
|
LOG("State: %s: set patat",state->getAliasNode()->fullName().c_str());
|
|
std::vector <CAIVector> points;
|
|
|
|
for (uint i=1;i<args.size();i+=2)
|
|
{
|
|
double x,y;
|
|
args[i-1].get(x);
|
|
args[i].get(y);
|
|
points.push_back(CAIVector(x,y));
|
|
LOG("---- - (%.3f,%.3f)",x,y);
|
|
}
|
|
if (!state->shape().setPatat(state->shape().getVerticalPos(), points))
|
|
{
|
|
nlwarning("CAIStatePositional: error while placing the points of '%s'",
|
|
state->getAliasFullName().c_str());
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// The NPC_STATE_CHAT context
|
|
//----------------------------------------------------------------------------
|
|
|
|
DEFINE_ACTION(ContextStateChat,BOTKEYS)
|
|
{
|
|
CAIStateChat *sc=CWorkPtr::stateChat();
|
|
if (!sc)
|
|
return;
|
|
|
|
sc->botKeywordFilterClear();
|
|
for (uint i=0;i<args.size();++i)
|
|
{
|
|
std::string s;
|
|
args[i].get(s);
|
|
sc->botKeywordFilterAdd(s);
|
|
LOG("State Profile: %s: bot keywords: %s",sc->getAliasNode()->fullName().c_str(),s.c_str());
|
|
}
|
|
}
|
|
|
|
DEFINE_ACTION(ContextStateChat,BOTNAMES)
|
|
{
|
|
CAIStateChat *sc=CWorkPtr::stateChat();
|
|
if (!sc)
|
|
return;
|
|
|
|
sc->botNameFilterClear();
|
|
for (uint i=0;i<args.size();++i)
|
|
{
|
|
std::string s;
|
|
args[i].get(s);
|
|
sc->botNameFilterAdd(s);
|
|
LOG("State Profile: %s: bot name: %s",sc->getAliasNode()->fullName().c_str(),s.c_str());
|
|
}
|
|
}
|
|
|
|
DEFINE_ACTION(ContextStateChat,CHAT)
|
|
{
|
|
CAIStateChat *sc=CWorkPtr::stateChat();
|
|
if (!sc)
|
|
return;
|
|
|
|
sc->chatProfile().clear();
|
|
for (uint i=0;i<args.size();++i)
|
|
{
|
|
std::string s;
|
|
args[i].get(s);
|
|
sc->chatProfile().add(CWorkPtr::aiInstance(), s);
|
|
LOG("State Profile: %s: chat: %s",sc->getAliasNode()->fullName().c_str(),s.c_str());
|
|
}
|
|
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// The NPC_STATE_PROFILE context
|
|
//----------------------------------------------------------------------------
|
|
|
|
DEFINE_ACTION(ContextStateProfile,GRPKEYS)
|
|
{
|
|
CAIStateProfile *sp=CWorkPtr::stateProfile();
|
|
if (!sp)
|
|
return;
|
|
|
|
sp->grpKeywordFilterClear();
|
|
for (uint i=0;i<args.size();++i)
|
|
{
|
|
std::string s;
|
|
args[i].get(s);
|
|
sp->grpKeywordFilterAdd(s);
|
|
LOG("State Profile: %s: grp keywords: %s",sp->getAliasNode()->fullName().c_str(),s.c_str());
|
|
}
|
|
}
|
|
|
|
DEFINE_ACTION(ContextStateProfile,GRPNAMES)
|
|
{
|
|
CAIStateProfile *sp=CWorkPtr::stateProfile();
|
|
if (!sp)
|
|
return;
|
|
|
|
sp->grpNameFilterClear();
|
|
for (uint i=0;i<args.size();++i)
|
|
{
|
|
std::string s;
|
|
args[i].get(s);
|
|
sp->grpNameFilterAdd(s);
|
|
LOG("State Profile: %s: grp name: %s",sp->getAliasNode()->fullName().c_str(),s.c_str());
|
|
}
|
|
}
|
|
|
|
DEFINE_ACTION(ContextStateProfile,MOVEPROF)
|
|
{
|
|
CAIStateProfile *sp=CWorkPtr::stateProfile();
|
|
if (!sp)
|
|
return;
|
|
|
|
string type;
|
|
if (!getArgs(args,name(),type)) return;
|
|
|
|
IAIProfileFactory* profile = lookupAIGrpProfile(type.c_str());
|
|
if (!profile)
|
|
{
|
|
nlwarning("Failed to set move profile to '%s' for state '%s' because no corresponding code module found",type.c_str(),sp->getName().c_str());
|
|
// drop through and assign 'NULL' to pointer anyway
|
|
}
|
|
|
|
sp->setMoveProfile(profile);
|
|
|
|
LOG("State Profile: %s: move profile : %s",sp->getAliasNode()->fullName().c_str(),type.c_str());
|
|
}
|
|
|
|
DEFINE_ACTION(ContextStateProfile,ACTPROF)
|
|
{
|
|
CAIStateProfile *const sp=CWorkPtr::stateProfile();
|
|
if (!sp)
|
|
return;
|
|
|
|
string type;
|
|
if (!getArgs(args,name(),type))
|
|
return;
|
|
|
|
IAIProfileFactory* profile = NULL;
|
|
if (!type.empty())
|
|
{
|
|
profile = lookupAIGrpProfile(type.c_str());
|
|
if (!profile)
|
|
{
|
|
nlwarning("Failed to set activity profile to '%s' for state '%s' because no corresponding code module found",type.c_str(),sp->getName().c_str());
|
|
// drop through and assign 'NULL' to pointer anyway
|
|
}
|
|
}
|
|
|
|
sp->setActivityProfile(profile);
|
|
|
|
LOG("State Profile: %s: activity profile : %s",sp->getAliasNode()->fullName().c_str(),type.c_str());
|
|
}
|
|
|
|
DEFINE_ACTION(ContextStateProfile,PROFPARM)
|
|
{
|
|
CAIStateProfile *sp=CWorkPtr::stateProfile();
|
|
if (!sp)
|
|
return;
|
|
|
|
vector<string> params;
|
|
|
|
for (uint i=0; i<args.size(); ++i)
|
|
{
|
|
string s;
|
|
args[i].get(s);
|
|
params.push_back(s);
|
|
}
|
|
|
|
LOG("State: %s: profiles parameters : %s%s",sp->getAliasNode()->fullName().c_str(),
|
|
!params.empty() ? params[0].c_str() : "no parameter",
|
|
params.size() > 1 ? "..." : "");
|
|
sp->setProfileParameters(params);
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// The NPC_GRP context
|
|
//----------------------------------------------------------------------------
|
|
|
|
DEFINE_ACTION(ContextNpcGrp,AUTOSPWN)
|
|
{
|
|
// set the feed and rest times
|
|
// args: float time0, float time1
|
|
|
|
if(!CWorkPtr::grpNpc())
|
|
return;
|
|
|
|
uint32 autoSpawn;
|
|
if (!getArgs(args, name(), autoSpawn))
|
|
return;
|
|
CWorkPtr::grpNpc()->setAutoSpawn(autoSpawn != 0);
|
|
LOG("AutoSpawn : %s", autoSpawn ? "true" : "false");
|
|
}
|
|
|
|
|
|
DEFINE_ACTION(ContextNpcGrp,KEYWORDS)
|
|
{
|
|
CGroupNpc *grp=CWorkPtr::grpNpc();
|
|
if (grp==NULL)
|
|
return;
|
|
|
|
grp->keywordsClear();
|
|
for (uint i=0;i<args.size();++i)
|
|
{
|
|
std::string s;
|
|
args[i].get(s);
|
|
CKeywordMask mask;
|
|
if (!CAIKeywords::groupMask(s, mask))
|
|
{
|
|
nlwarning("There are some keyword error in '%s'", grp->getAliasNode()->fullName().c_str());
|
|
}
|
|
grp->keywordsAdd(mask);
|
|
|
|
LOG("NPC Group: %s: keywords: %s",grp->getAliasNode()->fullName().c_str(),s.c_str());
|
|
}
|
|
}
|
|
|
|
DEFINE_ACTION(ContextNpcGrp,PARAMETR)
|
|
{
|
|
CGroupNpc *grp=CWorkPtr::grpNpc();
|
|
if (grp==NULL)
|
|
return;
|
|
|
|
grp->clearParameters();
|
|
for (uint i=0;i<args.size();++i)
|
|
{
|
|
std::string s;
|
|
args[i].get(s);
|
|
grp->addParameter(s);
|
|
LOG("NPC Group: %s: parameter: %s",grp->getAliasNode()->fullName().c_str(),s.c_str());
|
|
}
|
|
}
|
|
|
|
DEFINE_ACTION(ContextNpcGrp,BOTCOUNT)
|
|
{
|
|
// this is for the counter of automatically generated bots
|
|
// if the counter is '0' then only real bots should be here
|
|
|
|
CGroupNpc *grp=CWorkPtr::grpNpc();
|
|
if (!grp)
|
|
return;
|
|
|
|
uint32 count;
|
|
if (!getArgs(args,name(),count))
|
|
return;
|
|
|
|
if (count==0)
|
|
{
|
|
grp->setBotsAreNamedFlag();
|
|
}
|
|
else
|
|
{
|
|
grp->clrBotsAreNamedFlag();
|
|
LOG("NPC Group: %s: NPC auto generated bot count: %u",grp->getAliasNode()->fullName().c_str(),count);
|
|
|
|
// clear any unused bots
|
|
if (grp->bots().size() > count)
|
|
grp->bots().setChildSize(count);
|
|
|
|
// add any needed bots with a pseudo alias
|
|
// Todo remove getAlias()+i (wrong), there is other instances of this bug in the code.
|
|
uint i;
|
|
for (i=grp->bots().size();i<count;++i)
|
|
grp->bots().addChild(new CBotNpc(grp, grp->getAlias()+i, grp->getName()));
|
|
}
|
|
}
|
|
|
|
DEFINE_ACTION(ContextNpcGrp,BOTNPC)
|
|
{
|
|
|
|
CGroupNpc *grp=CWorkPtr::grpNpc();
|
|
if (!grp)
|
|
return;
|
|
|
|
if (grp->botsAreNamed())
|
|
{
|
|
uint32 alias;
|
|
if (!getArgs(args,name(),alias))
|
|
return;
|
|
|
|
LOG("Named NPC Group: %s: NPC bot: %u",grp->getAliasNode()->fullName().c_str(),alias);
|
|
|
|
// set workptr::bot to this bot
|
|
|
|
CWorkPtr::bot(grp->bots().getChildByAlias(alias)); //lookupBotInGrpNpc(alias));
|
|
if (!CWorkPtr::botNpc())
|
|
{
|
|
nlwarning("Failed to select bot %s as not found in group: %s",
|
|
LigoConfig.aliasToString(alias).c_str(),
|
|
CWorkPtr::grpNpc()->getName().c_str());
|
|
return;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
uint32 index;
|
|
if (!getArgs(args,name(),index))
|
|
return;
|
|
|
|
LOG("NPC Group: %s: NPC bot number : %u",grp->getAliasNode()->fullName().c_str(), index);
|
|
|
|
// set workptr::bot to this bot
|
|
CWorkPtr::bot(grp->bots()[index]);
|
|
if (!CWorkPtr::botNpc())
|
|
{
|
|
nlwarning("Failed to select bot (index:%u) as not found in group: %s", index, CWorkPtr::grpNpc()->getName().c_str());
|
|
return;
|
|
}
|
|
|
|
}
|
|
if (!(CWorkPtr::botNpc()->getChat().isNull()))
|
|
{
|
|
CWorkPtr::botNpc()->getChat()->clearMissions();
|
|
}
|
|
// set workptr state to this state
|
|
CContextStack::setContext(ContextNpcBot);
|
|
}
|
|
|
|
DEFINE_ACTION(ContextNpcGrp,PROFPARM)
|
|
{
|
|
CGroupNpc *grp=CWorkPtr::grpNpc();
|
|
if (grp==NULL)
|
|
return;
|
|
|
|
vector<string> params;
|
|
|
|
for (uint i=0; i<args.size(); ++i)
|
|
{
|
|
string s;
|
|
args[i].get(s);
|
|
params.push_back(s);
|
|
}
|
|
|
|
LOG("Group: %s: profiles parameters : %s%s", grp->getAliasNode()->fullName().c_str(),
|
|
!params.empty() ? params[0].c_str() : "no parameter",
|
|
params.size() > 1 ? "..." : "");
|
|
grp->setProfileParameters(params);
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// The NPC_BOT context
|
|
//----------------------------------------------------------------------------
|
|
|
|
DEFINE_ACTION(ContextNpcBot,MISSIONS)
|
|
{
|
|
CBotNpc *bot=CWorkPtr::botNpc();
|
|
if (bot==NULL)
|
|
return;
|
|
|
|
if (args.size() != 2)
|
|
{
|
|
nlwarning("Action MISSIONS : invalid number of argument, execpted 2, received %u", args.size());
|
|
return;
|
|
}
|
|
|
|
uint32 alias;
|
|
std::string name;
|
|
args[0].get(alias);
|
|
args[1].get(name);
|
|
if (bot->getChat().isNull())
|
|
{
|
|
bot->newChat();
|
|
}
|
|
bot->getChat()->addMission(alias);
|
|
|
|
CWorkPtr::aiInstance()->addMissionInfo(name, alias);
|
|
LOG("Bot: %s: mission: %u",bot->getAliasNode()->fullName().c_str(),alias);
|
|
}
|
|
|
|
DEFINE_ACTION(ContextNpcBot,ISSTUCK)
|
|
{
|
|
CBotNpc *bot=CWorkPtr::botNpc();
|
|
if (bot==NULL)
|
|
return;
|
|
|
|
uint32 isStuck;
|
|
args[0].get(isStuck);
|
|
|
|
bot->setStuck(isStuck!=0);
|
|
LOG("Bot: %s: is %sstuck",bot->getAliasNode()->fullName().c_str(),(isStuck!=0)?"":"not ");
|
|
}
|
|
|
|
DEFINE_ACTION(ContextNpcBot,BLDNGBOT)
|
|
{
|
|
CBotNpc *bot=CWorkPtr::botNpc();
|
|
if (bot==NULL)
|
|
return;
|
|
|
|
uint32 isBuildingBot;
|
|
args[0].get(isBuildingBot);
|
|
|
|
bot->setBuildingBot(isBuildingBot!=0);
|
|
LOG("Bot: %s: is %sbuildingbot",bot->getAliasNode()->fullName().c_str(),(isBuildingBot!=0)?"":"not ");
|
|
}
|
|
|
|
DEFINE_ACTION(ContextNpcBot,KEYWORDS)
|
|
{
|
|
CBotNpc *bot=CWorkPtr::botNpc();
|
|
if (bot==NULL)
|
|
return;
|
|
|
|
bot->keywordsClear();
|
|
for (uint i=0;i<args.size();++i)
|
|
{
|
|
std::string s;
|
|
args[i].get(s);
|
|
CKeywordMask mask;
|
|
if (!CAIKeywords::botMask(s, mask))
|
|
{
|
|
nlwarning("There are some keyword error in '%s'", bot->getAliasNode()->fullName().c_str());
|
|
}
|
|
bot->keywordsAdd(mask);
|
|
LOG("Bot: %s: keywords: %s",bot->getAliasNode()->fullName().c_str(),s.c_str());
|
|
}
|
|
}
|
|
|
|
DEFINE_ACTION(ContextNpcBot,EQUIP)
|
|
{
|
|
CBotNpc *bot=CWorkPtr::botNpc();
|
|
if (bot==NULL)
|
|
return;
|
|
|
|
bot->equipmentInit();
|
|
for (uint i=0;i<args.size();++i)
|
|
{
|
|
std::string s;
|
|
args[i].get(s);
|
|
bot->equipmentAdd(s);
|
|
LOG("Bot: %s: equipment: %s",bot->getAliasNode()->fullName().c_str(),s.c_str());
|
|
}
|
|
}
|
|
|
|
DEFINE_ACTION(ContextNpcBot,CHAT)
|
|
{
|
|
CBotNpc *bot=CWorkPtr::botNpc();
|
|
if (bot==NULL)
|
|
return;
|
|
|
|
if (!(bot->getChat().isNull()))
|
|
{
|
|
bot->getChat()->clearShopInfo();
|
|
}
|
|
else
|
|
{
|
|
bot->newChat();
|
|
}
|
|
|
|
for (uint i=0;i<args.size();++i)
|
|
{
|
|
std::string s;
|
|
args[i].get(s);
|
|
bot->getChat()->add(bot->getAIInstance(), s);
|
|
LOG("Bot: %s: chat: %s",bot->getAliasNode()->fullName().c_str(),s.c_str());
|
|
}
|
|
}
|
|
|
|
DEFINE_ACTION(ContextNpcBot,LOOK)
|
|
{
|
|
CBotNpc*bot=CWorkPtr::botNpc();
|
|
if (!bot)
|
|
return;
|
|
|
|
// set client look sheet
|
|
// args: string sheet
|
|
std::string sheetName;
|
|
if (!getArgs(args,name(),sheetName))
|
|
return;
|
|
|
|
// LOG("Bot: %s: look sheet: %s.creature",bot->getAliasNode()->fullName().c_str(),sheet.c_str());
|
|
NLMISC::CSheetId sheetId(sheetName+".creature");
|
|
if (sheetId==CSheetId::Unknown)
|
|
{
|
|
nlwarning("Parsing npc look: Invalid sheet: '%s' in '%s'",
|
|
sheetName.c_str(),
|
|
bot->getAliasFullName().c_str());
|
|
bot->grp().bots().removeChildByIndex(bot->getChildIndex());
|
|
CWorkPtr::bot(NULL);
|
|
return;
|
|
}
|
|
AISHEETS::ICreatureCPtr c = AISHEETS::CSheets::getInstance()->lookup(sheetId);
|
|
if (c == NULL)
|
|
{
|
|
nlwarning("Parsing npc look: can't find creature info for sheetId '%s' in '%s'",
|
|
sheetId.toString().c_str(),
|
|
bot->getAliasFullName().c_str());
|
|
bot->grp().bots().removeChildByIndex(bot->getChildIndex());
|
|
CWorkPtr::bot(NULL);
|
|
return;
|
|
}
|
|
bot->setSheet(c);
|
|
}
|
|
|
|
DEFINE_ACTION(ContextNpcBot,STATS)
|
|
{
|
|
CBotNpc*bot=CWorkPtr::botNpc();
|
|
if (bot==NULL)
|
|
return;
|
|
|
|
bot->initEnergy ((*NLMISC::safe_cast<CGroupNpc*>(bot->getOwner())).getEnergyCoef());
|
|
}
|
|
|
|
DEFINE_ACTION(ContextNpcBot,STARTPOS)
|
|
{
|
|
CBotNpc *bot=CWorkPtr::botNpc();
|
|
if (bot==NULL)
|
|
return;
|
|
|
|
// set the bot's start position
|
|
// args: int x, y
|
|
sint32 x,y;
|
|
float theta;
|
|
uint32 i;
|
|
if (!getArgs(args,name(), x, y, theta, i))
|
|
return;
|
|
|
|
TVerticalPos verticalPos = (TVerticalPos) i;
|
|
|
|
LOG("Bot: %s: startpos: %.3f,%.3f:%s %d",
|
|
bot->getAliasNode()->fullName().c_str(),
|
|
double(x)/1000.0,
|
|
double(y)/1000.0,
|
|
verticalPosToString(verticalPos).c_str(),
|
|
uint32(180.0*theta/3.14159265359+0.5)%360);
|
|
|
|
bot->setStartPos(double(x)/1000.0, double(y)/1000.0, theta, TVerticalPos(verticalPos));
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
// Control over verbose nature of logging
|
|
//---------------------------------------------------------------------------------------
|
|
|
|
NLMISC_COMMAND(verboseNPCParserLog,"Turn on or off or check the state of verbose .primitive parser logging","")
|
|
{
|
|
if(args.size()>1)
|
|
return false;
|
|
|
|
if(args.size()==1)
|
|
StrToBool (VerboseLog, args[0]);
|
|
|
|
nlinfo("verbose Logging is %s",VerboseLog?"ON":"OFF");
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
DEFINE_ACTION(ContextNpcMgr,GRPKAMI)
|
|
{
|
|
if (!CWorkPtr::mgrNpc())
|
|
return;
|
|
|
|
// extract the arguments
|
|
uint32 alias;
|
|
if (!getArgs(args,"ContextNpcMgrKami:GRP <persistent id>",alias))
|
|
return;
|
|
|
|
CWorkPtr::grp(CWorkPtr::mgrNpc()->groups().getChildByAlias(alias));
|
|
CWorkPtr::stateState(CWorkPtr::mgrNpc()->getStateMachine()->states().getChildByAlias(alias));
|
|
|
|
// setup the KamiGrp context for adding kamis to the group
|
|
CContextStack::push(ContextNpcGrp);
|
|
}
|
|
|
|
|
|
DEFINE_ACTION(ContextNpcMgr,DEPOSIT)
|
|
{
|
|
if (!CWorkPtr::mgrNpc())
|
|
return;
|
|
|
|
// extract the arguments
|
|
uint32 alias;
|
|
if (!getArgs(args,"ContextNpcMgrKami:GRP <persistent id>",alias))
|
|
return;
|
|
|
|
CWorkPtr::grp(CWorkPtr::mgrNpc()->groups().getChildByAlias(alias));
|
|
CWorkPtr::stateState(CWorkPtr::mgrNpc()->getStateMachine()->states().getChildByAlias(alias));
|
|
|
|
// setup the KamiGrp context for adding kamis to the group
|
|
CContextStack::push(ContextNpcGrp);
|
|
CWorkPtr::aiInstance()->registerKamiDeposit(alias,CWorkPtr::grpNpc());
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
|