mirror of
https://port.numenaute.org/aleajactaest/khanat-opennel-code.git
synced 2024-12-15 22:08:43 +00:00
4688 lines
143 KiB
C++
4688 lines
143 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 "script_compiler.h"
|
||
|
||
#include "ai_grp_npc.h"
|
||
#include "group_profile.h"
|
||
#include "ai_generic_fight.h"
|
||
#include "server_share/msg_brick_service.h"
|
||
|
||
#include "continent_inline.h"
|
||
#include "dyn_grp_inline.h"
|
||
|
||
#include "ai_script_data_manager.h"
|
||
|
||
#include "nf_helpers.h"
|
||
#include "ai_aggro.h"
|
||
#include "game_share/send_chat.h"
|
||
#include "game_share/string_manager_sender.h"
|
||
#include <time.h>
|
||
|
||
|
||
using std::string;
|
||
using std::vector;
|
||
using namespace NLMISC;
|
||
using namespace AIVM;
|
||
using namespace AICOMP;
|
||
using namespace AITYPES;
|
||
using namespace RYAI_MAP_CRUNCH;
|
||
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection spawn__
|
||
Spawns the current group.
|
||
|
||
Arguments: ->
|
||
|
||
*/
|
||
// CGroup
|
||
void spawn__(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
if (!entity)
|
||
{
|
||
nlwarning("spawnInstance failed");
|
||
return;
|
||
}
|
||
CGroup const* const grp = entity->getGroup();
|
||
if (grp)
|
||
{
|
||
if (grp->isSpawned())
|
||
grp->getSpawnObj()->spawnBots();
|
||
}
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection despawn_f_
|
||
Depawns the current group.
|
||
|
||
Arguments: f(Immediatly) ->
|
||
@param Immediatly is whether the groups spawns immediatly (1) or not (0)
|
||
|
||
@code
|
||
()despawn(0); // despawn
|
||
()despawn(1); // despawn immediatement
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void despawn_f_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
float const immediatly = stack.top();
|
||
stack.pop();
|
||
|
||
if (!entity)
|
||
{
|
||
nlwarning("despawnInstance failed");
|
||
return;
|
||
}
|
||
|
||
CGroup* const grp = entity->getGroup();
|
||
if (!grp)
|
||
{
|
||
nlwarning("despawn : entity '%s'%s is not a group ? ",
|
||
entity->aliasTreeOwner()->getAliasFullName().c_str(),
|
||
entity->aliasTreeOwner()->getAliasString().c_str());
|
||
return;
|
||
}
|
||
grp->despawnBots(immediatly!=0);
|
||
}
|
||
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection isAlived__f
|
||
Test if the group is alived
|
||
|
||
Arguments: -> f(Immediatly)
|
||
@return 1 if group is spawned
|
||
|
||
@code
|
||
(alive)isAlived();
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void isAlived__f(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
|
||
if (!entity)
|
||
{
|
||
stack.push(0.0f);
|
||
return;
|
||
}
|
||
|
||
CGroup* const grp = entity->getGroup();
|
||
if (!grp)
|
||
{
|
||
nlwarning("isAlived__f : entity '%s'%s is not a group ? ",
|
||
entity->aliasTreeOwner()->getAliasFullName().c_str(),
|
||
entity->aliasTreeOwner()->getAliasString().c_str());
|
||
stack.push(0.0f);
|
||
return;
|
||
}
|
||
|
||
if (!grp->isSpawned())
|
||
{
|
||
stack.push(0.0f);
|
||
return;
|
||
}
|
||
|
||
|
||
for (uint i=0; i<grp->bots().size(); ++i)
|
||
{
|
||
const CBot *const bot = grp->getBot(i);
|
||
if ( !bot
|
||
|| !bot->isSpawned())
|
||
continue;
|
||
|
||
|
||
CAIEntityPhysical *const ep=bot->getSpawnObj();
|
||
if (ep->isAlive())
|
||
{
|
||
stack.push(1.0f);
|
||
return;
|
||
}
|
||
}
|
||
|
||
stack.push(0.0f);
|
||
return;
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection newNpcChildGroupPos_ssfff_c
|
||
Used to create a dynamic npc group (a parent/children relation is defined).
|
||
|
||
Arguments: s(GroupTemplate), s(StateMachine), f(x), f(y), f(Dispersion) -> c(Group)
|
||
@param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
|
||
@param[in] StateMachine is the name of a state machine defined in the same AIInstance
|
||
@param[in] x position of the spawned group on x axis
|
||
@param[in] y position of the spawned group on y axis
|
||
@param[in] Dispersion is the dispersion radius in meters when spawning a group
|
||
@param[out] Group is the newly created group
|
||
|
||
@code
|
||
(@grp)newNpcChildGroupPos("class_forager", "state_machine_1", x, y, 30);
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup not in a family behaviour
|
||
void newNpcChildGroupPos_ssfff_c(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
double dispersionRadius = (double)(float)stack.top();
|
||
stack.pop();
|
||
float const y = stack.top();
|
||
stack.pop();
|
||
float const x = stack.top();
|
||
stack.pop();
|
||
|
||
IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
|
||
CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
|
||
if (!aiInstance)
|
||
return;
|
||
|
||
if (dispersionRadius<0.)
|
||
dispersionRadius = 0.;
|
||
stack.push(spawnNewGroup(entity, stack, aiInstance, CAIVector(x, y), -1, dispersionRadius));
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection newNpcChildGroupPos_ssfff_
|
||
Used to create a dynamic npc group (a parent/children relation is defined).
|
||
|
||
Arguments: s(GroupTemplate), s(StateMachine), f(x), f(y), f(Dispersion) ->
|
||
@param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
|
||
@param[in] StateMachine is the name of a state machine defined in the same AIInstance
|
||
@param[in] x position of the spawned group on x axis
|
||
@param[in] y position of the spawned group on y axis
|
||
@param[in] Dispersion is the dispersion radius in meters when spawning a group
|
||
|
||
@code
|
||
()newNpcChildGroupPos("class_forager", "state_machine_1", x, y, 30);
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup not in a family behaviour
|
||
void newNpcChildGroupPos_ssfff_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
double dispersionRadius = (double)(float)stack.top();
|
||
stack.pop();
|
||
float const y = stack.top();
|
||
stack.pop();
|
||
float const x = stack.top();
|
||
stack.pop();
|
||
|
||
IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
|
||
CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
|
||
if (!aiInstance)
|
||
return;
|
||
|
||
if (dispersionRadius<0.)
|
||
dispersionRadius = 0.;
|
||
spawnNewGroup(entity, stack, aiInstance, CAIVector(x, y), -1, dispersionRadius);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection newNpcChildGroupPos_ssff_c
|
||
Used to create a dynamic npc group (a parent/children relation is defined).
|
||
|
||
Arguments: s(GroupTemplate), s(StateMachine), f(x), f(y) -> c(Group)
|
||
@param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
|
||
@param[in] StateMachine is the name of a state machine defined in the same AIInstance
|
||
@param[in] x position of the spawned group on x axis
|
||
@param[in] y position of the spawned group on y axis
|
||
@param[out] Group is the newly created group
|
||
|
||
@code
|
||
(@grp)newNpcChildGroupPos("class_forager", "state_machine_1", x, y);
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup not in a family behaviour
|
||
void newNpcChildGroupPos_ssff_c(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
stack.push((float)-1.0f);
|
||
newNpcChildGroupPos_ssfff_c(entity, stack);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection newNpcChildGroupPos_ssff_
|
||
Used to create a dynamic npc group (a parent/children relation is defined).
|
||
|
||
Arguments: s(GroupTemplate), s(StateMachine), f(x), f(y) ->
|
||
@param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
|
||
@param[in] StateMachine is the name of a state machine defined in the same AIInstance
|
||
@param[in] x position of the spawned group on x axis
|
||
@param[in] y position of the spawned group on y axis
|
||
|
||
@code
|
||
()newNpcChildGroupPos("class_forager", "state_machine_1", x, y);
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup not in a family behaviour
|
||
void newNpcChildGroupPos_ssff_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
stack.push((float)-1.0f);
|
||
newNpcChildGroupPos_ssfff_(entity, stack);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection newNpcChildGroupPosMl_ssffff_c
|
||
Used to create a multilevel dynamic npc group (a parent/children relation is defined).
|
||
|
||
Arguments: s(GroupTemplate), s(StateMachine), f(x), f(y), f(BaseLevel), f(Dispersion) -> c(Group)
|
||
@param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
|
||
@param[in] StateMachine is the name of a state machine defined in the same AIInstance
|
||
@param[in] x position of the spawned group on x axis
|
||
@param[in] y position of the spawned group on y axis
|
||
@param[in] BaseLevel is the base level of the spawned group
|
||
@param[in] Dispersion is the dispersion radius in meters when spawning a group
|
||
@param[out] Group is the newly created group
|
||
|
||
@code
|
||
(@grp)newNpcChildGroupPosMl("class_forager", "state_machine_1", x, y, 13, 7.5);
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup not in a family behaviour
|
||
void newNpcChildGroupPosMl_ssffff_c(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
double dispersionRadius = (double)(float)stack.top();
|
||
stack.pop();
|
||
float const y = stack.top();
|
||
stack.pop();
|
||
float const x = stack.top();
|
||
stack.pop();
|
||
|
||
IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
|
||
CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
|
||
if (!aiInstance)
|
||
return;
|
||
|
||
if (dispersionRadius<0.)
|
||
dispersionRadius = 0.;
|
||
stack.push(spawnNewGroup(entity, stack, aiInstance, CAIVector(x,y), -1, dispersionRadius));
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection newNpcChildGroupPosMl_ssffff_
|
||
Used to create a multilevel dynamic npc group (a parent/children relation is defined).
|
||
|
||
Arguments: s(GroupTemplate), s(StateMachine), f(x), f(y), f(BaseLevel), f(Dispersion) ->
|
||
@param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
|
||
@param[in] StateMachine is the name of a state machine defined in the same AIInstance
|
||
@param[in] x position of the spawned group on x axis
|
||
@param[in] y position of the spawned group on y axis
|
||
@param[in] BaseLevel is the base level of the spawned group
|
||
@param[in] Dispersion is the dispersion radius in meters when spawning a group
|
||
|
||
@code
|
||
()newNpcChildGroupPosMl("class_forager", "state_machine_1", x, y, 13, 7.5);
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup not in a family behaviour
|
||
void newNpcChildGroupPosMl_ssffff_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
double dispersionRadius = (double)(float)stack.top();
|
||
stack.pop();
|
||
float const y = stack.top();
|
||
stack.pop();
|
||
float const x = stack.top();
|
||
stack.pop();
|
||
|
||
IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
|
||
CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
|
||
if (!aiInstance)
|
||
return;
|
||
|
||
if (dispersionRadius<0.)
|
||
dispersionRadius = 0.;
|
||
spawnNewGroup(entity, stack, aiInstance, CAIVector(x,y), -1, dispersionRadius);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection newNpcChildGroupPosMl_ssfff_c
|
||
Used to create a multilevel dynamic npc group (a parent/children relation is defined).
|
||
|
||
Arguments: s(GroupTemplate), s(StateMachine), f(x), f(y), f(BaseLevel) -> c(Group)
|
||
@param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
|
||
@param[in] StateMachine is the name of a state machine defined in the same AIInstance
|
||
@param[in] x position of the spawned group on x axis
|
||
@param[in] y position of the spawned group on y axis
|
||
@param[in] BaseLevel is the base level of the spawned group
|
||
@param[out] Group is the newly created group
|
||
|
||
@code
|
||
(@grp)newNpcChildGroupPosMl("class_forager", "state_machine_1", x, y, 13);
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup not in a family behaviour
|
||
void newNpcChildGroupPosMl_ssfff_c(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
stack.push((float)-1.0f);
|
||
newNpcChildGroupPosMl_ssffff_c(entity, stack);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection newNpcChildGroupPosMl_ssfff_
|
||
Used to create a multilevel dynamic npc group (a parent/children relation is defined).
|
||
|
||
Arguments: s(GroupTemplate), s(StateMachine), f(x), f(y), f(BaseLevel) ->
|
||
@param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
|
||
@param[in] StateMachine is the name of a state machine defined in the same AIInstance
|
||
@param[in] x position of the spawned group on x axis
|
||
@param[in] y position of the spawned group on y axis
|
||
@param[in] BaseLevel is the base level of the spawned group
|
||
|
||
@code
|
||
()newNpcChildGroupPosMl("class_forager", "state_machine_1", x, y, 13);
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup not in a family behaviour
|
||
void newNpcChildGroupPosMl_ssfff_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
stack.push((float)-1.0f);
|
||
newNpcChildGroupPosMl_ssffff_(entity, stack);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection getMidPos__ff
|
||
Returns the position (x, y) of the current group.
|
||
|
||
Arguments: -> f(x), f(y)
|
||
@param[out] x position of the group on x axis
|
||
@param[out] y position of the group on y axis
|
||
|
||
@code
|
||
(x, y)getMidPos();
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void getMidPos__ff(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
CGroup* const group = entity->getGroup();
|
||
|
||
CAIVector vect;
|
||
if (group->isSpawned())
|
||
{
|
||
if (!group->getSpawnObj()->calcCenterPos(vect))
|
||
group->getSpawnObj()->calcCenterPos(vect, true);
|
||
}
|
||
|
||
float x((float)vect.x().asDouble());
|
||
float y((float)vect.y().asDouble());
|
||
|
||
stack.push(y);
|
||
stack.push(x);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection newNpcChildGroup_sssf_c
|
||
Used to create dynamic npc group (a parent/children relation is defined).
|
||
|
||
Arguments: s(GroupTemplate), s(StateMachine), s(Zone), f(Dispersion) -> c(Group)
|
||
@param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
|
||
@param[in] StateMachine is the name of a state machine defined in the same AIInstance
|
||
@param[in] Zone is returned by the getZoneWithFlags methods
|
||
@param[in] Dispersion is the dispersion radius in meters when spawning a group
|
||
@param[out] Group is the newly created group
|
||
|
||
@code
|
||
(@grp)newNpcChildGroup("class_forager", "state_machine_1", $zone, 10);
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup not in a family behaviour
|
||
void newNpcChildGroup_sssf_c(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
double dispersionRadius = (double)(float)stack.top();
|
||
stack.pop();
|
||
TStringId const zoneName = CStringMapper::map(stack.top());
|
||
stack.pop();
|
||
|
||
IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
|
||
CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
|
||
if (!aiInstance)
|
||
return;
|
||
|
||
CNpcZone const* spawnZone = aiInstance->getZone(zoneName);
|
||
if (!spawnZone)
|
||
{
|
||
string StateMachine = stack.top();
|
||
stack.pop();
|
||
stack.pop();
|
||
nlwarning("newNpcChildGroup failed : spawnZone Not Found ! for StateMachine : %s", StateMachine.c_str());
|
||
return;
|
||
}
|
||
if (dispersionRadius<0.)
|
||
{
|
||
dispersionRadius = 0.;
|
||
CNpcZonePlace const* spawnZonePlace = dynamic_cast<CNpcZonePlace const*>(spawnZone);
|
||
if (spawnZonePlace!=NULL)
|
||
dispersionRadius = spawnZonePlace->getRadius();
|
||
}
|
||
stack.push(spawnNewGroup(entity, stack, aiInstance, spawnZone->midPos(), -1, dispersionRadius));
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection newNpcChildGroup_sssf_
|
||
Used to create dynamic npc group (a parent/children relation is defined).
|
||
|
||
Arguments: s(GroupTemplate), s(StateMachine), s(Zone), f(Dispersion) ->
|
||
@param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
|
||
@param[in] StateMachine is the name of a state machine defined in the same AIInstance
|
||
@param[in] Zone is returned by the getZoneWithFlags methods
|
||
@param[in] Dispersion is the dispersion radius in meters when spawning a group
|
||
|
||
@code
|
||
()newNpcChildGroup("class_forager", "state_machine_1", $zone, 10);
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup not in a family behaviour
|
||
void newNpcChildGroup_sssf_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
double dispersionRadius = (double)(float)stack.top();
|
||
stack.pop();
|
||
TStringId const zoneName = CStringMapper::map(stack.top());
|
||
stack.pop();
|
||
|
||
IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
|
||
CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
|
||
if (!aiInstance)
|
||
return;
|
||
|
||
CNpcZone const* spawnZone = aiInstance->getZone(zoneName);
|
||
if (!spawnZone)
|
||
{
|
||
string StateMachine = stack.top();
|
||
stack.pop();
|
||
stack.pop();
|
||
nlwarning("newNpcChildGroup failed : spawnZone Not Found ! for StateMachine : %s", StateMachine.c_str());
|
||
return;
|
||
}
|
||
if (dispersionRadius<0.)
|
||
{
|
||
dispersionRadius = 0.;
|
||
CNpcZonePlace const* spawnZonePlace = dynamic_cast<CNpcZonePlace const*>(spawnZone);
|
||
if (spawnZonePlace!=NULL)
|
||
dispersionRadius = spawnZonePlace->getRadius();
|
||
}
|
||
spawnNewGroup(entity, stack, aiInstance, spawnZone->midPos(), -1, dispersionRadius);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection newNpcChildGroup_sss_c
|
||
Used to create dynamic npc group (a parent/children relation is defined).
|
||
|
||
Arguments: s(GroupTemplate), s(StateMachine), s(Zone), f(Dispersion) -> c(Group)
|
||
@param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
|
||
@param[in] StateMachine is the name of a state machine defined in the same AIInstance
|
||
@param[in] Zone is returned by the getZoneWithFlags methods
|
||
@param[out] Group is the newly created group
|
||
|
||
@code
|
||
(@grp)newNpcChildGroup("class_forager", "state_machine_1", $zone);
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup not in a family behaviour
|
||
void newNpcChildGroup_sss_c(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
stack.push((float)-1.0f);
|
||
newNpcChildGroup_sssf_c(entity, stack);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection newNpcChildGroup_sss_
|
||
Used to create dynamic npc group (a parent/children relation is defined).
|
||
|
||
Arguments: s(GroupTemplate), s(StateMachine), s(Zone), f(Dispersion) ->
|
||
@param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
|
||
@param[in] StateMachine is the name of a state machine defined in the same AIInstance
|
||
@param[in] Zone is returned by the getZoneWithFlags methods
|
||
|
||
@code
|
||
()newNpcChildGroup("class_forager", "state_machine_1", $zone);
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup not in a family behaviour
|
||
void newNpcChildGroup_sss_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
stack.push((float)-1.0f);
|
||
newNpcChildGroup_sssf_(entity, stack);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection newNpcChildGroupMl_sssff_c
|
||
Used to create multilevel dynamic npc group (a parent/children relation is defined).
|
||
|
||
Arguments: s(GroupTemplate), s(StateMachine), s(Zone), f(BaseLevel), f(Dispersion) -> c(Group)
|
||
@param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
|
||
@param[in] StateMachine is the name of a state machine defined in the same AIInstance
|
||
@param[in] Zone is returned by the getZoneWithFlags methods
|
||
@param[in] BaseLevel is the base level of the spawned group
|
||
@param[in] Dispersion is the dispersion radius in meters when spawning a group
|
||
@param[out] Group is the newly created group
|
||
|
||
@code
|
||
(@grp)newNpcChildGroupMl("class_forager", "state_machine_1", $zone, 2, 50);
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup not in a family behaviour
|
||
void newNpcChildGroupMl_sssff_c(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
double dispersionRadius = (double)(float)stack.top();
|
||
stack.pop();
|
||
int baseLevel = (int)(float)stack.top();
|
||
stack.pop();
|
||
TStringId const zoneName = CStringMapper::map(stack.top());
|
||
stack.pop();
|
||
|
||
IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
|
||
CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
|
||
if (!aiInstance)
|
||
return;
|
||
|
||
CNpcZone const* spawnZone = aiInstance->getZone(zoneName);
|
||
if (!spawnZone)
|
||
{
|
||
string StateMachine = stack.top();
|
||
stack.pop();
|
||
stack.pop();
|
||
nlwarning("newNpcChildGroup failed : spawnZone Not Found ! for StateMachine : %s", StateMachine.c_str());
|
||
return;
|
||
}
|
||
if (dispersionRadius<0.)
|
||
{
|
||
dispersionRadius = 0.;
|
||
CNpcZonePlace const* spawnZonePlace = dynamic_cast<CNpcZonePlace const*>(spawnZone);
|
||
if (spawnZonePlace!=NULL)
|
||
dispersionRadius = spawnZonePlace->getRadius();
|
||
}
|
||
stack.push(spawnNewGroup(entity, stack, aiInstance, spawnZone->midPos(), baseLevel, dispersionRadius));
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection newNpcChildGroupMl_sssff_
|
||
Used to create multilevel dynamic npc group (a parent/children relation is defined).
|
||
|
||
Arguments: s(GroupTemplate), s(StateMachine), s(Zone), f(BaseLevel), f(Dispersion) ->
|
||
@param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
|
||
@param[in] StateMachine is the name of a state machine defined in the same AIInstance
|
||
@param[in] Zone is returned by the getZoneWithFlags methods
|
||
@param[in] BaseLevel is the base level of the spawned group
|
||
@param[in] Dispersion is the dispersion radius in meters when spawning a group
|
||
|
||
@code
|
||
()newNpcChildGroupMl("class_forager", "state_machine_1", $zone, 2, 50);
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup not in a family behaviour
|
||
void newNpcChildGroupMl_sssff_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
double dispersionRadius = (double)(float)stack.top();
|
||
stack.pop();
|
||
int baseLevel = (int)(float)stack.top();
|
||
stack.pop();
|
||
TStringId const zoneName = CStringMapper::map(stack.top());
|
||
stack.pop();
|
||
|
||
IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
|
||
CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
|
||
if (!aiInstance)
|
||
return;
|
||
|
||
CNpcZone const* spawnZone = aiInstance->getZone(zoneName);
|
||
if (!spawnZone)
|
||
{
|
||
string StateMachine = stack.top();
|
||
stack.pop();
|
||
stack.pop();
|
||
nlwarning("newNpcChildGroup failed : spawnZone Not Found ! for StateMachine : %s", StateMachine.c_str());
|
||
return;
|
||
}
|
||
if (dispersionRadius<0.)
|
||
{
|
||
dispersionRadius = 0.;
|
||
CNpcZonePlace const* spawnZonePlace = dynamic_cast<CNpcZonePlace const*>(spawnZone);
|
||
if (spawnZonePlace!=NULL)
|
||
dispersionRadius = spawnZonePlace->getRadius();
|
||
}
|
||
spawnNewGroup (entity, stack, aiInstance, spawnZone->midPos(), baseLevel, dispersionRadius);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection newNpcChildGroupMl_sssf_c
|
||
Used to create multilevel dynamic npc group (a parent/children relation is defined).
|
||
|
||
Arguments: s(GroupTemplate), s(StateMachine), s(Zone), f(BaseLevel) -> c(Group)
|
||
@param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
|
||
@param[in] StateMachine is the name of a state machine defined in the same AIInstance
|
||
@param[in] Zone is returned by the getZoneWithFlags methods
|
||
@param[in] BaseLevel is the base level of the spawned group
|
||
@param[out] Group is the newly created group
|
||
|
||
@code
|
||
(@grp)newNpcChildGroupMl("class_forager", "state_machine_1", $zone, 12);
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup not in a family behaviour
|
||
void newNpcChildGroupMl_sssf_c(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
stack.push((float)-1.0f);
|
||
newNpcChildGroupMl_sssff_c(entity, stack);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection newNpcChildGroupMl_sssf_
|
||
Used to create multilevel dynamic npc group (a parent/children relation is defined).
|
||
|
||
Arguments: s(GroupTemplate), s(StateMachine), s(Zone), f(BaseLevel) ->
|
||
@param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
|
||
@param[in] StateMachine is the name of a state machine defined in the same AIInstance
|
||
@param[in] Zone is returned by the getZoneWithFlags methods
|
||
@param[in] BaseLevel is the base level of the spawned group
|
||
|
||
@code
|
||
()newNpcChildGroupMl("class_forager", "state_machine_1", $zone, 12);
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup not in a family behaviour
|
||
void newNpcChildGroupMl_sssf_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
stack.push((float)-1.0f);
|
||
newNpcChildGroupMl_sssff_(entity, stack);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection spawnManager_s_
|
||
Spawns a manager.
|
||
|
||
Arguments: s(ManagerName) ->
|
||
@param[in] ManagerName is the name of the manager to spawn
|
||
|
||
@code
|
||
()spawnManager("NPC Manager"); // Spawns all the NPCs in the NPC manager called "NPC Manager"
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup not in a family behaviour
|
||
void spawnManager_s_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
string ManagerName = stack.top();
|
||
stack.pop();
|
||
|
||
breakable
|
||
{
|
||
if (!entity)
|
||
{
|
||
nlwarning("SpawnManager error entity not spawned");
|
||
break;
|
||
}
|
||
|
||
IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
|
||
CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
|
||
if (!aiInstance)
|
||
{
|
||
nlwarning("SpawnManager error AIInstance not Found");
|
||
break;
|
||
}
|
||
/** :TODO: If CStringFilter is available use it here and test the whole */
|
||
string/*CStringFilter*/ managerFilter(ManagerName);
|
||
FOREACH(itManager, CAliasCont<CManager>, aiInstance->managers())
|
||
{
|
||
CManager* manager = *itManager;
|
||
if (manager && managerFilter==manager->getName())
|
||
{
|
||
manager->spawn();
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
nlwarning("SpawnManager error");
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection despawnManager_s_
|
||
Despawns a manager.
|
||
|
||
Arguments: s(ManagerName) ->
|
||
@param[in] ManagerName is the name of the manager to despawn
|
||
|
||
@code
|
||
()despawnManager("NPC Manager"); // Despawns all the NPCs in the NPC manager called "NPC Manager"
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup not in a family behaviour
|
||
void despawnManager_s_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
string ManagerName = stack.top();
|
||
stack.pop();
|
||
|
||
breakable
|
||
{
|
||
if (!entity)
|
||
{
|
||
nlwarning("DespawnManager error entity not spawned");
|
||
break;
|
||
}
|
||
|
||
IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
|
||
CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
|
||
if (!aiInstance)
|
||
{
|
||
nlwarning("DespawnManager error AIInstance not Found");
|
||
break;
|
||
}
|
||
// :TODO: If CStringFilter is available use it here and test the whole
|
||
string/*CStringFilter*/ managerFilter(ManagerName);
|
||
FOREACH(itManager, CAliasCont<CManager>, aiInstance->managers())
|
||
{
|
||
CManager *manager=*itManager;
|
||
if (manager && managerFilter==manager->getName())
|
||
{
|
||
manager->despawnMgr();
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection getGroupTemplateWithFlags_sss_s
|
||
Returns the name of a randomly chosen group template corresponding to specified flags.
|
||
|
||
Arguments: s(OneOf), s(Mandatory), s(ExceptFlags) -> s(GroupTemplate)
|
||
@param[in] OneOf is a '|' separated list of flags
|
||
@param[in] Mandatory is a '|' separated list of flags
|
||
@param[in] ExceptFlags is a '|' separated list of flags
|
||
@param[out] GroupTemplate is a group template matching at least one of OneOf flags, all Manadatory flags and none of ExceptFlags
|
||
|
||
@code
|
||
($group)getGroupTemplateWithFlags("food|rest", "invasion|outpost"); // Get a group which matches 'invasion', 'outpost' and either 'food' or 'rest' flags.
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup not in a family behaviour
|
||
void getGroupTemplateWithFlags_sss_s(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
string exceptProperties = stack.top();
|
||
stack.pop();
|
||
string mandatoryProperties = stack.top();
|
||
stack.pop();
|
||
string oneOfProperties = stack.top();
|
||
stack.pop();
|
||
|
||
// If no AI instance return
|
||
IManagerParent* managerParent = entity->getGroup()->getOwner()->getOwner();
|
||
CAIInstance* aiInstance = dynamic_cast<CAIInstance*>(managerParent);
|
||
if (!aiInstance)
|
||
{
|
||
stack.push(string());
|
||
return;
|
||
}
|
||
|
||
// Fill the property sets.
|
||
AITYPES::CPropertySet oneOfSet = readSet(oneOfProperties);
|
||
AITYPES::CPropertySet mandatorySet = readSet(mandatoryProperties);
|
||
AITYPES::CPropertySet exceptSet = readSet(exceptProperties);
|
||
|
||
vector<CGroupDesc<CGroupFamily> const*> groupDescs;
|
||
FOREACH (itCont, CCont<CContinent>, aiInstance->continents())
|
||
{
|
||
FOREACH (itRegion, CCont<CRegion>, itCont->regions())
|
||
{
|
||
FOREACH (itFamily, CCont<CGroupFamily>, itRegion->groupFamilies())
|
||
{
|
||
FOREACH (itGroupDesc, CCont<CGroupDesc<CGroupFamily> >, itFamily->groupDescs())
|
||
{
|
||
// Skip groups not meeting the criteria
|
||
if (!itGroupDesc->properties().containsPartOfNotStrict(oneOfSet))
|
||
continue;
|
||
if (!itGroupDesc->properties().containsAllOf(mandatorySet))
|
||
continue;
|
||
if (itGroupDesc->properties().containsPartOfStrict(exceptSet))
|
||
continue;
|
||
groupDescs.push_back(*itGroupDesc);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (groupDescs.size()==0)
|
||
{
|
||
nlwarning("getGroupTemplateWithFlags failed: no group template found that contains all of '%s' and a part of'%s' ", mandatoryProperties.c_str(), oneOfProperties.c_str());
|
||
stack.push(string());
|
||
return;
|
||
}
|
||
|
||
CGroupDesc<CGroupFamily> const* groupDesc = groupDescs[CAIS::rand16((uint32)groupDescs.size())];
|
||
stack.push(groupDesc->getFullName());
|
||
return;
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection getGroupTemplateWithFlags_ss_s
|
||
Returns the name of a randomly chosen group template corresponding to specified flags.
|
||
|
||
Arguments: s(OneOf), s(Mandatory) -> s(GroupTemplate)
|
||
@param[in] OneOf is a '|' separated list of flags
|
||
@param[in] Mandatory is a '|' separated list of flags
|
||
@param[out] GroupTemplate is a group template matching at least one of OneOf flags and all Manadatory flags
|
||
|
||
@code
|
||
($group)getGroupTemplateWithFlags("food|rest", "invasion|outpost"); // Get a group which matches 'invasion', 'outpost' and either 'food' or 'rest' flags.
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup not in a family behaviour
|
||
void getGroupTemplateWithFlags_ss_s(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
stack.push(std::string(""));
|
||
getGroupTemplateWithFlags_sss_s(entity, stack);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection getZoneWithFlags_ssss_s
|
||
The first parameter is a list of 'one match enough' zone flags. The zones must
|
||
have at least one of these flags to be selected. The second parameter is a
|
||
list of 'all required' zone flag. The zones must have all these flags to be
|
||
selected. The fourth parameter is a list of 'all forbidden' zone flag. The
|
||
zones must not have any of these flags to be selected. Additionnaly the
|
||
returned zone cannot be ExceptZone. Last argument specifies a list of flags
|
||
that the selected zone cannot have.
|
||
|
||
With the list of selectable zone, the system then select a zone based on
|
||
entity density in each selected zone. The system will select the least
|
||
populated zone. It then returns the zone name.
|
||
|
||
Priority is given to current Cell, and after that to all cells.
|
||
|
||
Arguments: s(OneOf), s(Mandatory), s(ExceptZone), s(ExceptProperties) -> s(Zone)
|
||
@param[in] OneOf is a '|' separated list of flags
|
||
@param[in] Mandatory is a '|' separated list of flags
|
||
@param[in] ExceptZone is a zone name
|
||
@param[in] ExceptProperties is a '|' separated list of flags
|
||
@param[out] Zone is a zone matching at least one of OneOf flags, all Manadatory flags and can't be ExceptZone
|
||
|
||
@code
|
||
($zone)getZoneWithFlags("food|rest", "invasion|outpost", $oldzone); // Get a zone which matches invasion, outpost and either food or rest flags with the best score except $oldzone.
|
||
($zone)getZoneWithFlags("boss", "", $oldzone); // Get a zone which matches boss flag with the best score except the $oldzone
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup not in a family behaviour
|
||
void getZoneWithFlags_ssss_s(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
string exceptProperties = stack.top();
|
||
stack.pop();
|
||
TStringId curZoneId= CStringMapper::map(stack.top());
|
||
stack.pop();
|
||
string mandatoryProperties = stack.top();
|
||
stack.pop();
|
||
string oneOfProperties = stack.top();
|
||
stack.pop();
|
||
|
||
// If no AI instance return
|
||
IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
|
||
CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
|
||
if (!aiInstance)
|
||
{
|
||
stack.push(string());
|
||
return;
|
||
}
|
||
|
||
// Fill the property sets.
|
||
AITYPES::CPropertySet oneOfSet = readSet(oneOfProperties);
|
||
AITYPES::CPropertySet mandatorySet = readSet(mandatoryProperties);
|
||
AITYPES::CPropertySet exceptSet = readSet(exceptProperties);
|
||
// Get current zone
|
||
CNpcZone const* const curZone = aiInstance->getZone(curZoneId);
|
||
// Create the scorer
|
||
CZoneScorerMandatoryAndOneOfPlusExcept const scorer(oneOfSet, mandatorySet, exceptSet, curZone);
|
||
|
||
getZoneWithFlags_helper(entity, stack, aiInstance, scorer);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection getZoneWithFlags_sss_s
|
||
@sa @ref getZoneWithFlags_ssss_s
|
||
|
||
Arguments: s(OneOf), s(Mandatory), s(ExceptZone) -> s(Zone)
|
||
@param[in] OneOf is a '|' separated list of flags
|
||
@param[in] Mandatory is a '|' separated list of flags
|
||
@param[in] ExceptZone is a zone name
|
||
@param[out] Zone is a zone matching at least one of OneOf flags, all Manadatory flags and can't be ExceptZone
|
||
|
||
@code
|
||
($zone)getZoneWithFlags("food|rest", "invasion|outpost", $oldzone); // Get a zone which matches invasion, outpost and either food or rest flags with the best score except $oldzone.
|
||
($zone)getZoneWithFlags("boss", "", $oldzone); // Get a zone which matches boss flag with the best score except the $oldzone
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup not in a family behaviour
|
||
void getZoneWithFlags_sss_s(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
stack.push(std::string(""));
|
||
getZoneWithFlags_ssss_s(entity, stack);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection getNearestZoneWithFlags_ffsss_s
|
||
@sa @ref getZoneWithFlags_ssss_s
|
||
|
||
The zone returned by this function is the nearest from the specified point and taking into account the zone free space.
|
||
|
||
Arguments: f(X), f(Y), s(OneOf), s(Mandatory), s(ExceptProperties) -> s(Zone)
|
||
@param[in] X is the position of the zone we are looking for on the X axis
|
||
@param[in] Y is the position of the zone we are looking for on the X axis
|
||
@param[in] OneOf is a '|' separated list of flags
|
||
@param[in] Mandatory is a '|' separated list of flags
|
||
@param[in] ExceptProperties is a '|' separated list of flags
|
||
@param[out] Zone is a zone matching at least one of OneOf flags, all Manadatory flags and can't be ExceptZone
|
||
|
||
@code
|
||
($zone)getNearestZoneWithFlags(x, y, "food|rest", "invasion|outpost", "stayaway");
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup not in a family behaviour
|
||
void getNearestZoneWithFlags_ffsss_s(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
string exceptProperties = stack.top();
|
||
stack.pop();
|
||
string mandatoryProperties = stack.top();
|
||
stack.pop();
|
||
string oneOfProperties = stack.top();
|
||
stack.pop();
|
||
float const y = stack.top();
|
||
stack.pop();
|
||
float const x = stack.top();
|
||
stack.pop();
|
||
|
||
// If no AI instance return
|
||
IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
|
||
CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
|
||
if (!aiInstance)
|
||
{
|
||
stack.push(string());
|
||
return;
|
||
}
|
||
|
||
// Fill the property sets.
|
||
AITYPES::CPropertySet oneOfSet = readSet(oneOfProperties);
|
||
AITYPES::CPropertySet mandatorySet = readSet(mandatoryProperties);
|
||
AITYPES::CPropertySet exceptSet = readSet(exceptProperties);
|
||
// Create the scorer
|
||
CZoneScorerMandatoryAndOneOfAndDistAndSpace const scorer(oneOfSet, mandatorySet, exceptSet, CAIVector(x, y));
|
||
|
||
getZoneWithFlags_helper(entity, stack, aiInstance, scorer);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection getNearestZoneWithFlags_ffss_s
|
||
@sa @ref getZoneWithFlags_sss_s
|
||
|
||
The zone returned by this function is the nearest from the specified point and taking into account the zone free space.
|
||
|
||
Arguments: f(X), f(Y), s(OneOf), s(Mandatory), s(ExceptProperties) -> s(Zone)
|
||
@param[in] X is the position of the zone we are looking for on the X axis
|
||
@param[in] Y is the position of the zone we are looking for on the X axis
|
||
@param[in] OneOf is a '|' separated list of flags
|
||
@param[in] Mandatory is a '|' separated list of flags
|
||
@param[out] Zone is a zone matching at least one of OneOf flags, all Manadatory flags and can't be ExceptZone
|
||
|
||
@code
|
||
($zone)getNearestZoneWithFlags(x, y, "food|rest", "invasion|outpost");
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup not in a family behaviour
|
||
void getNearestZoneWithFlags_ffss_s(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
stack.push(std::string(""));
|
||
getNearestZoneWithFlags_ffsss_s(entity, stack);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection getNearestZoneWithFlagsStrict_ffsss_s
|
||
@sa @ref getZoneWithFlags_ssss_s
|
||
|
||
The zone returned by this function is the nearest from the specified point without taking into account the zone free space.
|
||
|
||
Arguments: f(X), f(Y), s(OneOf), s(Mandatory), s(ExceptProperties) -> s(Zone)
|
||
@param[in] X is the position of the zone we are looking for on the X axis
|
||
@param[in] Y is the position of the zone we are looking for on the X axis
|
||
@param[in] OneOf is a '|' separated list of flags
|
||
@param[in] Mandatory is a '|' separated list of flags
|
||
@param[in] ExceptProperties is a '|' separated list of flags
|
||
@param[out] Zone is a zone matching at least one of OneOf flags, all Manadatory flags and can't be ExceptZone
|
||
|
||
@code
|
||
($zone)getNearestZoneWithFlagsStrict(x, y, "food|rest", "invasion|outpost", "stayaway");
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup not in a family behaviour
|
||
void getNearestZoneWithFlagsStrict_ffsss_s(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
string exceptProperties = stack.top();
|
||
stack.pop();
|
||
string mandatoryProperties = stack.top();
|
||
stack.pop();
|
||
string oneOfProperties = stack.top();
|
||
stack.pop();
|
||
float const y = stack.top();
|
||
stack.pop();
|
||
float const x = stack.top();
|
||
stack.pop();
|
||
|
||
// If no AI instance return
|
||
IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
|
||
CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
|
||
if (!aiInstance)
|
||
{
|
||
stack.push(string());
|
||
return;
|
||
}
|
||
|
||
// Fill the property sets.
|
||
AITYPES::CPropertySet oneOfSet = readSet(oneOfProperties);
|
||
AITYPES::CPropertySet mandatorySet = readSet(mandatoryProperties);
|
||
AITYPES::CPropertySet exceptSet = readSet(exceptProperties);
|
||
// Create the scorer
|
||
const CZoneScorerMandatoryAndOneOfAndDist scorer(oneOfSet, mandatorySet, exceptSet, CAIVector(x, y));
|
||
|
||
getZoneWithFlags_helper(entity, stack, aiInstance, scorer);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection getNearestZoneWithFlagsStrict_ffss_s
|
||
@sa @ref getZoneWithFlags_sss_s
|
||
|
||
The zone returned by this function is the nearest from the specified point without taking into account the zone free space.
|
||
|
||
Arguments: f(X), f(Y), s(OneOf), s(Mandatory), s(ExceptProperties) -> s(Zone)
|
||
@param[in] X is the position of the zone we are looking for on the X axis
|
||
@param[in] Y is the position of the zone we are looking for on the X axis
|
||
@param[in] OneOf is a '|' separated list of flags
|
||
@param[in] Mandatory is a '|' separated list of flags
|
||
@param[out] Zone is a zone matching at least one of OneOf flags, all Manadatory flags and can't be ExceptZone
|
||
|
||
@code
|
||
($zone)getNearestZoneWithFlagsStrict(x, y, "food|rest", "invasion|outpost");
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup not in a family behaviour
|
||
void getNearestZoneWithFlagsStrict_ffss_s(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
stack.push(std::string(""));
|
||
getNearestZoneWithFlagsStrict_ffsss_s(entity, stack);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection getNeighbourZoneWithFlags_ssss_s
|
||
@sa @ref getZoneWithFlags_ssss_s
|
||
|
||
Here priority is given to current Cell, after that to neighbour Cells, and
|
||
finally to all cells. CurrentZone cannot be returned.
|
||
|
||
Arguments: s(CurrentZone), s(OneOf), s(Mandatory), s(ExceptProperties) -> s(Zone)
|
||
@param[in] CurrentZone is a zone name
|
||
@param[in] OneOf is a '|' separated list of flags
|
||
@param[in] Mandatory is a '|' separated list of flags
|
||
@param[in] ExceptProperties is a '|' separated list of flags
|
||
@param[out] Zone is a zone matching the specified flags
|
||
|
||
@code
|
||
($zone1)getNeighbourZoneWithFlags($zone, "boss", "", $exceptflag); // Get the zone in the neighbour cells of the one containing $zone which matches specified flags
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup not in a family behaviour
|
||
void getNeighbourZoneWithFlags_ssss_s(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
string exceptProperties = stack.top();
|
||
stack.pop();
|
||
string mandatoryProperties = stack.top();
|
||
stack.pop();
|
||
string oneOfProperties = stack.top();
|
||
stack.pop();
|
||
TStringId curZoneId = CStringMapper::map(stack.top());
|
||
stack.pop();
|
||
|
||
// If no AI instance return
|
||
IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
|
||
CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
|
||
if (!aiInstance)
|
||
{
|
||
stack.push(string());
|
||
return;
|
||
}
|
||
|
||
// If curzone is invalid return
|
||
CNpcZone const* const curZone = aiInstance->getZone(curZoneId);
|
||
if (!curZone)
|
||
{
|
||
nlwarning("getNeighbourZoneWithFlags failed: current zone is invalid!");
|
||
nlwarning(" - current zone: %s", CStringMapper::unmap(curZoneId).c_str());
|
||
nlwarning(" - oneOfProperties: %s", oneOfProperties.c_str());
|
||
nlwarning(" - mandatoryProperties: %s", mandatoryProperties.c_str());
|
||
nlwarning(" - exceptProperties: %s", exceptProperties.c_str());
|
||
stack.push(string());
|
||
return;
|
||
}
|
||
|
||
// Fill the property sets.
|
||
AITYPES::CPropertySet oneOfSet = readSet(oneOfProperties);
|
||
AITYPES::CPropertySet mandatorySet = readSet(mandatoryProperties);
|
||
AITYPES::CPropertySet exceptSet = readSet(exceptProperties);
|
||
// Create the scorer
|
||
CZoneScorerMandatoryAndOneOfPlusExcept const scorer(oneOfSet, mandatorySet, exceptSet, curZone);
|
||
|
||
vector<CCell*> cells;
|
||
curZone->getOwner()->getNeighBourgCellList(cells);
|
||
cells.push_back(curZone->getOwner());
|
||
std::random_shuffle(cells.begin(), cells.end());
|
||
|
||
CNpcZone const* const newZone = CCellZone::lookupNpcZoneScorer(cells, scorer);
|
||
|
||
if (newZone)
|
||
{
|
||
stack.push(newZone->getAliasTreeOwner().getAliasFullName());
|
||
return;
|
||
}
|
||
nlwarning("getNeighbourgZoneWithFlags failed: no zone found");
|
||
nlwarning(" - current zone: %s", CStringMapper::unmap(curZoneId).c_str());
|
||
nlwarning(" - oneOfProperties: %s", oneOfProperties.c_str());
|
||
nlwarning(" - mandatoryProperties: %s", mandatoryProperties.c_str());
|
||
nlwarning(" - exceptProperties: %s", exceptProperties.c_str());
|
||
|
||
stack.push(string());
|
||
return;
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection getNeighbourZoneWithFlags_sss_s
|
||
@sa @ref getZoneWithFlags_sss_s
|
||
|
||
Here priority is given to current Cell, after that to neighbour Cells, and
|
||
finally to all cells. CurrentZone cannot be returned.
|
||
|
||
Arguments: s(CurrentZone), s(OneOf), s(Mandatory) -> s(Zone)
|
||
@param[in] CurrentZone is a zone name
|
||
@param[in] OneOf is a '|' separated list of flags
|
||
@param[in] Mandatory is a '|' separated list of flags
|
||
@param[out] Zone is a zone matching the specified flags
|
||
|
||
@code
|
||
($zone1)getNeighbourZoneWithFlags($zone, "boss", ""); // Get the zone in the neighbour cells of the one containing $zone which matches specified flags
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup not in a family behaviour
|
||
void getNeighbourZoneWithFlags_sss_s(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
stack.push(std::string(""));
|
||
getNeighbourZoneWithFlags_ssss_s(entity, stack);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection setAggro_ff_
|
||
Sets aggro parameters of current group.
|
||
|
||
Arguments: f(Range), f(NbTicks) ->
|
||
@param[in] Range is a aggro range in meters
|
||
@param[in] NbTicks is a aggro update period in ticks
|
||
|
||
@code
|
||
()setAggro(Range, NbTicks); // Sets the aggro range of the group to Range, updated every NbTicks ticks
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void setAggro_ff_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
sint32 updateNbTicks = (sint32)(float)stack.top();
|
||
stack.pop();
|
||
float aggroRange = stack.top();
|
||
stack.pop();
|
||
|
||
CGroup* const grp = entity->getGroup();
|
||
if (grp)
|
||
{
|
||
grp->_AggroRange = aggroRange;
|
||
if (updateNbTicks>0)
|
||
grp->_UpdateNbTicks = updateNbTicks;
|
||
}
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection setCanAggro_f_
|
||
Let a bot aggro or prevent it from aggroing.
|
||
|
||
Arguments: f(CanAggro) ->
|
||
@param[in] CanAggro tells whether the bot can aggro (!=0) or not (==0)
|
||
|
||
@code
|
||
()setCanAggro(0);
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void setCanAggro_f_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
bool canAggro = ((float)stack.top())!=0.f;
|
||
stack.pop();
|
||
|
||
FOREACH(bot, CCont<CBot>, entity->getGroup()->bots())
|
||
{
|
||
if (!bot->isSpawned())
|
||
continue;
|
||
CSpawnBot* spBot = bot->getSpawnObj();
|
||
if (spBot)
|
||
spBot->setCanAggro(canAggro);
|
||
}
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection clearAggroList_f_
|
||
Reset the aggrolist of a bot.
|
||
|
||
Arguments: f(bool don't send lost aggro message to EGS) ->
|
||
|
||
@code
|
||
()clearAggroList(0/1);
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void clearAggroList_f_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
bool sendAggroLostMessage = ((float)stack.top())==0.f;
|
||
stack.pop();
|
||
|
||
FOREACH(bot, CCont<CBot>, entity->getGroup()->bots())
|
||
{
|
||
if (!bot->isSpawned())
|
||
continue;
|
||
CSpawnBot* spBot = bot->getSpawnObj();
|
||
if (spBot)
|
||
spBot->clearAggroList(sendAggroLostMessage);
|
||
}
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection clearAggroList__
|
||
Reset the aggrolist of a bot.
|
||
|
||
Arguments: ->
|
||
|
||
@code
|
||
()clearAggroList();
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void clearAggroList__(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
stack.push((float)0.f);
|
||
clearAggroList_f_(entity, stack);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection setMode_s_
|
||
Sets the mode of every bot of the group. Valid modes are:
|
||
- Normal
|
||
- Sit
|
||
- Eat
|
||
- Rest
|
||
- Alert
|
||
- Hungry
|
||
- Death
|
||
|
||
Arguments: s(Mode) ->
|
||
@param[in] Mode is the mode name to set
|
||
|
||
@code
|
||
()setMode("Alert");
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void setMode_s_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
string NewMode = stack.top();
|
||
stack.pop();
|
||
|
||
MBEHAV::EMode mode = MBEHAV::stringToMode(NewMode);
|
||
if (mode==MBEHAV::UNKNOWN_MODE)
|
||
return;
|
||
|
||
FOREACH(botIt, CCont<CBot>, entity->getGroup()->bots())
|
||
{
|
||
if (botIt->getSpawnObj())
|
||
botIt->getSpawnObj()->setMode(mode);
|
||
}
|
||
}
|
||
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection setAutoSpawn_f_
|
||
Determine if the current group should respawn automatically after despawn.
|
||
|
||
Arguments: f(AutoSpawn) ->
|
||
@param[in] AutoSpawn is whether the group automatically rewpawns (1) or not (0)
|
||
|
||
@code
|
||
()setAutoSpawn(1);
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void setAutoSpawn_f_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
float const autoSpawn = stack.top();
|
||
stack.pop();
|
||
|
||
CGroup* group = entity->getGroup();
|
||
|
||
group->setAutoSpawn(autoSpawn!=0.f);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
// HP related methods
|
||
/** @page code
|
||
|
||
@subsection setHPLevel_f_
|
||
Sets the current HP level of each bot of the group.
|
||
|
||
Arguments: f(Coef) ->
|
||
@param[in] Coef is the percentage of its max HP each creature will have
|
||
|
||
@code
|
||
()setHPLevel(0.8);
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void setHPLevel_f_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
float coef = stack.top();
|
||
stack.pop();
|
||
|
||
CChangeCreatureHPMsg& msgList = CAIS::instance().getCreatureChangeHP();
|
||
|
||
FOREACH(bot, CCont<CBot>, entity->getGroup()->bots())
|
||
{
|
||
if (!bot->isSpawned())
|
||
continue;
|
||
|
||
CSpawnBot* const sbot = bot->getSpawnObj();
|
||
|
||
msgList.Entities.push_back(sbot->dataSetRow());
|
||
msgList.DeltaHp.push_back((sint32)(sbot->maxHitPoints()*coef));
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
//----------------------------------------------------------------------------
|
||
// HP related methods
|
||
/** @page code
|
||
|
||
@subsection setHPScale_f__f_
|
||
Sets the current HP level of level of each bot of the group. its maxHitPoints
|
||
eg:
|
||
for a bot HP = 850 and MaxHP = 1000
|
||
()setHPScale_f_(0); HP will be 0 so DeltaHp = 850
|
||
()setHPScale_f_(1); HP will be 100 so DeltaHp = 150
|
||
()setHPScale_f_(0.5); HP will be 500 so DeltaHp = 350
|
||
if bot HP = 840 and Max abd setHpRatio(0) HP will be 0
|
||
|
||
|
||
Arguments: f(Coef) ->
|
||
@param[in] Coef is the percentage of its max HP each creature will *BE*
|
||
|
||
@code
|
||
()setHPLevel(0.8);
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void setHPScale_f_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
float coef = stack.top();
|
||
stack.pop();
|
||
|
||
CChangeCreatureHPMsg& msgList = CAIS::instance().getCreatureChangeHP();
|
||
|
||
FOREACH(bot, CCont<CBot>, entity->getGroup()->bots())
|
||
{
|
||
if (!bot->isSpawned())
|
||
continue;
|
||
|
||
CSpawnBot* const sbot = bot->getSpawnObj();
|
||
|
||
msgList.Entities.push_back(sbot->dataSetRow());
|
||
msgList.DeltaHp.push_back((sint32)( sbot->maxHitPoints() *coef - sbot->currentHitPoints()) );
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
/** @page code
|
||
|
||
@subsection scaleHP_f_
|
||
Scales the bots HP.
|
||
|
||
Arguments: f(Coef) ->
|
||
@param[in] Coef is the percentage of its current HP each creature will have
|
||
|
||
@code
|
||
()scaleHP(2);
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void scaleHP_f_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
float coef = stack.top();
|
||
stack.pop();
|
||
|
||
CChangeCreatureHPMsg& msgList = CAIS::instance().getCreatureChangeHP();
|
||
|
||
FOREACH(bot, CCont<CBot>, entity->getGroup()->bots())
|
||
{
|
||
if (!bot->isSpawned())
|
||
continue;
|
||
|
||
CSpawnBot* const sbot = bot->getSpawnObj();
|
||
|
||
msgList.Entities.push_back(sbot->dataSetRow());
|
||
msgList.DeltaHp.push_back((sint32)(sbot->currentHitPoints()*coef));
|
||
}
|
||
}
|
||
|
||
|
||
/** @page code
|
||
|
||
@subsection setBotHPScaleByAlias_fs_
|
||
Same as setHpSacale but only on a specific bot of a groupe from the current group by its bot alias
|
||
|
||
Arguments: f(alias),f(Coef), ->
|
||
@param[in] alias is the alias of the bot
|
||
@param[in] Coef is the percentage of its current HP each creature will have
|
||
|
||
|
||
@code
|
||
()scaleHpByAlias(2, '(A:1000:10560)');
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void setBotHPScaleByAlias_fs_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
uint32 alias = LigoConfig.aliasFromString((string)stack.top()) ; stack.pop();
|
||
|
||
float coef = stack.top(); stack.pop();
|
||
|
||
CChangeCreatureHPMsg& msgList = CAIS::instance().getCreatureChangeHP();
|
||
|
||
FOREACH(bot, CCont<CBot>, entity->getGroup()->bots())
|
||
{
|
||
|
||
if (bot->getAlias() != alias) { continue; }
|
||
if (!bot->isSpawned()) return;
|
||
|
||
CSpawnBot* const sbot = bot->getSpawnObj();
|
||
|
||
msgList.Entities.push_back(sbot->dataSetRow());
|
||
msgList.DeltaHp.push_back((sint32)( sbot->maxHitPoints() *coef - sbot->currentHitPoints()) );
|
||
}
|
||
}
|
||
|
||
|
||
/** @page code
|
||
|
||
@subsection downScaleHP_f_
|
||
Scales the bots HP down.
|
||
|
||
Arguments: f(Coef) ->
|
||
@param[in] Coef is a value
|
||
|
||
@code
|
||
()downScaleHP(2);
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void downScaleHP_f_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
float coef = stack.top();
|
||
stack.pop();
|
||
|
||
CChangeCreatureHPMsg& msgList = CAIS::instance().getCreatureChangeHP();
|
||
|
||
clamp(coef, 0.f, 1.f);
|
||
FOREACH(bot, CCont<CBot>, entity->getGroup()->bots())
|
||
{
|
||
if (!bot->isSpawned())
|
||
continue;
|
||
|
||
CSpawnBot* const sbot = bot->getSpawnObj();
|
||
|
||
msgList.Entities.push_back(sbot->dataSetRow());
|
||
msgList.DeltaHp.push_back((sint32)(sbot->currentHitPoints()*(coef-1)));
|
||
}
|
||
}
|
||
|
||
/** @page code
|
||
|
||
@subsection upScaleHP_f_
|
||
Scales the bots HP up.
|
||
|
||
Arguments: f(Coef) ->
|
||
@param[in] Coef is a value
|
||
|
||
@code
|
||
()upScaleHP(2);
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void upScaleHP_f_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
float coef = stack.top();
|
||
stack.pop();
|
||
|
||
CChangeCreatureHPMsg& msgList = CAIS::instance().getCreatureChangeHP();
|
||
|
||
clamp(coef, 0.f, 1.f);
|
||
FOREACH(bot, CCont<CBot>, entity->getGroup()->bots())
|
||
{
|
||
if (!bot->isSpawned())
|
||
continue;
|
||
CSpawnBot* spBot = bot->getSpawnObj();
|
||
if (spBot)
|
||
{
|
||
msgList.Entities.push_back(spBot->dataSetRow());
|
||
msgList.DeltaHp.push_back((sint32)((spBot->maxHitPoints()-spBot->currentHitPoints())*coef));
|
||
}
|
||
}
|
||
}
|
||
|
||
/** @page code
|
||
|
||
@subsection addHP_f_
|
||
Add HP to the bots.
|
||
|
||
Arguments: f(HP) ->
|
||
@param[in] HP is the amount of hit points to add to each bot
|
||
|
||
@code
|
||
()addHP(500);
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void addHP_f_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
float addHP = stack.top();
|
||
stack.pop();
|
||
|
||
CChangeCreatureHPMsg& msgList = CAIS::instance().getCreatureChangeHP();
|
||
|
||
FOREACH(bot, CCont<CBot>, entity->getGroup()->bots())
|
||
{
|
||
if (!bot->isSpawned())
|
||
continue;
|
||
|
||
CSpawnBot* const sbot = bot->getSpawnObj();
|
||
|
||
msgList.Entities.push_back(sbot->dataSetRow());
|
||
msgList.DeltaHp.push_back((sint32)(sbot->currentHitPoints()+addHP));
|
||
}
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection aiAction_s_
|
||
Triggers an AI action, defined by its sheet name, on the current target.
|
||
|
||
Arguments: s(actionSheetId) ->
|
||
@param[in] actionSheetId is a the sheet name of the action
|
||
|
||
@code
|
||
()aiAction("kick_his_ass.aiaction");
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void aiAction_s_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
std::string actionName = stack.top();
|
||
stack.pop();
|
||
NLMISC::CSheetId sheetId(actionName);
|
||
if (sheetId==NLMISC::CSheetId::Unknown)
|
||
{
|
||
nlwarning("Action SheetId Unknown %s", actionName.c_str());
|
||
return;
|
||
}
|
||
AISHEETS::IAIActionCPtr action = AISHEETS::CSheets::getInstance()->lookupAction(sheetId);
|
||
if (action.isNull())
|
||
{
|
||
nlwarning("Action SheetId Unknown %s", actionName.c_str());
|
||
return;
|
||
}
|
||
|
||
FOREACH(botIt, CCont<CBot>, entity->getGroup()->bots())
|
||
{
|
||
CSpawnBot* pbot = botIt->getSpawnObj();
|
||
if (pbot!=NULL)
|
||
{
|
||
CSpawnBot& bot = *pbot;
|
||
if (!bot.getAIProfile())
|
||
continue; // OK
|
||
|
||
CBotProfileFight* profile = dynamic_cast<CBotProfileFight*>(bot.getAIProfile());
|
||
if (!profile)
|
||
continue; // OK
|
||
|
||
if (!profile->atAttackDist())
|
||
continue; // NOT OK
|
||
|
||
TDataSetRow dataSetRow;
|
||
if ((CAIEntityPhysical*)bot.getTarget())
|
||
dataSetRow = bot.getTarget()->dataSetRow();
|
||
|
||
CEGSExecuteAiActionMsg msg(bot.dataSetRow(), dataSetRow, action->SheetId(), bot._DamageCoef, bot._DamageSpeedCoef);
|
||
msg.send(egsString);
|
||
bot.setActionFlags(RYZOMACTIONFLAGS::Attacks);
|
||
// OK
|
||
}
|
||
}
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection aiActionSelf_s_
|
||
Triggers an AI action, defined by its sheet name, on the bot itself.
|
||
|
||
Arguments: s(actionSheetId) ->
|
||
@param[in] actionSheetId is a the sheet name of the action
|
||
|
||
@code
|
||
()aiActionSelf("defensive_aura.aiaction");
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void aiActionSelf_s_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
std::string actionName = stack.top();
|
||
stack.pop();
|
||
NLMISC::CSheetId sheetId(actionName);
|
||
if (sheetId==NLMISC::CSheetId::Unknown)
|
||
{
|
||
nlwarning("Action SheetId Unknown %s", actionName.c_str());
|
||
return;
|
||
}
|
||
AISHEETS::IAIActionCPtr action = AISHEETS::CSheets::getInstance()->lookupAction(sheetId);
|
||
if (action.isNull())
|
||
{
|
||
nlwarning("Action SheetId Unknown %s", actionName.c_str());
|
||
return;
|
||
}
|
||
|
||
FOREACH(botIt, CCont<CBot>, entity->getGroup()->bots())
|
||
{
|
||
CSpawnBot* pbot = botIt->getSpawnObj();
|
||
if (pbot!=NULL)
|
||
{
|
||
CSpawnBot& bot = *pbot;
|
||
CEGSExecuteAiActionMsg msg(bot.dataSetRow(), bot.dataSetRow(), action->SheetId(), bot._DamageCoef, bot._DamageSpeedCoef);
|
||
msg.send(egsString);
|
||
bot.setActionFlags(RYZOMACTIONFLAGS::Attacks);
|
||
// OK
|
||
}
|
||
}
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection addProfileParameter_s_
|
||
Adds a profile parameter to the current group.
|
||
|
||
Arguments: s(parameterName) ->
|
||
@param[in] parameterName is a the id of the parameter to add
|
||
|
||
@code
|
||
()addProfileParameter("running"); // <20>quivalent <20> un parameter "running" dans la primitive du groupe
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void addProfileParameter_s_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
std::string name = (std::string)stack.top();
|
||
stack.pop();
|
||
|
||
CGroup* group = entity->getGroup();
|
||
|
||
if (group->isSpawned())
|
||
group->getSpawnObj()->addProfileParameter(name, "", 0.f);
|
||
}
|
||
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection addProfileParameter_ss_
|
||
Adds a profile parameter to the current group.
|
||
|
||
Arguments: s(parameterName),s(parameterContent) ->
|
||
@param[in] parameterName is a the id of the parameter to add
|
||
@param[in] parameterContent is the value of the parameter
|
||
|
||
@code
|
||
()addProfileParameter("foo", "bar"); // <20>quivalent <20> un parameter "foo:bar" dans la primitive du groupe
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void addProfileParameter_ss_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
std::string value = (std::string)stack.top();
|
||
stack.pop();
|
||
std::string name = (std::string)stack.top();
|
||
stack.pop();
|
||
|
||
CGroup* group = entity->getGroup();
|
||
|
||
if (group->isSpawned())
|
||
group->getSpawnObj()->addProfileParameter(name, value, 0.f);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection addProfileParameter_sf_
|
||
Adds a profile parameter to the current group.
|
||
|
||
Arguments: s(parameterName),f(parameterContent) ->
|
||
@param[in] parameterName is a the id of the parameter to add
|
||
@param[in] parameterContent is the value of the parameter
|
||
|
||
@code
|
||
()addProfileParameter("foo", 0.5); // <20>quivalent <20> un parameter "foo:0.5" dans la primitive du groupe
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void addProfileParameter_sf_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
float value = (float)stack.top();
|
||
stack.pop();
|
||
std::string name = (std::string)stack.top();
|
||
stack.pop();
|
||
|
||
CGroup* group = entity->getGroup();
|
||
|
||
if (group->isSpawned())
|
||
group->getSpawnObj()->addProfileParameter(name, "", value);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection removeProfileParameter_s_
|
||
removes a profile parameter from the current group.
|
||
|
||
Arguments: s(parameterName) ->
|
||
@param[in] parameterName is a the id of the parameter to remove
|
||
|
||
@code
|
||
()removeProfileParameter("running"); // retire le param<61>tre "running" ou "running:<*>" du groupe
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void removeProfileParameter_s_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
std::string name = (std::string)stack.top();
|
||
stack.pop();
|
||
|
||
CGroup* group = entity->getGroup();
|
||
|
||
if (group->isSpawned())
|
||
group->getSpawnObj()->removeProfileParameter(name);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection addPersistentProfileParameter_s_
|
||
Adds a profile parameter to the current group.
|
||
|
||
Arguments: s(parameterName) ->
|
||
@param[in] parameterName is a the id of the parameter to add
|
||
|
||
@code
|
||
()addProfileParameter("running"); // <20>quivalent <20> un parameter "running" dans la primitive du groupe
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void addPersistentProfileParameter_s_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
std::string name = (std::string)stack.top();
|
||
stack.pop();
|
||
|
||
CGroup* group = entity->getGroup();
|
||
|
||
if (group->isSpawned())
|
||
group->getSpawnObj()->addProfileParameter(name, "", 0.f);
|
||
|
||
group->addProfileParameter(name, "", 0.f);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection addPersistentProfileParameter_ss_
|
||
Adds a profile parameter to the current group.
|
||
|
||
Arguments: s(parameterName),s(parameterContent) ->
|
||
@param[in] parameterName is a the id of the parameter to add
|
||
@param[in] parameterContent is the value of the parameter
|
||
|
||
@code
|
||
()addPersistentProfileParameter("foo", "bar"); // <20>quivalent <20> un parameter "foo:bar" dans la primitive du groupe
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void addPersistentProfileParameter_ss_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
std::string value = (std::string)stack.top();
|
||
stack.pop();
|
||
std::string name = (std::string)stack.top();
|
||
stack.pop();
|
||
|
||
CGroup* group = entity->getGroup();
|
||
|
||
if (group->isSpawned())
|
||
group->getSpawnObj()->addProfileParameter(name, value, 0.f);
|
||
|
||
group->addProfileParameter(name, value, 0.f);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection addPersistentProfileParameter_sf_
|
||
Adds a profile parameter to the current group.
|
||
|
||
Arguments: s(parameterName),f(parameterContent) ->
|
||
@param[in] parameterName is a the id of the parameter to add
|
||
@param[in] parameterContent is the value of the parameter
|
||
|
||
@code
|
||
()addPersistentProfileParameter("foo", 0.5); // <20>quivalent <20> un parameter "foo:0.5" dans la primitive du groupe
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void addPersistentProfileParameter_sf_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
float value = (float)stack.top();
|
||
stack.pop();
|
||
std::string name = (std::string)stack.top();
|
||
stack.pop();
|
||
|
||
CGroup* group = entity->getGroup();
|
||
if (group->isSpawned())
|
||
group->getSpawnObj()->addProfileParameter(name, "", value);
|
||
|
||
group->addProfileParameter(name, "", value);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection removePersistentProfileParameter_s_
|
||
removes a profile parameter from the current group.
|
||
|
||
Arguments: s(parameterName) ->
|
||
@param[in] parameterName is a the id of the parameter to remove
|
||
|
||
@code
|
||
()removeProfileParameter("running"); // retire le param<61>tre "running" ou "running:<*>" du groupe
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void removePersistentProfileParameter_s_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
std::string name = (std::string)stack.top();
|
||
stack.pop();
|
||
|
||
CGroup* group = entity->getGroup();
|
||
if (group->isSpawned())
|
||
group->getSpawnObj()->removeProfileParameter(name);
|
||
|
||
group->removeProfileParameter(name);
|
||
}
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection getOutpostState__s
|
||
Returns the name of the current outpost state (group must be in an outpost).
|
||
|
||
Arguments: -> s(StateName)
|
||
@param[out] StateName is the name of the current outpost state
|
||
|
||
@code
|
||
($name)getOutpostState();
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void getOutpostStateName__s(CStateInstance* si, CScriptStack& stack)
|
||
{
|
||
string str;
|
||
|
||
breakable
|
||
{
|
||
if (!si)
|
||
break;
|
||
|
||
CGroup* group = si->getGroup();
|
||
if (!group)
|
||
break;
|
||
|
||
COutpostManager* manager = dynamic_cast<COutpostManager*>(group->getOwner());
|
||
if (!manager)
|
||
break;
|
||
|
||
str = static_cast<COutpost*>(manager->getOwner())->getStateName();
|
||
}
|
||
|
||
stack.push(str);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection isOutpostTribeOwner__f
|
||
Returns whether the current outpost owner is a tribe (group must be in an outpost).
|
||
|
||
Arguments: -> f(TribeOwner)
|
||
@param[out] TribeOwner is whether the current outpost owner is a tribe (1) or not (0)
|
||
|
||
@code
|
||
(tribeOwner)isOutpostTribeOwner();
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void isOutpostTribeOwner__f(CStateInstance* si, CScriptStack& stack)
|
||
{
|
||
float tribeOwner = 0.f;
|
||
|
||
breakable
|
||
{
|
||
if (!si)
|
||
break;
|
||
|
||
CGroup* group = si->getGroup();
|
||
if (!group)
|
||
break;
|
||
|
||
COutpostManager* manager = dynamic_cast<COutpostManager*>(group->getOwner());
|
||
if (!manager)
|
||
break;
|
||
|
||
if (!static_cast<COutpost*>(manager->getOwner())->isBelongingToAGuild())
|
||
tribeOwner = 1.f;
|
||
}
|
||
|
||
stack.push(tribeOwner);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection isOutpostGuildOwner__f
|
||
Returns whether the current outpost owner is a guild (group must be in an outpost).
|
||
|
||
Arguments: -> f(TribeOwner)
|
||
@param[out] TribeOwner is whether the current outpost owner is a guild (1) or not (0)
|
||
|
||
@code
|
||
(guildOwner)isOutpostGuildOwner();
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void isOutpostGuildOwner__f(CStateInstance* si, CScriptStack& stack)
|
||
{
|
||
float guildOwner = 0.f;
|
||
|
||
breakable
|
||
{
|
||
if (!si)
|
||
break;
|
||
|
||
CGroup* group = si->getGroup();
|
||
if (!group)
|
||
break;
|
||
|
||
COutpostManager* manager = dynamic_cast<COutpostManager*>(group->getOwner());
|
||
if (!manager)
|
||
break;
|
||
|
||
if (static_cast<COutpost*>(manager->getOwner())->isBelongingToAGuild())
|
||
guildOwner = 1.f;
|
||
}
|
||
|
||
stack.push(guildOwner);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection getEventParam_f_f
|
||
Returns the content of a param
|
||
|
||
Arguments: f(paramIndex) -> f(value)
|
||
@param[in] paramIndex is the parameter index passed by EGS ai_event message
|
||
@param[out] value is a the value of the parameter
|
||
|
||
@code
|
||
(val)getEventParam(2);
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void getEventParam_f_f(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
uint32 varId = (uint32)((float)stack.top());
|
||
|
||
CGroup* group = entity->getGroup();
|
||
|
||
stack.top() = group->getEventParamFloat(varId);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection getEventParam_f_s
|
||
Returns the content of a param
|
||
|
||
Arguments: f(paramIndex) -> s(value)
|
||
@param[in] paramIndex is the parameter index passed by EGS ai_event message
|
||
@param[out] value is a the value of the parameter
|
||
|
||
@code
|
||
($val)getEventParam(2);
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void getEventParam_f_s(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
uint32 varId = (uint32)((float)stack.top());
|
||
|
||
CGroup* group = entity->getGroup();
|
||
|
||
stack.top() = group->getEventParamString(varId);
|
||
}
|
||
|
||
|
||
|
||
// -- Boss functions
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection getPlayerStat_ss_f
|
||
Get some player stat.
|
||
|
||
A player EntityId is used to identify the player. This EntityId is passed as string as argument. The EntityId can be obtains via getCurrentPlayerAggroListTarget or getRandomPlayerAggroListTarget.
|
||
The player must be in the same AI Instance (same continent).
|
||
If the player is not in the same Ai Instance or the input string is empty the function return zero and *display* a warning message on the log. You can think of using isPlayerAlived to be sure that the id is still a valid value.
|
||
If param is not one of "HP", "MaxHp", "RatioHp" zero is return and a warning message is printed on the log.
|
||
- The "Hp" stat is the property CURRENT_HIT_POINTS as seen in the mirror.
|
||
- The "MaxHp" stat is the property MAX_HIT_POINTS as seen in the mirror.
|
||
- The "RatioHp" stat is (Hp * 100) / MaxHp
|
||
Be careful the argument is case sensitive.
|
||
|
||
Arguments: s(playerEidAsString), s(statName) -> s(result)
|
||
@param[in] playerEidAsString is EntityId as string from the player we want infos
|
||
@param[in] statName is the name of the property (can be "HP", "MaxHp", "RatioHp")
|
||
@param[out] value is a the value of the parameter
|
||
|
||
@code
|
||
($playerEid)getCurrentPlayerEid();
|
||
print($playerEid); //log (0x00001fbd50:00:00:81)
|
||
(maxHp)getPlayerStat($playerEid, "MaxHp");
|
||
@endcode
|
||
*/
|
||
void getPlayerStat_ss_f(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
std::string funName = "getPlayerStat_ss_f";
|
||
// reaed input
|
||
std::string statName = ((std::string)stack.top()); stack.pop();
|
||
std::string playerEidStr = ((std::string)stack.top()); stack.pop();
|
||
|
||
|
||
// get Dataset of the player to have access to mirror values
|
||
NLMISC::CEntityId playerEid;
|
||
playerEid.fromString(playerEidStr.c_str());
|
||
TDataSetRow playerRow = TheDataset.getDataSetRow( playerEid );
|
||
if (! TheDataset.isAccessible( playerRow ) )
|
||
{
|
||
nlwarning("Try to call %s with on a player '%s' that is not accessible. The isPlayerAlived function must be called to be sure that the palyer is still alived.", funName.c_str(), playerEidStr.c_str() );
|
||
stack.push((float)0);
|
||
return;
|
||
}
|
||
|
||
if (statName == "Hp" )
|
||
{
|
||
// return DSPropertyCURRENT_HIT_POINTS Mirror value
|
||
CMirrorPropValue<sint32> mirrorSymbol( TheDataset, playerRow, DSPropertyCURRENT_HIT_POINTS );
|
||
stack.push((float)mirrorSymbol.getValue());
|
||
return;
|
||
}
|
||
else if (statName == "MaxHp")
|
||
{
|
||
// return DSPropertyMAX_HIT_POINTS Mirror value
|
||
CMirrorPropValue<sint32> mirrorSymbol( TheDataset, playerRow, DSPropertyMAX_HIT_POINTS );
|
||
stack.push((float)mirrorSymbol.getValue());
|
||
return;
|
||
}
|
||
else if (statName == "RatioHp")
|
||
{
|
||
// return percentage of live (read from mirror values)
|
||
CMirrorPropValue<sint32> mirrorSymbol( TheDataset, playerRow, DSPropertyCURRENT_HIT_POINTS );
|
||
CMirrorPropValue<sint32> mirrorSymbol2( TheDataset, playerRow, DSPropertyMAX_HIT_POINTS );
|
||
|
||
stack.push((float)(100.0*mirrorSymbol.getValue() / mirrorSymbol2.getValue()));
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
nlwarning("Try to call %s with wrong state %s", funName.c_str(), statName.c_str() );
|
||
}
|
||
stack.push((float)0);
|
||
return;
|
||
|
||
}
|
||
|
||
/** @page code
|
||
|
||
@subsection getPlayerDistance_fs_f
|
||
Get the distance between a player and a bot in meters.
|
||
|
||
A player EntityId is used to identify the player. This EntityId is passed as string as argument. The EntityId can be obtains via getCurrentPlayerAggroListTarget or getRandomPlayerAggroListTarget.
|
||
The player must be in the same AI Instance (same continent).
|
||
If the player is not in the same Ai Instance or the input string is empty the function return -1 and display a warning message on the log. You can think of using isPlayerAlived to be sure that the player id is still a valid value.
|
||
|
||
A bot index is used to identify the bot. If there is only one spawned bot in a group then the index value is 0. If we want the bot index of a specific bot the getBotIndexByName function can be used. The function getBotCount can be used to know the number of bot in a group. The function isGroupAlived or isBotAlived can be used to verify if the index is valid.
|
||
If no bot are identified by the bot index the function returns -1 and display a warning message. You can this of using isBotAlived to be sure that the bot index is still a valid value.
|
||
|
||
Arguments: s(playerEidAsString), f(botIndex) -> s(result)
|
||
@param[in] playerEidAsString is EntityId as string from the player we want infos
|
||
@param[in] botIndex is the index of an bot member of the current group
|
||
@param[out] value is a the distance between the player on the bot (or -1 if error)
|
||
|
||
@code
|
||
($playerEid)getCurrentPlayerEid();
|
||
(index)getBotIndexByName("toto");
|
||
(distance)getPlayerDistance(index, $playerEid);
|
||
@endcode
|
||
*/
|
||
void getPlayerDistance_fs_f(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
std::string funName = "getPlayerDistance_is_f";
|
||
|
||
// read input params
|
||
std::string playerEidStr = ((std::string)stack.top()); stack.pop();
|
||
sint32 botIndex = (sint32)((float)stack.top()); stack.pop();
|
||
|
||
// get the player Eid
|
||
NLMISC::CEntityId playerEid;
|
||
playerEid.fromString(playerEidStr.c_str());
|
||
|
||
// get the Spawn bot by its index
|
||
CGroup* group = entity->getGroup();
|
||
if (!group)
|
||
{
|
||
nlwarning("%s on a non Npc Group, doesn't work", funName.c_str());
|
||
stack.push((float) -1);
|
||
return;
|
||
}
|
||
if (!group->isSpawned() || botIndex <0 || group->bots().size() <= static_cast<uint32>(botIndex))
|
||
{
|
||
nlwarning("%s used bad index %d/%d (or group not spawn)", funName.c_str(), botIndex, group->bots().size());
|
||
stack.push((float)-1);
|
||
return;
|
||
}
|
||
CBot* bot = group->getBot(botIndex);
|
||
CSpawnBot* spBot = bot?bot->getSpawnObj():0;
|
||
if (!spBot)
|
||
{
|
||
nlwarning("%s used bad index %d/%d (or bot not spawn)", funName.c_str(), botIndex, group->bots().size());
|
||
stack.push((float)-1);
|
||
return;
|
||
}
|
||
|
||
// get DataSetRow of player to read mirro values
|
||
TDataSetRow playerRow = TheDataset.getDataSetRow( playerEid );
|
||
if (! TheDataset.isAccessible( playerRow ) )
|
||
{
|
||
nlwarning("Try to call %s with on a player '%s' that is not accessible. The isPlayerAlived function must be called to be sure that the player is still alived.", funName.c_str(), playerEidStr.c_str() );
|
||
stack.push((float)-1);
|
||
return;
|
||
}
|
||
|
||
// calculate the size between position of the player (from mirro) to position of the spawn bot.
|
||
CMirrorPropValue<sint32> mirrorSymbol( TheDataset, playerRow, DSPropertyPOSX );
|
||
CMirrorPropValue<sint32> mirrorSymbol2( TheDataset, playerRow, DSPropertyPOSY );
|
||
const double dx = double (mirrorSymbol.getValue()) - double(spBot->x().asInt());
|
||
const double dy = double (mirrorSymbol2.getValue()) - double(spBot->y().asInt());
|
||
const double dist2 = (dx*dx + dy*dy) / 1000000.0;
|
||
const double dist = sqrt(dist2);
|
||
|
||
stack.push(float(dist));
|
||
|
||
return;
|
||
|
||
}
|
||
|
||
|
||
|
||
/** @page code
|
||
|
||
@subsection getCurrentPlayerAggroListTarget_f_s
|
||
Get the player entity id (as string) that has the most aggro in the aggro list of a bot.
|
||
|
||
A bot index is used to identify the bot. If there is only one spawned bot in a group then the index value is 0. If we want the bot index of a specific bot the getBotIndexByName function can be used. The function getBotCount can be used to know the number of bot in a group. The function isGroupAlived or isBotAlived can be used to verify if the index is valid.
|
||
If no bot are identified by the bot index (or bot not spawaned) the function returns an empty string and display a warning message. You can this of using isBotAlived to be sure that the bot index is still a valid value.
|
||
|
||
A player EntityId is used to identify the player. This EntityId is returned as result. If the aggro list is empty an empty string is returned (but *NO* warning messages)
|
||
|
||
|
||
Arguments: f(botIndex) -> s(playerEidAsString)
|
||
@param[in] botIndex is the index of an bot member of the current group
|
||
@param[out] playerEidAsString is EntityId as string from the player we want infos
|
||
|
||
@code
|
||
($playerId)getCurrentPlayerAggroListTarget(4);
|
||
(distance)getPlayerDistance(4, $playerId);
|
||
@endcode
|
||
|
||
*/
|
||
|
||
void getCurrentPlayerAggroListTarget_f_s(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
|
||
std::string funName = "getCurrentPlayerAggroListTarget_f_s";
|
||
|
||
// get input params
|
||
sint32 botIndex = (sint32)((float)stack.top()); stack.pop();
|
||
|
||
// get spawn Bot
|
||
CGroup* group = entity->getGroup();
|
||
if (!group)
|
||
{
|
||
nlwarning("%s on a non Npc Group, doesn't work", funName.c_str());
|
||
stack.push(std::string(""));
|
||
return;
|
||
}
|
||
if (!group->isSpawned() || botIndex <0 || group->bots().size() <= static_cast<uint32>(botIndex))
|
||
{
|
||
nlwarning("%s used bad index %d/%d (or group not spawn)", funName.c_str(), botIndex, group->bots().size());
|
||
stack.push(std::string(""));
|
||
|
||
return;
|
||
}
|
||
CBot* bot = group->getBot(botIndex);
|
||
CSpawnBot* spBot = bot?bot->getSpawnObj():0;
|
||
if (!spBot)
|
||
{
|
||
nlwarning("%s used bad index %d/%d (or bot not spawn)", funName.c_str(), botIndex, group->bots().size());
|
||
stack.push(std::string(""));
|
||
return;
|
||
}
|
||
|
||
// iteratre throug aggro list to have the eid with max aggro
|
||
CBotAggroOwner::TBotAggroList const& aggroList = spBot->getBotAggroList();
|
||
CBotAggroOwner::TBotAggroList::const_iterator aggroIt(aggroList.begin()), aggroEnd(aggroList.end());
|
||
TDataSetRow foundRow = TDataSetRow();
|
||
float foundAggro = 0;
|
||
for (; aggroIt != aggroEnd; ++aggroIt)
|
||
{
|
||
float aggro = aggroIt->second->finalAggro();
|
||
if (aggro > foundAggro)
|
||
{
|
||
if (CMirrors::getEntityId(aggroIt->first).getType() != RYZOMID::player)
|
||
{
|
||
continue;
|
||
}
|
||
CAIEntityPhysical* ep = CAIS::instance().getEntityPhysical(aggroIt->first);
|
||
if (!ep)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
CBotPlayer const* const player = NLMISC::safe_cast<CBotPlayer const*>(ep);
|
||
if (!player)
|
||
{
|
||
continue;
|
||
}
|
||
if (!player->isAggroable())
|
||
{
|
||
continue;
|
||
}
|
||
foundAggro = aggro;
|
||
foundRow = aggroIt->first;
|
||
}
|
||
}
|
||
|
||
if ( foundRow == TDataSetRow())
|
||
{ // Empty aggro list so no warning displayed
|
||
stack.push(std::string(""));
|
||
return;
|
||
}
|
||
|
||
const NLMISC::CEntityId& found = CMirrors::getEntityId(foundRow);
|
||
stack.push(std::string(found.toString()));
|
||
}
|
||
|
||
|
||
|
||
|
||
/** @page code
|
||
|
||
@subsection getRandomPlayerAggroListTarget_f_s
|
||
Get a player entity id (as string) from the aggro list of a bot.
|
||
|
||
A bot index is used to identify the bot. If there is only one spawned bot in a group then the index value is 0. If we want the bot index of a specific bot the getBotIndexByName function can be used. The function getBotCount can be used to know the number of bot in a group. The function isGroupAlived or isBotAlived can be used to verify if the index is valid.
|
||
If no bot are identified by the bot index (or bot not spawaned) the function returns an empty string and display a warning message. You can this of using isBotAlived to be sure that the bot index is still a valid value.
|
||
|
||
A player EntityId is used to identify the player. This EntityId is returned as result. If the aggro list is empty an empty string is returned (but *NO* warning messages)
|
||
|
||
|
||
Arguments: f(botIndex) -> s(playerEidAsString)
|
||
@param[in] botIndex is the index of an bot member of the current group
|
||
@param[out] playerEidAsString is EntityId as string from the player we want infos
|
||
|
||
@code
|
||
($playerId)getRandomPlayerAggroListTarget(4);
|
||
()setAggroListTarget(4, $playerId);
|
||
@endcode
|
||
*/
|
||
|
||
|
||
void getRandomPlayerAggroListTarget_f_s(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
|
||
std::string funName = "getRandomPlayerAggroListTarget_f_s";
|
||
|
||
// test botIndex
|
||
uint32 botIndex = (uint32)((float)stack.top()); stack.pop();
|
||
|
||
// get Spawn bot
|
||
CGroup* group = entity->getGroup();
|
||
if (!group || !group->isSpawned() || botIndex <0 || group->bots().size() <= static_cast<uint32>(botIndex))
|
||
{
|
||
nlwarning("%s used bad index %d/%d (or group not spawn)", funName.c_str(), botIndex, group->bots().size());
|
||
stack.push(std::string(""));
|
||
return;
|
||
}
|
||
CBot* bot = group->getBot(botIndex);
|
||
CSpawnBot* spBot = bot?bot->getSpawnObj():0;
|
||
if (!spBot)
|
||
{
|
||
nlwarning("%s used bad index %d/%d (or bot not spawn)", funName.c_str(), botIndex, group->bots().size());
|
||
stack.push(std::string(""));
|
||
return;
|
||
}
|
||
|
||
// make a vector of aggroable player
|
||
CBotAggroOwner::TBotAggroList const& aggroList = spBot->getBotAggroList();
|
||
//typedef std::map<TDataSetRow, TAggroEntryPtr> TBotAggroList;
|
||
CBotAggroOwner::TBotAggroList::const_iterator aggroIt(aggroList.begin()), aggroEnd(aggroList.end());
|
||
TDataSetRow foundRow = TDataSetRow();
|
||
std::vector<TDataSetRow> playerAggroable;
|
||
for (; aggroIt != aggroEnd; ++aggroIt)
|
||
{
|
||
if (CMirrors::getEntityId(aggroIt->first).getType() != RYZOMID::player)
|
||
{
|
||
continue;
|
||
}
|
||
CAIEntityPhysical* ep = CAIS::instance().getEntityPhysical(aggroIt->first);
|
||
if (!ep)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
CBotPlayer const* const player = NLMISC::safe_cast<CBotPlayer const*>(ep);
|
||
if (!player)
|
||
{
|
||
continue;
|
||
}
|
||
if (!player->isAggroable())
|
||
{
|
||
continue;
|
||
}
|
||
playerAggroable.push_back(aggroIt->first);
|
||
|
||
}
|
||
|
||
|
||
if ( playerAggroable.empty())
|
||
{
|
||
stack.push(std::string(""));
|
||
return;
|
||
}
|
||
// chose a randomly a player among the container
|
||
uint32 index = static_cast<uint32>( static_cast<double>(playerAggroable.size())*rand()/(RAND_MAX+1.0) );
|
||
|
||
const NLMISC::CEntityId& found = CMirrors::getEntityId(playerAggroable[ index ]);
|
||
stack.push(std::string(found.toString()));
|
||
}
|
||
|
||
|
||
/** @page code
|
||
|
||
@subsection getAggroListElement_ff_s
|
||
Get a player entity id (as string) from the aggro list of a bot by it aggro list index.
|
||
|
||
A bot index is used to identify the bot. If there is only one spawned bot in a group then the index value is 0. If we want the bot index of a specific bot the getBotIndexByName function can be used. The function getBotCount can be used to know the number of bot in a group. The function isGroupAlived or isBotAlived can be used to verify if the index is valid.
|
||
If no bot are identified by the bot index (or bot not spawaned) the function returns an empty string and display a warning message. You can this of using isBotAlived to be sure that the bot index is still a valid value.
|
||
|
||
A aggro list index is used to identified the player in the aggro list. The size of the aggro list is given by getAggroListSize_f_s
|
||
)
|
||
|
||
|
||
Arguments: f(botIndex), f(aggroListIndex) -> s(playerEidAsString)
|
||
@param[in] botIndex is the index of an bot member of the current group
|
||
@param[in] aggroListIndex is the index of a aggroable player in the aggro list of the bot identified by botIndex
|
||
@param[out] playerEidAsString is EntityId as string from the player we want infos
|
||
|
||
@code
|
||
(aggroSize)getAggorListSize(0);
|
||
// to much player are attacking the boss
|
||
if (aggoroSize > 10)
|
||
{
|
||
($player1)getAggroListElement(0);
|
||
($player2)getAggroListElement(1);
|
||
($player3)getAggroListElement(2);
|
||
// so the boss teleport 3 person from its aggro list at the end of the world
|
||
teleportPlayer($player1, 14233, 123123, 0, 0);
|
||
teleportPlayer($player2, 14233, 123123, 0, 0);
|
||
teleportPlayer($player2, 14233, 123123, 0, 0);
|
||
clearAggroList();
|
||
}
|
||
|
||
@endcode
|
||
*/
|
||
void getAggroListElement_ff_s(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
|
||
std::string funName = "getAggroListElement_ff_s";
|
||
|
||
|
||
|
||
// get params
|
||
uint32 elementIndex = (uint32)((float)stack.top()); stack.pop();
|
||
sint32 botIndex = (uint32)((float)stack.top()); stack.pop();
|
||
|
||
// get spawn bot by its index
|
||
CGroup* group = entity->getGroup();
|
||
if (!group || !group->isSpawned() || botIndex <0 || group->bots().size() <= static_cast<uint32>(botIndex))
|
||
{
|
||
nlwarning("%s used bad index %d/%d (or group not spawn)", funName.c_str(), botIndex, group->bots().size());
|
||
stack.push(std::string(""));
|
||
return;
|
||
}
|
||
CBot* bot = group->getBot(botIndex);
|
||
CSpawnBot* spBot = bot?bot->getSpawnObj():0;
|
||
if (!spBot)
|
||
{
|
||
nlwarning("%s used bad index %d/%d (or bot not spawn)", funName.c_str(), botIndex, group->bots().size());
|
||
stack.push(std::string(""));
|
||
return;
|
||
}
|
||
|
||
// make a vector of aggroable player
|
||
CBotAggroOwner::TBotAggroList const& aggroList = spBot->getBotAggroList();
|
||
//typedef std::map<TDataSetRow, TAggroEntryPtr> TBotAggroList;
|
||
CBotAggroOwner::TBotAggroList::const_iterator aggroIt(aggroList.begin()), aggroEnd(aggroList.end());
|
||
TDataSetRow foundRow = TDataSetRow();
|
||
|
||
std::vector<TDataSetRow> playerAggroable;
|
||
for (; aggroIt != aggroEnd; ++aggroIt)
|
||
{
|
||
if (CMirrors::getEntityId(aggroIt->first).getType() != RYZOMID::player)
|
||
{
|
||
continue;
|
||
}
|
||
CAIEntityPhysical* ep = CAIS::instance().getEntityPhysical(aggroIt->first);
|
||
if (!ep)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
CBotPlayer const* const player = NLMISC::safe_cast<CBotPlayer const*>(ep);
|
||
if (!player)
|
||
{
|
||
continue;
|
||
}
|
||
if (!player->isAggroable())
|
||
{
|
||
continue;
|
||
}
|
||
playerAggroable.push_back(aggroIt->first);
|
||
|
||
}
|
||
|
||
|
||
if ( playerAggroable.empty())
|
||
{
|
||
stack.push(std::string(""));
|
||
return;
|
||
}
|
||
// if index outside return "";
|
||
if (0 > elementIndex && elementIndex >= playerAggroable.size())
|
||
{
|
||
stack.push(std::string(""));
|
||
return;
|
||
}
|
||
|
||
const NLMISC::CEntityId& found = CMirrors::getEntityId(playerAggroable[ uint32(elementIndex) ]);
|
||
stack.push(std::string(found.toString()));
|
||
}
|
||
|
||
|
||
/** @page code
|
||
|
||
@subsection getAggroListSize_f_f
|
||
Get a size of the aggro lsit of a bot (list of aggroable PLAYER)
|
||
|
||
A bot index is used to identify the bot. If there is only one spawned bot in a group then the index value is 0. If we want the bot index of a specific bot the getBotIndexByName function can be used. The function getBotCount can be used to know the number of bot in a group. The function isGroupAlived or isBotAlived can be used to verify if the index is valid.
|
||
If no bot are identified by the bot index (or bot not spawaned) the function returns an empty string and display a warning message. You can this of using isBotAlived to be sure that the bot index is still a valid value.
|
||
|
||
A number is used to indicate the size of the aggro lsit
|
||
|
||
Arguments: f(aggroListIndex) -> f(sizeOfAggroList)
|
||
@param[in] botIndex is the index of an bot member of the current group.
|
||
@param[out] sizeOfAggroList The size of the aggro list index.
|
||
|
||
@code
|
||
(aggroSize)getAggorListSize(0);
|
||
// to much player are attacking the boss
|
||
if (aggoroSize > 10)
|
||
{
|
||
($player1)getAggroListElement(0);
|
||
($player2)getAggroListElement(1);
|
||
($player3)getAggroListElement(2);
|
||
// so the boss teleport 3 person from its aggro list at the end of the world
|
||
teleportPlayer($player1, 14233, 123123, 0, 0);
|
||
teleportPlayer($player2, 14233, 123123, 0, 0);
|
||
teleportPlayer($player2, 14233, 123123, 0, 0);
|
||
clearAggroList();
|
||
}
|
||
|
||
@endcode
|
||
*/
|
||
void getAggroListSize_f_f(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
|
||
std::string funName = "getRandomPlayerAggroListTarget_f_s";
|
||
|
||
|
||
|
||
// input params
|
||
uint32 botIndex = (uint32)((float)stack.top()); stack.pop();
|
||
|
||
// get spawn bot by index of the bot
|
||
CGroup* group = entity->getGroup();
|
||
if (!group || !group->isSpawned() || botIndex <0 || group->bots().size() <= static_cast<uint32>(botIndex))
|
||
{
|
||
nlwarning("%s used bad index %d/%d (or group not spawn)", funName.c_str(), botIndex, group->bots().size());
|
||
stack.push(float(0) );
|
||
return;
|
||
}
|
||
CBot* bot = group->getBot(botIndex);
|
||
CSpawnBot* spBot = bot?bot->getSpawnObj():0;
|
||
if (!spBot)
|
||
{
|
||
nlwarning("%s used bad index %d/%d (or bot not spawn)", funName.c_str(), botIndex, group->bots().size());
|
||
stack.push(float(0) );
|
||
return;
|
||
}
|
||
|
||
// make a vector of aggroable player
|
||
CBotAggroOwner::TBotAggroList const& aggroList = spBot->getBotAggroList();
|
||
//typedef std::map<TDataSetRow, TAggroEntryPtr> TBotAggroList;
|
||
CBotAggroOwner::TBotAggroList::const_iterator aggroIt(aggroList.begin()), aggroEnd(aggroList.end());
|
||
TDataSetRow foundRow = TDataSetRow();
|
||
|
||
std::vector<TDataSetRow> playerAggroable;
|
||
for (; aggroIt != aggroEnd; ++aggroIt)
|
||
{
|
||
if (CMirrors::getEntityId(aggroIt->first).getType() != RYZOMID::player)
|
||
{
|
||
continue;
|
||
}
|
||
CAIEntityPhysical* ep = CAIS::instance().getEntityPhysical(aggroIt->first);
|
||
if (!ep)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
CBotPlayer const* const player = NLMISC::safe_cast<CBotPlayer const*>(ep);
|
||
if (!player)
|
||
{
|
||
continue;
|
||
}
|
||
if (!player->isAggroable())
|
||
{
|
||
continue;
|
||
}
|
||
playerAggroable.push_back(aggroIt->first);
|
||
|
||
}
|
||
|
||
|
||
// return the size of the aggro list
|
||
stack.push(float(playerAggroable.size()));
|
||
}
|
||
|
||
|
||
/** @page code
|
||
|
||
@subsection setAggroListTarget_fs_
|
||
|
||
Maximize the Aggro of a target from the Aggro list of one bot (this id can be given by getRandomPlayerAggroListTarget)..
|
||
|
||
A bot index is used to identify the bot. If there is only one spawned bot in a group then the index value is 0. If we want the bot index of a specific bot the getBotIndexByName function can be used. The function getBotCount can be used to know the number of bot in a group. The function isGroupAlived or isBotAlived can be used to verify if the index is valid.
|
||
If no bot are identified by the bot index (or bot not spawaned) the function display a warning message. You can this of using isBotAlived to be sure that the bot index is still a valid value.
|
||
|
||
A player EntityId is used to identify the player. If the entityId is not from the aggro list then a warning message is shown in the log. If the entityId is a empty string nothing no message are displayed.
|
||
|
||
Arguments: f(botIndex) >s(playerEidAsString) >
|
||
@param[in] botIndex is the index of an bot member of the current group
|
||
@param[in] playerEidAsString is EntityId of the player that will be attacked
|
||
|
||
@code
|
||
($playerId)getRandomPlayerAggroListTarget(4);
|
||
()setAggroListTarget(4, $playerId);
|
||
@endcode
|
||
*/
|
||
|
||
void setAggroListTarget_fs_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
|
||
std::string funName = "setAggroListTarget_fs_";
|
||
|
||
|
||
|
||
std::string playerEidStr = ((std::string)stack.top()); stack.pop();
|
||
sint32 botIndex = (sint32)((float)stack.top());stack.pop();
|
||
|
||
// get the entity id
|
||
NLMISC::CEntityId playerEid;
|
||
playerEid.fromString(playerEidStr.c_str());
|
||
|
||
// get the spawn bot by its indesx
|
||
CGroup* group = entity->getGroup();
|
||
if (!group || !group->isSpawned() || botIndex <0 || group->bots().size() <= static_cast<uint32>(botIndex))
|
||
{
|
||
nlwarning("%s used bad index %d/%d (or group not spawn)", funName.c_str(), botIndex, group->bots().size());
|
||
return;
|
||
}
|
||
CBot* bot = group->getBot(botIndex);
|
||
CSpawnBot* spBot = bot?bot->getSpawnObj():0;
|
||
if (!spBot)
|
||
{
|
||
nlwarning("%s used bad index %d/%d (or bot not spawn)", funName.c_str(), botIndex, group->bots().size());
|
||
return;
|
||
}
|
||
|
||
|
||
// test if player eid is ok
|
||
if (playerEidStr.empty()) { return; }
|
||
TDataSetRow playerRow = TheDataset.getDataSetRow( playerEid );
|
||
bool accessible = TheDataset.isAccessible( playerRow );
|
||
bool pj = playerEid.getType() == RYZOMID::player;
|
||
CAIEntityPhysical* ep = accessible && pj ? CAIS::instance().getEntityPhysical(playerRow):0;
|
||
CBotPlayer const* const player = ep ? NLMISC::safe_cast<CBotPlayer const*>(ep):0;
|
||
if (!ep || !player ||!player->isAggroable() )
|
||
{
|
||
nlwarning("Try to call %s with on a player '%s' that is not accessible (or not aggroable). The isPlayerAlived function must be called to be sure that the player is still alived.", funName.c_str(), playerEidStr.c_str() );
|
||
return;
|
||
}
|
||
|
||
|
||
// maximize aggro from the bot for the player
|
||
spBot->maximizeAggroFor(playerRow);
|
||
}
|
||
|
||
|
||
/** @page code
|
||
|
||
@subsection setGroupAggroListTarget_s_
|
||
|
||
Maximize the Aggro of a target from the Aggro list of one bot to his group (this id can be given by getRandomPlayerAggroListTarget)..
|
||
|
||
A player EntityId is used to identify the player. If the entityId is not from the aggro list then a warning message is shown in the log. If the entityId is a empty string nothing no message are displayed.
|
||
|
||
Arguments: s(playerEidAsString) >
|
||
@param[in] playerEidAsString is EntityId of the player that will be attacked by the group
|
||
|
||
@code
|
||
($playerId)getRandomPlayerAggroListTarget(4);
|
||
()setGroupAggroListTarget($playerId);
|
||
@endcode
|
||
*/
|
||
|
||
void setGroupAggroListTarget_s_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
|
||
std::string funName = "setGroupAggroListTarget_s_";
|
||
|
||
// read params
|
||
std::string playerEidStr = ((std::string)stack.top()); stack.pop();
|
||
|
||
// read eid of the player
|
||
NLMISC::CEntityId playerEid;
|
||
playerEid.fromString(playerEidStr.c_str());
|
||
|
||
|
||
// test if player eid is ok
|
||
if (playerEidStr.empty()) { return; }
|
||
TDataSetRow playerRow = TheDataset.getDataSetRow( playerEid );
|
||
bool accessible = TheDataset.isAccessible( playerRow );
|
||
bool pj = playerEid.getType() == RYZOMID::player;
|
||
CAIEntityPhysical* ep = accessible && pj ? CAIS::instance().getEntityPhysical(playerRow):0;
|
||
CBotPlayer const* const player = ep ? NLMISC::safe_cast<CBotPlayer const*>(ep):0;
|
||
if (!ep || !player ||!player->isAggroable() )
|
||
{
|
||
nlwarning("Try to call %s with on a player '%s' that is not accessible (or not aggroable). The isPlayerAlived function must be called to be sure that the player is still alived.", funName.c_str(), playerEidStr.c_str() );
|
||
return;
|
||
}
|
||
|
||
// test if group is spawn
|
||
CGroup* group = entity->getGroup();
|
||
if (!group || !group->isSpawned() || group->bots().isEmpty() )
|
||
{
|
||
nlwarning("Call %s on a empty/not spawned group", funName.c_str() );
|
||
return;
|
||
}
|
||
|
||
// apply maximizeAggroFor on all member of the group
|
||
CCont<CBot>::iterator itBot = group->bots().begin();
|
||
CCont<CBot>::iterator itEnd = group->bots().end();
|
||
|
||
for (; itBot != itEnd; ++itBot)
|
||
{
|
||
|
||
CSpawnBot* spBot = itBot->getSpawnObj();
|
||
if (!spBot) { continue; }
|
||
spBot->maximizeAggroFor(playerRow);
|
||
}
|
||
|
||
}
|
||
|
||
/** @page code
|
||
|
||
@subsection setManagerAggroListTarget_ss_
|
||
|
||
Maximize the Aggro of a target of one bot to some groups of his manage.
|
||
|
||
A player EntityId is used to identify the player. If the entityId is not from the aggro list then a warning message is shown in the log. If the entityId is a empty string nothing no message are displayed.
|
||
|
||
A string is used to select groups of the manager (groups name must contains this string)
|
||
|
||
Arguments: f(botIndex), s(playerEidAsString) >
|
||
@param[in] playerId is EntityId of the player
|
||
@param[in] nameElement The element of the name of all group we are interest in.
|
||
|
||
@code
|
||
($playerId)getRandomPlayerAggroListTarget(0);
|
||
()setManagerAggroListTarget($playerId, "group_bandit_"); // all group that have name like "group_bandit_*" will attack the player
|
||
@endcode
|
||
*/
|
||
|
||
void setManagerAggroListTarget_ss_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
|
||
std::string funName = "setManagerAggroListTarget_ss_";
|
||
|
||
|
||
// read params
|
||
std::string playerEidStr = ((std::string)stack.top()); stack.pop();
|
||
std::string groupNameStr = ((std::string)stack.top()); stack.pop();
|
||
|
||
|
||
// test if player eid is ok
|
||
NLMISC::CEntityId playerEid;
|
||
playerEid.fromString(playerEidStr.c_str());
|
||
|
||
if (playerEidStr.empty()) { return; }
|
||
TDataSetRow playerRow = TheDataset.getDataSetRow( playerEid );
|
||
bool accessible = TheDataset.isAccessible( playerRow );
|
||
bool pj = playerEid.getType() == RYZOMID::player;
|
||
CAIEntityPhysical* ep = accessible && pj ? CAIS::instance().getEntityPhysical(playerRow):0;
|
||
CBotPlayer const* const player = ep ? NLMISC::safe_cast<CBotPlayer const*>(ep):0;
|
||
if (!ep || !player ||!player->isAggroable() )
|
||
{
|
||
nlwarning("Try to call %s with on a player '%s' that is not accessible (or not aggroable). The isPlayerAlived function must be called to be sure that the player is still alived.", funName.c_str(), playerEidStr.c_str() );
|
||
return;
|
||
}
|
||
|
||
|
||
CGroup* group = entity->getGroup();
|
||
if (!group )
|
||
{
|
||
nlwarning("Call %s on a non exisiting group", funName.c_str() );
|
||
return;
|
||
}
|
||
// get the manager of the group
|
||
CManager* manager = group->getOwner();
|
||
if (!manager)
|
||
{
|
||
nlwarning("Call %s on a non exisiting manager", funName.c_str() );
|
||
return;
|
||
}
|
||
// for all group of the manager maximize aaggro *IF* the group name contains groupNameStr
|
||
group=manager->getNextValidGroupChild();
|
||
while (group!=NULL)
|
||
{
|
||
if ( ! (!group || !group->isSpawned() || group->bots().isEmpty() ) && group->getName().find(groupNameStr) != std::string::npos )
|
||
{
|
||
// apply maximizeAggroFor on all member of the group
|
||
CCont<CBot>::iterator itBot = group->bots().begin();
|
||
CCont<CBot>::iterator itEnd = group->bots().end();
|
||
|
||
for (; itBot != itEnd; ++itBot)
|
||
{
|
||
|
||
CSpawnBot* spBot = itBot->getSpawnObj();
|
||
if (!spBot) { continue; }
|
||
spBot->maximizeAggroFor(playerRow);
|
||
}
|
||
}
|
||
group = manager->getNextValidGroupChild(group);
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
/** @page code
|
||
|
||
@subsection getBotIndexByName_s_f
|
||
|
||
Get the index of a bot of a group by its name (or return -1). Mainly usefull for scripted boss.
|
||
|
||
botIndex begins at zero for the first member of the group, -1 if the bot is not found.
|
||
|
||
Arguments:, s(botName) > f(botIndex)
|
||
|
||
@param[in] name is the name of the bot
|
||
@param[out] botIndex is the index of an bot member of the current group
|
||
|
||
@code
|
||
(botIndex)getBotIndexByName("boss_random_aggro");
|
||
($playerId)getRandomPlayerAggroListTarget(botIndex);
|
||
()setAggroListTarget(botIndex, $playerId);
|
||
}
|
||
@endcode
|
||
*/
|
||
void getBotIndexByName_s_f(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
std::string funName = "getBotIndexByName_s_f";
|
||
|
||
// read params
|
||
std::string botName = (std::string)stack.top(); stack.pop();
|
||
|
||
// test if group is spawned
|
||
CGroup* group = entity->getGroup();
|
||
if (!group || group->bots().isEmpty() )
|
||
{
|
||
nlwarning("Call %s on a empty group", funName.c_str() );
|
||
stack.push((float)-1);
|
||
return;
|
||
}
|
||
|
||
|
||
// Search on all persistent bot of the groupe the bot that have the searched name
|
||
CCont<CBot>::iterator itBot = group->bots().begin();
|
||
CCont<CBot>::iterator itEnd = group->bots().end();
|
||
|
||
sint32 index = -1;
|
||
for (; itBot != itEnd; ++itBot)
|
||
{
|
||
++index;
|
||
const std::string& name = itBot->getName();
|
||
if (name == botName)
|
||
{
|
||
stack.push((float)index);
|
||
return;
|
||
}
|
||
}
|
||
|
||
// Bot not found
|
||
stack.push((float)-1);
|
||
return;
|
||
}
|
||
|
||
|
||
/** @page code
|
||
|
||
@subsection isGroupAlived__f
|
||
|
||
Test if a group is alived (at least one member is alived)
|
||
|
||
A bot index is used to identify the bot. If there is only one spawned bot in a group then the index value is 0. If we want the bot index of a specific bot the getBotIndexByName function can be used. The function getBotCount can be used to know the number of bot in a group. The function isGroupAlived or isBotAlived can be used to verify if the index is valid.
|
||
If no bot are identified by the bot index (or bot not spawaned) the function display a warning message. You can this of using isBotAlived to be sure that the bot index is still a valid value.
|
||
|
||
|
||
Arguments: s(playerid) > f(success)
|
||
|
||
@param[out] sucess is 1.0f if there is at least one member of the group alived (0.0f if not alived bot are found)
|
||
|
||
@code
|
||
($alived)isGroupAlived();
|
||
if ($alived == 1.0f) {
|
||
}
|
||
@endcode
|
||
|
||
*/
|
||
void isGroupAlived__f(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
isAlived__f(entity, stack);
|
||
}
|
||
|
||
|
||
/** @page code
|
||
|
||
@subsection isBotAlived_f_f
|
||
|
||
Test if a bot of the current group is alived. The bot is identified by its index.
|
||
|
||
Arguments: f(botIndex) > f(success)
|
||
|
||
@param[int] botIndex the index of the bot.
|
||
@param[out] sucess is 1.0f if there is at least one member of the group alived (0.0f if not alived bot are found)
|
||
|
||
@code
|
||
($botIndex)getBotIndexByName("boss_3");
|
||
$alived)isBotAlived($botIndex);
|
||
if (alived == 1.0f) {
|
||
}
|
||
@endcode
|
||
|
||
*/
|
||
void isBotAlived_f_f(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
std::string funName = "isBotAlived_f_f";
|
||
// get input index
|
||
sint32 botIndex = (sint32)((float)stack.top()); stack.pop();
|
||
|
||
// get Spawn Bot
|
||
CGroup* group = entity->getGroup();
|
||
if (!group)
|
||
{
|
||
nlwarning("%s on a non Npc Group, doesn't work", funName.c_str());
|
||
stack.push((float)0);
|
||
return;
|
||
}
|
||
if (!group->isSpawned() || group->bots().isEmpty() || botIndex < 0 || group->bots().size() < static_cast<uint32>(botIndex))
|
||
{
|
||
stack.push(0.0f);return;
|
||
}
|
||
const CBot *const bot = group->getBot(botIndex);
|
||
if ( !bot || !bot->isSpawned()) { stack.push(0.0f); return;};
|
||
CAIEntityPhysical *const ep=bot->getSpawnObj();
|
||
if ( !ep) { stack.push(0.0f); return;};
|
||
|
||
// test if spawn bot is alive
|
||
if (ep->isAlive()) { stack.push(1.0f); return;}
|
||
|
||
stack.push(0.0f);
|
||
return;
|
||
}
|
||
|
||
|
||
/** @page code
|
||
|
||
@subsection isPlayerAlived_s_f
|
||
|
||
Test if a a player is is alived.
|
||
|
||
A player EntityId is used to identify the player. If the player is not connected, not in the same continent, or dead 0 is returned.
|
||
|
||
Arguments: s(playerId) > f(success)
|
||
|
||
@param[in] palyerId
|
||
@param[out] success is 1.0f if the entity id of a player is alived.
|
||
|
||
@code
|
||
($botIndex)getBotIndexByName("boss_3");
|
||
($playerId)getCurrentPlayerAggroListTarget($botIndex):
|
||
(alived)isPlayerlived($playerId);
|
||
if (alived == 1.0f) {
|
||
}
|
||
@endcode
|
||
*/
|
||
void isPlayerAlived_s_f(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
// get input data
|
||
std::string playerEidStr = (std::string)stack.top(); stack.pop();
|
||
|
||
//get CAIEntityPhysical of the player
|
||
NLMISC::CEntityId playerEid;
|
||
playerEid.fromString(playerEidStr.c_str());
|
||
TDataSetRow playeDataSetRow = TheDataset.getDataSetRow( playerEid) ;
|
||
if (playerEidStr.empty() || !TheDataset.isAccessible( playeDataSetRow ) || playerEid.getType() != RYZOMID::player )
|
||
{
|
||
stack.push(0.0f); return;
|
||
}
|
||
CAIEntityPhysical* ep = CAIS::instance().getEntityPhysical(playeDataSetRow);
|
||
if (!ep)
|
||
{
|
||
|
||
stack.push(0.0f); return;
|
||
}
|
||
// test if the player is alived
|
||
if (ep->isAlive())
|
||
{
|
||
stack.push(1.0f); return;
|
||
}
|
||
|
||
stack.push(0.0f); return;
|
||
|
||
}
|
||
|
||
/** @page code
|
||
@subsection getServerTimeStr__s
|
||
|
||
Gets the server time as string "eg 21:17:14 the x"
|
||
This function is usefull for stat purpose or debug (to know when a boss is down)
|
||
|
||
Arguments: > s(serverTime)
|
||
|
||
|
||
@param[out] The server time as debug string
|
||
|
||
@code
|
||
($serverTime)getServerTimeAsString();
|
||
@endcode
|
||
*/
|
||
|
||
void getServerTimeStr__s(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
//get the server time (as debug string)
|
||
time_t currentTime;
|
||
time( ¤tTime );
|
||
std::string str = NLMISC::toString("%s", asctime(localtime(¤tTime)));
|
||
stack.push(str);
|
||
}
|
||
|
||
/** @page code
|
||
@subsection getServerTime__s
|
||
|
||
Gets the server time as number (it is the number of seconde since 1970). This value is useful for saving the server date on a file
|
||
|
||
Arguments: > s(serverTime)
|
||
|
||
@param[out] The server time as string (a float is not sharp enough
|
||
|
||
@code
|
||
($serverTime)getServerTime();
|
||
@endcode
|
||
*/
|
||
|
||
void getServerTime__s(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
//get the server time (as time stamp)
|
||
time_t currentTime;
|
||
time( ¤tTime );
|
||
std::string ret = NLMISC::toString("%d", currentTime);
|
||
// convert to string
|
||
stack.push((std::string)ret);
|
||
}
|
||
|
||
|
||
|
||
/** @page code
|
||
@subsection getRyzomDateStr__s
|
||
|
||
Gets the ryzom date as string
|
||
Arguments: > s(ryzomDateStr)
|
||
|
||
@param[out] ryzomTimeAndDateAsString The time and date of the ryzom univers as debug string.
|
||
|
||
@code
|
||
($ryzomDateStr)getRyzomDateStr);
|
||
@endcode
|
||
*/
|
||
void getRyzomDateStr__s(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
// Display time using ryzom style
|
||
std::string result;
|
||
const CRyzomTime &rt = CTimeInterface::getRyzomTime();
|
||
result = NLMISC::toString("%d:%d:00", (int) floorf(rt.getRyzomTime()) , (int) floorf(60.f * fmodf(rt.getRyzomTime(), 1.f)));
|
||
|
||
uint32 month = rt.getRyzomMonth();
|
||
MONTH::EMonth monthInCycle = rt.getRyzomMonthInCurrentCycle();
|
||
std::string monthName = MONTH::toString((MONTH::EMonth) monthInCycle);
|
||
uint32 dayOfMonth = rt.getRyzomDayOfMonth();
|
||
std::string dayName = WEEKDAY::toString((WEEKDAY::EWeekDay) rt.getRyzomDayOfWeek());
|
||
result += NLMISC::toString(" / %s %d %s(%d) %d",
|
||
dayName.c_str(),
|
||
(int) (dayOfMonth + 1),
|
||
monthName.c_str(),
|
||
(int) (month + 1),
|
||
(int) rt.getRyzomYear());
|
||
|
||
stack.push( result );
|
||
}
|
||
|
||
/** @page code
|
||
@subsection getRyzomDate__s
|
||
|
||
Gets the ryzom tick game cycle. Useful for computing difference of time.
|
||
The return value is a string and not a float because float is not sharp enought?
|
||
Arguments: > s(tickGameCycle)
|
||
|
||
@param[out] TickGameCycle The time of the ryzom univers (stops when server stops). 10 tick is 1 second.
|
||
|
||
@code
|
||
($tickGameCycle)getRyzomDate();
|
||
@endcode
|
||
*/
|
||
void getRyzomDate__s(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
//get GameTickCycle
|
||
const NLMISC::TGameCycle ryzomTime= CTickEventHandler::getGameCycle();
|
||
std::string ret = NLMISC::toString("%d", ryzomTime);
|
||
// convert to string
|
||
stack.push((std::string)ret);
|
||
}
|
||
|
||
|
||
|
||
class CPhraseParameters
|
||
{
|
||
public:
|
||
enum TMode {NpcMsg, SystemMsg, EmoteMsg};
|
||
TVectorParamCheck Values;
|
||
};
|
||
|
||
CPhraseParameters PhraseParameters;
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection phraseBegin__
|
||
Clear the parameters stack.
|
||
|
||
Used when creating a customized msg via phraseEndSystemMsg_fss_, phraseEndNpcMsg_fss_, phraseEndSystemMsg_fss_.
|
||
It Must be called at start of phrase if we are not sure that the parameter stack is clean.
|
||
|
||
Parameter stack is unclean when someone has called a phrasePush* function but *not* a phraseEnd function before (which is *very* bad).
|
||
|
||
Arguments: ->
|
||
|
||
@code
|
||
()phraseBegin();
|
||
()phrasePushValue("money", 15);
|
||
()phrasePushValue("integer", 15);
|
||
()phrasePushValue("time", 15);
|
||
()phraseEndSystemMsg(0, "say", "PHRASE_FROM_PHRASE_WITH_3_PARAMETERS");
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void phraseBegin__(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
PhraseParameters.Values.clear();
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection phrasePushValue_sf_
|
||
This function push a value as number on the parameter stack. This stack is used by phraseEndSystemMsg_fss_, phraseEndNpcMsg_fss_, phraseEndSystemMsg_fss_ functions.
|
||
@see phraseBegin__
|
||
@see phrasePushString_ss_
|
||
@see phraseEndSystemMsg_fss_
|
||
@see phraseEndNpcMsg_fss_
|
||
@see phraseEndSystemMsg_fss_
|
||
|
||
|
||
The value *Must* be an number and only few type are handled.
|
||
- money
|
||
- integer
|
||
- time
|
||
|
||
Some value other can be handled *BUT* the value *MUST* be the C++ code enum value. So LD must ask to coder to do a scripting fonction that have as input a string that contains enum value as string eg "matis" and that return the C++ enum value as int (eg 4).
|
||
- skill
|
||
- faction
|
||
- power_type
|
||
- race
|
||
- damage_type
|
||
- characteristic
|
||
- score
|
||
- body_part
|
||
|
||
Arguments: s(paramType), f(value) ->
|
||
@param[in] paramType the type of the parameter
|
||
@param[in] value the value of the parameter
|
||
|
||
|
||
@code
|
||
()phraseBegin();
|
||
()phrasePushValue("money", 15);
|
||
()phrasePushValue("integer", 15);
|
||
()phrasePushValue("time", 15);
|
||
()phraseEndSystemMsg(0, "say", "PHRASE_WITH_3_PARAMETERS");
|
||
@endcode
|
||
|
||
*/
|
||
// CGroup
|
||
void phrasePushValue_sf_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
float f = (float)stack.top();stack.pop(); // get the value as float
|
||
std::string typeStr = (std::string)stack.top(); stack.pop(); // get the param type
|
||
// create the good STRING_MANAGER::TParam in fonction of its type and is value
|
||
STRING_MANAGER::TParamType type = STRING_MANAGER::stringToParamType(typeStr);
|
||
STRING_MANAGER::TParam param;
|
||
param.Type = type;
|
||
switch( type )
|
||
{
|
||
|
||
case STRING_MANAGER::money:
|
||
{
|
||
param.Money = static_cast<uint64>(f);
|
||
break;
|
||
}
|
||
|
||
|
||
case STRING_MANAGER::integer:
|
||
{
|
||
param.Int = static_cast<sint32>(f);
|
||
break;
|
||
}
|
||
|
||
case STRING_MANAGER::time:
|
||
{
|
||
param.Time = static_cast<uint32>(f);
|
||
break;
|
||
}
|
||
|
||
case STRING_MANAGER::skill:
|
||
case STRING_MANAGER::faction:
|
||
case STRING_MANAGER::power_type:
|
||
case STRING_MANAGER::race:
|
||
case STRING_MANAGER::damage_type:
|
||
case STRING_MANAGER::characteristic:
|
||
case STRING_MANAGER::score:
|
||
case STRING_MANAGER::body_part:
|
||
{
|
||
param.Enum = static_cast<uint32>( f );
|
||
break;
|
||
}
|
||
|
||
default:
|
||
param.Type = STRING_MANAGER::invalid_value;
|
||
|
||
break;
|
||
}
|
||
|
||
PhraseParameters.Values.push_back(param);
|
||
}
|
||
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection phrasePushString_ss_
|
||
This function push a value as string on the parameter stack. This stack is used by phraseEndSystemMsg_fss_, phraseEndNpcMsg_fss_, phraseEndSystemMsg_fss_ functions.
|
||
@see phraseBegin__
|
||
@see phrasePushValue_sf_
|
||
@see phraseEndSystemMsg_fss_
|
||
@see phraseEndNpcMsg_fss_
|
||
@see phraseEndSystemMsg_fss_
|
||
|
||
|
||
The value *Must* be a string.
|
||
The string is internal converted to number, sheetId, entityId when needed.
|
||
|
||
Input as a number:
|
||
- money
|
||
- integer
|
||
- time
|
||
|
||
Input as string literal
|
||
- literal
|
||
|
||
Input as an entityId (obtains via getCurrentPlayerAggroListTarget_f_s, getRandomPlayerAggroListTarget_f_s, getBotEid_f_s, getCurrentSpeakerEid__s, getAggroListElement_ff_s)
|
||
- player
|
||
- bot
|
||
- entity
|
||
|
||
Input as sheetId name (example: "toto.sbrick", "toto.sitem", "toto.creature")
|
||
- item
|
||
- outpost
|
||
- creature_model
|
||
- creature
|
||
- sphrase
|
||
- sbrick
|
||
|
||
Input as string identifier
|
||
- place
|
||
- event_faction
|
||
- title
|
||
- bot_name
|
||
|
||
Input as stringId (number): *WARNING* LD must as coder to do function that return string_id if they want to use that type
|
||
- dyn_string_id
|
||
- string_id
|
||
|
||
|
||
Input must be a enum value:
|
||
Some value other can be handled *BUT* the value *MUST* be the C++ code enum value. So LD must ask to coder to do a scripting fonction that have as input a string that contains enum value as string eg "matis" and that return the C++ enum value as int (eg 4).
|
||
- skill
|
||
- faction
|
||
- power_type
|
||
- race
|
||
- damage_type
|
||
- characteristic
|
||
- score
|
||
- body_part
|
||
|
||
Arguments: s(paramType), f(value) ->
|
||
@param[in] paramType the type of the parameter
|
||
@param[in] value the value of the parameter
|
||
|
||
|
||
@code
|
||
($playerEid)getCurrentPlayerEid();
|
||
($botEid)group3.getBotEid(4);
|
||
()phraseBegin();
|
||
()phrasePushValue("integer", 15);
|
||
()phrasePushString("integer", "15");
|
||
()phrasePushString("literal", "Test 123");
|
||
()phrasePushString("player", $playerEid);
|
||
()phrasePushString("bot", $botEid);
|
||
()phrasePushString("item", "abc.sitem");
|
||
()phrasePushString("sbrick", "toto.sbrick");
|
||
()phrasePushString("creature_model", "toto.creature");
|
||
()phraseEndSystemMsg(0, "say", "PHRASE_WITH_SOME_PARAMETERS");
|
||
@endcode
|
||
*/
|
||
void phrasePushString_ss_(CStateInstance* entity, CScriptStack& stack )
|
||
{
|
||
std::string s = (std::string)stack.top(); stack.pop(); // get the param value
|
||
std::string typeStr = (std::string)stack.top(); stack.pop(); // get the param type
|
||
|
||
// construct a STRING_MANAGER::TParam in fonction of its type and its value
|
||
STRING_MANAGER::TParamType type = STRING_MANAGER::stringToParamType(typeStr);
|
||
STRING_MANAGER::TParam param;
|
||
param.Type = type;
|
||
switch( type )
|
||
{
|
||
|
||
case STRING_MANAGER::money:
|
||
{
|
||
param.Money = static_cast<uint64>(atoi( s.c_str() ));
|
||
break;
|
||
}
|
||
|
||
case STRING_MANAGER::player:
|
||
case STRING_MANAGER::bot:
|
||
case STRING_MANAGER::entity:
|
||
{
|
||
|
||
NLMISC::CEntityId id;
|
||
uint32 alias = 0;
|
||
id.fromString(s.c_str());
|
||
CAIEntityPhysical* entityPhysical=CAIS::instance().getEntityPhysical(TheDataset.getDataSetRow(id));
|
||
if (entityPhysical)
|
||
{
|
||
switch( entityPhysical->getRyzomType())
|
||
{
|
||
case RYZOMID::creature:
|
||
case RYZOMID::npc:
|
||
{
|
||
|
||
CSpawnBot* sb = NLMISC::safe_cast<CSpawnBot*>(entityPhysical);
|
||
alias = sb->getPersistent().getAlias();
|
||
break;
|
||
}
|
||
default:
|
||
;
|
||
// player or other have no alias
|
||
}
|
||
}
|
||
param.setEIdAIAlias( id, alias );
|
||
}
|
||
break;
|
||
|
||
case STRING_MANAGER::integer:
|
||
{
|
||
param.Int = atoi( s.c_str());
|
||
break;
|
||
}
|
||
|
||
case STRING_MANAGER::time:
|
||
{
|
||
param.Time = atoi( s.c_str());
|
||
break;
|
||
}
|
||
|
||
|
||
case STRING_MANAGER::item:
|
||
case STRING_MANAGER::outpost:
|
||
case STRING_MANAGER::creature_model:
|
||
case STRING_MANAGER::creature:
|
||
case STRING_MANAGER::sphrase:
|
||
case STRING_MANAGER::sbrick:
|
||
{
|
||
if (s.empty())
|
||
{
|
||
nlwarning("Sheet name expected but not found in script");
|
||
param.SheetId= CSheetId();
|
||
}
|
||
else
|
||
{
|
||
param.SheetId = CSheetId(s);
|
||
}
|
||
break;
|
||
}
|
||
|
||
|
||
case STRING_MANAGER::place:
|
||
case STRING_MANAGER::event_faction:
|
||
case STRING_MANAGER::title:
|
||
case STRING_MANAGER::bot_name:
|
||
{
|
||
param.Identifier = s;
|
||
break;
|
||
}
|
||
|
||
case STRING_MANAGER::skill:
|
||
case STRING_MANAGER::faction:
|
||
case STRING_MANAGER::power_type:
|
||
case STRING_MANAGER::race:
|
||
case STRING_MANAGER::damage_type:
|
||
case STRING_MANAGER::characteristic:
|
||
case STRING_MANAGER::score:
|
||
case STRING_MANAGER::body_part:
|
||
{
|
||
param.Enum = static_cast<uint32>( atoi( s.c_str()) );
|
||
break;
|
||
}
|
||
|
||
case STRING_MANAGER::literal:
|
||
param.Literal.fromUtf8(s);
|
||
break;
|
||
|
||
case STRING_MANAGER::dyn_string_id:
|
||
case STRING_MANAGER::string_id:
|
||
param.StringId = static_cast<uint32>( atoi( s.c_str()) );
|
||
break;
|
||
|
||
case STRING_MANAGER::self:
|
||
case STRING_MANAGER::role:
|
||
case STRING_MANAGER::compass:
|
||
case STRING_MANAGER::guild:
|
||
case STRING_MANAGER::ecosystem:
|
||
case STRING_MANAGER::classification_type:
|
||
default:
|
||
param.Type = STRING_MANAGER::invalid_value;
|
||
|
||
break;
|
||
}
|
||
|
||
PhraseParameters.Values.push_back(param);
|
||
}
|
||
|
||
|
||
|
||
static void phraseEnd(CStateInstance* entity, CScriptStack& stack, CPhraseParameters::TMode mode)
|
||
{
|
||
std::string funName = "phraseEnd";
|
||
|
||
// get Function parameters
|
||
|
||
std::string phraseId = (std::string)stack.top();stack.pop();
|
||
std::string sayMode;
|
||
if (mode != CPhraseParameters::EmoteMsg)
|
||
{
|
||
sayMode = (std::string)stack.top();stack.pop();
|
||
}
|
||
sint32 botIndex = (sint32)((float)stack.top());stack.pop();
|
||
|
||
|
||
// Verify is bot is alived
|
||
|
||
|
||
CGroup* group = entity->getGroup();
|
||
if (!group)
|
||
{
|
||
nlwarning("%s on a non Npc Group, doesn't work", funName.c_str());
|
||
PhraseParameters.Values.clear();
|
||
return;
|
||
}
|
||
if (!group->isSpawned() || group->bots().isEmpty() || botIndex < 0 || group->bots().size() < static_cast<uint32>(botIndex))
|
||
{
|
||
PhraseParameters.Values.clear();
|
||
return;
|
||
}
|
||
const CBot *const bot = group->getBot(botIndex);
|
||
if ( !bot || !bot->isSpawned())
|
||
{
|
||
PhraseParameters.Values.clear();
|
||
return;
|
||
}
|
||
CSpawnBot *const sp= bot->getSpawnObj();
|
||
if ( !sp || !sp->isAlive() )
|
||
{
|
||
PhraseParameters.Values.clear();
|
||
return;
|
||
}
|
||
|
||
// parse type of chat
|
||
CChatGroup::TGroupType groupType;
|
||
if (mode != CPhraseParameters::EmoteMsg)
|
||
{
|
||
groupType = CChatGroup::stringToGroupType(sayMode);
|
||
}
|
||
|
||
// verify phraseId validity
|
||
if (phraseId.empty())
|
||
{
|
||
nlwarning("%s %d: Phrase identifier is empty", funName.c_str(),static_cast<uint32>(mode));
|
||
return;
|
||
}
|
||
|
||
// send chat to client
|
||
switch (mode)
|
||
{
|
||
case CPhraseParameters::NpcMsg:
|
||
npcChatParamToChannel(sp->dataSetRow(), groupType, phraseId.c_str(), PhraseParameters.Values);
|
||
break;
|
||
case CPhraseParameters::SystemMsg:
|
||
STRING_MANAGER::sendSystemStringToClientAudience(sp->dataSetRow(),std::vector<NLMISC::CEntityId>(), groupType, phraseId.c_str(), PhraseParameters.Values);
|
||
break;
|
||
|
||
case CPhraseParameters::EmoteMsg:
|
||
STRING_MANAGER::sendCustomEmoteTextToClientAudience(sp->dataSetRow(),std::vector<NLMISC::CEntityId>(), phraseId.c_str(), PhraseParameters.Values);
|
||
break;
|
||
}
|
||
|
||
PhraseParameters.Values.clear();
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection phraseEndNpcMsg_fss_
|
||
Send a message with parameter through a bot says.
|
||
Parameters are taken from the parameters stack.
|
||
@see phrasePushValue_sf_
|
||
@see phrasePushString_ss_
|
||
|
||
Arguments: s(botIndex), s(sayType), s(phraseIdentifier) ->
|
||
@param[in] botIndex the Position of the bot in the group ( see getBotIndexByName_s_f)
|
||
@param[in] sayType Is the type of the say dialog ("say", "shout", "civilization", "territory", "universe", "arround", "system", "region")
|
||
@param[in] phraseIdentifier Is the identifier phrase as seen in phrase_wk.uxt
|
||
|
||
@code
|
||
()phrasePushString("literal", "text non traduit");
|
||
()groupOf5Bot.phraseEndNpcMsg(4, "say", "PHRASE_TOTO");
|
||
@endcode
|
||
|
||
WARNING
|
||
In this case in the phrase_wk.txt PHRASE_TOTO must be defined as
|
||
@code
|
||
PHRASE_TOTO(bot b, literal l)
|
||
{
|
||
[I am $b$, on this text is not translated $l$ ]
|
||
}
|
||
@endcode
|
||
|
||
The first parameter is ALWAYS the bot that says the text (value is automaticaly set)
|
||
*/
|
||
void phraseEndNpcMsg_fss_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
phraseEnd(entity, stack, CPhraseParameters::NpcMsg);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection phraseEndSystemMsg_fss_
|
||
Send a message with parameter through system braodcast msg.
|
||
Parameters are taken from the parameters stack.
|
||
@see phrasePushValue_sf_
|
||
@see phrasePushString_ss_
|
||
|
||
Arguments: s(botIndex), s(sayType), s(phraseIdentifier) ->
|
||
@param[in] botIndex the Position of the bot in the group ( see getBotIndexByName_s_f)
|
||
@param[in] sayType Is the type of the say dialog ("say", "shout", "civilization", "territory", "universe", "arround", "system", "region")
|
||
@param[in] phraseIdentifier Is the identifier phrase as seen in phrase_wk.uxt
|
||
|
||
@code
|
||
()phrasePushString("literal", "Test des levels designer");
|
||
()groupOf5Bot.phraseEndSystemMsg(4, "say", "PHRASE_TOTO");
|
||
@endcode
|
||
|
||
*WARNING*
|
||
In this case in the phrase_wk.txt PHRASE_TOTO must be defined as
|
||
@code
|
||
PHRASE_TOTO(literal l)
|
||
{
|
||
[$l$]
|
||
}
|
||
@endcode
|
||
The first parameter is *NOT* automaticaly set to the bot that send the system msg as phraseEndNpcMsg_fss_.
|
||
|
||
Because the msg can be send as "around". The broadcas msg must be send by a bot (that have a valid position)
|
||
*/
|
||
void phraseEndSystemMsg_fss_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
phraseEnd(entity, stack, CPhraseParameters::SystemMsg);
|
||
}
|
||
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection phraseEndEmoteMsg_fs_
|
||
Send a custom emote message with parameter through system braodcast msg.
|
||
Parameters are taken from the parameters stack.
|
||
@see phrasePushValue_sf_
|
||
@see phrasePushString_ss_
|
||
|
||
Arguments: s(botIndex), s(phraseIdentifier) ->
|
||
@param[in] botIndex the Position of the bot in the group ( see getBotIndexByName_s_f)
|
||
@param[in] phraseIdentifier Is the identifier phrase as seen in phrase_wk.uxt
|
||
|
||
@code
|
||
($playerEid)getCurrentPlayerEid();
|
||
($botEid)getCurrentSpeakerEid();
|
||
|
||
()phrasePushString("player", $playerEid);
|
||
()groupOf5Bot.phraseEndEmoteMsg(,"PHRASE_TOTO1");
|
||
|
||
()phrasePushString("bot", $botEid);
|
||
()groupOf5Bot.phraseEndEmoteMsg(,"PHRASE_TOTO2");
|
||
@endcode
|
||
|
||
*WARNING*
|
||
In this case in the phrase_wk.txt PHRASE_TOTO must be defined as
|
||
@code
|
||
PHRASE_TOTO1(player p)
|
||
{
|
||
[$p$ is laughing ]
|
||
}
|
||
PHRASE_TOTO2(bot b)
|
||
{
|
||
[$b$ is sad ]
|
||
}
|
||
@endcode
|
||
The first parameter is NOT automaticaly the bot that says the text as phraseEndNpcMsg_fss_ because a bot can make a player doing a emote text.
|
||
|
||
The emote msg must be send by a bot (that have a valid position).
|
||
*/
|
||
void phraseEndEmoteMsg_fs_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
phraseEnd(entity, stack, CPhraseParameters::EmoteMsg);
|
||
}
|
||
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection queryEgs_sscfs_
|
||
Send a query msg to egs to know infos on a player.
|
||
Answer is asynchronous so we have to indicates a group and a user event that will be triggered when answer will come back to AIS
|
||
|
||
Possible info to know are
|
||
- Name
|
||
- Hp
|
||
- MaxHp
|
||
- RatioHp
|
||
- Sap
|
||
- MaxSap
|
||
- RatioSap
|
||
- Focus
|
||
- MaxFocus
|
||
- RatioFocus
|
||
- Stamina
|
||
- MaxStamina
|
||
- RatioStamina
|
||
|
||
|
||
Arguments: s(botIndex), s(query), c(groupThatWillBeTriggered), f(idOfTheUserEvent), s(msgId)
|
||
@param[in] botIndex the Position of the bot in the group ( see getBotIndexByName_s_f)
|
||
@param[in] query The query we want to send
|
||
@param[in] groupThatWillBeTriggered The group that will receive a user_event when the answer will come
|
||
@param[in] idOfTheUserEvent The number of the user event that will be triggered
|
||
@param[in] msgId The id of the msg
|
||
|
||
Answer will be given by the getParam
|
||
|
||
@code
|
||
//Sening msg to EGS
|
||
(@groupToNotify)boss_group.context();
|
||
()queryEgs("Name", $playerEid, @groupToNotify, 4, "MSG_NAME");
|
||
()queryEgs("Hp", $playerEid, @groupToNotify, 4, "msg1");
|
||
()queryEgs("MaxHp", $playerEid, @groupToNotify, 4, "msg2");
|
||
()queryEgs("RatioHp", $playerEid, @groupToNotify, 4, "msg3");
|
||
()queryEgs("Sap", $playerEid, @groupToNotify, 4, "msg4");
|
||
()queryEgs("MaxSap", $playerEid, @groupToNotify, 4, "msg5");
|
||
()queryEgs("RatioSap", $playerEid, @groupToNotify, 4, "msg6");
|
||
()queryEgs("Focus", $playerEid, @groupToNotify, 4, "msg7");
|
||
()queryEgs("MaxFocus", $playerEid, @groupToNotify, 4, "msg8");
|
||
()queryEgs("RatioFocus", $playerEid, @groupToNotify, 4, "msg9");
|
||
()queryEgs("Stamina", $playerEid, @groupToNotify, 4, "msg10");
|
||
()queryEgs("MaxStamina", $playerEid, @groupToNotify, 4, "msg11");
|
||
()queryEgs("RatioStamina", $playerEid, @groupToNotify, 4, "msg12");
|
||
()queryEgs("BestSkillLevel", $playerEid, @groupToNotify, 4, "msg13");
|
||
@endcode
|
||
Answer of the EGS
|
||
@code
|
||
// the user_event 4 of groupToNotify will be trigered
|
||
($msgName)getEventParam(0); // the msg name
|
||
($ret)getEventParam(1); // the return
|
||
($funName)getEventParam(2); // the name of the function
|
||
($playerEid)getEventParam(3); // the id of the player
|
||
($param1)getEventParam(4); // empty ot item, or sbrick or botEid
|
||
|
||
if ($msgName == "MSG_NAME") {
|
||
()phrasePushString("literal", $ret);
|
||
()phrasePushString("player", $playerEid);
|
||
()boss_group.phraseEndNpcMsg(0, "say", "TEST_BOSS_TEST_MSG");
|
||
}
|
||
else
|
||
{
|
||
()phrasePushString("player", $playerEid);
|
||
()phrasePushString("literal", $funName);
|
||
()phrasePushString("literal", $msgName);
|
||
()phrasePushString("integer", $ret);
|
||
()boss_group.phraseEndNpcMsg(0, "say", "TEST_BOSS_TEST_EGS_QUERY");
|
||
|
||
}
|
||
@endcode
|
||
|
||
*/
|
||
void queryEgs_sscfs_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
std::string funName = "queryEgs_sscfs_";
|
||
// read input params
|
||
string literal = (string)stack.top(); stack.pop();
|
||
float useEventId = (float)stack.top(); stack.pop();
|
||
CGroupNpc* const groupToNotify = dynamic_cast<CGroupNpc*>( (IScriptContext*)stack.top() ); stack.pop();
|
||
string param1 = (string)stack.top(); stack.pop();
|
||
string func = (string)stack.top(); stack.pop();
|
||
|
||
// create a CUserEventMsg to send to EGS
|
||
CGroup* const group = entity ? entity->getGroup() : 0;
|
||
IManagerParent* const managerParent = (group&& group->getOwner()) ? group->getOwner()->getOwner():0;
|
||
CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
|
||
if (aiInstance == NULL)
|
||
{
|
||
nlwarning("%s failed: the AI instance of the entity is NULL", funName.c_str());
|
||
DEBUG_STOP;
|
||
return;
|
||
}
|
||
CQueryEgs msg;
|
||
msg.InstanceId = aiInstance->getInstanceNumber();
|
||
msg.GroupAlias = groupToNotify->getAlias();
|
||
msg.EventId = (int)useEventId;
|
||
msg.Params.push_back(literal);
|
||
msg.Params.push_back(func);
|
||
msg.Params.push_back(param1);
|
||
msg.send("EGS");
|
||
|
||
}
|
||
|
||
/*
|
||
@subsection queryEgs_ssscfs_
|
||
Send a query msg to egs to know infos on a player.
|
||
Answer is asynchronous so we have to indicates a group and a user event that will be triggered when answer will come back to AIS
|
||
|
||
Possible info to know are:
|
||
- KnowBrick (to knwo if the player know a specific brick); return value is 0 or 1 (if the player know the brick)
|
||
- IsInInventory (to knwo has an item in inventory of in equipement); return value is 0, 1(item in equipment), 2(item in bag)
|
||
- Target (to know if a player target a bot; return value is 0, 1(player target the bot)
|
||
|
||
Arguments: s(botIndex), s(query), s(queryParam), c(groupThatWillBeTriggered), f(idOfTheUserEvent), s(msgId)
|
||
@param[in] botIndex the Position of the bot in the group ( see getBotIndexByName_s_f)
|
||
@param[in] query The query we want to send
|
||
@param[in] queryParam Is the paramter of the query (a .creature of IsInInventory, a .sbrick for KnowBrick, a Bot EntityId for Target
|
||
@param[in] groupThatWillBeTriggered The group that will receive a user_event when the answer will come
|
||
@param[in] idOfTheUserEvent The number of the user event that will be triggered
|
||
@param[in] msgId The id of the msg
|
||
|
||
Answer will be given by the getParam
|
||
@code
|
||
//Sening msg to EGS
|
||
//($playerEid)getCurrentPlayerEid();
|
||
(@groupToNotify)boss_group.context();
|
||
()queryEgs("KnowBrick", $playerEid, "bfma01.sbrick", @groupToNotify, 4, "MSG_BRICK");
|
||
()queryEgs("IsInInventory", $playerEid, "iccm1bm.sitem", @groupToNotify, 4, "MSG_ITEM");
|
||
()queryEgs("Target", $playerEid, $botEid, @groupToNotify, 4, "msg14");
|
||
@endcode
|
||
|
||
Answer of the EGS
|
||
@code
|
||
($msgName)getEventParam(0); // the msg name
|
||
($ret)getEventParam(1); // the return
|
||
($funName)getEventParam(2); // the name of the function
|
||
($playerEid)getEventParam(3); // the id of the player
|
||
($param1)getEventParam(4); // empty ot item, or sbrick or botEid
|
||
|
||
if ($msgName == "MSG_ITEM")
|
||
{
|
||
()phrasePushString("item", $param1);
|
||
()phrasePushString("integer", $ret);
|
||
()boss_group.phraseEndNpcMsg(0, "say", "TEST_BOSS_TEST_EGS_QUERY_ITEM");
|
||
} else if ($msgName == "MSG_BRICK") {
|
||
()phrasePushString("sbrick", $param1);
|
||
()phrasePushString("integer", $ret);
|
||
()boss_group.phraseEndNpcMsg(0, "say", "TEST_BOSS_TEST_EGS_QUERY_BRICK");
|
||
|
||
} else if ($msgName == "MSG_NAME") {
|
||
()phrasePushString("literal", $ret);
|
||
()phrasePushString("player", $playerEid);
|
||
()boss_group.phraseEndNpcMsg(0, "say", "TEST_BOSS_TEST_MSG");
|
||
}
|
||
else
|
||
{
|
||
()phrasePushString("player", $playerEid);
|
||
()phrasePushString("literal", $funName);
|
||
()phrasePushString("literal", $msgName);
|
||
()phrasePushString("integer", $ret);
|
||
()boss_group.phraseEndNpcMsg(0, "say", "TEST_BOSS_TEST_EGS_QUERY");
|
||
|
||
}
|
||
@endcode
|
||
*/
|
||
void queryEgs_ssscfs_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
std::string funName = "queryEgs_ssscfs_";
|
||
// get input params
|
||
string literal = (string)stack.top(); stack.pop();
|
||
float useEventId = (float)stack.top(); stack.pop();
|
||
CGroupNpc* const groupToNotify = dynamic_cast<CGroupNpc*>( (IScriptContext*)stack.top() ); stack.pop();
|
||
string param2 = (string)stack.top(); stack.pop();
|
||
string param1 = (string)stack.top(); stack.pop();
|
||
string func = (string)stack.top(); stack.pop();
|
||
|
||
// create CQueryEgs to send to egs
|
||
CGroup* const group = entity ? entity->getGroup() : 0;
|
||
IManagerParent* const managerParent = (group&& group->getOwner()) ? group->getOwner()->getOwner():0;
|
||
CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
|
||
if (aiInstance == NULL)
|
||
{
|
||
nlwarning("%s failed: the AI instance of the entity is NULL", funName.c_str());
|
||
DEBUG_STOP;
|
||
return;
|
||
}
|
||
CQueryEgs msg;
|
||
msg.InstanceId = aiInstance->getInstanceNumber();
|
||
msg.GroupAlias = groupToNotify->getAlias();
|
||
msg.EventId = (int)useEventId;
|
||
msg.Params.push_back(literal);
|
||
msg.Params.push_back(func);
|
||
msg.Params.push_back(param1);
|
||
msg.Params.push_back(param2);
|
||
msg.send("EGS");
|
||
|
||
}
|
||
|
||
|
||
/** @page code
|
||
|
||
@subsection summonPlayer_fs_
|
||
|
||
Summon a player to a bot.
|
||
|
||
Can be used by a boss to teleport a player. Or the create a teleporter.
|
||
|
||
A player EntityId is used to identify the player.
|
||
A index is used to identified the bot (index for the current group)
|
||
|
||
|
||
Arguments: f(botIndex), s(playerEid) >
|
||
@param[in] botIndex is the index of the bot in the current group(static group)
|
||
@param[in] playerEid The entityId of the player
|
||
|
||
@code
|
||
($playerId)getRandomPlayerAggroListTarget(0);
|
||
()teleportPlayer(0, $playerEid); // teleport player to the boss.
|
||
@endcode
|
||
*/
|
||
void summonPlayer_fs_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
|
||
std::string funName = "summonPlayer_fffs_";
|
||
std::string playerEidStr = ((std::string)stack.top()); stack.pop();
|
||
sint32 botIndex = (sint32)((float)stack.top()); stack.pop();
|
||
|
||
|
||
// Verify is bot is alived
|
||
CGroup* group = entity->getGroup();
|
||
if (!group)
|
||
{
|
||
nlwarning("%s on a non Npc Group, doesn't work", funName.c_str());
|
||
return;
|
||
}
|
||
if (!group->isSpawned() || group->bots().isEmpty() || botIndex < 0 || group->bots().size() < static_cast<uint32>(botIndex))
|
||
{
|
||
return;
|
||
}
|
||
const CBot *const bot = group->getBot(botIndex);
|
||
if ( !bot || !bot->isSpawned())
|
||
{
|
||
return;
|
||
}
|
||
CSpawnBot *const sp= bot->getSpawnObj();
|
||
if ( !sp || !sp->isAlive() )
|
||
{
|
||
return;
|
||
}
|
||
|
||
|
||
// Read position for mirror
|
||
TDataSetRow row = sp->dataSetRow();
|
||
if (! TheDataset.isAccessible( row ) )
|
||
{
|
||
return;
|
||
}
|
||
|
||
CMirrorPropValue<sint32> mirrorSymbolX( TheDataset, row, DSPropertyPOSX );
|
||
CMirrorPropValue<sint32> mirrorSymbolY( TheDataset, row, DSPropertyPOSY );
|
||
|
||
// retrieve the CBotPlayer
|
||
NLMISC::CEntityId playerEid;
|
||
playerEid.fromString(playerEidStr.c_str());
|
||
CAIEntityPhysical *charEntity=CAIS::instance().getEntityPhysical(TheDataset.getDataSetRow(playerEid));
|
||
if (!charEntity)
|
||
return;
|
||
|
||
// do nothing if one of them is dead
|
||
if (!charEntity->isAlive() )
|
||
{
|
||
return;
|
||
}
|
||
|
||
|
||
// send teleport MSG
|
||
TDataSetRow CharacterRowId = charEntity->dataSetRow();
|
||
|
||
NLMISC::CEntityId player = CMirrors::getEntityId(CharacterRowId);
|
||
|
||
if (player != NLMISC::CEntityId::Unknown)
|
||
{
|
||
sint32 x2 = mirrorSymbolX.getValue();
|
||
sint32 y2 = mirrorSymbolY.getValue();
|
||
sint32 z2 = 0;
|
||
float t = 0; // TODO direction to mob?
|
||
|
||
NLNET::CMessage msgout( "TELEPORT_PLAYER" );
|
||
nlWrite(msgout, serial, player );
|
||
msgout.serial( const_cast<sint32 &>(x2) );
|
||
msgout.serial( const_cast<sint32 &>(y2) );
|
||
msgout.serial( const_cast<sint32 &>(z2) );
|
||
msgout.serial( const_cast<float &>(t) );
|
||
sendMessageViaMirror( "EGS", msgout );
|
||
}
|
||
|
||
|
||
}
|
||
|
||
/** @page code
|
||
|
||
@subsection teleportPlayer_sffff_
|
||
|
||
Teleport a player to a position
|
||
|
||
A player EntityId is used to identify the player.
|
||
The position is identified by the value x,y,z and the heading
|
||
|
||
|
||
Arguments: s(playerId), f(x), f(y), f(z), f(heading) >
|
||
@param[in] playerId is EntityId of the player
|
||
@param[in] x,y,z,heading is the new position of the player
|
||
|
||
@code
|
||
($playerId)getRandomPlayerAggroListTarget(0);
|
||
()teleportPlayer($playerEid, 1000, 1000, 100, 0);
|
||
@endcode
|
||
*/
|
||
void teleportPlayer_sffff_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
// get player and position parameters
|
||
float t = (float)stack.top(); stack.pop(); // heading
|
||
float z = (float)stack.top(); stack.pop();
|
||
float y = (float)stack.top(); stack.pop();
|
||
float x = (float)stack.top(); stack.pop();
|
||
std::string playerEidStr = (std::string)stack.top(); stack.pop();
|
||
NLMISC::CEntityId playerEid;
|
||
playerEid.fromString(playerEidStr.c_str());
|
||
|
||
// retrieve the CBotPlayer
|
||
CAIEntityPhysical *charEntity=CAIS::instance().getEntityPhysical(TheDataset.getDataSetRow(playerEid));
|
||
if (!charEntity)
|
||
return;
|
||
|
||
// do nothing if one of them is dead
|
||
if (!charEntity->isAlive() )
|
||
{
|
||
return;
|
||
}
|
||
|
||
// teleport player to position
|
||
if (playerEid != NLMISC::CEntityId::Unknown)
|
||
{
|
||
sint32 x2 = static_cast<sint32>(x*1000);
|
||
sint32 y2 = static_cast<sint32>(y*1000);
|
||
sint32 z2 = static_cast<sint32>(z*1000);
|
||
|
||
NLNET::CMessage msgout( "TELEPORT_PLAYER" );
|
||
msgout.serial( const_cast<CEntityId &>(playerEid) );
|
||
msgout.serial( const_cast<sint32 &>(x2) );
|
||
msgout.serial( const_cast<sint32 &>(y2) );
|
||
msgout.serial( const_cast<sint32 &>(z2) );
|
||
msgout.serial( const_cast<float &>(t) );
|
||
sendMessageViaMirror( "EGS", msgout );
|
||
}
|
||
|
||
}
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection getBotEid_f_s
|
||
Get the bot EntityId by its Index.
|
||
Arguments: f(botIndex) -> s(botEid)
|
||
|
||
@param[in] botIndex the Position of the bot in the group
|
||
@param[out] botEid The entity Id given by the bot (or empty) if the indexed bot is not from the group
|
||
|
||
@code
|
||
(index)getBotIndexByName("bot_toto");
|
||
($botEid)getBotEid(index);
|
||
if (index != -1)
|
||
{
|
||
()phrasePushValue("entity", $botEid);
|
||
()phraseEndEmoteMsg(index, "PHRASE_YOUR_ARE_CLICKING_ON_ME");
|
||
}
|
||
@endcode
|
||
*/
|
||
|
||
void getBotEid_f_s(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
std::string funName = "getBotEid_f_s";
|
||
// get spawn Bot by its index
|
||
CGroup* group = entity->getGroup();
|
||
if (!group)
|
||
{
|
||
nlwarning("%s on a non Npc Group, doesn't work", funName.c_str());
|
||
stack.push(std::string(CEntityId::Unknown.toString()));
|
||
return;
|
||
}
|
||
sint32 botIndex = (sint32)((float)stack.top());stack.pop();
|
||
if (!group->isSpawned() || group->bots().isEmpty() || botIndex < 0 || group->bots().size() < static_cast<uint32>(botIndex))
|
||
{
|
||
stack.push(std::string(CEntityId::Unknown.toString()));
|
||
return;
|
||
}
|
||
|
||
const CBot *const bot = group->getBot(botIndex);
|
||
if ( !bot || !bot->isSpawned()) { stack.push(std::string(CEntityId::Unknown.toString())); return;}
|
||
|
||
|
||
CSpawnBot *const sb= bot->getSpawnObj();
|
||
if ( !sb ||!sb->isAlive()) {stack.push(std::string(CEntityId::Unknown.toString())); return;};
|
||
|
||
// return the entity id of the spawn bot
|
||
CEntityId id= sb->getEntityId();
|
||
stack.push(std::string(id.toString()));
|
||
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection getBotIndex_s_f
|
||
Get the bot Index by its entityId.
|
||
Entity Id of a bot can be given via getCurrentSpeackerEid().
|
||
It can be usefull to Known the index of the bot in the group with the EntityId.
|
||
|
||
Arguments: s(botEid) -> f(botIndex),
|
||
|
||
@param[in] botEid The entity Id given by the bot
|
||
@param[out] botIndex the Position of the bot in the group (or -1 if the entity_id is not from a bot of the group)
|
||
|
||
@code
|
||
($botEid)getCurrentSpeakerEid();
|
||
(index)getBotIndex($botEid);
|
||
if (index != -1)
|
||
{
|
||
()phrasePushValue("entity", $botEid);
|
||
()phraseEndNpcg(index, "PHRASE_YOUR_ARE_CLICKING_ON_ME");
|
||
}
|
||
@endcode
|
||
*/
|
||
void getBotIndex_s_f(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
std::string funName = "getBotEid_f_s";
|
||
CGroup* group = entity->getGroup();
|
||
if (!group)
|
||
{
|
||
nlwarning("%s on a non Npc Group, doesn't work", funName.c_str());
|
||
stack.push(std::string(CEntityId::Unknown.toString()));
|
||
return;
|
||
}
|
||
std::string botEid = (std::string)stack.top(); stack.pop();
|
||
|
||
// look in the group if the bot is alived
|
||
uint32 botIndex = 0, last = group->bots().size();
|
||
for ( ;botIndex != last; ++botIndex)
|
||
{
|
||
if (!group->isSpawned() || group->bots().isEmpty() || group->bots().size() < static_cast<uint32>(botIndex))
|
||
{
|
||
continue;
|
||
}
|
||
|
||
const CBot *const bot = group->getBot(botIndex);
|
||
if ( !bot || !bot->isSpawned()) { continue; }
|
||
|
||
|
||
CSpawnBot *const sb= bot->getSpawnObj();
|
||
if ( !sb ||!sb->isAlive()) {continue;};
|
||
CEntityId id= sb->getEntityId();
|
||
// if bot is alived return its index
|
||
if (botEid == id.toString())
|
||
{
|
||
stack.push((float)botIndex);
|
||
return;
|
||
}
|
||
|
||
}
|
||
stack.push((float)-1);
|
||
return;
|
||
|
||
}
|
||
|
||
/** @page code
|
||
|
||
@subsection getCurrentPlayerEid__s
|
||
Get the entity id of the player that is clicking on a bot.
|
||
|
||
WARNING the function is only valid when called from an player_target_npc event.
|
||
|
||
|
||
Arguments: -> s(playerEidAsString),
|
||
@param[out] playerEidAsString is EntityId as string from the player.
|
||
|
||
@code
|
||
($playerEid)getCurrentPlayerEid();
|
||
(index)getBotIndexByName("toto");
|
||
(distance)getPlayerDistance(index, $playerEid);
|
||
phrasePushString("player", $playerEid);
|
||
phrasePushValue("interger", distance);
|
||
phraseEndNpcMsg(index, "say", "MSG_BOT_B_SAYS_THE_PLAYER_P_IS_AT_DISTANCE_D");
|
||
@endcode
|
||
*/
|
||
void getCurrentPlayerEid__s(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
std::string funName = "getCurrentPlayerEid__s";
|
||
CEntityId id = CEntityId::Unknown;
|
||
// if we are in player_target_npc event TempPlayer is valid
|
||
if (!TempPlayer)
|
||
{
|
||
//TempPlayer is invalid so return Unkwn eid
|
||
std::string s = id.toString();
|
||
stack.push(s);
|
||
return;
|
||
}
|
||
// TempPlayer is valid so return eid
|
||
id = TempPlayer->getEntityId();
|
||
std::string s = id.toString();
|
||
stack.push(s);
|
||
return;
|
||
}
|
||
|
||
|
||
/** @page code
|
||
|
||
@subsection getCurrentSpeakerEid__s
|
||
Get the entity id of the bot at which the player as that is clicking at.
|
||
|
||
WARNING the function is only valid when called from an player_target_npc event.
|
||
|
||
|
||
Arguments: -> s(botEidAsString),
|
||
@param[out] botEidAsString is EntityId as string from the bot.
|
||
|
||
@code
|
||
($botEid)getCurrentSpeakerEid();
|
||
($playerEid)getCurrentSpeakerEid();
|
||
|
||
phrasePushString("player", $playerEid);
|
||
phrasePushValue("bot", $botEid);
|
||
phraseEndEmotMsg(index, "EMOT_PLAYER_INSULT_BOT");
|
||
@endcode
|
||
*/
|
||
void getCurrentSpeakerEid__s(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
std::string funName = "getCurrentSpeakerEid__s";
|
||
CEntityId id = CEntityId::Unknown;
|
||
// if we are in player_target_npc event TempSpeaker is valid
|
||
if (!TempSpeaker)
|
||
{
|
||
//TempSpeaker is invalid so return Unkwn eid
|
||
std::string s = id.toString();
|
||
stack.push(s);
|
||
return;
|
||
}
|
||
//TempSpeaker is valid so return correct eid
|
||
id = TempSpeaker->getEntityId();
|
||
std::string s = id.toString();
|
||
stack.push(s);
|
||
return;
|
||
}
|
||
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
// Undocumented methods //
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
//----------------------------------------------------------------------------
|
||
// CGroup
|
||
void setSheet_s_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
string sheetname = stack.top();
|
||
stack.pop();
|
||
|
||
CSheetId sheetId(sheetname+".creature");
|
||
if (sheetId==CSheetId::Unknown)
|
||
return;
|
||
|
||
FOREACH(itBot, CCont<CBot>, entity->getGroup()->bots())
|
||
{
|
||
CBot* bot = *itBot;
|
||
if (bot)
|
||
{
|
||
AISHEETS::ICreatureCPtr const sheet = AISHEETS::CSheets::getInstance()->lookup(sheetId);
|
||
if (!sheet.isNull())
|
||
bot->triggerSetSheet(sheet);
|
||
}
|
||
}
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
// CGroup
|
||
void setHealer_f_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
bool value = ((float)stack.top())!=0.f;
|
||
stack.pop();
|
||
|
||
CGroup* group = entity->getGroup();
|
||
|
||
if (group->isSpawned())
|
||
{
|
||
FOREACH(itBot, CCont<CBot>, group->bots())
|
||
{
|
||
CBot* bot = *itBot;
|
||
if (bot)
|
||
{
|
||
bot->setHealer(value);
|
||
// break; // :NOTE: Only set first bot as a healer
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/****************************************************************************/
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection sitDown__
|
||
Make the group sit Down
|
||
|
||
Arguments: ->
|
||
|
||
@code
|
||
()sitDown();
|
||
|
||
@endcode
|
||
|
||
*/
|
||
// CStateInstance
|
||
void sitDown__(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
|
||
CGroup* group = entity->getGroup();
|
||
|
||
if (!group)
|
||
{
|
||
nlwarning("sitDown__ failed");
|
||
return;
|
||
}
|
||
|
||
CAILogicActionSitDownHelper::sitDown(group);
|
||
}
|
||
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection standUp
|
||
Make the group stand up (if was previously stand down)
|
||
|
||
Arguments: ->
|
||
|
||
@code
|
||
()standUp();
|
||
|
||
@endcode
|
||
|
||
*/
|
||
// CStateInstance
|
||
void standUp__(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
CGroup* group = entity->getGroup();
|
||
if (!group)
|
||
{
|
||
nlwarning("standUp__ failed");
|
||
return;
|
||
}
|
||
|
||
CAILogicActionSitDownHelper::standUp(group);
|
||
}
|
||
|
||
//----------------------------------------------------------------------------
|
||
/** @page code
|
||
|
||
@subsection standUp
|
||
Use to implement setConditionRet
|
||
|
||
Arguments: ->
|
||
|
||
@code
|
||
()setConditionRet(1);
|
||
|
||
@endcode
|
||
|
||
*/
|
||
// CStateInstance
|
||
void setConditionSuccess_f_(CStateInstance* entity, CScriptStack& stack)
|
||
{
|
||
bool conditionState = (uint32)((float)stack.top()) != 0;
|
||
CGroup* group = entity->getGroup();
|
||
if (!group)
|
||
{
|
||
nlwarning("setConditionSuccess_f_ failed");
|
||
return;
|
||
}
|
||
|
||
CAILogicDynamicIfHelper::setConditionSuccess(conditionState);
|
||
}
|
||
|
||
|
||
std::map<std::string, FScrptNativeFunc> nfGetGroupNativeFunctions()
|
||
{
|
||
std::map<std::string, FScrptNativeFunc> functions;
|
||
|
||
#define REGISTER_NATIVE_FUNC(cont, func) cont.insert(std::make_pair(std::string(#func), &func))
|
||
|
||
REGISTER_NATIVE_FUNC(functions, spawn__);
|
||
REGISTER_NATIVE_FUNC(functions, despawn_f_);
|
||
REGISTER_NATIVE_FUNC(functions, isAlived__f);
|
||
REGISTER_NATIVE_FUNC(functions, newNpcChildGroupPos_ssfff_c);
|
||
REGISTER_NATIVE_FUNC(functions, newNpcChildGroupPos_ssfff_);
|
||
REGISTER_NATIVE_FUNC(functions, newNpcChildGroupPos_ssff_c);
|
||
REGISTER_NATIVE_FUNC(functions, newNpcChildGroupPos_ssff_);
|
||
REGISTER_NATIVE_FUNC(functions, newNpcChildGroupPosMl_ssffff_c);
|
||
REGISTER_NATIVE_FUNC(functions, newNpcChildGroupPosMl_ssffff_);
|
||
REGISTER_NATIVE_FUNC(functions, newNpcChildGroupPosMl_ssfff_c);
|
||
REGISTER_NATIVE_FUNC(functions, newNpcChildGroupPosMl_ssfff_);
|
||
REGISTER_NATIVE_FUNC(functions, newNpcChildGroup_sssf_c);
|
||
REGISTER_NATIVE_FUNC(functions, newNpcChildGroup_sssf_);
|
||
REGISTER_NATIVE_FUNC(functions, newNpcChildGroup_sss_c);
|
||
REGISTER_NATIVE_FUNC(functions, newNpcChildGroup_sss_);
|
||
REGISTER_NATIVE_FUNC(functions, newNpcChildGroupMl_sssff_c);
|
||
REGISTER_NATIVE_FUNC(functions, newNpcChildGroupMl_sssff_);
|
||
REGISTER_NATIVE_FUNC(functions, newNpcChildGroupMl_sssf_c);
|
||
REGISTER_NATIVE_FUNC(functions, newNpcChildGroupMl_sssf_);
|
||
REGISTER_NATIVE_FUNC(functions, spawnManager_s_);
|
||
REGISTER_NATIVE_FUNC(functions, sitDown__);
|
||
REGISTER_NATIVE_FUNC(functions, standUp__);
|
||
REGISTER_NATIVE_FUNC(functions, despawnManager_s_);
|
||
REGISTER_NATIVE_FUNC(functions, getMidPos__ff);
|
||
REGISTER_NATIVE_FUNC(functions, getGroupTemplateWithFlags_sss_s);
|
||
REGISTER_NATIVE_FUNC(functions, getGroupTemplateWithFlags_ss_s);
|
||
REGISTER_NATIVE_FUNC(functions, getZoneWithFlags_ssss_s);
|
||
REGISTER_NATIVE_FUNC(functions, getZoneWithFlags_sss_s);
|
||
REGISTER_NATIVE_FUNC(functions, getNearestZoneWithFlags_ffsss_s);
|
||
REGISTER_NATIVE_FUNC(functions, getNearestZoneWithFlags_ffss_s);
|
||
REGISTER_NATIVE_FUNC(functions, getNearestZoneWithFlagsStrict_ffsss_s);
|
||
REGISTER_NATIVE_FUNC(functions, getNearestZoneWithFlagsStrict_ffss_s);
|
||
REGISTER_NATIVE_FUNC(functions, getNeighbourZoneWithFlags_ssss_s);
|
||
REGISTER_NATIVE_FUNC(functions, getNeighbourZoneWithFlags_sss_s);
|
||
REGISTER_NATIVE_FUNC(functions, setAggro_ff_);
|
||
REGISTER_NATIVE_FUNC(functions, setCanAggro_f_);
|
||
REGISTER_NATIVE_FUNC(functions, clearAggroList_f_);
|
||
REGISTER_NATIVE_FUNC(functions, clearAggroList__);
|
||
REGISTER_NATIVE_FUNC(functions, setMode_s_);
|
||
REGISTER_NATIVE_FUNC(functions, setAutoSpawn_f_);
|
||
REGISTER_NATIVE_FUNC(functions, setHPLevel_f_);
|
||
REGISTER_NATIVE_FUNC(functions, setHPScale_f_);
|
||
REGISTER_NATIVE_FUNC(functions, scaleHP_f_);
|
||
REGISTER_NATIVE_FUNC(functions, setBotHPScaleByAlias_fs_);
|
||
REGISTER_NATIVE_FUNC(functions, downScaleHP_f_);
|
||
REGISTER_NATIVE_FUNC(functions, upScaleHP_f_);
|
||
REGISTER_NATIVE_FUNC(functions, addHP_f_);
|
||
REGISTER_NATIVE_FUNC(functions, aiAction_s_);
|
||
REGISTER_NATIVE_FUNC(functions, aiActionSelf_s_);
|
||
REGISTER_NATIVE_FUNC(functions, addProfileParameter_s_);
|
||
REGISTER_NATIVE_FUNC(functions, addProfileParameter_ss_);
|
||
REGISTER_NATIVE_FUNC(functions, addProfileParameter_sf_);
|
||
REGISTER_NATIVE_FUNC(functions, removeProfileParameter_s_);
|
||
REGISTER_NATIVE_FUNC(functions, addPersistentProfileParameter_s_);
|
||
REGISTER_NATIVE_FUNC(functions, addPersistentProfileParameter_ss_);
|
||
REGISTER_NATIVE_FUNC(functions, addPersistentProfileParameter_sf_);
|
||
REGISTER_NATIVE_FUNC(functions, removePersistentProfileParameter_s_);
|
||
REGISTER_NATIVE_FUNC(functions, getOutpostStateName__s);
|
||
REGISTER_NATIVE_FUNC(functions, isOutpostTribeOwner__f);
|
||
REGISTER_NATIVE_FUNC(functions, isOutpostGuildOwner__f);
|
||
REGISTER_NATIVE_FUNC(functions, getEventParam_f_f);
|
||
REGISTER_NATIVE_FUNC(functions, getEventParam_f_s);
|
||
REGISTER_NATIVE_FUNC(functions, setSheet_s_);
|
||
REGISTER_NATIVE_FUNC(functions, setHealer_f_);
|
||
REGISTER_NATIVE_FUNC(functions, setConditionSuccess_f_);
|
||
|
||
|
||
|
||
// Boss functions (custom text)
|
||
REGISTER_NATIVE_FUNC(functions, phraseBegin__);
|
||
REGISTER_NATIVE_FUNC(functions, phrasePushValue_sf_);
|
||
REGISTER_NATIVE_FUNC(functions, phrasePushString_ss_);
|
||
REGISTER_NATIVE_FUNC(functions, phraseEndNpcMsg_fss_);
|
||
REGISTER_NATIVE_FUNC(functions, phraseEndSystemMsg_fss_);
|
||
REGISTER_NATIVE_FUNC(functions, phraseEndEmoteMsg_fs_);
|
||
|
||
// Boss functions (Bot infos)
|
||
REGISTER_NATIVE_FUNC(functions, getBotIndex_s_f);
|
||
REGISTER_NATIVE_FUNC(functions, getBotEid_f_s);
|
||
REGISTER_NATIVE_FUNC(functions, getCurrentSpeakerEid__s);
|
||
REGISTER_NATIVE_FUNC(functions, getBotIndexByName_s_f);
|
||
REGISTER_NATIVE_FUNC(functions, isGroupAlived__f);
|
||
REGISTER_NATIVE_FUNC(functions, isBotAlived_f_f);
|
||
|
||
// Boss functions (Player infos)
|
||
REGISTER_NATIVE_FUNC(functions, isPlayerAlived_s_f);
|
||
REGISTER_NATIVE_FUNC(functions, getPlayerStat_ss_f);
|
||
REGISTER_NATIVE_FUNC(functions, getPlayerDistance_fs_f);
|
||
REGISTER_NATIVE_FUNC(functions, getCurrentPlayerEid__s);
|
||
REGISTER_NATIVE_FUNC(functions, queryEgs_sscfs_);
|
||
REGISTER_NATIVE_FUNC(functions, queryEgs_ssscfs_);
|
||
|
||
// Boss functions (Aggro list)
|
||
REGISTER_NATIVE_FUNC(functions, getCurrentPlayerAggroListTarget_f_s);
|
||
REGISTER_NATIVE_FUNC(functions, getRandomPlayerAggroListTarget_f_s);
|
||
REGISTER_NATIVE_FUNC(functions, getAggroListElement_ff_s);
|
||
REGISTER_NATIVE_FUNC(functions, getAggroListSize_f_f);
|
||
REGISTER_NATIVE_FUNC(functions, setAggroListTarget_fs_);
|
||
REGISTER_NATIVE_FUNC(functions, setGroupAggroListTarget_s_);
|
||
REGISTER_NATIVE_FUNC(functions, setManagerAggroListTarget_ss_);
|
||
|
||
// Boss functions (Time infos)
|
||
REGISTER_NATIVE_FUNC(functions, getServerTimeStr__s);
|
||
REGISTER_NATIVE_FUNC(functions, getServerTime__s);
|
||
REGISTER_NATIVE_FUNC(functions, getRyzomDateStr__s);
|
||
REGISTER_NATIVE_FUNC(functions, getRyzomDate__s);
|
||
|
||
// Boss function (teleport actions)
|
||
REGISTER_NATIVE_FUNC(functions, teleportPlayer_sffff_);
|
||
REGISTER_NATIVE_FUNC(functions, summonPlayer_fs_);
|
||
|
||
|
||
|
||
|
||
|
||
#undef REGISTER_NATIVE_FUNC
|
||
|
||
return functions;
|
||
}
|