1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "script_compiler.h"
21 #include "ai_grp_npc.h"
22 #include "group_profile.h"
23 #include "ai_generic_fight.h"
24 #include "server_share/msg_brick_service.h"
26 #include "continent_inline.h"
27 #include "dyn_grp_inline.h"
29 #include "ai_script_data_manager.h"
31 #include "nf_helpers.h"
33 #include "game_share/send_chat.h"
34 #include "game_share/string_manager_sender.h"
40 using namespace NLMISC
;
42 using namespace AICOMP
;
43 using namespace AITYPES
;
44 using namespace RYAI_MAP_CRUNCH
;
47 //----------------------------------------------------------------------------
51 Spawns the current group.
57 void spawn__(CStateInstance
* entity
, CScriptStack
& stack
)
61 nlwarning("spawnInstance failed");
64 CGroup
const* const grp
= entity
->getGroup();
68 grp
->getSpawnObj()->spawnBots();
72 //----------------------------------------------------------------------------
75 @subsection despawn_f_
76 Depawns the current group.
78 Arguments: f(Immediatly) ->
79 @param Immediatly is whether the groups spawns immediatly (1) or not (0)
82 ()despawn(0); // despawn
83 ()despawn(1); // despawn immediatement
88 void despawn_f_(CStateInstance
* entity
, CScriptStack
& stack
)
90 float const immediatly
= stack
.top();
95 nlwarning("despawnInstance failed");
99 CGroup
* const grp
= entity
->getGroup();
102 nlwarning("despawn : entity '%s'%s is not a group ? ",
103 entity
->aliasTreeOwner()->getAliasFullName().c_str(),
104 entity
->aliasTreeOwner()->getAliasString().c_str());
107 grp
->despawnBots(immediatly
!=0);
110 //----------------------------------------------------------------------------
113 @subsection spawnBot_fsssffff_
114 Spawn new bots in the current group.
116 Arguments: f(NbrBots), s(Sheet), s(Name), s(Look), f(x), f(y), f(orientation), f(dispersion) ->
124 void spawnBot_fsssffff_(CStateInstance
* entity
, CScriptStack
& stack
)
126 double dispersionRadius
= (double)(float)stack
.top();
128 double orientation
= (double)(float)stack
.top();
130 double y
= (double)(float)stack
.top();
132 double x
= (double)(float)stack
.top();
134 string look
= (string
)stack
.top();
136 string name
= (string
)stack
.top();
139 CSheetId
sheetId((string
)stack
.top());
141 uint nbBots
= (uint
)(float)stack
.top();
144 IManagerParent
* const managerParent
= entity
->getGroup()->getOwner()->getOwner();
145 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
149 CGroupNpc
* grp
= dynamic_cast<CGroupNpc
*>(entity
->getGroup());
151 aiInstance
->eventCreateNpcBot(grp
, nbBots
, true, sheetId
, CAIVector(x
, y
), name
, orientation
, dispersionRadius
, look
);
157 //----------------------------------------------------------------------------
160 @subsection isAlived__f
161 Test if the group is alived
163 Arguments: -> f(Immediatly)
164 @return 1 if group is spawned
172 void isAlived__f(CStateInstance
* entity
, CScriptStack
& stack
)
181 CGroup
* const grp
= entity
->getGroup();
184 nlwarning("isAlived__f : entity '%s'%s is not a group ? ",
185 entity
->aliasTreeOwner()->getAliasFullName().c_str(),
186 entity
->aliasTreeOwner()->getAliasString().c_str());
191 if (!grp
->isSpawned())
198 for (uint i
=0; i
<grp
->bots().size(); ++i
)
200 const CBot
*const bot
= grp
->getBot(i
);
202 || !bot
->isSpawned())
206 CAIEntityPhysical
*const ep
=bot
->getSpawnObj();
218 //----------------------------------------------------------------------------
221 @subsection newNpcChildGroupPos_ssfff_c
222 Used to create a dynamic npc group (a parent/children relation is defined).
224 Arguments: s(GroupTemplate), s(StateMachine), f(x), f(y), f(Dispersion) -> c(Group)
225 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
226 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
227 @param[in] x position of the spawned group on x axis
228 @param[in] y position of the spawned group on y axis
229 @param[in] Dispersion is the dispersion radius in meters when spawning a group
230 @param[out] Group is the newly created group
233 (@grp)newNpcChildGroupPos("class_forager", "state_machine_1", x, y, 30);
237 // CGroup not in a family behaviour
238 void newNpcChildGroupPos_ssfff_c(CStateInstance
* entity
, CScriptStack
& stack
)
240 double dispersionRadius
= (double)(float)stack
.top();
242 float const y
= stack
.top();
244 float const x
= stack
.top();
247 IManagerParent
* const managerParent
= entity
->getGroup()->getOwner()->getOwner();
248 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
252 if (dispersionRadius
<0.)
253 dispersionRadius
= 0.;
254 stack
.push(spawnNewGroup(entity
, stack
, aiInstance
, CAIVector(x
, y
), -1, dispersionRadius
));
257 //----------------------------------------------------------------------------
260 @subsection newNpcChildGroupPos_ssfff_
261 Used to create a dynamic npc group (a parent/children relation is defined).
263 Arguments: s(GroupTemplate), s(StateMachine), f(x), f(y), f(Dispersion) ->
264 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
265 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
266 @param[in] x position of the spawned group on x axis
267 @param[in] y position of the spawned group on y axis
268 @param[in] Dispersion is the dispersion radius in meters when spawning a group
271 ()newNpcChildGroupPos("class_forager", "state_machine_1", x, y, 30);
275 // CGroup not in a family behaviour
276 void newNpcChildGroupPos_ssfff_(CStateInstance
* entity
, CScriptStack
& stack
)
278 double dispersionRadius
= (double)(float)stack
.top();
280 float const y
= stack
.top();
282 float const x
= stack
.top();
285 IManagerParent
* const managerParent
= entity
->getGroup()->getOwner()->getOwner();
286 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
290 if (dispersionRadius
<0.)
291 dispersionRadius
= 0.;
292 spawnNewGroup(entity
, stack
, aiInstance
, CAIVector(x
, y
), -1, dispersionRadius
);
295 //----------------------------------------------------------------------------
298 @subsection newNpcChildGroupPos_ssff_c
299 Used to create a dynamic npc group (a parent/children relation is defined).
301 Arguments: s(GroupTemplate), s(StateMachine), f(x), f(y) -> c(Group)
302 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
303 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
304 @param[in] x position of the spawned group on x axis
305 @param[in] y position of the spawned group on y axis
306 @param[out] Group is the newly created group
309 (@grp)newNpcChildGroupPos("class_forager", "state_machine_1", x, y);
313 // CGroup not in a family behaviour
314 void newNpcChildGroupPos_ssff_c(CStateInstance
* entity
, CScriptStack
& stack
)
316 stack
.push((float)-1.0f
);
317 newNpcChildGroupPos_ssfff_c(entity
, stack
);
320 //----------------------------------------------------------------------------
323 @subsection newNpcChildGroupPos_ssff_
324 Used to create a dynamic npc group (a parent/children relation is defined).
326 Arguments: s(GroupTemplate), s(StateMachine), f(x), f(y) ->
327 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
328 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
329 @param[in] x position of the spawned group on x axis
330 @param[in] y position of the spawned group on y axis
333 ()newNpcChildGroupPos("class_forager", "state_machine_1", x, y);
337 // CGroup not in a family behaviour
338 void newNpcChildGroupPos_ssff_(CStateInstance
* entity
, CScriptStack
& stack
)
340 stack
.push((float)-1.0f
);
341 newNpcChildGroupPos_ssfff_(entity
, stack
);
344 //----------------------------------------------------------------------------
347 @subsection newNpcChildGroupPosMl_ssffff_c
348 Used to create a multilevel dynamic npc group (a parent/children relation is defined).
350 Arguments: s(GroupTemplate), s(StateMachine), f(x), f(y), f(BaseLevel), f(Dispersion) -> c(Group)
351 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
352 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
353 @param[in] x position of the spawned group on x axis
354 @param[in] y position of the spawned group on y axis
355 @param[in] BaseLevel is the base level of the spawned group
356 @param[in] Dispersion is the dispersion radius in meters when spawning a group
357 @param[out] Group is the newly created group
360 (@grp)newNpcChildGroupPosMl("class_forager", "state_machine_1", x, y, 13, 7.5);
364 // CGroup not in a family behaviour
365 void newNpcChildGroupPosMl_ssffff_c(CStateInstance
* entity
, CScriptStack
& stack
)
367 double dispersionRadius
= (double)(float)stack
.top();
369 float const y
= stack
.top();
371 float const x
= stack
.top();
374 IManagerParent
* const managerParent
= entity
->getGroup()->getOwner()->getOwner();
375 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
379 if (dispersionRadius
<0.)
380 dispersionRadius
= 0.;
381 stack
.push(spawnNewGroup(entity
, stack
, aiInstance
, CAIVector(x
,y
), -1, dispersionRadius
));
384 //----------------------------------------------------------------------------
387 @subsection newNpcChildGroupPosMl_ssffff_
388 Used to create a multilevel dynamic npc group (a parent/children relation is defined).
390 Arguments: s(GroupTemplate), s(StateMachine), f(x), f(y), f(BaseLevel), f(Dispersion) ->
391 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
392 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
393 @param[in] x position of the spawned group on x axis
394 @param[in] y position of the spawned group on y axis
395 @param[in] BaseLevel is the base level of the spawned group
396 @param[in] Dispersion is the dispersion radius in meters when spawning a group
399 ()newNpcChildGroupPosMl("class_forager", "state_machine_1", x, y, 13, 7.5);
403 // CGroup not in a family behaviour
404 void newNpcChildGroupPosMl_ssffff_(CStateInstance
* entity
, CScriptStack
& stack
)
406 double dispersionRadius
= (double)(float)stack
.top();
408 float const y
= stack
.top();
410 float const x
= stack
.top();
413 IManagerParent
* const managerParent
= entity
->getGroup()->getOwner()->getOwner();
414 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
418 if (dispersionRadius
<0.)
419 dispersionRadius
= 0.;
420 spawnNewGroup(entity
, stack
, aiInstance
, CAIVector(x
,y
), -1, dispersionRadius
);
423 //----------------------------------------------------------------------------
426 @subsection newNpcChildGroupPosMl_ssfff_c
427 Used to create a multilevel dynamic npc group (a parent/children relation is defined).
429 Arguments: s(GroupTemplate), s(StateMachine), f(x), f(y), f(BaseLevel) -> c(Group)
430 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
431 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
432 @param[in] x position of the spawned group on x axis
433 @param[in] y position of the spawned group on y axis
434 @param[in] BaseLevel is the base level of the spawned group
435 @param[out] Group is the newly created group
438 (@grp)newNpcChildGroupPosMl("class_forager", "state_machine_1", x, y, 13);
442 // CGroup not in a family behaviour
443 void newNpcChildGroupPosMl_ssfff_c(CStateInstance
* entity
, CScriptStack
& stack
)
445 stack
.push((float)-1.0f
);
446 newNpcChildGroupPosMl_ssffff_c(entity
, stack
);
449 //----------------------------------------------------------------------------
452 @subsection newNpcChildGroupPosMl_ssfff_
453 Used to create a multilevel dynamic npc group (a parent/children relation is defined).
455 Arguments: s(GroupTemplate), s(StateMachine), f(x), f(y), f(BaseLevel) ->
456 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
457 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
458 @param[in] x position of the spawned group on x axis
459 @param[in] y position of the spawned group on y axis
460 @param[in] BaseLevel is the base level of the spawned group
463 ()newNpcChildGroupPosMl("class_forager", "state_machine_1", x, y, 13);
467 // CGroup not in a family behaviour
468 void newNpcChildGroupPosMl_ssfff_(CStateInstance
* entity
, CScriptStack
& stack
)
470 stack
.push((float)-1.0f
);
471 newNpcChildGroupPosMl_ssffff_(entity
, stack
);
474 //----------------------------------------------------------------------------
477 @subsection getMidPos__ff
478 Returns the position (x, y) of the current group.
480 Arguments: -> f(x), f(y)
481 @param[out] x position of the group on x axis
482 @param[out] y position of the group on y axis
490 void getMidPos__ff(CStateInstance
* entity
, CScriptStack
& stack
)
492 CGroup
* const group
= entity
->getGroup();
495 if (group
->isSpawned())
497 if (!group
->getSpawnObj()->calcCenterPos(vect
))
498 group
->getSpawnObj()->calcCenterPos(vect
, true);
501 float x((float)vect
.x().asDouble());
502 float y((float)vect
.y().asDouble());
508 //----------------------------------------------------------------------------
511 @subsection newNpcChildGroup_sssf_c
512 Used to create dynamic npc group (a parent/children relation is defined).
514 Arguments: s(GroupTemplate), s(StateMachine), s(Zone), f(Dispersion) -> c(Group)
515 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
516 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
517 @param[in] Zone is returned by the getZoneWithFlags methods
518 @param[in] Dispersion is the dispersion radius in meters when spawning a group
519 @param[out] Group is the newly created group
522 (@grp)newNpcChildGroup("class_forager", "state_machine_1", $zone, 10);
526 // CGroup not in a family behaviour
527 void newNpcChildGroup_sssf_c(CStateInstance
* entity
, CScriptStack
& stack
)
529 double dispersionRadius
= (double)(float)stack
.top();
531 TStringId
const zoneName
= CStringMapper::map(stack
.top());
534 IManagerParent
* const managerParent
= entity
->getGroup()->getOwner()->getOwner();
535 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
539 CNpcZone
const* spawnZone
= aiInstance
->getZone(zoneName
);
542 string StateMachine
= stack
.top();
545 nlwarning("newNpcChildGroup failed : spawnZone Not Found ! for StateMachine : %s", StateMachine
.c_str());
548 if (dispersionRadius
<0.)
550 dispersionRadius
= 0.;
551 CNpcZonePlace
const* spawnZonePlace
= dynamic_cast<CNpcZonePlace
const*>(spawnZone
);
552 if (spawnZonePlace
!=NULL
)
553 dispersionRadius
= spawnZonePlace
->getRadius();
555 stack
.push(spawnNewGroup(entity
, stack
, aiInstance
, spawnZone
->midPos(), -1, dispersionRadius
));
558 //----------------------------------------------------------------------------
561 @subsection newNpcChildGroup_sssf_
562 Used to create dynamic npc group (a parent/children relation is defined).
564 Arguments: s(GroupTemplate), s(StateMachine), s(Zone), f(Dispersion) ->
565 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
566 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
567 @param[in] Zone is returned by the getZoneWithFlags methods
568 @param[in] Dispersion is the dispersion radius in meters when spawning a group
571 ()newNpcChildGroup("class_forager", "state_machine_1", $zone, 10);
575 // CGroup not in a family behaviour
576 void newNpcChildGroup_sssf_(CStateInstance
* entity
, CScriptStack
& stack
)
578 double dispersionRadius
= (double)(float)stack
.top();
580 TStringId
const zoneName
= CStringMapper::map(stack
.top());
583 IManagerParent
* const managerParent
= entity
->getGroup()->getOwner()->getOwner();
584 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
588 CNpcZone
const* spawnZone
= aiInstance
->getZone(zoneName
);
591 string StateMachine
= stack
.top();
594 nlwarning("newNpcChildGroup failed : spawnZone Not Found ! for StateMachine : %s", StateMachine
.c_str());
597 if (dispersionRadius
<0.)
599 dispersionRadius
= 0.;
600 CNpcZonePlace
const* spawnZonePlace
= dynamic_cast<CNpcZonePlace
const*>(spawnZone
);
601 if (spawnZonePlace
!=NULL
)
602 dispersionRadius
= spawnZonePlace
->getRadius();
604 spawnNewGroup(entity
, stack
, aiInstance
, spawnZone
->midPos(), -1, dispersionRadius
);
607 //----------------------------------------------------------------------------
610 @subsection newNpcChildGroup_sss_c
611 Used to create dynamic npc group (a parent/children relation is defined).
613 Arguments: s(GroupTemplate), s(StateMachine), s(Zone), f(Dispersion) -> c(Group)
614 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
615 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
616 @param[in] Zone is returned by the getZoneWithFlags methods
617 @param[out] Group is the newly created group
620 (@grp)newNpcChildGroup("class_forager", "state_machine_1", $zone);
624 // CGroup not in a family behaviour
625 void newNpcChildGroup_sss_c(CStateInstance
* entity
, CScriptStack
& stack
)
627 stack
.push((float)-1.0f
);
628 newNpcChildGroup_sssf_c(entity
, stack
);
631 //----------------------------------------------------------------------------
634 @subsection newNpcChildGroup_sss_
635 Used to create dynamic npc group (a parent/children relation is defined).
637 Arguments: s(GroupTemplate), s(StateMachine), s(Zone), f(Dispersion) ->
638 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
639 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
640 @param[in] Zone is returned by the getZoneWithFlags methods
643 ()newNpcChildGroup("class_forager", "state_machine_1", $zone);
647 // CGroup not in a family behaviour
648 void newNpcChildGroup_sss_(CStateInstance
* entity
, CScriptStack
& stack
)
650 stack
.push((float)-1.0f
);
651 newNpcChildGroup_sssf_(entity
, stack
);
654 //----------------------------------------------------------------------------
657 @subsection newNpcChildGroupMl_sssff_c
658 Used to create multilevel dynamic npc group (a parent/children relation is defined).
660 Arguments: s(GroupTemplate), s(StateMachine), s(Zone), f(BaseLevel), f(Dispersion) -> c(Group)
661 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
662 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
663 @param[in] Zone is returned by the getZoneWithFlags methods
664 @param[in] BaseLevel is the base level of the spawned group
665 @param[in] Dispersion is the dispersion radius in meters when spawning a group
666 @param[out] Group is the newly created group
669 (@grp)newNpcChildGroupMl("class_forager", "state_machine_1", $zone, 2, 50);
673 // CGroup not in a family behaviour
674 void newNpcChildGroupMl_sssff_c(CStateInstance
* entity
, CScriptStack
& stack
)
676 double dispersionRadius
= (double)(float)stack
.top();
678 int baseLevel
= (int)(float)stack
.top();
680 TStringId
const zoneName
= CStringMapper::map(stack
.top());
683 IManagerParent
* const managerParent
= entity
->getGroup()->getOwner()->getOwner();
684 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
688 CNpcZone
const* spawnZone
= aiInstance
->getZone(zoneName
);
691 string StateMachine
= stack
.top();
694 nlwarning("newNpcChildGroup failed : spawnZone Not Found ! for StateMachine : %s", StateMachine
.c_str());
697 if (dispersionRadius
<0.)
699 dispersionRadius
= 0.;
700 CNpcZonePlace
const* spawnZonePlace
= dynamic_cast<CNpcZonePlace
const*>(spawnZone
);
701 if (spawnZonePlace
!=NULL
)
702 dispersionRadius
= spawnZonePlace
->getRadius();
704 stack
.push(spawnNewGroup(entity
, stack
, aiInstance
, spawnZone
->midPos(), baseLevel
, dispersionRadius
));
707 //----------------------------------------------------------------------------
710 @subsection newNpcChildGroupMl_sssff_
711 Used to create multilevel dynamic npc group (a parent/children relation is defined).
713 Arguments: s(GroupTemplate), s(StateMachine), s(Zone), f(BaseLevel), f(Dispersion) ->
714 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
715 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
716 @param[in] Zone is returned by the getZoneWithFlags methods
717 @param[in] BaseLevel is the base level of the spawned group
718 @param[in] Dispersion is the dispersion radius in meters when spawning a group
721 ()newNpcChildGroupMl("class_forager", "state_machine_1", $zone, 2, 50);
725 // CGroup not in a family behaviour
726 void newNpcChildGroupMl_sssff_(CStateInstance
* entity
, CScriptStack
& stack
)
728 double dispersionRadius
= (double)(float)stack
.top();
730 int baseLevel
= (int)(float)stack
.top();
732 TStringId
const zoneName
= CStringMapper::map(stack
.top());
735 IManagerParent
* const managerParent
= entity
->getGroup()->getOwner()->getOwner();
736 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
740 CNpcZone
const* spawnZone
= aiInstance
->getZone(zoneName
);
743 string StateMachine
= stack
.top();
746 nlwarning("newNpcChildGroup failed : spawnZone Not Found ! for StateMachine : %s", StateMachine
.c_str());
749 if (dispersionRadius
<0.)
751 dispersionRadius
= 0.;
752 CNpcZonePlace
const* spawnZonePlace
= dynamic_cast<CNpcZonePlace
const*>(spawnZone
);
753 if (spawnZonePlace
!=NULL
)
754 dispersionRadius
= spawnZonePlace
->getRadius();
756 spawnNewGroup (entity
, stack
, aiInstance
, spawnZone
->midPos(), baseLevel
, dispersionRadius
);
759 //----------------------------------------------------------------------------
762 @subsection newNpcChildGroupMl_sssf_c
763 Used to create multilevel dynamic npc group (a parent/children relation is defined).
765 Arguments: s(GroupTemplate), s(StateMachine), s(Zone), f(BaseLevel) -> c(Group)
766 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
767 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
768 @param[in] Zone is returned by the getZoneWithFlags methods
769 @param[in] BaseLevel is the base level of the spawned group
770 @param[out] Group is the newly created group
773 (@grp)newNpcChildGroupMl("class_forager", "state_machine_1", $zone, 12);
777 // CGroup not in a family behaviour
778 void newNpcChildGroupMl_sssf_c(CStateInstance
* entity
, CScriptStack
& stack
)
780 stack
.push((float)-1.0f
);
781 newNpcChildGroupMl_sssff_c(entity
, stack
);
784 //----------------------------------------------------------------------------
787 @subsection newNpcChildGroupMl_sssf_
788 Used to create multilevel dynamic npc group (a parent/children relation is defined).
790 Arguments: s(GroupTemplate), s(StateMachine), s(Zone), f(BaseLevel) ->
791 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
792 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
793 @param[in] Zone is returned by the getZoneWithFlags methods
794 @param[in] BaseLevel is the base level of the spawned group
797 ()newNpcChildGroupMl("class_forager", "state_machine_1", $zone, 12);
801 // CGroup not in a family behaviour
802 void newNpcChildGroupMl_sssf_(CStateInstance
* entity
, CScriptStack
& stack
)
804 stack
.push((float)-1.0f
);
805 newNpcChildGroupMl_sssff_(entity
, stack
);
808 //----------------------------------------------------------------------------
811 @subsection spawnManager_s_
814 Arguments: s(ManagerName) ->
815 @param[in] ManagerName is the name of the manager to spawn
818 ()spawnManager("NPC Manager"); // Spawns all the NPCs in the NPC manager called "NPC Manager"
822 // CGroup not in a family behaviour
823 void spawnManager_s_(CStateInstance
* entity
, CScriptStack
& stack
)
825 string ManagerName
= stack
.top();
832 nlwarning("SpawnManager error entity not spawned");
836 IManagerParent
* const managerParent
= entity
->getGroup()->getOwner()->getOwner();
837 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
840 nlwarning("SpawnManager error AIInstance not Found");
843 /** :TODO: If CStringFilter is available use it here and test the whole */
844 string
/*CStringFilter*/ managerFilter(ManagerName
);
845 FOREACH(itManager
, CAliasCont
<CManager
>, aiInstance
->managers())
847 CManager
* manager
= *itManager
;
848 if (manager
&& managerFilter
==manager
->getName())
855 nlwarning("SpawnManager error");
858 //----------------------------------------------------------------------------
861 @subsection despawnManager_s_
864 Arguments: s(ManagerName) ->
865 @param[in] ManagerName is the name of the manager to despawn
868 ()despawnManager("NPC Manager"); // Despawns all the NPCs in the NPC manager called "NPC Manager"
872 // CGroup not in a family behaviour
873 void despawnManager_s_(CStateInstance
* entity
, CScriptStack
& stack
)
875 string ManagerName
= stack
.top();
882 nlwarning("DespawnManager error entity not spawned");
886 IManagerParent
* const managerParent
= entity
->getGroup()->getOwner()->getOwner();
887 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
890 nlwarning("DespawnManager error AIInstance not Found");
893 // :TODO: If CStringFilter is available use it here and test the whole
894 string
/*CStringFilter*/ managerFilter(ManagerName
);
895 FOREACH(itManager
, CAliasCont
<CManager
>, aiInstance
->managers())
897 CManager
*manager
=*itManager
;
898 if (manager
&& managerFilter
==manager
->getName())
900 manager
->despawnMgr();
907 //----------------------------------------------------------------------------
910 @subsection getGroupTemplateWithFlags_sss_s
911 Returns the name of a randomly chosen group template corresponding to specified flags.
913 Arguments: s(OneOf), s(Mandatory), s(ExceptFlags) -> s(GroupTemplate)
914 @param[in] OneOf is a '|' separated list of flags
915 @param[in] Mandatory is a '|' separated list of flags
916 @param[in] ExceptFlags is a '|' separated list of flags
917 @param[out] GroupTemplate is a group template matching at least one of OneOf flags, all Manadatory flags and none of ExceptFlags
920 ($group)getGroupTemplateWithFlags("food|rest", "invasion|outpost"); // Get a group which matches 'invasion', 'outpost' and either 'food' or 'rest' flags.
924 // CGroup not in a family behaviour
925 void getGroupTemplateWithFlags_sss_s(CStateInstance
* entity
, CScriptStack
& stack
)
927 string exceptProperties
= stack
.top();
929 string mandatoryProperties
= stack
.top();
931 string oneOfProperties
= stack
.top();
934 // If no AI instance return
935 IManagerParent
* managerParent
= entity
->getGroup()->getOwner()->getOwner();
936 CAIInstance
* aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
939 stack
.push(string());
943 // Fill the property sets.
944 AITYPES::CPropertySet oneOfSet
= readSet(oneOfProperties
);
945 AITYPES::CPropertySet mandatorySet
= readSet(mandatoryProperties
);
946 AITYPES::CPropertySet exceptSet
= readSet(exceptProperties
);
948 vector
<CGroupDesc
<CGroupFamily
> const*> groupDescs
;
949 FOREACH (itCont
, CCont
<CContinent
>, aiInstance
->continents())
951 FOREACH (itRegion
, CCont
<CRegion
>, itCont
->regions())
953 FOREACH (itFamily
, CCont
<CGroupFamily
>, itRegion
->groupFamilies())
955 FOREACH (itGroupDesc
, CCont
<CGroupDesc
<CGroupFamily
> >, itFamily
->groupDescs())
957 // Skip groups not meeting the criteria
958 if (!itGroupDesc
->properties().containsPartOfNotStrict(oneOfSet
))
960 if (!itGroupDesc
->properties().containsAllOf(mandatorySet
))
962 if (itGroupDesc
->properties().containsPartOfStrict(exceptSet
))
964 groupDescs
.push_back(*itGroupDesc
);
970 if (groupDescs
.size()==0)
972 nlwarning("getGroupTemplateWithFlags failed: no group template found that contains all of '%s' and a part of'%s' ", mandatoryProperties
.c_str(), oneOfProperties
.c_str());
973 stack
.push(string());
977 CGroupDesc
<CGroupFamily
> const* groupDesc
= groupDescs
[CAIS::rand16((uint32
)groupDescs
.size())];
978 stack
.push(groupDesc
->getFullName());
982 //----------------------------------------------------------------------------
985 @subsection getGroupTemplateWithFlags_ss_s
986 Returns the name of a randomly chosen group template corresponding to specified flags.
988 Arguments: s(OneOf), s(Mandatory) -> s(GroupTemplate)
989 @param[in] OneOf is a '|' separated list of flags
990 @param[in] Mandatory is a '|' separated list of flags
991 @param[out] GroupTemplate is a group template matching at least one of OneOf flags and all Manadatory flags
994 ($group)getGroupTemplateWithFlags("food|rest", "invasion|outpost"); // Get a group which matches 'invasion', 'outpost' and either 'food' or 'rest' flags.
998 // CGroup not in a family behaviour
999 void getGroupTemplateWithFlags_ss_s(CStateInstance
* entity
, CScriptStack
& stack
)
1001 stack
.push(std::string(""));
1002 getGroupTemplateWithFlags_sss_s(entity
, stack
);
1005 //----------------------------------------------------------------------------
1008 @subsection getZoneWithFlags_ssss_s
1009 The first parameter is a list of 'one match enough' zone flags. The zones must
1010 have at least one of these flags to be selected. The second parameter is a
1011 list of 'all required' zone flag. The zones must have all these flags to be
1012 selected. The fourth parameter is a list of 'all forbidden' zone flag. The
1013 zones must not have any of these flags to be selected. Additionnaly the
1014 returned zone cannot be ExceptZone. Last argument specifies a list of flags
1015 that the selected zone cannot have.
1017 With the list of selectable zone, the system then select a zone based on
1018 entity density in each selected zone. The system will select the least
1019 populated zone. It then returns the zone name.
1021 Priority is given to current Cell, and after that to all cells.
1023 Arguments: s(OneOf), s(Mandatory), s(ExceptZone), s(ExceptProperties) -> s(Zone)
1024 @param[in] OneOf is a '|' separated list of flags
1025 @param[in] Mandatory is a '|' separated list of flags
1026 @param[in] ExceptZone is a zone name
1027 @param[in] ExceptProperties is a '|' separated list of flags
1028 @param[out] Zone is a zone matching at least one of OneOf flags, all Manadatory flags and can't be ExceptZone
1031 ($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.
1032 ($zone)getZoneWithFlags("boss", "", $oldzone); // Get a zone which matches boss flag with the best score except the $oldzone
1036 // CGroup not in a family behaviour
1037 void getZoneWithFlags_ssss_s(CStateInstance
* entity
, CScriptStack
& stack
)
1039 string exceptProperties
= stack
.top();
1041 TStringId curZoneId
= CStringMapper::map(stack
.top());
1043 string mandatoryProperties
= stack
.top();
1045 string oneOfProperties
= stack
.top();
1048 // If no AI instance return
1049 IManagerParent
* const managerParent
= entity
->getGroup()->getOwner()->getOwner();
1050 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
1053 stack
.push(string());
1057 // Fill the property sets.
1058 AITYPES::CPropertySet oneOfSet
= readSet(oneOfProperties
);
1059 AITYPES::CPropertySet mandatorySet
= readSet(mandatoryProperties
);
1060 AITYPES::CPropertySet exceptSet
= readSet(exceptProperties
);
1062 CNpcZone
const* const curZone
= aiInstance
->getZone(curZoneId
);
1063 // Create the scorer
1064 CZoneScorerMandatoryAndOneOfPlusExcept
const scorer(oneOfSet
, mandatorySet
, exceptSet
, curZone
);
1066 getZoneWithFlags_helper(entity
, stack
, aiInstance
, scorer
);
1069 //----------------------------------------------------------------------------
1072 @subsection getZoneWithFlags_sss_s
1073 @sa @ref getZoneWithFlags_ssss_s
1075 Arguments: s(OneOf), s(Mandatory), s(ExceptZone) -> s(Zone)
1076 @param[in] OneOf is a '|' separated list of flags
1077 @param[in] Mandatory is a '|' separated list of flags
1078 @param[in] ExceptZone is a zone name
1079 @param[out] Zone is a zone matching at least one of OneOf flags, all Manadatory flags and can't be ExceptZone
1082 ($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.
1083 ($zone)getZoneWithFlags("boss", "", $oldzone); // Get a zone which matches boss flag with the best score except the $oldzone
1087 // CGroup not in a family behaviour
1088 void getZoneWithFlags_sss_s(CStateInstance
* entity
, CScriptStack
& stack
)
1090 stack
.push(std::string(""));
1091 getZoneWithFlags_ssss_s(entity
, stack
);
1094 //----------------------------------------------------------------------------
1097 @subsection getNearestZoneWithFlags_ffsss_s
1098 @sa @ref getZoneWithFlags_ssss_s
1100 The zone returned by this function is the nearest from the specified point and taking into account the zone free space.
1102 Arguments: f(X), f(Y), s(OneOf), s(Mandatory), s(ExceptProperties) -> s(Zone)
1103 @param[in] X is the position of the zone we are looking for on the X axis
1104 @param[in] Y is the position of the zone we are looking for on the X axis
1105 @param[in] OneOf is a '|' separated list of flags
1106 @param[in] Mandatory is a '|' separated list of flags
1107 @param[in] ExceptProperties is a '|' separated list of flags
1108 @param[out] Zone is a zone matching at least one of OneOf flags, all Manadatory flags and can't be ExceptZone
1111 ($zone)getNearestZoneWithFlags(x, y, "food|rest", "invasion|outpost", "stayaway");
1115 // CGroup not in a family behaviour
1116 void getNearestZoneWithFlags_ffsss_s(CStateInstance
* entity
, CScriptStack
& stack
)
1118 string exceptProperties
= stack
.top();
1120 string mandatoryProperties
= stack
.top();
1122 string oneOfProperties
= stack
.top();
1124 float const y
= stack
.top();
1126 float const x
= stack
.top();
1129 // If no AI instance return
1130 IManagerParent
* const managerParent
= entity
->getGroup()->getOwner()->getOwner();
1131 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
1134 stack
.push(string());
1138 // Fill the property sets.
1139 AITYPES::CPropertySet oneOfSet
= readSet(oneOfProperties
);
1140 AITYPES::CPropertySet mandatorySet
= readSet(mandatoryProperties
);
1141 AITYPES::CPropertySet exceptSet
= readSet(exceptProperties
);
1142 // Create the scorer
1143 CZoneScorerMandatoryAndOneOfAndDistAndSpace
const scorer(oneOfSet
, mandatorySet
, exceptSet
, CAIVector(x
, y
));
1145 getZoneWithFlags_helper(entity
, stack
, aiInstance
, scorer
);
1148 //----------------------------------------------------------------------------
1151 @subsection getNearestZoneWithFlags_ffss_s
1152 @sa @ref getZoneWithFlags_sss_s
1154 The zone returned by this function is the nearest from the specified point and taking into account the zone free space.
1156 Arguments: f(X), f(Y), s(OneOf), s(Mandatory), s(ExceptProperties) -> s(Zone)
1157 @param[in] X is the position of the zone we are looking for on the X axis
1158 @param[in] Y is the position of the zone we are looking for on the X axis
1159 @param[in] OneOf is a '|' separated list of flags
1160 @param[in] Mandatory is a '|' separated list of flags
1161 @param[out] Zone is a zone matching at least one of OneOf flags, all Manadatory flags and can't be ExceptZone
1164 ($zone)getNearestZoneWithFlags(x, y, "food|rest", "invasion|outpost");
1168 // CGroup not in a family behaviour
1169 void getNearestZoneWithFlags_ffss_s(CStateInstance
* entity
, CScriptStack
& stack
)
1171 stack
.push(std::string(""));
1172 getNearestZoneWithFlags_ffsss_s(entity
, stack
);
1175 //----------------------------------------------------------------------------
1178 @subsection getNearestZoneWithFlagsStrict_ffsss_s
1179 @sa @ref getZoneWithFlags_ssss_s
1181 The zone returned by this function is the nearest from the specified point without taking into account the zone free space.
1183 Arguments: f(X), f(Y), s(OneOf), s(Mandatory), s(ExceptProperties) -> s(Zone)
1184 @param[in] X is the position of the zone we are looking for on the X axis
1185 @param[in] Y is the position of the zone we are looking for on the X axis
1186 @param[in] OneOf is a '|' separated list of flags
1187 @param[in] Mandatory is a '|' separated list of flags
1188 @param[in] ExceptProperties is a '|' separated list of flags
1189 @param[out] Zone is a zone matching at least one of OneOf flags, all Manadatory flags and can't be ExceptZone
1192 ($zone)getNearestZoneWithFlagsStrict(x, y, "food|rest", "invasion|outpost", "stayaway");
1196 // CGroup not in a family behaviour
1197 void getNearestZoneWithFlagsStrict_ffsss_s(CStateInstance
* entity
, CScriptStack
& stack
)
1199 string exceptProperties
= stack
.top();
1201 string mandatoryProperties
= stack
.top();
1203 string oneOfProperties
= stack
.top();
1205 float const y
= stack
.top();
1207 float const x
= stack
.top();
1210 // If no AI instance return
1211 IManagerParent
* const managerParent
= entity
->getGroup()->getOwner()->getOwner();
1212 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
1215 stack
.push(string());
1219 // Fill the property sets.
1220 AITYPES::CPropertySet oneOfSet
= readSet(oneOfProperties
);
1221 AITYPES::CPropertySet mandatorySet
= readSet(mandatoryProperties
);
1222 AITYPES::CPropertySet exceptSet
= readSet(exceptProperties
);
1223 // Create the scorer
1224 const CZoneScorerMandatoryAndOneOfAndDist
scorer(oneOfSet
, mandatorySet
, exceptSet
, CAIVector(x
, y
));
1226 getZoneWithFlags_helper(entity
, stack
, aiInstance
, scorer
);
1229 //----------------------------------------------------------------------------
1232 @subsection getNearestZoneWithFlagsStrict_ffss_s
1233 @sa @ref getZoneWithFlags_sss_s
1235 The zone returned by this function is the nearest from the specified point without taking into account the zone free space.
1237 Arguments: f(X), f(Y), s(OneOf), s(Mandatory), s(ExceptProperties) -> s(Zone)
1238 @param[in] X is the position of the zone we are looking for on the X axis
1239 @param[in] Y is the position of the zone we are looking for on the X axis
1240 @param[in] OneOf is a '|' separated list of flags
1241 @param[in] Mandatory is a '|' separated list of flags
1242 @param[out] Zone is a zone matching at least one of OneOf flags, all Manadatory flags and can't be ExceptZone
1245 ($zone)getNearestZoneWithFlagsStrict(x, y, "food|rest", "invasion|outpost");
1249 // CGroup not in a family behaviour
1250 void getNearestZoneWithFlagsStrict_ffss_s(CStateInstance
* entity
, CScriptStack
& stack
)
1252 stack
.push(std::string(""));
1253 getNearestZoneWithFlagsStrict_ffsss_s(entity
, stack
);
1256 //----------------------------------------------------------------------------
1259 @subsection getNeighbourZoneWithFlags_ssss_s
1260 @sa @ref getZoneWithFlags_ssss_s
1262 Here priority is given to current Cell, after that to neighbour Cells, and
1263 finally to all cells. CurrentZone cannot be returned.
1265 Arguments: s(CurrentZone), s(OneOf), s(Mandatory), s(ExceptProperties) -> s(Zone)
1266 @param[in] CurrentZone is a zone name
1267 @param[in] OneOf is a '|' separated list of flags
1268 @param[in] Mandatory is a '|' separated list of flags
1269 @param[in] ExceptProperties is a '|' separated list of flags
1270 @param[out] Zone is a zone matching the specified flags
1273 ($zone1)getNeighbourZoneWithFlags($zone, "boss", "", $exceptflag); // Get the zone in the neighbour cells of the one containing $zone which matches specified flags
1277 // CGroup not in a family behaviour
1278 void getNeighbourZoneWithFlags_ssss_s(CStateInstance
* entity
, CScriptStack
& stack
)
1280 string exceptProperties
= stack
.top();
1282 string mandatoryProperties
= stack
.top();
1284 string oneOfProperties
= stack
.top();
1286 TStringId curZoneId
= CStringMapper::map(stack
.top());
1289 // If no AI instance return
1290 IManagerParent
* const managerParent
= entity
->getGroup()->getOwner()->getOwner();
1291 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
1294 stack
.push(string());
1298 // If curzone is invalid return
1299 CNpcZone
const* const curZone
= aiInstance
->getZone(curZoneId
);
1302 nlwarning("getNeighbourZoneWithFlags failed: current zone is invalid!");
1303 nlwarning(" - current zone: %s", CStringMapper::unmap(curZoneId
).c_str());
1304 nlwarning(" - oneOfProperties: %s", oneOfProperties
.c_str());
1305 nlwarning(" - mandatoryProperties: %s", mandatoryProperties
.c_str());
1306 nlwarning(" - exceptProperties: %s", exceptProperties
.c_str());
1307 stack
.push(string());
1311 // Fill the property sets.
1312 AITYPES::CPropertySet oneOfSet
= readSet(oneOfProperties
);
1313 AITYPES::CPropertySet mandatorySet
= readSet(mandatoryProperties
);
1314 AITYPES::CPropertySet exceptSet
= readSet(exceptProperties
);
1315 // Create the scorer
1316 CZoneScorerMandatoryAndOneOfPlusExcept
const scorer(oneOfSet
, mandatorySet
, exceptSet
, curZone
);
1318 vector
<CCell
*> cells
;
1319 curZone
->getOwner()->getNeighBourgCellList(cells
);
1320 cells
.push_back(curZone
->getOwner());
1321 std::random_shuffle(cells
.begin(), cells
.end());
1323 CNpcZone
const* const newZone
= CCellZone::lookupNpcZoneScorer(cells
, scorer
);
1327 stack
.push(newZone
->getAliasTreeOwner().getAliasFullName());
1330 nlwarning("getNeighbourgZoneWithFlags failed: no zone found");
1331 nlwarning(" - current zone: %s", CStringMapper::unmap(curZoneId
).c_str());
1332 nlwarning(" - oneOfProperties: %s", oneOfProperties
.c_str());
1333 nlwarning(" - mandatoryProperties: %s", mandatoryProperties
.c_str());
1334 nlwarning(" - exceptProperties: %s", exceptProperties
.c_str());
1336 stack
.push(string());
1340 //----------------------------------------------------------------------------
1343 @subsection getNeighbourZoneWithFlags_sss_s
1344 @sa @ref getZoneWithFlags_sss_s
1346 Here priority is given to current Cell, after that to neighbour Cells, and
1347 finally to all cells. CurrentZone cannot be returned.
1349 Arguments: s(CurrentZone), s(OneOf), s(Mandatory) -> s(Zone)
1350 @param[in] CurrentZone is a zone name
1351 @param[in] OneOf is a '|' separated list of flags
1352 @param[in] Mandatory is a '|' separated list of flags
1353 @param[out] Zone is a zone matching the specified flags
1356 ($zone1)getNeighbourZoneWithFlags($zone, "boss", ""); // Get the zone in the neighbour cells of the one containing $zone which matches specified flags
1360 // CGroup not in a family behaviour
1361 void getNeighbourZoneWithFlags_sss_s(CStateInstance
* entity
, CScriptStack
& stack
)
1363 stack
.push(std::string(""));
1364 getNeighbourZoneWithFlags_ssss_s(entity
, stack
);
1367 //----------------------------------------------------------------------------
1370 @subsection setAggro_ff_
1371 Sets aggro parameters of current group.
1373 Arguments: f(Range), f(NbTicks) ->
1374 @param[in] Range is a aggro range in meters
1375 @param[in] NbTicks is a aggro update period in ticks
1378 ()setAggro(Range, NbTicks); // Sets the aggro range of the group to Range, updated every NbTicks ticks
1383 void setAggro_ff_(CStateInstance
* entity
, CScriptStack
& stack
)
1385 sint32 updateNbTicks
= (sint32
)(float)stack
.top();
1387 uint32 aggroRange
= (uint32
)(float)stack
.top();
1390 CGroup
* const grp
= entity
->getGroup();
1393 grp
->_AggroRange
= aggroRange
;
1394 if (updateNbTicks
>0)
1395 grp
->_UpdateNbTicks
= updateNbTicks
;
1399 //----------------------------------------------------------------------------
1402 @subsection setCanAggro_f_
1403 Let a bot aggro or prevent it from aggroing.
1405 Arguments: f(CanAggro) ->
1406 @param[in] CanAggro tells whether the bot can aggro (!=0) or not (==0)
1414 void setCanAggro_f_(CStateInstance
* entity
, CScriptStack
& stack
)
1416 bool canAggro
= ((float)stack
.top())!=0.f
;
1419 FOREACH(bot
, CCont
<CBot
>, entity
->getGroup()->bots())
1421 if (!bot
->isSpawned())
1423 CSpawnBot
* spBot
= bot
->getSpawnObj();
1425 spBot
->setCanAggro(canAggro
);
1429 //----------------------------------------------------------------------------
1432 @subsection clearAggroList_f_
1433 Reset the aggrolist of a bot.
1435 Arguments: f(bool don't send lost aggro message to EGS) ->
1438 ()clearAggroList(0/1);
1443 void clearAggroList_f_(CStateInstance
* entity
, CScriptStack
& stack
)
1445 bool sendAggroLostMessage
= ((float)stack
.top())==0.f
;
1448 FOREACH(bot
, CCont
<CBot
>, entity
->getGroup()->bots())
1450 if (!bot
->isSpawned())
1452 CSpawnBot
* spBot
= bot
->getSpawnObj();
1454 spBot
->clearAggroList(sendAggroLostMessage
);
1458 //----------------------------------------------------------------------------
1461 @subsection clearAggroList__
1462 Reset the aggrolist of a bot.
1472 void clearAggroList__(CStateInstance
* entity
, CScriptStack
& stack
)
1474 stack
.push((float)0.f
);
1475 clearAggroList_f_(entity
, stack
);
1478 //----------------------------------------------------------------------------
1481 @subsection setMode_s_
1482 Sets the mode of every bot of the group. Valid modes are:
1491 Arguments: s(Mode) ->
1492 @param[in] Mode is the mode name to set
1500 void setMode_s_(CStateInstance
* entity
, CScriptStack
& stack
)
1502 string NewMode
= stack
.top();
1505 MBEHAV::EMode mode
= MBEHAV::stringToMode(NewMode
);
1506 if (mode
==MBEHAV::UNKNOWN_MODE
)
1509 FOREACH(botIt
, CCont
<CBot
>, entity
->getGroup()->bots())
1511 if (botIt
->getSpawnObj())
1512 botIt
->getSpawnObj()->setMode(mode
);
1517 //----------------------------------------------------------------------------
1520 @subsection setAutoSpawn_f_
1521 Determine if the current group should respawn automatically after despawn.
1523 Arguments: f(AutoSpawn) ->
1524 @param[in] AutoSpawn is whether the group automatically rewpawns (1) or not (0)
1532 void setAutoSpawn_f_(CStateInstance
* entity
, CScriptStack
& stack
)
1534 float const autoSpawn
= stack
.top();
1537 CGroup
* group
= entity
->getGroup();
1539 group
->setAutoSpawn(autoSpawn
!=0.f
);
1542 //----------------------------------------------------------------------------
1543 // HP related methods
1546 @subsection setMaxHP_ff_
1547 Sets the Max HP level of each bot of the group.
1549 Arguments: f(MaxHp) f(SetFull) ->
1550 @param[in] MaxHP is the new maximum HP for each bot
1551 @param[in] SetFull if not 0, will set the HP to the new maximum
1554 ()setMaxHP(50000,1);
1559 void setMaxHP_ff_(CStateInstance
* entity
, CScriptStack
& stack
)
1561 bool setFull
= ((float)stack
.top() != 0.f
); stack
.pop();
1562 float maxHp
= ((float)stack
.top()); stack
.pop();
1564 CChangeCreatureMaxHPMsg
& msgList
= CAIS::instance().getCreatureChangeMaxHP();
1566 FOREACH(bot
, CCont
<CBot
>, entity
->getGroup()->bots())
1568 if (!bot
->isSpawned())
1573 CSpawnBot
* const sbot
= bot
->getSpawnObj();
1574 msgList
.Entities
.push_back(sbot
->dataSetRow());
1575 msgList
.MaxHp
.push_back((uint32
)(maxHp
));
1576 msgList
.SetFull
.push_back((uint8
)(setFull
?1:0));
1578 bot
->setCustomMaxHp((uint32
)maxHp
);
1584 @subsection setHPLevel_f_
1585 Sets the current HP level of each bot of the group.
1587 Arguments: f(Coef) ->
1588 @param[in] Coef is the percentage of its max HP each creature will have
1596 void setHPLevel_f_(CStateInstance
* entity
, CScriptStack
& stack
)
1598 float coef
= stack
.top();
1601 CChangeCreatureHPMsg
& msgList
= CAIS::instance().getCreatureChangeHP();
1603 FOREACH(bot
, CCont
<CBot
>, entity
->getGroup()->bots())
1605 if (!bot
->isSpawned())
1608 CSpawnBot
* const sbot
= bot
->getSpawnObj();
1610 msgList
.Entities
.push_back(sbot
->dataSetRow());
1611 msgList
.DeltaHp
.push_back((sint32
)(sbot
->maxHitPoints()*coef
));
1618 //----------------------------------------------------------------------------
1619 // HP related methods
1622 @subsection setHPScale_f__f_
1623 Sets the current HP level of level of each bot of the group. its maxHitPoints
1625 for a bot HP = 850 and MaxHP = 1000
1626 ()setHPScale_f_(0); HP will be 0 so DeltaHp = 850
1627 ()setHPScale_f_(1); HP will be 100 so DeltaHp = 150
1628 ()setHPScale_f_(0.5); HP will be 500 so DeltaHp = 350
1629 if bot HP = 840 and Max abd setHpRatio(0) HP will be 0
1632 Arguments: f(Coef) ->
1633 @param[in] Coef is the percentage of its max HP each creature will *BE*
1641 void setHPScale_f_(CStateInstance
* entity
, CScriptStack
& stack
)
1643 float coef
= stack
.top();
1646 CChangeCreatureHPMsg
& msgList
= CAIS::instance().getCreatureChangeHP();
1648 FOREACH(bot
, CCont
<CBot
>, entity
->getGroup()->bots())
1650 if (!bot
->isSpawned())
1653 CSpawnBot
* const sbot
= bot
->getSpawnObj();
1655 msgList
.Entities
.push_back(sbot
->dataSetRow());
1656 msgList
.DeltaHp
.push_back((sint32
)( sbot
->maxHitPoints() *coef
- sbot
->currentHitPoints()) );
1660 //----------------------------------------------------------------------------
1661 // Url related method
1664 @subsection setUrl_ss_
1665 Sets the name and url of right-click action
1667 Arguments: s(actionName),s(url) ->
1668 @param[in] actionName of action when player mouse over
1669 @param[in] url of action when player mouse over
1672 ()setUrl("Click on Me", "http://www.domain.com/script.php");
1677 void setUrl_ss_(CStateInstance
* entity
, CScriptStack
& stack
)
1679 CGroup
* group
= entity
->getGroup();
1681 std::string url
= (std::string
)stack
.top();stack
.pop();
1682 std::string actionName
= (std::string
)stack
.top();stack
.pop();
1684 CCreatureSetUrlMsg msg
;
1685 FOREACH(botIt
, CCont
<CBot
>, group
->bots())
1687 CSpawnBot
* pbot
= botIt
->getSpawnObj();
1690 msg
.Entities
.push_back(pbot
->dataSetRow());
1693 CSpawnGroup
* spawnGroup
= group
->getSpawnObj();
1694 spawnGroup
->setActionName(actionName
);
1695 spawnGroup
->setUrl(url
);
1696 msg
.ActionName
= actionName
;
1698 msg
.send(egsString
);
1705 @subsection scaleHP_f_
1708 Arguments: f(Coef) ->
1709 @param[in] Coef is the percentage of its current HP each creature will have
1717 void scaleHP_f_(CStateInstance
* entity
, CScriptStack
& stack
)
1719 float coef
= stack
.top();
1722 CChangeCreatureHPMsg
& msgList
= CAIS::instance().getCreatureChangeHP();
1724 FOREACH(bot
, CCont
<CBot
>, entity
->getGroup()->bots())
1726 if (!bot
->isSpawned())
1729 CSpawnBot
* const sbot
= bot
->getSpawnObj();
1731 msgList
.Entities
.push_back(sbot
->dataSetRow());
1732 msgList
.DeltaHp
.push_back((sint32
)(sbot
->currentHitPoints()*coef
));
1739 @subsection setBotHPScaleByAlias_fs_
1740 Same as setHpSacale but only on a specific bot of a groupe from the current group by its bot alias
1742 Arguments: f(alias),f(Coef), ->
1743 @param[in] alias is the alias of the bot
1744 @param[in] Coef is the percentage of its current HP each creature will have
1748 ()scaleHpByAlias(2, '(A:1000:10560)');
1753 void setBotHPScaleByAlias_fs_(CStateInstance
* entity
, CScriptStack
& stack
)
1755 uint32 alias
= LigoConfig
.aliasFromString((string
)stack
.top()) ; stack
.pop();
1757 float coef
= stack
.top(); stack
.pop();
1759 CChangeCreatureHPMsg
& msgList
= CAIS::instance().getCreatureChangeHP();
1761 FOREACH(bot
, CCont
<CBot
>, entity
->getGroup()->bots())
1764 if (bot
->getAlias() != alias
) { continue; }
1765 if (!bot
->isSpawned()) return;
1767 CSpawnBot
* const sbot
= bot
->getSpawnObj();
1769 msgList
.Entities
.push_back(sbot
->dataSetRow());
1770 msgList
.DeltaHp
.push_back((sint32
)( sbot
->maxHitPoints() *coef
- sbot
->currentHitPoints()) );
1777 @subsection downScaleHP_f_
1778 Scales the bots HP down.
1780 Arguments: f(Coef) ->
1781 @param[in] Coef is a value
1789 void downScaleHP_f_(CStateInstance
* entity
, CScriptStack
& stack
)
1791 float coef
= stack
.top();
1794 CChangeCreatureHPMsg
& msgList
= CAIS::instance().getCreatureChangeHP();
1796 clamp(coef
, 0.f
, 1.f
);
1797 FOREACH(bot
, CCont
<CBot
>, entity
->getGroup()->bots())
1799 if (!bot
->isSpawned())
1802 CSpawnBot
* const sbot
= bot
->getSpawnObj();
1804 msgList
.Entities
.push_back(sbot
->dataSetRow());
1805 msgList
.DeltaHp
.push_back((sint32
)(sbot
->currentHitPoints()*(coef
-1)));
1811 @subsection upScaleHP_f_
1812 Scales the bots HP up.
1814 Arguments: f(Coef) ->
1815 @param[in] Coef is a value
1823 void upScaleHP_f_(CStateInstance
* entity
, CScriptStack
& stack
)
1825 float coef
= stack
.top();
1828 CChangeCreatureHPMsg
& msgList
= CAIS::instance().getCreatureChangeHP();
1830 clamp(coef
, 0.f
, 1.f
);
1831 FOREACH(bot
, CCont
<CBot
>, entity
->getGroup()->bots())
1833 if (!bot
->isSpawned())
1835 CSpawnBot
* spBot
= bot
->getSpawnObj();
1838 msgList
.Entities
.push_back(spBot
->dataSetRow());
1839 msgList
.DeltaHp
.push_back((sint32
)((spBot
->maxHitPoints()-spBot
->currentHitPoints())*coef
));
1846 @subsection addHP_f_
1850 @param[in] HP is the amount of hit points to add to each bot
1858 void addHP_f_(CStateInstance
* entity
, CScriptStack
& stack
)
1860 float addHP
= stack
.top();
1863 CChangeCreatureHPMsg
& msgList
= CAIS::instance().getCreatureChangeHP();
1865 FOREACH(bot
, CCont
<CBot
>, entity
->getGroup()->bots())
1867 if (!bot
->isSpawned())
1870 CSpawnBot
* const sbot
= bot
->getSpawnObj();
1872 msgList
.Entities
.push_back(sbot
->dataSetRow());
1873 msgList
.DeltaHp
.push_back((sint32
)(sbot
->currentHitPoints()+addHP
));
1877 void giveHP_f_(CStateInstance
* entity
, CScriptStack
& stack
)
1879 float addHP
= stack
.top();
1882 CChangeCreatureHPMsg
& msgList
= CAIS::instance().getCreatureChangeHP();
1884 FOREACH(bot
, CCont
<CBot
>, entity
->getGroup()->bots())
1886 if (!bot
->isSpawned())
1889 CSpawnBot
* const sbot
= bot
->getSpawnObj();
1891 msgList
.Entities
.push_back(sbot
->dataSetRow());
1892 msgList
.DeltaHp
.push_back((sint32
)(addHP
));
1896 //----------------------------------------------------------------------------
1899 @subsection aiAction_s_
1900 Triggers an AI action, defined by its sheet name, on the current target.
1902 Arguments: s(actionSheetId) ->
1903 @param[in] actionSheetId is a the sheet name of the action
1906 ()aiAction("kick_his_ass.aiaction");
1911 void aiAction_s_(CStateInstance
* entity
, CScriptStack
& stack
)
1913 std::string actionName
= stack
.top();
1915 NLMISC::CSheetId
sheetId(actionName
);
1916 if (sheetId
==NLMISC::CSheetId::Unknown
)
1918 nlwarning("Action SheetId Unknown %s", actionName
.c_str());
1921 AISHEETS::IAIActionCPtr action
= AISHEETS::CSheets::getInstance()->lookupAction(sheetId
);
1922 if (action
.isNull())
1924 nlwarning("Action SheetId Unknown %s", actionName
.c_str());
1928 FOREACH(botIt
, CCont
<CBot
>, entity
->getGroup()->bots())
1930 CSpawnBot
* pbot
= botIt
->getSpawnObj();
1933 CSpawnBot
& bot
= *pbot
;
1934 if (!bot
.getAIProfile())
1937 CBotProfileFight
* profile
= dynamic_cast<CBotProfileFight
*>(bot
.getAIProfile());
1941 if (!profile
->atAttackDist())
1944 TDataSetRow dataSetRow
;
1945 if ((CAIEntityPhysical
*)bot
.getTarget())
1946 dataSetRow
= bot
.getTarget()->dataSetRow();
1948 CEGSExecuteAiActionMsg
msg(bot
.dataSetRow(), dataSetRow
, action
->SheetId(), bot
._DamageCoef
, bot
._DamageSpeedCoef
);
1949 msg
.send(egsString
);
1950 bot
.setActionFlags(RYZOMACTIONFLAGS::Attacks
);
1956 //----------------------------------------------------------------------------
1959 @subsection aiActionSelf_s_
1960 Triggers an AI action, defined by its sheet name, on the bot itself.
1962 Arguments: s(actionSheetId) ->
1963 @param[in] actionSheetId is a the sheet name of the action
1966 ()aiActionSelf("defensive_aura.aiaction");
1971 void aiActionSelf_s_(CStateInstance
* entity
, CScriptStack
& stack
)
1973 std::string actionName
= stack
.top();
1975 NLMISC::CSheetId
sheetId(actionName
);
1976 if (sheetId
==NLMISC::CSheetId::Unknown
)
1978 nlwarning("Action SheetId Unknown %s", actionName
.c_str());
1981 AISHEETS::IAIActionCPtr action
= AISHEETS::CSheets::getInstance()->lookupAction(sheetId
);
1982 if (action
.isNull())
1984 nlwarning("Action SheetId Unknown %s", actionName
.c_str());
1988 FOREACH(botIt
, CCont
<CBot
>, entity
->getGroup()->bots())
1990 CSpawnBot
* pbot
= botIt
->getSpawnObj();
1993 CSpawnBot
& bot
= *pbot
;
1994 CEGSExecuteAiActionMsg
msg(bot
.dataSetRow(), bot
.dataSetRow(), action
->SheetId(), bot
._DamageCoef
, bot
._DamageSpeedCoef
);
1995 msg
.send(egsString
);
1996 bot
.setActionFlags(RYZOMACTIONFLAGS::Attacks
);
2002 //----------------------------------------------------------------------------
2005 @subsection addProfileParameter_s_
2006 Adds a profile parameter to the current group.
2008 Arguments: s(parameterName) ->
2009 @param[in] parameterName is a the id of the parameter to add
2012 ()addProfileParameter("running"); // equivalent to "running" parameter in group primitive
2017 void addProfileParameter_s_(CStateInstance
* entity
, CScriptStack
& stack
)
2019 std::string name
= (std::string
)stack
.top();
2022 CGroup
* group
= entity
->getGroup();
2024 if (group
->isSpawned())
2025 group
->getSpawnObj()->addProfileParameter(name
, "", 0.f
);
2029 //----------------------------------------------------------------------------
2032 @subsection addProfileParameter_ss_
2033 Adds a profile parameter to the current group.
2035 Arguments: s(parameterName),s(parameterContent) ->
2036 @param[in] parameterName is a the id of the parameter to add
2037 @param[in] parameterContent is the value of the parameter
2040 ()addProfileParameter("foo", "bar"); // equivalent to "foo:bar" parameter in group primitive
2045 void addProfileParameter_ss_(CStateInstance
* entity
, CScriptStack
& stack
)
2047 std::string value
= (std::string
)stack
.top();
2049 std::string name
= (std::string
)stack
.top();
2052 CGroup
* group
= entity
->getGroup();
2054 if (group
->isSpawned())
2055 group
->getSpawnObj()->addProfileParameter(name
, value
, 0.f
);
2058 //----------------------------------------------------------------------------
2061 @subsection addProfileParameter_sf_
2062 Adds a profile parameter to the current group.
2064 Arguments: s(parameterName),f(parameterContent) ->
2065 @param[in] parameterName is a the id of the parameter to add
2066 @param[in] parameterContent is the value of the parameter
2069 ()addProfileParameter("foo", 0.5); // equivalent to "foo:0.5" parameter in group primitive
2074 void addProfileParameter_sf_(CStateInstance
* entity
, CScriptStack
& stack
)
2076 float value
= (float)stack
.top();
2078 std::string name
= (std::string
)stack
.top();
2081 CGroup
* group
= entity
->getGroup();
2083 if (group
->isSpawned())
2084 group
->getSpawnObj()->addProfileParameter(name
, "", value
);
2087 //----------------------------------------------------------------------------
2090 @subsection removeProfileParameter_s_
2091 removes a profile parameter from the current group.
2093 Arguments: s(parameterName) ->
2094 @param[in] parameterName is a the id of the parameter to remove
2097 ()removeProfileParameter("running"); // remove "running" or "running:<*>" parameter from group
2102 void removeProfileParameter_s_(CStateInstance
* entity
, CScriptStack
& stack
)
2104 std::string name
= (std::string
)stack
.top();
2107 CGroup
* group
= entity
->getGroup();
2109 if (group
->isSpawned())
2110 group
->getSpawnObj()->removeProfileParameter(name
);
2113 //----------------------------------------------------------------------------
2116 @subsection addPersistentProfileParameter_s_
2117 Adds a profile parameter to the current group.
2119 Arguments: s(parameterName) ->
2120 @param[in] parameterName is a the id of the parameter to add
2123 ()addProfileParameter("running"); // equivalent to "running" parameter in group primitive
2128 void addPersistentProfileParameter_s_(CStateInstance
* entity
, CScriptStack
& stack
)
2130 std::string name
= (std::string
)stack
.top();
2133 CGroup
* group
= entity
->getGroup();
2135 if (group
->isSpawned())
2136 group
->getSpawnObj()->addProfileParameter(name
, "", 0.f
);
2138 group
->addProfileParameter(name
, "", 0.f
);
2141 //----------------------------------------------------------------------------
2144 @subsection addPersistentProfileParameter_ss_
2145 Adds a profile parameter to the current group.
2147 Arguments: s(parameterName),s(parameterContent) ->
2148 @param[in] parameterName is a the id of the parameter to add
2149 @param[in] parameterContent is the value of the parameter
2152 ()addPersistentProfileParameter("foo", "bar"); // equivalent to "foo:bar" parameter in group primitive
2157 void addPersistentProfileParameter_ss_(CStateInstance
* entity
, CScriptStack
& stack
)
2159 std::string value
= (std::string
)stack
.top();
2161 std::string name
= (std::string
)stack
.top();
2164 CGroup
* group
= entity
->getGroup();
2166 if (group
->isSpawned())
2167 group
->getSpawnObj()->addProfileParameter(name
, value
, 0.f
);
2169 group
->addProfileParameter(name
, value
, 0.f
);
2172 //----------------------------------------------------------------------------
2175 @subsection addPersistentProfileParameter_sf_
2176 Adds a profile parameter to the current group.
2178 Arguments: s(parameterName),f(parameterContent) ->
2179 @param[in] parameterName is a the id of the parameter to add
2180 @param[in] parameterContent is the value of the parameter
2183 ()addPersistentProfileParameter("foo", 0.5); // equivalent to "foo:0.5" parameter in group primitive
2188 void addPersistentProfileParameter_sf_(CStateInstance
* entity
, CScriptStack
& stack
)
2190 float value
= (float)stack
.top();
2192 std::string name
= (std::string
)stack
.top();
2195 CGroup
* group
= entity
->getGroup();
2196 if (group
->isSpawned())
2197 group
->getSpawnObj()->addProfileParameter(name
, "", value
);
2199 group
->addProfileParameter(name
, "", value
);
2202 //----------------------------------------------------------------------------
2205 @subsection removePersistentProfileParameter_s_
2206 removes a profile parameter from the current group.
2208 Arguments: s(parameterName) ->
2209 @param[in] parameterName is a the id of the parameter to remove
2212 ()removeProfileParameter("running"); // remove "running" or "running:<*>" parameters from group
2217 void removePersistentProfileParameter_s_(CStateInstance
* entity
, CScriptStack
& stack
)
2219 std::string name
= (std::string
)stack
.top();
2222 CGroup
* group
= entity
->getGroup();
2223 if (group
->isSpawned())
2224 group
->getSpawnObj()->removeProfileParameter(name
);
2226 group
->removeProfileParameter(name
);
2228 //----------------------------------------------------------------------------
2231 @subsection getOutpostState__s
2232 Returns the name of the current outpost state (group must be in an outpost).
2234 Arguments: -> s(StateName)
2235 @param[out] StateName is the name of the current outpost state
2238 ($name)getOutpostState();
2243 void getOutpostStateName__s(CStateInstance
* si
, CScriptStack
& stack
)
2252 CGroup
* group
= si
->getGroup();
2256 COutpostManager
* manager
= dynamic_cast<COutpostManager
*>(group
->getOwner());
2260 str
= static_cast<COutpost
*>(manager
->getOwner())->getStateName();
2266 //----------------------------------------------------------------------------
2269 @subsection isOutpostTribeOwner__f
2270 Returns whether the current outpost owner is a tribe (group must be in an outpost).
2272 Arguments: -> f(TribeOwner)
2273 @param[out] TribeOwner is whether the current outpost owner is a tribe (1) or not (0)
2276 (tribeOwner)isOutpostTribeOwner();
2281 void isOutpostTribeOwner__f(CStateInstance
* si
, CScriptStack
& stack
)
2283 float tribeOwner
= 0.f
;
2290 CGroup
* group
= si
->getGroup();
2294 COutpostManager
* manager
= dynamic_cast<COutpostManager
*>(group
->getOwner());
2298 if (!static_cast<COutpost
*>(manager
->getOwner())->isBelongingToAGuild())
2302 stack
.push(tribeOwner
);
2305 //----------------------------------------------------------------------------
2308 @subsection isOutpostGuildOwner__f
2309 Returns whether the current outpost owner is a guild (group must be in an outpost).
2311 Arguments: -> f(TribeOwner)
2312 @param[out] TribeOwner is whether the current outpost owner is a guild (1) or not (0)
2315 (guildOwner)isOutpostGuildOwner();
2320 void isOutpostGuildOwner__f(CStateInstance
* si
, CScriptStack
& stack
)
2322 float guildOwner
= 0.f
;
2329 CGroup
* group
= si
->getGroup();
2333 COutpostManager
* manager
= dynamic_cast<COutpostManager
*>(group
->getOwner());
2337 if (static_cast<COutpost
*>(manager
->getOwner())->isBelongingToAGuild())
2341 stack
.push(guildOwner
);
2344 //----------------------------------------------------------------------------
2347 @subsection getEventParam_f_f
2348 Returns the content of a param
2350 Arguments: f(paramIndex) -> f(value)
2351 @param[in] paramIndex is the parameter index passed by EGS ai_event message
2352 @param[out] value is a the value of the parameter
2355 (val)getEventParam(2);
2360 void getEventParam_f_f(CStateInstance
* entity
, CScriptStack
& stack
)
2362 uint32 varId
= (uint32
)((float)stack
.top());
2364 CGroup
* group
= entity
->getGroup();
2366 stack
.top() = group
->getEventParamFloat(varId
);
2369 //----------------------------------------------------------------------------
2372 @subsection getEventParam_f_s
2373 Returns the content of a param
2375 Arguments: f(paramIndex) -> s(value)
2376 @param[in] paramIndex is the parameter index passed by EGS ai_event message
2377 @param[out] value is a the value of the parameter
2380 ($val)getEventParam(2);
2385 void getEventParam_f_s(CStateInstance
* entity
, CScriptStack
& stack
)
2387 uint32 varId
= (uint32
)((float)stack
.top());
2389 CGroup
* group
= entity
->getGroup();
2391 stack
.top() = group
->getEventParamString(varId
);
2396 // -- Boss functions
2398 //----------------------------------------------------------------------------
2401 @subsection getPlayerStat_ss_f
2402 Get some player stat.
2404 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.
2405 The player must be in the same AI Instance (same continent).
2406 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.
2407 If param is not one of "HP", "MaxHp", "RatioHp" zero is return and a warning message is printed on the log.
2408 - The "Hp" stat is the property CURRENT_HIT_POINTS as seen in the mirror.
2409 - The "MaxHp" stat is the property MAX_HIT_POINTS as seen in the mirror.
2410 - The "RatioHp" stat is (Hp * 100) / MaxHp
2411 Be careful the argument is case sensitive.
2413 Arguments: s(playerEidAsString), s(statName) -> s(result)
2414 @param[in] playerEidAsString is EntityId as string from the player we want infos
2415 @param[in] statName is the name of the property (can be "HP", "MaxHp", "RatioHp")
2416 @param[out] value is a the value of the parameter
2419 ($playerEid)getCurrentPlayerEid();
2420 print($playerEid); //log (0x00001fbd50:00:00:81)
2421 (maxHp)getPlayerStat($playerEid, "MaxHp");
2424 void getPlayerStat_ss_f(CStateInstance
* entity
, CScriptStack
& stack
)
2426 std::string funName
= "getPlayerStat_ss_f";
2428 std::string statName
= ((std::string
)stack
.top()); stack
.pop();
2429 std::string playerEidStr
= ((std::string
)stack
.top()); stack
.pop();
2432 // get Dataset of the player to have access to mirror values
2433 NLMISC::CEntityId playerEid
;
2434 playerEid
.fromString(playerEidStr
.c_str());
2435 TDataSetRow playerRow
= TheDataset
.getDataSetRow( playerEid
);
2436 if (! TheDataset
.isAccessible( playerRow
) )
2438 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() );
2439 stack
.push((float)0);
2443 if (statName
== "Hp" )
2445 // return DSPropertyCURRENT_HIT_POINTS Mirror value
2446 CMirrorPropValue
<sint32
> mirrorSymbol( TheDataset
, playerRow
, DSPropertyCURRENT_HIT_POINTS
);
2447 stack
.push((float)mirrorSymbol
.getValue());
2450 else if (statName
== "MaxHp")
2452 // return DSPropertyMAX_HIT_POINTS Mirror value
2453 CMirrorPropValue
<sint32
> mirrorSymbol( TheDataset
, playerRow
, DSPropertyMAX_HIT_POINTS
);
2454 stack
.push((float)mirrorSymbol
.getValue());
2457 else if (statName
== "RatioHp")
2459 // return percentage of live (read from mirror values)
2460 CMirrorPropValue
<sint32
> mirrorSymbol( TheDataset
, playerRow
, DSPropertyCURRENT_HIT_POINTS
);
2461 CMirrorPropValue
<sint32
> mirrorSymbol2( TheDataset
, playerRow
, DSPropertyMAX_HIT_POINTS
);
2463 stack
.push((float)(100.0*mirrorSymbol
.getValue() / mirrorSymbol2
.getValue()));
2468 nlwarning("Try to call %s with wrong state %s", funName
.c_str(), statName
.c_str() );
2470 stack
.push((float)0);
2475 //----------------------------------------------------------------------------
2478 @subsection getPlayerPosition_ss_ff
2479 Get player position (x or y).
2481 Arguments: s(playerEidAsString), s(statName) -> s(result)
2482 @param[in] playerEidAsString is EntityId as string from the player we want infos
2483 @param[in] axis ("X" or "Y")
2484 @param[out] value is a the value of the parameter
2487 ($playerEid)getCurrentPlayerEid();
2488 (x, y)getPlayerPosition($playerEid);
2491 void getPlayerPosition_s_ff(CStateInstance
* entity
, CScriptStack
& stack
)
2493 std::string funName
= "getPlayerPosition_s_ff";
2495 std::string statName
= ((std::string
)stack
.top()); stack
.pop();
2496 std::string playerEidStr
= ((std::string
)stack
.top()); stack
.pop();
2499 // get Dataset of the player to have access to mirror values
2500 NLMISC::CEntityId playerEid
;
2501 playerEid
.fromString(playerEidStr
.c_str());
2502 TDataSetRow playerRow
= TheDataset
.getDataSetRow( playerEid
);
2503 if (! TheDataset
.isAccessible( playerRow
) )
2505 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() );
2506 stack
.push((float)0);
2510 CMirrorPropValue
<sint32
> mirrorSymbol( TheDataset
, playerRow
, DSPropertyPOSY
);
2511 stack
.push((float)mirrorSymbol
.getValue());
2512 CMirrorPropValue
<sint32
> mirrorSymbol2( TheDataset
, playerRow
, DSPropertyPOSX
);
2513 stack
.push((float)mirrorSymbol2
.getValue());
2520 @subsection getPlayerDistance_fs_f
2521 Get the distance between a player and a bot in meters.
2523 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.
2524 The player must be in the same AI Instance (same continent).
2525 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.
2527 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.
2528 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.
2530 Arguments: s(playerEidAsString), f(botIndex) -> s(result)
2531 @param[in] playerEidAsString is EntityId as string from the player we want infos
2532 @param[in] botIndex is the index of an bot member of the current group
2533 @param[out] value is a the distance between the player on the bot (or -1 if error)
2536 ($playerEid)getCurrentPlayerEid();
2537 (index)getBotIndexByName("toto");
2538 (distance)getPlayerDistance(index, $playerEid);
2541 void getPlayerDistance_fs_f(CStateInstance
* entity
, CScriptStack
& stack
)
2543 std::string funName
= "getPlayerDistance_is_f";
2545 // read input params
2546 std::string playerEidStr
= ((std::string
)stack
.top()); stack
.pop();
2547 sint32 botIndex
= (sint32
)((float)stack
.top()); stack
.pop();
2549 // get the player Eid
2550 NLMISC::CEntityId playerEid
;
2551 playerEid
.fromString(playerEidStr
.c_str());
2553 // get the Spawn bot by its index
2554 CGroup
* group
= entity
->getGroup();
2557 nlwarning("%s on a non Npc Group, doesn't work", funName
.c_str());
2558 stack
.push((float) -1);
2561 if (!group
->isSpawned() || botIndex
<0 || group
->bots().size() <= static_cast<uint32
>(botIndex
))
2563 nlwarning("%s used bad index %d/%d (or group not spawn)", funName
.c_str(), botIndex
, group
->bots().size());
2564 stack
.push((float)-1);
2567 CBot
* bot
= group
->getBot(botIndex
);
2568 CSpawnBot
* spBot
= bot
?bot
->getSpawnObj():0;
2571 nlwarning("%s used bad index %d/%d (or bot not spawn)", funName
.c_str(), botIndex
, group
->bots().size());
2572 stack
.push((float)-1);
2576 // get DataSetRow of player to read mirro values
2577 TDataSetRow playerRow
= TheDataset
.getDataSetRow( playerEid
);
2578 if (! TheDataset
.isAccessible( playerRow
) )
2580 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() );
2581 stack
.push((float)-1);
2585 // calculate the size between position of the player (from mirro) to position of the spawn bot.
2586 CMirrorPropValue
<sint32
> mirrorSymbol( TheDataset
, playerRow
, DSPropertyPOSX
);
2587 CMirrorPropValue
<sint32
> mirrorSymbol2( TheDataset
, playerRow
, DSPropertyPOSY
);
2588 const double dx
= double (mirrorSymbol
.getValue()) - double(spBot
->x().asInt());
2589 const double dy
= double (mirrorSymbol2
.getValue()) - double(spBot
->y().asInt());
2590 const double dist2
= (dx
*dx
+ dy
*dy
) / 1000000.0;
2591 const double dist
= sqrt(dist2
);
2593 stack
.push(float(dist
));
2603 @subsection getCurrentPlayerAggroListTarget_f_s
2604 Get the player entity id (as string) that has the most aggro in the aggro list of a bot.
2606 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.
2607 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.
2609 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)
2612 Arguments: f(botIndex) -> s(playerEidAsString)
2613 @param[in] botIndex is the index of an bot member of the current group
2614 @param[out] playerEidAsString is EntityId as string from the player we want infos
2617 ($playerId)getCurrentPlayerAggroListTarget(4);
2618 (distance)getPlayerDistance(4, $playerId);
2623 void getCurrentPlayerAggroListTarget_f_s(CStateInstance
* entity
, CScriptStack
& stack
)
2626 std::string funName
= "getCurrentPlayerAggroListTarget_f_s";
2629 sint32 botIndex
= (sint32
)((float)stack
.top()); stack
.pop();
2632 CGroup
* group
= entity
->getGroup();
2635 nlwarning("%s on a non Npc Group, doesn't work", funName
.c_str());
2636 stack
.push(std::string(""));
2639 if (!group
->isSpawned() || botIndex
<0 || group
->bots().size() <= static_cast<uint32
>(botIndex
))
2641 nlwarning("%s used bad index %d/%d (or group not spawn)", funName
.c_str(), botIndex
, group
->bots().size());
2642 stack
.push(std::string(""));
2646 CBot
* bot
= group
->getBot(botIndex
);
2647 CSpawnBot
* spBot
= bot
?bot
->getSpawnObj():0;
2650 nlwarning("%s used bad index %d/%d (or bot not spawn)", funName
.c_str(), botIndex
, group
->bots().size());
2651 stack
.push(std::string(""));
2655 // iteratre throug aggro list to have the eid with max aggro
2656 CBotAggroOwner::TBotAggroList
const& aggroList
= spBot
->getBotAggroList();
2657 CBotAggroOwner::TBotAggroList::const_iterator
aggroIt(aggroList
.begin()), aggroEnd(aggroList
.end());
2658 TDataSetRow foundRow
= TDataSetRow();
2659 float foundAggro
= 0;
2660 for (; aggroIt
!= aggroEnd
; ++aggroIt
)
2662 float aggro
= aggroIt
->second
->finalAggro();
2663 if (aggro
> foundAggro
)
2665 if (CMirrors::getEntityId(aggroIt
->first
).getType() != RYZOMID::player
)
2669 CAIEntityPhysical
* ep
= CAIS::instance().getEntityPhysical(aggroIt
->first
);
2675 CBotPlayer
const* const player
= NLMISC::safe_cast
<CBotPlayer
const*>(ep
);
2680 if (!player
->isAggroable())
2685 foundRow
= aggroIt
->first
;
2689 if ( foundRow
== TDataSetRow())
2690 { // Empty aggro list so no warning displayed
2691 stack
.push(std::string(""));
2695 const NLMISC::CEntityId
& found
= CMirrors::getEntityId(foundRow
);
2696 stack
.push(std::string(found
.toString()));
2704 @subsection getRandomPlayerAggroListTarget_f_s
2705 Get a player entity id (as string) from the aggro list of a bot.
2707 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.
2708 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.
2710 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)
2713 Arguments: f(botIndex) -> s(playerEidAsString)
2714 @param[in] botIndex is the index of an bot member of the current group
2715 @param[out] playerEidAsString is EntityId as string from the player we want infos
2718 ($playerId)getRandomPlayerAggroListTarget(4);
2719 ()setAggroListTarget(4, $playerId);
2724 void getRandomPlayerAggroListTarget_f_s(CStateInstance
* entity
, CScriptStack
& stack
)
2727 std::string funName
= "getRandomPlayerAggroListTarget_f_s";
2730 uint32 botIndex
= (uint32
)((float)stack
.top()); stack
.pop();
2733 CGroup
* group
= entity
->getGroup();
2734 if (!group
|| !group
->isSpawned() || botIndex
<0 || group
->bots().size() <= static_cast<uint32
>(botIndex
))
2736 nlwarning("%s used bad index %d/%d (or group not spawn)", funName
.c_str(), botIndex
, group
->bots().size());
2737 stack
.push(std::string(""));
2740 CBot
* bot
= group
->getBot(botIndex
);
2741 CSpawnBot
* spBot
= bot
?bot
->getSpawnObj():0;
2744 nlwarning("%s used bad index %d/%d (or bot not spawn)", funName
.c_str(), botIndex
, group
->bots().size());
2745 stack
.push(std::string(""));
2749 // make a vector of aggroable player
2750 CBotAggroOwner::TBotAggroList
const& aggroList
= spBot
->getBotAggroList();
2751 //typedef std::map<TDataSetRow, TAggroEntryPtr> TBotAggroList;
2752 CBotAggroOwner::TBotAggroList::const_iterator
aggroIt(aggroList
.begin()), aggroEnd(aggroList
.end());
2753 TDataSetRow foundRow
= TDataSetRow();
2754 std::vector
<TDataSetRow
> playerAggroable
;
2755 for (; aggroIt
!= aggroEnd
; ++aggroIt
)
2757 if (CMirrors::getEntityId(aggroIt
->first
).getType() != RYZOMID::player
)
2761 CAIEntityPhysical
* ep
= CAIS::instance().getEntityPhysical(aggroIt
->first
);
2767 CBotPlayer
const* const player
= NLMISC::safe_cast
<CBotPlayer
const*>(ep
);
2772 if (!player
->isAggroable())
2776 playerAggroable
.push_back(aggroIt
->first
);
2781 if ( playerAggroable
.empty())
2783 stack
.push(std::string(""));
2786 // chose a randomly a player among the container
2787 uint32 index
= static_cast<uint32
>( static_cast<double>(playerAggroable
.size())*rand()/(RAND_MAX
+1.0) );
2789 const NLMISC::CEntityId
& found
= CMirrors::getEntityId(playerAggroable
[ index
]);
2790 stack
.push(std::string(found
.toString()));
2796 @subsection getAggroListElement_ff_s
2797 Get a player entity id (as string) from the aggro list of a bot by it aggro list index.
2799 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.
2800 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.
2802 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
2806 Arguments: f(botIndex), f(aggroListIndex) -> s(playerEidAsString)
2807 @param[in] botIndex is the index of an bot member of the current group
2808 @param[in] aggroListIndex is the index of a aggroable player in the aggro list of the bot identified by botIndex
2809 @param[out] playerEidAsString is EntityId as string from the player we want infos
2812 (aggroSize)getAggorListSize(0);
2813 // to much player are attacking the boss
2814 if (aggoroSize > 10)
2816 ($player1)getAggroListElement(0);
2817 ($player2)getAggroListElement(1);
2818 ($player3)getAggroListElement(2);
2819 // so the boss teleport 3 person from its aggro list at the end of the world
2820 teleportPlayer($player1, 14233, 123123, 0, 0);
2821 teleportPlayer($player2, 14233, 123123, 0, 0);
2822 teleportPlayer($player2, 14233, 123123, 0, 0);
2828 void getAggroListElement_ff_s(CStateInstance
* entity
, CScriptStack
& stack
)
2831 std::string funName
= "getAggroListElement_ff_s";
2836 uint32 elementIndex
= (uint32
)((float)stack
.top()); stack
.pop();
2837 sint32 botIndex
= (uint32
)((float)stack
.top()); stack
.pop();
2839 // get spawn bot by its index
2840 CGroup
* group
= entity
->getGroup();
2841 if (!group
|| !group
->isSpawned() || botIndex
<0 || group
->bots().size() <= static_cast<uint32
>(botIndex
))
2843 nlwarning("%s used bad index %d/%d (or group not spawn)", funName
.c_str(), botIndex
, group
->bots().size());
2844 stack
.push(std::string(""));
2847 CBot
* bot
= group
->getBot(botIndex
);
2848 CSpawnBot
* spBot
= bot
?bot
->getSpawnObj():0;
2851 nlwarning("%s used bad index %d/%d (or bot not spawn)", funName
.c_str(), botIndex
, group
->bots().size());
2852 stack
.push(std::string(""));
2856 // make a vector of aggroable player
2857 CBotAggroOwner::TBotAggroList
const& aggroList
= spBot
->getBotAggroList();
2858 //typedef std::map<TDataSetRow, TAggroEntryPtr> TBotAggroList;
2859 CBotAggroOwner::TBotAggroList::const_iterator
aggroIt(aggroList
.begin()), aggroEnd(aggroList
.end());
2860 TDataSetRow foundRow
= TDataSetRow();
2862 std::vector
<TDataSetRow
> playerAggroable
;
2863 for (; aggroIt
!= aggroEnd
; ++aggroIt
)
2865 if (CMirrors::getEntityId(aggroIt
->first
).getType() != RYZOMID::player
)
2869 CAIEntityPhysical
* ep
= CAIS::instance().getEntityPhysical(aggroIt
->first
);
2875 CBotPlayer
const* const player
= NLMISC::safe_cast
<CBotPlayer
const*>(ep
);
2880 if (!player
->isAggroable())
2884 playerAggroable
.push_back(aggroIt
->first
);
2889 if ( playerAggroable
.empty())
2891 stack
.push(std::string(""));
2894 // if index outside return "";
2895 if (0 > elementIndex
&& elementIndex
>= playerAggroable
.size())
2897 stack
.push(std::string(""));
2901 const NLMISC::CEntityId
& found
= CMirrors::getEntityId(playerAggroable
[ uint32(elementIndex
) ]);
2902 stack
.push(std::string(found
.toString()));
2908 @subsection getAggroListSize_f_f
2909 Get a size of the aggro lsit of a bot (list of aggroable PLAYER)
2911 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.
2912 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.
2914 A number is used to indicate the size of the aggro lsit
2916 Arguments: f(aggroListIndex) -> f(sizeOfAggroList)
2917 @param[in] botIndex is the index of an bot member of the current group.
2918 @param[out] sizeOfAggroList The size of the aggro list index.
2921 (aggroSize)getAggorListSize(0);
2922 // to much player are attacking the boss
2923 if (aggoroSize > 10)
2925 ($player1)getAggroListElement(0);
2926 ($player2)getAggroListElement(1);
2927 ($player3)getAggroListElement(2);
2928 // so the boss teleport 3 person from its aggro list at the end of the world
2929 teleportPlayer($player1, 14233, 123123, 0, 0);
2930 teleportPlayer($player2, 14233, 123123, 0, 0);
2931 teleportPlayer($player2, 14233, 123123, 0, 0);
2937 void getAggroListSize_f_f(CStateInstance
* entity
, CScriptStack
& stack
)
2940 std::string funName
= "getRandomPlayerAggroListTarget_f_s";
2945 uint32 botIndex
= (uint32
)((float)stack
.top()); stack
.pop();
2947 // get spawn bot by index of the bot
2948 CGroup
* group
= entity
->getGroup();
2949 if (!group
|| !group
->isSpawned() || botIndex
<0 || group
->bots().size() <= static_cast<uint32
>(botIndex
))
2951 nlwarning("%s used bad index %d/%d (or group not spawn)", funName
.c_str(), botIndex
, group
->bots().size());
2952 stack
.push(float(0) );
2955 CBot
* bot
= group
->getBot(botIndex
);
2956 CSpawnBot
* spBot
= bot
?bot
->getSpawnObj():0;
2959 nlwarning("%s used bad index %d/%d (or bot not spawn)", funName
.c_str(), botIndex
, group
->bots().size());
2960 stack
.push(float(0) );
2964 // make a vector of aggroable player
2965 CBotAggroOwner::TBotAggroList
const& aggroList
= spBot
->getBotAggroList();
2966 //typedef std::map<TDataSetRow, TAggroEntryPtr> TBotAggroList;
2967 CBotAggroOwner::TBotAggroList::const_iterator
aggroIt(aggroList
.begin()), aggroEnd(aggroList
.end());
2968 TDataSetRow foundRow
= TDataSetRow();
2970 std::vector
<TDataSetRow
> playerAggroable
;
2971 for (; aggroIt
!= aggroEnd
; ++aggroIt
)
2973 if (CMirrors::getEntityId(aggroIt
->first
).getType() != RYZOMID::player
)
2977 CAIEntityPhysical
* ep
= CAIS::instance().getEntityPhysical(aggroIt
->first
);
2983 CBotPlayer
const* const player
= NLMISC::safe_cast
<CBotPlayer
const*>(ep
);
2988 if (!player
->isAggroable())
2992 playerAggroable
.push_back(aggroIt
->first
);
2997 // return the size of the aggro list
2998 stack
.push(float(playerAggroable
.size()));
3004 @subsection setAggroListTarget_fs_
3006 Maximize the Aggro of a target from the Aggro list of one bot (this id can be given by getRandomPlayerAggroListTarget)..
3008 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.
3009 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.
3011 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.
3013 Arguments: f(botIndex) >s(playerEidAsString) >
3014 @param[in] botIndex is the index of an bot member of the current group
3015 @param[in] playerEidAsString is EntityId of the player that will be attacked
3018 ($playerId)getRandomPlayerAggroListTarget(4);
3019 ()setAggroListTarget(4, $playerId);
3023 void setAggroListTarget_fs_(CStateInstance
* entity
, CScriptStack
& stack
)
3026 std::string funName
= "setAggroListTarget_fs_";
3030 std::string playerEidStr
= ((std::string
)stack
.top()); stack
.pop();
3031 sint32 botIndex
= (sint32
)((float)stack
.top());stack
.pop();
3033 // get the entity id
3034 NLMISC::CEntityId playerEid
;
3035 playerEid
.fromString(playerEidStr
.c_str());
3037 // get the spawn bot by its indesx
3038 CGroup
* group
= entity
->getGroup();
3039 if (!group
|| !group
->isSpawned() || botIndex
<0 || group
->bots().size() <= static_cast<uint32
>(botIndex
))
3041 nlwarning("%s used bad index %d/%d (or group not spawn)", funName
.c_str(), botIndex
, group
->bots().size());
3044 CBot
* bot
= group
->getBot(botIndex
);
3045 CSpawnBot
* spBot
= bot
?bot
->getSpawnObj():0;
3048 nlwarning("%s used bad index %d/%d (or bot not spawn)", funName
.c_str(), botIndex
, group
->bots().size());
3053 // test if player eid is ok
3054 if (playerEidStr
.empty()) { return; }
3055 TDataSetRow playerRow
= TheDataset
.getDataSetRow( playerEid
);
3056 bool accessible
= TheDataset
.isAccessible( playerRow
);
3057 bool pj
= playerEid
.getType() == RYZOMID::player
;
3058 CAIEntityPhysical
* ep
= accessible
&& pj
? CAIS::instance().getEntityPhysical(playerRow
):0;
3059 CBotPlayer
const* const player
= ep
? NLMISC::safe_cast
<CBotPlayer
const*>(ep
):0;
3060 if (!ep
|| !player
||!player
->isAggroable() )
3062 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() );
3067 // maximize aggro from the bot for the player
3068 spBot
->maximizeAggroFor(playerRow
);
3074 @subsection setGroupAggroListTarget_s_
3076 Maximize the Aggro of a target from the Aggro list of one bot to his group (this id can be given by getRandomPlayerAggroListTarget)..
3078 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.
3080 Arguments: s(playerEidAsString) >
3081 @param[in] playerEidAsString is EntityId of the player that will be attacked by the group
3084 ($playerId)getRandomPlayerAggroListTarget(4);
3085 ()setGroupAggroListTarget($playerId);
3089 void setGroupAggroListTarget_s_(CStateInstance
* entity
, CScriptStack
& stack
)
3092 std::string funName
= "setGroupAggroListTarget_s_";
3095 std::string playerEidStr
= ((std::string
)stack
.top()); stack
.pop();
3097 // read eid of the player
3098 NLMISC::CEntityId playerEid
;
3099 playerEid
.fromString(playerEidStr
.c_str());
3102 // test if player eid is ok
3103 if (playerEidStr
.empty()) { return; }
3104 TDataSetRow playerRow
= TheDataset
.getDataSetRow( playerEid
);
3105 bool accessible
= TheDataset
.isAccessible( playerRow
);
3106 bool pj
= playerEid
.getType() == RYZOMID::player
;
3107 CAIEntityPhysical
* ep
= accessible
&& pj
? CAIS::instance().getEntityPhysical(playerRow
):0;
3108 CBotPlayer
const* const player
= ep
? NLMISC::safe_cast
<CBotPlayer
const*>(ep
):0;
3109 if (!ep
|| !player
||!player
->isAggroable() )
3111 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() );
3115 // test if group is spawn
3116 CGroup
* group
= entity
->getGroup();
3117 if (!group
|| !group
->isSpawned() || group
->bots().isEmpty() )
3119 nlwarning("Call %s on a empty/not spawned group", funName
.c_str() );
3123 // apply maximizeAggroFor on all member of the group
3124 CCont
<CBot
>::iterator itBot
= group
->bots().begin();
3125 CCont
<CBot
>::iterator itEnd
= group
->bots().end();
3127 for (; itBot
!= itEnd
; ++itBot
)
3130 CSpawnBot
* spBot
= itBot
->getSpawnObj();
3131 if (!spBot
) { continue; }
3132 spBot
->maximizeAggroFor(playerRow
);
3139 @subsection setManagerAggroListTarget_ss_
3141 Maximize the Aggro of a target of one bot to some groups of his manage.
3143 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.
3145 A string is used to select groups of the manager (groups name must contains this string)
3147 Arguments: f(botIndex), s(playerEidAsString) >
3148 @param[in] playerId is EntityId of the player
3149 @param[in] nameElement The element of the name of all group we are interest in.
3152 ($playerId)getRandomPlayerAggroListTarget(0);
3153 ()setManagerAggroListTarget($playerId, "group_bandit_"); // all group that have name like "group_bandit_*" will attack the player
3157 void setManagerAggroListTarget_ss_(CStateInstance
* entity
, CScriptStack
& stack
)
3160 std::string funName
= "setManagerAggroListTarget_ss_";
3164 std::string playerEidStr
= ((std::string
)stack
.top()); stack
.pop();
3165 std::string groupNameStr
= ((std::string
)stack
.top()); stack
.pop();
3168 // test if player eid is ok
3169 NLMISC::CEntityId playerEid
;
3170 playerEid
.fromString(playerEidStr
.c_str());
3172 if (playerEidStr
.empty()) { return; }
3173 TDataSetRow playerRow
= TheDataset
.getDataSetRow( playerEid
);
3174 bool accessible
= TheDataset
.isAccessible( playerRow
);
3175 bool pj
= playerEid
.getType() == RYZOMID::player
;
3176 CAIEntityPhysical
* ep
= accessible
&& pj
? CAIS::instance().getEntityPhysical(playerRow
):0;
3177 CBotPlayer
const* const player
= ep
? NLMISC::safe_cast
<CBotPlayer
const*>(ep
):0;
3178 if (!ep
|| !player
||!player
->isAggroable() )
3180 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() );
3185 CGroup
* group
= entity
->getGroup();
3188 nlwarning("Call %s on a non exisiting group", funName
.c_str() );
3191 // get the manager of the group
3192 CManager
* manager
= group
->getOwner();
3195 nlwarning("Call %s on a non exisiting manager", funName
.c_str() );
3198 // for all group of the manager maximize aaggro *IF* the group name contains groupNameStr
3199 group
=manager
->getNextValidGroupChild();
3202 if ( ! (!group
|| !group
->isSpawned() || group
->bots().isEmpty() ) && group
->getName().find(groupNameStr
) != std::string::npos
)
3204 // apply maximizeAggroFor on all member of the group
3205 CCont
<CBot
>::iterator itBot
= group
->bots().begin();
3206 CCont
<CBot
>::iterator itEnd
= group
->bots().end();
3208 for (; itBot
!= itEnd
; ++itBot
)
3211 CSpawnBot
* spBot
= itBot
->getSpawnObj();
3212 if (!spBot
) { continue; }
3213 spBot
->maximizeAggroFor(playerRow
);
3216 group
= manager
->getNextValidGroupChild(group
);
3225 @subsection getBotIndexByName_s_f
3227 Get the index of a bot of a group by its name (or return -1). Mainly useful for scripted boss.
3229 botIndex begins at zero for the first member of the group, -1 if the bot is not found.
3231 Arguments:, s(botName) > f(botIndex)
3233 @param[in] name is the name of the bot
3234 @param[out] botIndex is the index of an bot member of the current group
3237 (botIndex)getBotIndexByName("boss_random_aggro");
3238 ($playerId)getRandomPlayerAggroListTarget(botIndex);
3239 ()setAggroListTarget(botIndex, $playerId);
3243 void getBotIndexByName_s_f(CStateInstance
* entity
, CScriptStack
& stack
)
3245 std::string funName
= "getBotIndexByName_s_f";
3248 std::string botName
= (std::string
)stack
.top(); stack
.pop();
3250 // test if group is spawned
3251 CGroup
* group
= entity
->getGroup();
3252 if (!group
|| group
->bots().isEmpty() )
3254 nlwarning("Call %s on a empty group", funName
.c_str() );
3255 stack
.push((float)-1);
3260 // Search on all persistent bot of the groupe the bot that have the searched name
3261 CCont
<CBot
>::iterator itBot
= group
->bots().begin();
3262 CCont
<CBot
>::iterator itEnd
= group
->bots().end();
3265 for (; itBot
!= itEnd
; ++itBot
)
3268 const std::string
& name
= itBot
->getName();
3269 if (name
== botName
)
3271 stack
.push((float)index
);
3277 stack
.push((float)-1);
3284 @subsection isGroupAlived__f
3286 Test if a group is alived (at least one member is alived)
3288 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.
3289 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.
3292 Arguments: s(playerid) > f(success)
3294 @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)
3297 ($alived)isGroupAlived();
3298 if ($alived == 1.0f) {
3303 void isGroupAlived__f(CStateInstance
* entity
, CScriptStack
& stack
)
3305 isAlived__f(entity
, stack
);
3311 @subsection isBotAlived_f_f
3313 Test if a bot of the current group is alived. The bot is identified by its index.
3315 Arguments: f(botIndex) > f(success)
3317 @param[int] botIndex the index of the bot.
3318 @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)
3321 ($botIndex)getBotIndexByName("boss_3");
3322 $alived)isBotAlived($botIndex);
3323 if (alived == 1.0f) {
3328 void isBotAlived_f_f(CStateInstance
* entity
, CScriptStack
& stack
)
3330 std::string funName
= "isBotAlived_f_f";
3332 sint32 botIndex
= (sint32
)((float)stack
.top()); stack
.pop();
3335 CGroup
* group
= entity
->getGroup();
3338 nlwarning("%s on a non Npc Group, doesn't work", funName
.c_str());
3339 stack
.push((float)0);
3342 if (!group
->isSpawned() || group
->bots().isEmpty() || botIndex
< 0 || group
->bots().size() < static_cast<uint32
>(botIndex
))
3344 stack
.push(0.0f
);return;
3346 const CBot
*const bot
= group
->getBot(botIndex
);
3347 if ( !bot
|| !bot
->isSpawned()) { stack
.push(0.0f
); return;};
3348 CAIEntityPhysical
*const ep
=bot
->getSpawnObj();
3349 if ( !ep
) { stack
.push(0.0f
); return;};
3351 // test if spawn bot is alive
3352 if (ep
->isAlive()) { stack
.push(1.0f
); return;}
3361 @subsection isPlayerAlived_s_f
3363 Test if a a player is is alived.
3365 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.
3367 Arguments: s(playerId) > f(success)
3370 @param[out] success is 1.0f if the entity id of a player is alived.
3373 ($botIndex)getBotIndexByName("boss_3");
3374 ($playerId)getCurrentPlayerAggroListTarget($botIndex):
3375 (alived)isPlayerlived($playerId);
3376 if (alived == 1.0f) {
3380 void isPlayerAlived_s_f(CStateInstance
* entity
, CScriptStack
& stack
)
3383 std::string playerEidStr
= (std::string
)stack
.top(); stack
.pop();
3385 //get CAIEntityPhysical of the player
3386 NLMISC::CEntityId playerEid
;
3387 playerEid
.fromString(playerEidStr
.c_str());
3388 TDataSetRow playeDataSetRow
= TheDataset
.getDataSetRow( playerEid
) ;
3389 if (playerEidStr
.empty() || !TheDataset
.isAccessible( playeDataSetRow
) || playerEid
.getType() != RYZOMID::player
)
3391 stack
.push(0.0f
); return;
3393 CAIEntityPhysical
* ep
= CAIS::instance().getEntityPhysical(playeDataSetRow
);
3397 stack
.push(0.0f
); return;
3399 // test if the player is alived
3402 stack
.push(1.0f
); return;
3405 stack
.push(0.0f
); return;
3410 @subsection getServerTimeStr__s
3412 Gets the server time as string "eg 21:17:14 the x"
3413 This function is useful for stat purpose or debug (to know when a boss is down)
3415 Arguments: > s(serverTime)
3418 @param[out] The server time as debug string
3421 ($serverTime)getServerTimeAsString();
3425 void getServerTimeStr__s(CStateInstance
* entity
, CScriptStack
& stack
)
3427 //get the server time (as debug string)
3429 time( ¤tTime
);
3430 std::string str
= NLMISC::toString("%s", asctime(localtime(¤tTime
)));
3435 @subsection getServerTime__s
3437 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
3439 Arguments: > s(serverTime)
3441 @param[out] The server time as string (a float is not sharp enough
3444 ($serverTime)getServerTime();
3448 void getServerTime__s(CStateInstance
* entity
, CScriptStack
& stack
)
3450 //get the server time (as time stamp)
3452 time( ¤tTime
);
3453 std::string ret
= NLMISC::toString("%d", currentTime
);
3454 // convert to string
3455 stack
.push((std::string
)ret
);
3461 @subsection getRyzomDateStr__s
3463 Gets the ryzom date as string
3464 Arguments: > s(ryzomDateStr)
3466 @param[out] ryzomTimeAndDateAsString The time and date of the ryzom univers as debug string.
3469 ($ryzomDateStr)getRyzomDateStr);
3472 void getRyzomDateStr__s(CStateInstance
* entity
, CScriptStack
& stack
)
3474 // Display time using ryzom style
3476 const CRyzomTime
&rt
= CTimeInterface::getRyzomTime();
3477 result
= NLMISC::toString("%d:%d:00", (int) floorf(rt
.getRyzomTime()) , (int) floorf(60.f
* fmodf(rt
.getRyzomTime(), 1.f
)));
3479 uint32 month
= rt
.getRyzomMonth();
3480 MONTH::EMonth monthInCycle
= rt
.getRyzomMonthInCurrentCycle();
3481 std::string monthName
= MONTH::toString((MONTH::EMonth
) monthInCycle
);
3482 uint32 dayOfMonth
= rt
.getRyzomDayOfMonth();
3483 std::string dayName
= WEEKDAY::toString((WEEKDAY::EWeekDay
) rt
.getRyzomDayOfWeek());
3484 result
+= NLMISC::toString(" / %s %d %s(%d) %d",
3486 (int) (dayOfMonth
+ 1),
3489 (int) rt
.getRyzomYear());
3491 stack
.push( result
);
3495 @subsection getRyzomDate__s
3497 Gets the ryzom tick game cycle. Useful for computing difference of time.
3498 The return value is a string and not a float because float is not sharp enought?
3499 Arguments: > s(tickGameCycle)
3501 @param[out] TickGameCycle The time of the ryzom univers (stops when server stops). 10 tick is 1 second.
3504 ($tickGameCycle)getRyzomDate();
3507 void getRyzomDate__s(CStateInstance
* entity
, CScriptStack
& stack
)
3510 const NLMISC::TGameCycle ryzomTime
= CTickEventHandler::getGameCycle();
3511 std::string ret
= NLMISC::toString("%d", ryzomTime
);
3512 // convert to string
3513 stack
.push((std::string
)ret
);
3518 class CPhraseParameters
3521 enum TMode
{NpcMsg
, SystemMsg
, EmoteMsg
};
3522 TVectorParamCheck Values
;
3525 CPhraseParameters PhraseParameters
;
3527 //----------------------------------------------------------------------------
3530 @subsection phraseBegin__
3531 Clear the parameters stack.
3533 Used when creating a customized msg via phraseEndSystemMsg_fss_, phraseEndNpcMsg_fss_, phraseEndSystemMsg_fss_.
3534 It Must be called at start of phrase if we are not sure that the parameter stack is clean.
3536 Parameter stack is unclean when someone has called a phrasePush* function but *not* a phraseEnd function before (which is *very* bad).
3542 ()phrasePushValue("money", 15);
3543 ()phrasePushValue("integer", 15);
3544 ()phrasePushValue("time", 15);
3545 ()phraseEndSystemMsg(0, "say", "PHRASE_FROM_PHRASE_WITH_3_PARAMETERS");
3550 void phraseBegin__(CStateInstance
* entity
, CScriptStack
& stack
)
3552 PhraseParameters
.Values
.clear();
3555 //----------------------------------------------------------------------------
3558 @subsection phrasePushValue_sf_
3559 This function push a value as number on the parameter stack. This stack is used by phraseEndSystemMsg_fss_, phraseEndNpcMsg_fss_, phraseEndSystemMsg_fss_ functions.
3561 @see phrasePushString_ss_
3562 @see phraseEndSystemMsg_fss_
3563 @see phraseEndNpcMsg_fss_
3564 @see phraseEndSystemMsg_fss_
3567 The value *Must* be an number and only few type are handled.
3572 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).
3582 Arguments: s(paramType), f(value) ->
3583 @param[in] paramType the type of the parameter
3584 @param[in] value the value of the parameter
3589 ()phrasePushValue("money", 15);
3590 ()phrasePushValue("integer", 15);
3591 ()phrasePushValue("time", 15);
3592 ()phraseEndSystemMsg(0, "say", "PHRASE_WITH_3_PARAMETERS");
3597 void phrasePushValue_sf_(CStateInstance
* entity
, CScriptStack
& stack
)
3599 float f
= (float)stack
.top();stack
.pop(); // get the value as float
3600 std::string typeStr
= (std::string
)stack
.top(); stack
.pop(); // get the param type
3601 // create the good STRING_MANAGER::TParam in fonction of its type and is value
3602 STRING_MANAGER::TParamType type
= STRING_MANAGER::stringToParamType(typeStr
);
3603 STRING_MANAGER::TParam param
;
3608 case STRING_MANAGER::money
:
3610 param
.Money
= static_cast<uint64
>(f
);
3615 case STRING_MANAGER::integer
:
3617 param
.Int
= static_cast<sint32
>(f
);
3621 case STRING_MANAGER::time
:
3623 param
.Time
= static_cast<uint32
>(f
);
3627 case STRING_MANAGER::skill
:
3628 case STRING_MANAGER::faction
:
3629 case STRING_MANAGER::power_type
:
3630 case STRING_MANAGER::race
:
3631 case STRING_MANAGER::damage_type
:
3632 case STRING_MANAGER::characteristic
:
3633 case STRING_MANAGER::score
:
3634 case STRING_MANAGER::body_part
:
3636 param
.Enum
= static_cast<uint32
>( f
);
3641 param
.Type
= STRING_MANAGER::invalid_value
;
3646 PhraseParameters
.Values
.push_back(param
);
3650 //----------------------------------------------------------------------------
3653 @subsection phrasePushString_ss_
3654 This function push a value as string on the parameter stack. This stack is used by phraseEndSystemMsg_fss_, phraseEndNpcMsg_fss_, phraseEndSystemMsg_fss_ functions.
3656 @see phrasePushValue_sf_
3657 @see phraseEndSystemMsg_fss_
3658 @see phraseEndNpcMsg_fss_
3659 @see phraseEndSystemMsg_fss_
3662 The value *Must* be a string.
3663 The string is internal converted to number, sheetId, entityId when needed.
3670 Input as string literal
3673 Input as an entityId (obtains via getCurrentPlayerAggroListTarget_f_s, getRandomPlayerAggroListTarget_f_s, getBotEid_f_s, getCurrentSpeakerEid__s, getAggroListElement_ff_s)
3678 Input as sheetId name (example: "toto.sbrick", "toto.sitem", "toto.creature")
3686 Input as string identifier
3692 Input as stringId (number): *WARNING* LD must as coder to do function that return string_id if they want to use that type
3697 Input must be a enum value:
3698 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).
3708 Arguments: s(paramType), f(value) ->
3709 @param[in] paramType the type of the parameter
3710 @param[in] value the value of the parameter
3714 ($playerEid)getCurrentPlayerEid();
3715 ($botEid)group3.getBotEid(4);
3717 ()phrasePushValue("integer", 15);
3718 ()phrasePushString("integer", "15");
3719 ()phrasePushString("literal", "Test 123");
3720 ()phrasePushString("player", $playerEid);
3721 ()phrasePushString("bot", $botEid);
3722 ()phrasePushString("item", "abc.sitem");
3723 ()phrasePushString("sbrick", "toto.sbrick");
3724 ()phrasePushString("creature_model", "toto.creature");
3725 ()phraseEndSystemMsg(0, "say", "PHRASE_WITH_SOME_PARAMETERS");
3728 void phrasePushString_ss_(CStateInstance
* entity
, CScriptStack
& stack
)
3730 std::string s
= (std::string
)stack
.top(); stack
.pop(); // get the param value
3731 std::string typeStr
= (std::string
)stack
.top(); stack
.pop(); // get the param type
3733 // construct a STRING_MANAGER::TParam in fonction of its type and its value
3734 STRING_MANAGER::TParamType type
= STRING_MANAGER::stringToParamType(typeStr
);
3735 STRING_MANAGER::TParam param
;
3740 case STRING_MANAGER::money
:
3742 NLMISC::fromString(s
, param
.Money
);
3746 case STRING_MANAGER::player
:
3747 case STRING_MANAGER::bot
:
3748 case STRING_MANAGER::entity
:
3751 NLMISC::CEntityId id
;
3753 id
.fromString(s
.c_str());
3754 CAIEntityPhysical
* entityPhysical
=CAIS::instance().getEntityPhysical(TheDataset
.getDataSetRow(id
));
3757 switch( entityPhysical
->getRyzomType())
3759 case RYZOMID::creature
:
3763 CSpawnBot
* sb
= NLMISC::safe_cast
<CSpawnBot
*>(entityPhysical
);
3764 alias
= sb
->getPersistent().getAlias();
3769 // player or other have no alias
3772 param
.setEIdAIAlias( id
, alias
);
3776 case STRING_MANAGER::integer
:
3778 NLMISC::fromString(s
, param
.Int
);
3782 case STRING_MANAGER::time
:
3784 NLMISC::fromString(s
, param
.Time
);
3789 case STRING_MANAGER::item
:
3790 case STRING_MANAGER::outpost
:
3791 case STRING_MANAGER::creature_model
:
3792 case STRING_MANAGER::creature
:
3793 case STRING_MANAGER::sphrase
:
3794 case STRING_MANAGER::sbrick
:
3798 nlwarning("Sheet name expected but not found in script");
3799 param
.SheetId
= CSheetId();
3803 param
.SheetId
= CSheetId(s
);
3809 case STRING_MANAGER::place
:
3810 case STRING_MANAGER::event_faction
:
3811 case STRING_MANAGER::title
:
3812 case STRING_MANAGER::bot_name
:
3814 param
.Identifier
= s
;
3818 case STRING_MANAGER::skill
:
3819 case STRING_MANAGER::faction
:
3820 case STRING_MANAGER::power_type
:
3821 case STRING_MANAGER::race
:
3822 case STRING_MANAGER::damage_type
:
3823 case STRING_MANAGER::characteristic
:
3824 case STRING_MANAGER::score
:
3825 case STRING_MANAGER::body_part
:
3827 NLMISC::fromString(s
, param
.Enum
);
3831 case STRING_MANAGER::literal
:
3832 param
.Literal
.fromUtf8(s
);
3835 case STRING_MANAGER::dyn_string_id
:
3836 case STRING_MANAGER::string_id
:
3837 NLMISC::fromString(s
, param
.StringId
);
3840 case STRING_MANAGER::self
:
3841 case STRING_MANAGER::role
:
3842 case STRING_MANAGER::compass
:
3843 case STRING_MANAGER::guild
:
3844 case STRING_MANAGER::ecosystem
:
3845 case STRING_MANAGER::classification_type
:
3847 param
.Type
= STRING_MANAGER::invalid_value
;
3852 PhraseParameters
.Values
.push_back(param
);
3857 static void phraseEnd(CStateInstance
* entity
, CScriptStack
& stack
, CPhraseParameters::TMode mode
)
3859 std::string funName
= "phraseEnd";
3861 // get Function parameters
3863 std::string phraseId
= (std::string
)stack
.top();stack
.pop();
3864 std::string sayMode
;
3865 if (mode
!= CPhraseParameters::EmoteMsg
)
3867 sayMode
= (std::string
)stack
.top();stack
.pop();
3869 sint32 botIndex
= (sint32
)((float)stack
.top());stack
.pop();
3872 // Verify is bot is alived
3875 CGroup
* group
= entity
->getGroup();
3878 nlwarning("%s on a non Npc Group, doesn't work", funName
.c_str());
3879 PhraseParameters
.Values
.clear();
3882 if (!group
->isSpawned() || group
->bots().isEmpty() || botIndex
< 0 || group
->bots().size() < static_cast<uint32
>(botIndex
))
3884 PhraseParameters
.Values
.clear();
3887 const CBot
*const bot
= group
->getBot(botIndex
);
3888 if ( !bot
|| !bot
->isSpawned())
3890 PhraseParameters
.Values
.clear();
3893 CSpawnBot
*const sp
= bot
->getSpawnObj();
3894 if ( !sp
|| !sp
->isAlive() )
3896 PhraseParameters
.Values
.clear();
3900 // parse type of chat
3901 CChatGroup::TGroupType groupType
;
3902 if (mode
!= CPhraseParameters::EmoteMsg
)
3904 groupType
= CChatGroup::stringToGroupType(sayMode
);
3907 // verify phraseId validity
3908 if (phraseId
.empty())
3910 nlwarning("%s %d: Phrase identifier is empty", funName
.c_str(),static_cast<uint32
>(mode
));
3914 // send chat to client
3917 case CPhraseParameters::NpcMsg
:
3918 npcChatParamToChannel(sp
->dataSetRow(), groupType
, phraseId
.c_str(), PhraseParameters
.Values
);
3920 case CPhraseParameters::SystemMsg
:
3921 STRING_MANAGER::sendSystemStringToClientAudience(sp
->dataSetRow(),std::vector
<NLMISC::CEntityId
>(), groupType
, phraseId
.c_str(), PhraseParameters
.Values
);
3924 case CPhraseParameters::EmoteMsg
:
3925 STRING_MANAGER::sendCustomEmoteTextToClientAudience(sp
->dataSetRow(),std::vector
<NLMISC::CEntityId
>(), phraseId
.c_str(), PhraseParameters
.Values
);
3929 PhraseParameters
.Values
.clear();
3932 //----------------------------------------------------------------------------
3935 @subsection phraseEndNpcMsg_fss_
3936 Send a message with parameter through a bot says.
3937 Parameters are taken from the parameters stack.
3938 @see phrasePushValue_sf_
3939 @see phrasePushString_ss_
3941 Arguments: s(botIndex), s(sayType), s(phraseIdentifier) ->
3942 @param[in] botIndex the Position of the bot in the group ( see getBotIndexByName_s_f)
3943 @param[in] sayType Is the type of the say dialog ("say", "shout", "civilization", "territory", "universe", "arround", "system", "region")
3944 @param[in] phraseIdentifier Is the identifier phrase as seen in phrase_wk.uxt
3947 ()phrasePushString("literal", "text non traduit");
3948 ()groupOf5Bot.phraseEndNpcMsg(4, "say", "PHRASE_TOTO");
3952 In this case in the phrase_wk.txt PHRASE_TOTO must be defined as
3954 PHRASE_TOTO(bot b, literal l)
3956 [I am $b$, on this text is not translated $l$ ]
3960 The first parameter is ALWAYS the bot that says the text (value is automaticaly set)
3962 void phraseEndNpcMsg_fss_(CStateInstance
* entity
, CScriptStack
& stack
)
3964 phraseEnd(entity
, stack
, CPhraseParameters::NpcMsg
);
3967 //----------------------------------------------------------------------------
3970 @subsection phraseEndSystemMsg_fss_
3971 Send a message with parameter through system braodcast msg.
3972 Parameters are taken from the parameters stack.
3973 @see phrasePushValue_sf_
3974 @see phrasePushString_ss_
3976 Arguments: s(botIndex), s(sayType), s(phraseIdentifier) ->
3977 @param[in] botIndex the Position of the bot in the group ( see getBotIndexByName_s_f)
3978 @param[in] sayType Is the type of the say dialog ("say", "shout", "civilization", "territory", "universe", "arround", "system", "region")
3979 @param[in] phraseIdentifier Is the identifier phrase as seen in phrase_wk.uxt
3982 ()phrasePushString("literal", "Test des levels designer");
3983 ()groupOf5Bot.phraseEndSystemMsg(4, "say", "PHRASE_TOTO");
3987 In this case in the phrase_wk.txt PHRASE_TOTO must be defined as
3989 PHRASE_TOTO(literal l)
3994 The first parameter is *NOT* automaticaly set to the bot that send the system msg as phraseEndNpcMsg_fss_.
3996 Because the msg can be send as "around". The broadcas msg must be send by a bot (that have a valid position)
3998 void phraseEndSystemMsg_fss_(CStateInstance
* entity
, CScriptStack
& stack
)
4000 phraseEnd(entity
, stack
, CPhraseParameters::SystemMsg
);
4004 //----------------------------------------------------------------------------
4007 @subsection phraseEndEmoteMsg_fs_
4008 Send a custom emote message with parameter through system braodcast msg.
4009 Parameters are taken from the parameters stack.
4010 @see phrasePushValue_sf_
4011 @see phrasePushString_ss_
4013 Arguments: s(botIndex), s(phraseIdentifier) ->
4014 @param[in] botIndex the Position of the bot in the group ( see getBotIndexByName_s_f)
4015 @param[in] phraseIdentifier Is the identifier phrase as seen in phrase_wk.uxt
4018 ($playerEid)getCurrentPlayerEid();
4019 ($botEid)getCurrentSpeakerEid();
4021 ()phrasePushString("player", $playerEid);
4022 ()groupOf5Bot.phraseEndEmoteMsg(,"PHRASE_TOTO1");
4024 ()phrasePushString("bot", $botEid);
4025 ()groupOf5Bot.phraseEndEmoteMsg(,"PHRASE_TOTO2");
4029 In this case in the phrase_wk.txt PHRASE_TOTO must be defined as
4031 PHRASE_TOTO1(player p)
4040 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.
4042 The emote msg must be send by a bot (that have a valid position).
4044 void phraseEndEmoteMsg_fs_(CStateInstance
* entity
, CScriptStack
& stack
)
4046 phraseEnd(entity
, stack
, CPhraseParameters::EmoteMsg
);
4050 //----------------------------------------------------------------------------
4053 @subsection queryEgs_sscfs_
4054 Send a query msg to egs to know infos on a player.
4055 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
4057 Possible info to know are
4073 Arguments: s(botIndex), s(query), c(groupThatWillBeTriggered), f(idOfTheUserEvent), s(msgId)
4074 @param[in] botIndex the Position of the bot in the group ( see getBotIndexByName_s_f)
4075 @param[in] query The query we want to send
4076 @param[in] groupThatWillBeTriggered The group that will receive a user_event when the answer will come
4077 @param[in] idOfTheUserEvent The number of the user event that will be triggered
4078 @param[in] msgId The id of the msg
4080 Answer will be given by the getParam
4084 (@groupToNotify)boss_group.context();
4085 ()queryEgs("Name", $playerEid, @groupToNotify, 4, "MSG_NAME");
4086 ()queryEgs("Hp", $playerEid, @groupToNotify, 4, "msg1");
4087 ()queryEgs("MaxHp", $playerEid, @groupToNotify, 4, "msg2");
4088 ()queryEgs("RatioHp", $playerEid, @groupToNotify, 4, "msg3");
4089 ()queryEgs("Sap", $playerEid, @groupToNotify, 4, "msg4");
4090 ()queryEgs("MaxSap", $playerEid, @groupToNotify, 4, "msg5");
4091 ()queryEgs("RatioSap", $playerEid, @groupToNotify, 4, "msg6");
4092 ()queryEgs("Focus", $playerEid, @groupToNotify, 4, "msg7");
4093 ()queryEgs("MaxFocus", $playerEid, @groupToNotify, 4, "msg8");
4094 ()queryEgs("RatioFocus", $playerEid, @groupToNotify, 4, "msg9");
4095 ()queryEgs("Stamina", $playerEid, @groupToNotify, 4, "msg10");
4096 ()queryEgs("MaxStamina", $playerEid, @groupToNotify, 4, "msg11");
4097 ()queryEgs("RatioStamina", $playerEid, @groupToNotify, 4, "msg12");
4098 ()queryEgs("BestSkillLevel", $playerEid, @groupToNotify, 4, "msg13");
4102 // the user_event 4 of groupToNotify will be trigered
4103 ($msgName)getEventParam(0); // the msg name
4104 ($ret)getEventParam(1); // the return
4105 ($funName)getEventParam(2); // the name of the function
4106 ($playerEid)getEventParam(3); // the id of the player
4107 ($param1)getEventParam(4); // empty ot item, or sbrick or botEid
4109 if ($msgName == "MSG_NAME") {
4110 ()phrasePushString("literal", $ret);
4111 ()phrasePushString("player", $playerEid);
4112 ()boss_group.phraseEndNpcMsg(0, "say", "TEST_BOSS_TEST_MSG");
4116 ()phrasePushString("player", $playerEid);
4117 ()phrasePushString("literal", $funName);
4118 ()phrasePushString("literal", $msgName);
4119 ()phrasePushString("integer", $ret);
4120 ()boss_group.phraseEndNpcMsg(0, "say", "TEST_BOSS_TEST_EGS_QUERY");
4126 void queryEgs_sscfs_(CStateInstance
* entity
, CScriptStack
& stack
)
4128 std::string funName
= "queryEgs_sscfs_";
4129 // read input params
4130 string literal
= (string
)stack
.top(); stack
.pop();
4131 float useEventId
= (float)stack
.top(); stack
.pop();
4132 CGroupNpc
* const groupToNotify
= dynamic_cast<CGroupNpc
*>( (IScriptContext
*)stack
.top() ); stack
.pop();
4133 string param1
= (string
)stack
.top(); stack
.pop();
4134 string func
= (string
)stack
.top(); stack
.pop();
4136 // create a CUserEventMsg to send to EGS
4137 CGroup
* const group
= entity
? entity
->getGroup() : 0;
4138 IManagerParent
* const managerParent
= (group
&& group
->getOwner()) ? group
->getOwner()->getOwner():0;
4139 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
4140 if (aiInstance
== NULL
)
4142 nlwarning("%s failed: the AI instance of the entity is NULL", funName
.c_str());
4147 msg
.InstanceId
= aiInstance
->getInstanceNumber();
4148 msg
.GroupAlias
= groupToNotify
->getAlias();
4149 msg
.EventId
= (int)useEventId
;
4150 msg
.Params
.push_back(literal
);
4151 msg
.Params
.push_back(func
);
4152 msg
.Params
.push_back(param1
);
4158 @subsection queryEgs_ssscfs_
4159 Send a query msg to egs to know infos on a player.
4160 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
4162 Possible info to know are:
4163 - KnowBrick (to knwo if the player know a specific brick); return value is 0 or 1 (if the player know the brick)
4164 - IsInInventory (to knwo has an item in inventory of in equipement); return value is 0, 1(item in equipment), 2(item in bag)
4165 - Target (to know if a player target a bot; return value is 0, 1(player target the bot)
4167 Arguments: s(botIndex), s(query), s(queryParam), c(groupThatWillBeTriggered), f(idOfTheUserEvent), s(msgId)
4168 @param[in] botIndex the Position of the bot in the group ( see getBotIndexByName_s_f)
4169 @param[in] query The query we want to send
4170 @param[in] queryParam Is the paramter of the query (a .creature of IsInInventory, a .sbrick for KnowBrick, a Bot EntityId for Target
4171 @param[in] groupThatWillBeTriggered The group that will receive a user_event when the answer will come
4172 @param[in] idOfTheUserEvent The number of the user event that will be triggered
4173 @param[in] msgId The id of the msg
4175 Answer will be given by the getParam
4178 //($playerEid)getCurrentPlayerEid();
4179 (@groupToNotify)boss_group.context();
4180 ()queryEgs("KnowBrick", $playerEid, "bfma01.sbrick", @groupToNotify, 4, "MSG_BRICK");
4181 ()queryEgs("IsInInventory", $playerEid, "iccm1bm.sitem", @groupToNotify, 4, "MSG_ITEM");
4182 ()queryEgs("Target", $playerEid, $botEid, @groupToNotify, 4, "msg14");
4187 ($msgName)getEventParam(0); // the msg name
4188 ($ret)getEventParam(1); // the return
4189 ($funName)getEventParam(2); // the name of the function
4190 ($playerEid)getEventParam(3); // the id of the player
4191 ($param1)getEventParam(4); // empty ot item, or sbrick or botEid
4193 if ($msgName == "MSG_ITEM")
4195 ()phrasePushString("item", $param1);
4196 ()phrasePushString("integer", $ret);
4197 ()boss_group.phraseEndNpcMsg(0, "say", "TEST_BOSS_TEST_EGS_QUERY_ITEM");
4198 } else if ($msgName == "MSG_BRICK") {
4199 ()phrasePushString("sbrick", $param1);
4200 ()phrasePushString("integer", $ret);
4201 ()boss_group.phraseEndNpcMsg(0, "say", "TEST_BOSS_TEST_EGS_QUERY_BRICK");
4203 } else if ($msgName == "MSG_NAME") {
4204 ()phrasePushString("literal", $ret);
4205 ()phrasePushString("player", $playerEid);
4206 ()boss_group.phraseEndNpcMsg(0, "say", "TEST_BOSS_TEST_MSG");
4210 ()phrasePushString("player", $playerEid);
4211 ()phrasePushString("literal", $funName);
4212 ()phrasePushString("literal", $msgName);
4213 ()phrasePushString("integer", $ret);
4214 ()boss_group.phraseEndNpcMsg(0, "say", "TEST_BOSS_TEST_EGS_QUERY");
4219 void queryEgs_ssscfs_(CStateInstance
* entity
, CScriptStack
& stack
)
4221 std::string funName
= "queryEgs_ssscfs_";
4223 string literal
= (string
)stack
.top(); stack
.pop();
4224 float useEventId
= (float)stack
.top(); stack
.pop();
4225 CGroupNpc
* const groupToNotify
= dynamic_cast<CGroupNpc
*>( (IScriptContext
*)stack
.top() ); stack
.pop();
4226 string param2
= (string
)stack
.top(); stack
.pop();
4227 string param1
= (string
)stack
.top(); stack
.pop();
4228 string func
= (string
)stack
.top(); stack
.pop();
4230 // create CQueryEgs to send to egs
4231 CGroup
* const group
= entity
? entity
->getGroup() : 0;
4232 IManagerParent
* const managerParent
= (group
&& group
->getOwner()) ? group
->getOwner()->getOwner():0;
4233 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
4234 if (aiInstance
== NULL
)
4236 nlwarning("%s failed: the AI instance of the entity is NULL", funName
.c_str());
4241 msg
.InstanceId
= aiInstance
->getInstanceNumber();
4242 msg
.GroupAlias
= groupToNotify
->getAlias();
4243 msg
.EventId
= (int)useEventId
;
4244 msg
.Params
.push_back(literal
);
4245 msg
.Params
.push_back(func
);
4246 msg
.Params
.push_back(param1
);
4247 msg
.Params
.push_back(param2
);
4255 @subsection summonPlayer_fs_
4257 Summon a player to a bot.
4259 Can be used by a boss to teleport a player. Or the create a teleporter.
4261 A player EntityId is used to identify the player.
4262 A index is used to identified the bot (index for the current group)
4265 Arguments: f(botIndex), s(playerEid) >
4266 @param[in] botIndex is the index of the bot in the current group(static group)
4267 @param[in] playerEid The entityId of the player
4270 ($playerId)getRandomPlayerAggroListTarget(0);
4271 ()teleportPlayer(0, $playerEid); // teleport player to the boss.
4274 void summonPlayer_fs_(CStateInstance
* entity
, CScriptStack
& stack
)
4277 std::string funName
= "summonPlayer_fffs_";
4278 std::string playerEidStr
= ((std::string
)stack
.top()); stack
.pop();
4279 sint32 botIndex
= (sint32
)((float)stack
.top()); stack
.pop();
4282 // Verify is bot is alived
4283 CGroup
* group
= entity
->getGroup();
4286 nlwarning("%s on a non Npc Group, doesn't work", funName
.c_str());
4289 if (!group
->isSpawned() || group
->bots().isEmpty() || botIndex
< 0 || group
->bots().size() < static_cast<uint32
>(botIndex
))
4293 const CBot
*const bot
= group
->getBot(botIndex
);
4294 if ( !bot
|| !bot
->isSpawned())
4298 CSpawnBot
*const sp
= bot
->getSpawnObj();
4299 if ( !sp
|| !sp
->isAlive() )
4305 // Read position for mirror
4306 TDataSetRow row
= sp
->dataSetRow();
4307 if (! TheDataset
.isAccessible( row
) )
4312 CMirrorPropValue
<sint32
> mirrorSymbolX( TheDataset
, row
, DSPropertyPOSX
);
4313 CMirrorPropValue
<sint32
> mirrorSymbolY( TheDataset
, row
, DSPropertyPOSY
);
4315 // retrieve the CBotPlayer
4316 NLMISC::CEntityId playerEid
;
4317 playerEid
.fromString(playerEidStr
.c_str());
4318 CAIEntityPhysical
*charEntity
=CAIS::instance().getEntityPhysical(TheDataset
.getDataSetRow(playerEid
));
4322 // do nothing if one of them is dead
4323 if (!charEntity
->isAlive() )
4329 // send teleport MSG
4330 TDataSetRow CharacterRowId
= charEntity
->dataSetRow();
4332 NLMISC::CEntityId player
= CMirrors::getEntityId(CharacterRowId
);
4334 if (player
!= NLMISC::CEntityId::Unknown
)
4336 sint32 x2
= mirrorSymbolX
.getValue();
4337 sint32 y2
= mirrorSymbolY
.getValue();
4339 float t
= 0; // TODO direction to mob?
4341 NLNET::CMessage
msgout( "TELEPORT_PLAYER" );
4342 nlWrite(msgout
, serial
, player
);
4343 msgout
.serial( const_cast<sint32
&>(x2
) );
4344 msgout
.serial( const_cast<sint32
&>(y2
) );
4345 msgout
.serial( const_cast<sint32
&>(z2
) );
4346 msgout
.serial( const_cast<float &>(t
) );
4347 sendMessageViaMirror( "EGS", msgout
);
4355 @subsection teleportPlayer_sffff_
4357 Teleport a player to a position
4359 A player EntityId is used to identify the player.
4360 The position is identified by the value x,y,z and the heading
4363 Arguments: s(playerId), f(x), f(y), f(z), f(heading) >
4364 @param[in] playerId is EntityId of the player
4365 @param[in] x,y,z,heading is the new position of the player
4368 ($playerId)getRandomPlayerAggroListTarget(0);
4369 ()teleportPlayer($playerEid, 1000, 1000, 100, 0);
4372 void teleportPlayer_sffff_(CStateInstance
* entity
, CScriptStack
& stack
)
4374 // get player and position parameters
4375 float t
= (float)stack
.top(); stack
.pop(); // heading
4376 float z
= (float)stack
.top(); stack
.pop();
4377 float y
= (float)stack
.top(); stack
.pop();
4378 float x
= (float)stack
.top(); stack
.pop();
4379 std::string playerEidStr
= (std::string
)stack
.top(); stack
.pop();
4380 NLMISC::CEntityId playerEid
;
4381 playerEid
.fromString(playerEidStr
.c_str());
4383 // retrieve the CBotPlayer
4384 CAIEntityPhysical
*charEntity
=CAIS::instance().getEntityPhysical(TheDataset
.getDataSetRow(playerEid
));
4388 // do nothing if one of them is dead
4389 if (!charEntity
->isAlive() )
4394 // teleport player to position
4395 if (playerEid
!= NLMISC::CEntityId::Unknown
)
4397 sint32 x2
= static_cast<sint32
>(x
*1000);
4398 sint32 y2
= static_cast<sint32
>(y
*1000);
4399 sint32 z2
= static_cast<sint32
>(z
*1000);
4401 NLNET::CMessage
msgout( "TELEPORT_PLAYER" );
4402 msgout
.serial( const_cast<CEntityId
&>(playerEid
) );
4403 msgout
.serial( const_cast<sint32
&>(x2
) );
4404 msgout
.serial( const_cast<sint32
&>(y2
) );
4405 msgout
.serial( const_cast<sint32
&>(z2
) );
4406 msgout
.serial( const_cast<float &>(t
) );
4407 sendMessageViaMirror( "EGS", msgout
);
4411 //----------------------------------------------------------------------------
4414 @subsection getBotEid_f_s
4415 Get the bot EntityId by its Index.
4416 Arguments: f(botIndex) -> s(botEid)
4418 @param[in] botIndex the Position of the bot in the group
4419 @param[out] botEid The entity Id given by the bot (or empty) if the indexed bot is not from the group
4422 (index)getBotIndexByName("bot_toto");
4423 ($botEid)getBotEid(index);
4426 ()phrasePushValue("entity", $botEid);
4427 ()phraseEndEmoteMsg(index, "PHRASE_YOUR_ARE_CLICKING_ON_ME");
4432 void getBotEid_f_s(CStateInstance
* entity
, CScriptStack
& stack
)
4434 std::string funName
= "getBotEid_f_s";
4435 // get spawn Bot by its index
4436 CGroup
* group
= entity
->getGroup();
4439 nlwarning("%s on a non Npc Group, doesn't work", funName
.c_str());
4440 stack
.push(std::string(CEntityId::Unknown
.toString()));
4443 sint32 botIndex
= (sint32
)((float)stack
.top());stack
.pop();
4444 if (!group
->isSpawned() || group
->bots().isEmpty() || botIndex
< 0 || group
->bots().size() < static_cast<uint32
>(botIndex
))
4446 stack
.push(std::string(CEntityId::Unknown
.toString()));
4450 const CBot
*const bot
= group
->getBot(botIndex
);
4451 if ( !bot
|| !bot
->isSpawned()) { stack
.push(std::string(CEntityId::Unknown
.toString())); return;}
4454 CSpawnBot
*const sb
= bot
->getSpawnObj();
4455 if ( !sb
||!sb
->isAlive()) {stack
.push(std::string(CEntityId::Unknown
.toString())); return;};
4457 // return the entity id of the spawn bot
4458 CEntityId id
= sb
->getEntityId();
4459 stack
.push(std::string(id
.toString()));
4463 //----------------------------------------------------------------------------
4466 @subsection getBotIndex_s_f
4467 Get the bot Index by its entityId.
4468 Entity Id of a bot can be given via getCurrentSpeackerEid().
4469 It can be useful to Known the index of the bot in the group with the EntityId.
4471 Arguments: s(botEid) -> f(botIndex),
4473 @param[in] botEid The entity Id given by the bot
4474 @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)
4477 ($botEid)getCurrentSpeakerEid();
4478 (index)getBotIndex($botEid);
4481 ()phrasePushValue("entity", $botEid);
4482 ()phraseEndNpcg(index, "PHRASE_YOUR_ARE_CLICKING_ON_ME");
4486 void getBotIndex_s_f(CStateInstance
* entity
, CScriptStack
& stack
)
4488 std::string funName
= "getBotEid_f_s";
4489 CGroup
* group
= entity
->getGroup();
4492 nlwarning("%s on a non Npc Group, doesn't work", funName
.c_str());
4493 stack
.push(std::string(CEntityId::Unknown
.toString()));
4496 std::string botEid
= (std::string
)stack
.top(); stack
.pop();
4498 // look in the group if the bot is alived
4499 uint32 botIndex
= 0, last
= group
->bots().size();
4500 for ( ;botIndex
!= last
; ++botIndex
)
4502 if (!group
->isSpawned() || group
->bots().isEmpty() || group
->bots().size() < static_cast<uint32
>(botIndex
))
4507 const CBot
*const bot
= group
->getBot(botIndex
);
4508 if ( !bot
|| !bot
->isSpawned()) { continue; }
4511 CSpawnBot
*const sb
= bot
->getSpawnObj();
4512 if ( !sb
||!sb
->isAlive()) {continue;};
4513 CEntityId id
= sb
->getEntityId();
4514 // if bot is alived return its index
4515 if (botEid
== id
.toString())
4517 stack
.push((float)botIndex
);
4522 stack
.push((float)-1);
4529 @subsection getCurrentPlayerEid__s
4530 Get the entity id of the player that is clicking on a bot.
4532 WARNING the function is only valid when called from an player_target_npc event.
4535 Arguments: -> s(playerEidAsString),
4536 @param[out] playerEidAsString is EntityId as string from the player.
4539 ($playerEid)getCurrentPlayerEid();
4540 (index)getBotIndexByName("toto");
4541 (distance)getPlayerDistance(index, $playerEid);
4542 phrasePushString("player", $playerEid);
4543 phrasePushValue("interger", distance);
4544 phraseEndNpcMsg(index, "say", "MSG_BOT_B_SAYS_THE_PLAYER_P_IS_AT_DISTANCE_D");\x13
4547 void getCurrentPlayerEid__s(CStateInstance
* entity
, CScriptStack
& stack
)
4549 std::string funName
= "getCurrentPlayerEid__s";
4550 CEntityId id
= CEntityId::Unknown
;
4551 // if we are in player_target_npc event TempPlayer is valid
4554 //TempPlayer is invalid so return Unkwn eid
4555 std::string s
= id
.toString();
4559 // TempPlayer is valid so return eid
4560 id
= TempPlayer
->getEntityId();
4561 std::string s
= id
.toString();
4569 @subsection getCurrentSpeakerEid__s
4570 Get the entity id of the bot at which the player as that is clicking at.
4572 WARNING the function is only valid when called from an player_target_npc event.
4575 Arguments: -> s(botEidAsString),
4576 @param[out] botEidAsString is EntityId as string from the bot.
4579 ($botEid)getCurrentSpeakerEid();
4580 ($playerEid)getCurrentSpeakerEid();
4582 phrasePushString("player", $playerEid);
4583 phrasePushValue("bot", $botEid);
4584 phraseEndEmotMsg(index, "EMOT_PLAYER_INSULT_BOT");
4587 void getCurrentSpeakerEid__s(CStateInstance
* entity
, CScriptStack
& stack
)
4589 std::string funName
= "getCurrentSpeakerEid__s";
4590 CEntityId id
= CEntityId::Unknown
;
4591 // if we are in player_target_npc event TempSpeaker is valid
4594 //TempSpeaker is invalid so return Unkwn eid
4595 std::string s
= id
.toString();
4599 //TempSpeaker is valid so return correct eid
4600 id
= TempSpeaker
->getEntityId();
4601 std::string s
= id
.toString();
4606 //----------------------------------------------------------------------------
4609 @subsection setSheet_s_
4610 Change the sheet of a creature
4612 Arguments: -> s(sheetName)
4615 ()setSheet('ccdeb2');
4620 void setSheet_s_(CStateInstance
* entity
, CScriptStack
& stack
)
4622 string sheetname
= stack
.top();
4625 CSheetId
sheetId(sheetname
+".creature");
4626 if (sheetId
==CSheetId::Unknown
)
4629 FOREACH(itBot
, CCont
<CBot
>, entity
->getGroup()->bots())
4634 AISHEETS::ICreatureCPtr
const sheet
= AISHEETS::CSheets::getInstance()->lookup(sheetId
);
4635 if (!sheet
.isNull())
4636 bot
->triggerSetSheet(sheet
);
4641 //----------------------------------------------------------------------------
4644 @subsection setClientSheet_s_
4645 Change the client sheet of a creature
4647 Arguments: -> s(sheetName)
4650 ()setClientSheet('ccdeb2');
4655 void setClientSheet_s_(CStateInstance
* entity
, CScriptStack
& stack
)
4657 string sheetname
= stack
.top();
4660 if (sheetname
.find(".creature") == string::npos
)
4661 sheetname
+= ".creature";
4663 FOREACH(itBot
, CCont
<CBot
>, entity
->getGroup()->bots())
4668 bot
->setClientSheet(sheetname
);
4673 /****************************************************************************/
4675 //----------------------------------------------------------------------------
4678 @subsection setHealer_f_
4679 Make the group healer (need test)
4681 Arguments: -> f(isHealer)
4689 void setHealer_f_(CStateInstance
* entity
, CScriptStack
& stack
)
4691 bool value
= ((float)stack
.top())!=0.f
;
4694 CGroup
* group
= entity
->getGroup();
4696 if (group
->isSpawned())
4698 FOREACH(itBot
, CCont
<CBot
>, group
->bots())
4703 bot
->setHealer(value
);
4704 // break; // :NOTE: Only set first bot as a healer
4710 /****************************************************************************/
4712 //----------------------------------------------------------------------------
4715 @subsection sitDown__
4716 Make the group sit Down
4727 void sitDown__(CStateInstance
* entity
, CScriptStack
& stack
)
4730 CGroup
* group
= entity
->getGroup();
4734 nlwarning("sitDown__ failed");
4738 CAILogicActionSitDownHelper::sitDown(group
);
4742 //----------------------------------------------------------------------------
4746 Make the group stand up (if was previously stand down)
4757 void standUp__(CStateInstance
* entity
, CScriptStack
& stack
)
4759 CGroup
* group
= entity
->getGroup();
4762 nlwarning("standUp__ failed");
4766 CAILogicActionSitDownHelper::standUp(group
);
4769 //----------------------------------------------------------------------------
4773 Use to implement setConditionRet
4778 ()setConditionRet(1);
4784 void setConditionSuccess_f_(CStateInstance
* entity
, CScriptStack
& stack
)
4786 bool conditionState
= (uint32
)((float)stack
.top()) != 0;
4787 CGroup
* group
= entity
->getGroup();
4790 nlwarning("setConditionSuccess_f_ failed");
4794 CAILogicDynamicIfHelper::setConditionSuccess(conditionState
);
4798 static float randomAngle()
4800 uint32
const maxLimit
= CAngle::PI
*2;
4801 float val
= (float)CAIS::rand32(maxLimit
);
4805 //----------------------------------------------------------------------------
4808 @subsection facing_f_
4810 The npc will face the given direction
4813 Arguments: f(direction)
4814 @param[in] direction is the new angle of the bot in radians
4823 void facing_f_(CStateInstance
* entity
, CScriptStack
& stack
)
4825 float const theta
= (float)stack
.top(); stack
.pop();
4826 CGroup
* group
= entity
->getGroup();
4828 bool bRandomAngle
= false;
4829 if (theta
> (NLMISC::Pi
* 2.0) || theta
< (-NLMISC::Pi
* 2.0))
4830 bRandomAngle
= true;
4832 if (group
->isSpawned())
4834 FOREACH(itBot
, CCont
<CBot
>, group
->bots())
4839 if (bot
->isSpawned())
4841 CSpawnBot
*spawnBot
= bot
->getSpawnObj();
4844 spawnBot
->setTheta(randomAngle());
4846 spawnBot
->setTheta(theta
);
4854 std::map
<std::string
, FScrptNativeFunc
> nfGetGroupNativeFunctions()
4856 std::map
<std::string
, FScrptNativeFunc
> functions
;
4858 #define REGISTER_NATIVE_FUNC(cont, func) cont.insert(std::make_pair(std::string(#func), &func))
4860 REGISTER_NATIVE_FUNC(functions
, spawn__
);
4861 REGISTER_NATIVE_FUNC(functions
, despawn_f_
);
4862 REGISTER_NATIVE_FUNC(functions
, isAlived__f
);
4863 REGISTER_NATIVE_FUNC(functions
, spawnBot_fsssffff_
);
4864 REGISTER_NATIVE_FUNC(functions
, newNpcChildGroupPos_ssfff_c
);
4865 REGISTER_NATIVE_FUNC(functions
, newNpcChildGroupPos_ssfff_
);
4866 REGISTER_NATIVE_FUNC(functions
, newNpcChildGroupPos_ssff_c
);
4867 REGISTER_NATIVE_FUNC(functions
, newNpcChildGroupPos_ssff_
);
4868 REGISTER_NATIVE_FUNC(functions
, newNpcChildGroupPosMl_ssffff_c
);
4869 REGISTER_NATIVE_FUNC(functions
, newNpcChildGroupPosMl_ssffff_
);
4870 REGISTER_NATIVE_FUNC(functions
, newNpcChildGroupPosMl_ssfff_c
);
4871 REGISTER_NATIVE_FUNC(functions
, newNpcChildGroupPosMl_ssfff_
);
4872 REGISTER_NATIVE_FUNC(functions
, newNpcChildGroup_sssf_c
);
4873 REGISTER_NATIVE_FUNC(functions
, newNpcChildGroup_sssf_
);
4874 REGISTER_NATIVE_FUNC(functions
, newNpcChildGroup_sss_c
);
4875 REGISTER_NATIVE_FUNC(functions
, newNpcChildGroup_sss_
);
4876 REGISTER_NATIVE_FUNC(functions
, newNpcChildGroupMl_sssff_c
);
4877 REGISTER_NATIVE_FUNC(functions
, newNpcChildGroupMl_sssff_
);
4878 REGISTER_NATIVE_FUNC(functions
, newNpcChildGroupMl_sssf_c
);
4879 REGISTER_NATIVE_FUNC(functions
, newNpcChildGroupMl_sssf_
);
4880 REGISTER_NATIVE_FUNC(functions
, spawnManager_s_
);
4881 REGISTER_NATIVE_FUNC(functions
, sitDown__
);
4882 REGISTER_NATIVE_FUNC(functions
, standUp__
);
4883 REGISTER_NATIVE_FUNC(functions
, despawnManager_s_
);
4884 REGISTER_NATIVE_FUNC(functions
, getMidPos__ff
);
4885 REGISTER_NATIVE_FUNC(functions
, getGroupTemplateWithFlags_sss_s
);
4886 REGISTER_NATIVE_FUNC(functions
, getGroupTemplateWithFlags_ss_s
);
4887 REGISTER_NATIVE_FUNC(functions
, getZoneWithFlags_ssss_s
);
4888 REGISTER_NATIVE_FUNC(functions
, getZoneWithFlags_sss_s
);
4889 REGISTER_NATIVE_FUNC(functions
, getNearestZoneWithFlags_ffsss_s
);
4890 REGISTER_NATIVE_FUNC(functions
, getNearestZoneWithFlags_ffss_s
);
4891 REGISTER_NATIVE_FUNC(functions
, getNearestZoneWithFlagsStrict_ffsss_s
);
4892 REGISTER_NATIVE_FUNC(functions
, getNearestZoneWithFlagsStrict_ffss_s
);
4893 REGISTER_NATIVE_FUNC(functions
, getNeighbourZoneWithFlags_ssss_s
);
4894 REGISTER_NATIVE_FUNC(functions
, getNeighbourZoneWithFlags_sss_s
);
4895 REGISTER_NATIVE_FUNC(functions
, setAggro_ff_
);
4896 REGISTER_NATIVE_FUNC(functions
, setCanAggro_f_
);
4897 REGISTER_NATIVE_FUNC(functions
, clearAggroList_f_
);
4898 REGISTER_NATIVE_FUNC(functions
, clearAggroList__
);
4899 REGISTER_NATIVE_FUNC(functions
, setMode_s_
);
4900 REGISTER_NATIVE_FUNC(functions
, setAutoSpawn_f_
);
4901 REGISTER_NATIVE_FUNC(functions
, setMaxHP_ff_
);
4902 REGISTER_NATIVE_FUNC(functions
, setHPLevel_f_
);
4903 REGISTER_NATIVE_FUNC(functions
, setHPScale_f_
);
4904 REGISTER_NATIVE_FUNC(functions
, scaleHP_f_
);
4905 REGISTER_NATIVE_FUNC(functions
, setBotHPScaleByAlias_fs_
);
4906 REGISTER_NATIVE_FUNC(functions
, downScaleHP_f_
);
4907 REGISTER_NATIVE_FUNC(functions
, upScaleHP_f_
);
4908 REGISTER_NATIVE_FUNC(functions
, addHP_f_
);
4909 REGISTER_NATIVE_FUNC(functions
, giveHP_f_
);
4910 REGISTER_NATIVE_FUNC(functions
, aiAction_s_
);
4911 REGISTER_NATIVE_FUNC(functions
, aiActionSelf_s_
);
4912 REGISTER_NATIVE_FUNC(functions
, addProfileParameter_s_
);
4913 REGISTER_NATIVE_FUNC(functions
, addProfileParameter_ss_
);
4914 REGISTER_NATIVE_FUNC(functions
, addProfileParameter_sf_
);
4915 REGISTER_NATIVE_FUNC(functions
, removeProfileParameter_s_
);
4916 REGISTER_NATIVE_FUNC(functions
, addPersistentProfileParameter_s_
);
4917 REGISTER_NATIVE_FUNC(functions
, addPersistentProfileParameter_ss_
);
4918 REGISTER_NATIVE_FUNC(functions
, addPersistentProfileParameter_sf_
);
4919 REGISTER_NATIVE_FUNC(functions
, removePersistentProfileParameter_s_
);
4920 REGISTER_NATIVE_FUNC(functions
, getOutpostStateName__s
);
4921 REGISTER_NATIVE_FUNC(functions
, isOutpostTribeOwner__f
);
4922 REGISTER_NATIVE_FUNC(functions
, isOutpostGuildOwner__f
);
4923 REGISTER_NATIVE_FUNC(functions
, getEventParam_f_f
);
4924 REGISTER_NATIVE_FUNC(functions
, getEventParam_f_s
);
4925 REGISTER_NATIVE_FUNC(functions
, setSheet_s_
);
4926 REGISTER_NATIVE_FUNC(functions
, setClientSheet_s_
);
4927 REGISTER_NATIVE_FUNC(functions
, setHealer_f_
);
4928 REGISTER_NATIVE_FUNC(functions
, setConditionSuccess_f_
);
4929 REGISTER_NATIVE_FUNC(functions
, facing_f_
);
4930 REGISTER_NATIVE_FUNC(functions
, setUrl_ss_
);
4932 // Boss functions (custom text)
4933 REGISTER_NATIVE_FUNC(functions
, phraseBegin__
);
4934 REGISTER_NATIVE_FUNC(functions
, phrasePushValue_sf_
);
4935 REGISTER_NATIVE_FUNC(functions
, phrasePushString_ss_
);
4936 REGISTER_NATIVE_FUNC(functions
, phraseEndNpcMsg_fss_
);
4937 REGISTER_NATIVE_FUNC(functions
, phraseEndSystemMsg_fss_
);
4938 REGISTER_NATIVE_FUNC(functions
, phraseEndEmoteMsg_fs_
);
4940 // Boss functions (Bot infos)
4941 REGISTER_NATIVE_FUNC(functions
, getBotIndex_s_f
);
4942 REGISTER_NATIVE_FUNC(functions
, getBotEid_f_s
);
4943 REGISTER_NATIVE_FUNC(functions
, getCurrentSpeakerEid__s
);
4944 REGISTER_NATIVE_FUNC(functions
, getBotIndexByName_s_f
);
4945 REGISTER_NATIVE_FUNC(functions
, isGroupAlived__f
);
4946 REGISTER_NATIVE_FUNC(functions
, isBotAlived_f_f
);
4948 // Boss functions (Player infos)
4949 REGISTER_NATIVE_FUNC(functions
, isPlayerAlived_s_f
);
4950 REGISTER_NATIVE_FUNC(functions
, getPlayerStat_ss_f
);
4951 REGISTER_NATIVE_FUNC(functions
, getPlayerPosition_s_ff
);
4952 REGISTER_NATIVE_FUNC(functions
, getPlayerDistance_fs_f
);
4953 REGISTER_NATIVE_FUNC(functions
, getCurrentPlayerEid__s
);
4954 REGISTER_NATIVE_FUNC(functions
, queryEgs_sscfs_
);
4955 REGISTER_NATIVE_FUNC(functions
, queryEgs_ssscfs_
);
4957 // Boss functions (Aggro list)
4958 REGISTER_NATIVE_FUNC(functions
, getCurrentPlayerAggroListTarget_f_s
);
4959 REGISTER_NATIVE_FUNC(functions
, getRandomPlayerAggroListTarget_f_s
);
4960 REGISTER_NATIVE_FUNC(functions
, getAggroListElement_ff_s
);
4961 REGISTER_NATIVE_FUNC(functions
, getAggroListSize_f_f
);
4962 REGISTER_NATIVE_FUNC(functions
, setAggroListTarget_fs_
);
4963 REGISTER_NATIVE_FUNC(functions
, setGroupAggroListTarget_s_
);
4964 REGISTER_NATIVE_FUNC(functions
, setManagerAggroListTarget_ss_
);
4966 // Boss functions (Time infos)
4967 REGISTER_NATIVE_FUNC(functions
, getServerTimeStr__s
);
4968 REGISTER_NATIVE_FUNC(functions
, getServerTime__s
);
4969 REGISTER_NATIVE_FUNC(functions
, getRyzomDateStr__s
);
4970 REGISTER_NATIVE_FUNC(functions
, getRyzomDate__s
);
4972 // Boss function (teleport actions)
4973 REGISTER_NATIVE_FUNC(functions
, teleportPlayer_sffff_
);
4974 REGISTER_NATIVE_FUNC(functions
, summonPlayer_fs_
);
4977 #undef REGISTER_NATIVE_FUNC