spawnBots accept now name and vpx, addedspawnGroup_ffsssffff_c
[ryzomcore.git] / ryzom / server / src / ai_service / nf_grp.cpp
blob333c45107bbf1038e164193ec4985557792c9671
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "stdpch.h"
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"
32 #include "ai_aggro.h"
33 #include "game_share/send_chat.h"
34 #include "game_share/string_manager_sender.h"
35 #include <time.h>
38 using std::string;
39 using std::vector;
40 using namespace NLMISC;
41 using namespace AIVM;
42 using namespace AICOMP;
43 using namespace AITYPES;
44 using namespace RYAI_MAP_CRUNCH;
47 //----------------------------------------------------------------------------
48 /** @page code
50 @subsection spawn__
51 Spawns the current group.
53 Arguments: ->
56 // CGroup
57 void spawn__(CStateInstance* entity, CScriptStack& stack)
59 if (!entity)
61 nlwarning("spawnInstance failed");
62 return;
64 CGroup const* const grp = entity->getGroup();
65 if (grp)
67 if (grp->isSpawned())
68 grp->getSpawnObj()->spawnBots(grp->botName, grp->botVpx);
72 //----------------------------------------------------------------------------
73 /** @page code
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)
81 @code
82 ()despawn(0); // despawn
83 ()despawn(1); // despawn immediatement
84 @endcode
87 // CGroup
88 void despawn_f_(CStateInstance* entity, CScriptStack& stack)
90 float const immediatly = stack.top();
91 stack.pop();
93 if (!entity)
95 nlwarning("despawnInstance failed");
96 return;
99 CGroup* const grp = entity->getGroup();
100 if (!grp)
102 nlwarning("despawn : entity '%s'%s is not a group ? ",
103 entity->aliasTreeOwner()->getAliasFullName().c_str(),
104 entity->aliasTreeOwner()->getAliasString().c_str());
105 return;
107 grp->despawnBots(immediatly!=0);
110 //----------------------------------------------------------------------------
111 /** @page code
113 @subsection spawnBot_fsssfffff_
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), f(cell) ->
118 @code
120 @endcode
123 // CGroup
124 void spawnBot_fsssffff_(CStateInstance* entity, CScriptStack& stack)
126 double dispersionRadius = (double)(float)stack.top();
127 stack.pop();
128 double orientation = (double)(float)stack.top();
129 stack.pop();
130 double y = (double)(float)stack.top();
131 stack.pop();
132 double x = (double)(float)stack.top();
133 stack.pop();
134 string look = (string)stack.top();
135 stack.pop();
136 string name = (string)stack.top();
138 stack.pop();
139 CSheetId sheetId((string)stack.top());
140 stack.pop();
141 uint nbBots = (uint)(float)stack.top();
142 stack.pop();
144 IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
145 CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
146 if (!aiInstance)
147 return;
149 CGroupNpc* grp = dynamic_cast<CGroupNpc*>(entity->getGroup());
150 if (grp)
151 aiInstance->eventCreateNpcBot(grp, nbBots, true, sheetId, CAIVector(x, y), name, orientation, dispersionRadius, look, grp->botName, grp->botVpx);
152 return;
155 //----------------------------------------------------------------------------
156 /** @page code
158 @subsection isAlived__f
159 Test if the group is alived
161 Arguments: -> f(Immediatly)
162 @return 1 if group is spawned
164 @code
165 (alive)isAlived();
166 @endcode
169 // CGroup
170 void isAlived__f(CStateInstance* entity, CScriptStack& stack)
173 if (!entity)
175 stack.push(0.0f);
176 return;
179 CGroup* const grp = entity->getGroup();
180 if (!grp)
182 nlwarning("isAlived__f : entity '%s'%s is not a group ? ",
183 entity->aliasTreeOwner()->getAliasFullName().c_str(),
184 entity->aliasTreeOwner()->getAliasString().c_str());
185 stack.push(0.0f);
186 return;
189 if (!grp->isSpawned())
191 stack.push(0.0f);
192 return;
196 for (uint i=0; i<grp->bots().size(); ++i)
198 const CBot *const bot = grp->getBot(i);
199 if ( !bot
200 || !bot->isSpawned())
201 continue;
204 CAIEntityPhysical *const ep=bot->getSpawnObj();
205 if (ep->isAlive())
207 stack.push(1.0f);
208 return;
212 stack.push(0.0f);
213 return;
216 //----------------------------------------------------------------------------
217 /** @page code
219 @subsection newNpcChildGroupPos_ssfff_c
220 Used to create a dynamic npc group (a parent/children relation is defined).
222 Arguments: s(GroupTemplate), s(StateMachine), f(x), f(y), f(Dispersion) -> c(Group)
223 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
224 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
225 @param[in] x position of the spawned group on x axis
226 @param[in] y position of the spawned group on y axis
227 @param[in] Dispersion is the dispersion radius in meters when spawning a group
228 @param[out] Group is the newly created group
230 @code
231 (@grp)newNpcChildGroupPos("class_forager", "state_machine_1", x, y, 30);
232 @endcode
235 // CGroup not in a family behaviour
236 void newNpcChildGroupPos_ssfff_c(CStateInstance* entity, CScriptStack& stack)
238 double dispersionRadius = (double)(float)stack.top();
239 stack.pop();
240 float const y = stack.top();
241 stack.pop();
242 float const x = stack.top();
243 stack.pop();
245 IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
246 CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
247 if (!aiInstance)
248 return;
250 if (dispersionRadius<0.)
251 dispersionRadius = 0.;
252 stack.push(spawnNewGroup(entity, stack, aiInstance, CAIVector(x, y), -1, dispersionRadius));
255 //----------------------------------------------------------------------------
256 /** @page code
258 @subsection newNpcChildGroupPos_ssfff_
259 Used to create a dynamic npc group (a parent/children relation is defined).
261 Arguments: s(GroupTemplate), s(StateMachine), f(x), f(y), f(Dispersion) ->
262 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
263 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
264 @param[in] x position of the spawned group on x axis
265 @param[in] y position of the spawned group on y axis
266 @param[in] Dispersion is the dispersion radius in meters when spawning a group
268 @code
269 ()newNpcChildGroupPos("class_forager", "state_machine_1", x, y, 30);
270 @endcode
273 // CGroup not in a family behaviour
274 void newNpcChildGroupPos_ssfff_(CStateInstance* entity, CScriptStack& stack)
276 double dispersionRadius = (double)(float)stack.top();
277 stack.pop();
278 float const y = stack.top();
279 stack.pop();
280 float const x = stack.top();
281 stack.pop();
283 IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
284 CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
285 if (!aiInstance)
286 return;
288 if (dispersionRadius<0.)
289 dispersionRadius = 0.;
290 spawnNewGroup(entity, stack, aiInstance, CAIVector(x, y), -1, dispersionRadius);
293 //----------------------------------------------------------------------------
294 /** @page code
296 @subsection newNpcChildGroupPos_ssff_c
297 Used to create a dynamic npc group (a parent/children relation is defined).
299 Arguments: s(GroupTemplate), s(StateMachine), f(x), f(y) -> c(Group)
300 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
301 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
302 @param[in] x position of the spawned group on x axis
303 @param[in] y position of the spawned group on y axis
304 @param[out] Group is the newly created group
306 @code
307 (@grp)newNpcChildGroupPos("class_forager", "state_machine_1", x, y);
308 @endcode
311 // CGroup not in a family behaviour
312 void newNpcChildGroupPos_ssff_c(CStateInstance* entity, CScriptStack& stack)
314 stack.push((float)-1.0f);
315 newNpcChildGroupPos_ssfff_c(entity, stack);
318 //----------------------------------------------------------------------------
319 /** @page code
321 @subsection newNpcChildGroupPos_ssff_
322 Used to create a dynamic npc group (a parent/children relation is defined).
324 Arguments: s(GroupTemplate), s(StateMachine), f(x), f(y) ->
325 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
326 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
327 @param[in] x position of the spawned group on x axis
328 @param[in] y position of the spawned group on y axis
330 @code
331 ()newNpcChildGroupPos("class_forager", "state_machine_1", x, y);
332 @endcode
335 // CGroup not in a family behaviour
336 void newNpcChildGroupPos_ssff_(CStateInstance* entity, CScriptStack& stack)
338 stack.push((float)-1.0f);
339 newNpcChildGroupPos_ssfff_(entity, stack);
342 //----------------------------------------------------------------------------
343 /** @page code
345 @subsection newNpcChildGroupPosMl_ssffff_c
346 Used to create a multilevel dynamic npc group (a parent/children relation is defined).
348 Arguments: s(GroupTemplate), s(StateMachine), f(x), f(y), f(BaseLevel), f(Dispersion) -> c(Group)
349 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
350 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
351 @param[in] x position of the spawned group on x axis
352 @param[in] y position of the spawned group on y axis
353 @param[in] BaseLevel is the base level of the spawned group
354 @param[in] Dispersion is the dispersion radius in meters when spawning a group
355 @param[out] Group is the newly created group
357 @code
358 (@grp)newNpcChildGroupPosMl("class_forager", "state_machine_1", x, y, 13, 7.5);
359 @endcode
362 // CGroup not in a family behaviour
363 void newNpcChildGroupPosMl_ssffff_c(CStateInstance* entity, CScriptStack& stack)
365 double dispersionRadius = (double)(float)stack.top();
366 stack.pop();
367 float const y = stack.top();
368 stack.pop();
369 float const x = stack.top();
370 stack.pop();
372 IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
373 CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
374 if (!aiInstance)
375 return;
377 if (dispersionRadius<0.)
378 dispersionRadius = 0.;
379 stack.push(spawnNewGroup(entity, stack, aiInstance, CAIVector(x,y), -1, dispersionRadius));
382 //----------------------------------------------------------------------------
383 /** @page code
385 @subsection newNpcChildGroupPosMl_ssffff_
386 Used to create a multilevel dynamic npc group (a parent/children relation is defined).
388 Arguments: s(GroupTemplate), s(StateMachine), f(x), f(y), f(BaseLevel), f(Dispersion) ->
389 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
390 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
391 @param[in] x position of the spawned group on x axis
392 @param[in] y position of the spawned group on y axis
393 @param[in] BaseLevel is the base level of the spawned group
394 @param[in] Dispersion is the dispersion radius in meters when spawning a group
396 @code
397 ()newNpcChildGroupPosMl("class_forager", "state_machine_1", x, y, 13, 7.5);
398 @endcode
401 // CGroup not in a family behaviour
402 void newNpcChildGroupPosMl_ssffff_(CStateInstance* entity, CScriptStack& stack)
404 double dispersionRadius = (double)(float)stack.top();
405 stack.pop();
406 float const y = stack.top();
407 stack.pop();
408 float const x = stack.top();
409 stack.pop();
411 IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
412 CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
413 if (!aiInstance)
414 return;
416 if (dispersionRadius<0.)
417 dispersionRadius = 0.;
418 spawnNewGroup(entity, stack, aiInstance, CAIVector(x,y), -1, dispersionRadius);
421 //----------------------------------------------------------------------------
422 /** @page code
424 @subsection newNpcChildGroupPosMl_ssfff_c
425 Used to create a multilevel dynamic npc group (a parent/children relation is defined).
427 Arguments: s(GroupTemplate), s(StateMachine), f(x), f(y), f(BaseLevel) -> c(Group)
428 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
429 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
430 @param[in] x position of the spawned group on x axis
431 @param[in] y position of the spawned group on y axis
432 @param[in] BaseLevel is the base level of the spawned group
433 @param[out] Group is the newly created group
435 @code
436 (@grp)newNpcChildGroupPosMl("class_forager", "state_machine_1", x, y, 13);
437 @endcode
440 // CGroup not in a family behaviour
441 void newNpcChildGroupPosMl_ssfff_c(CStateInstance* entity, CScriptStack& stack)
443 stack.push((float)-1.0f);
444 newNpcChildGroupPosMl_ssffff_c(entity, stack);
447 //----------------------------------------------------------------------------
448 /** @page code
450 @subsection newNpcChildGroupPosMl_ssfff_
451 Used to create a multilevel dynamic npc group (a parent/children relation is defined).
453 Arguments: s(GroupTemplate), s(StateMachine), f(x), f(y), f(BaseLevel) ->
454 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
455 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
456 @param[in] x position of the spawned group on x axis
457 @param[in] y position of the spawned group on y axis
458 @param[in] BaseLevel is the base level of the spawned group
460 @code
461 ()newNpcChildGroupPosMl("class_forager", "state_machine_1", x, y, 13);
462 @endcode
465 // CGroup not in a family behaviour
466 void newNpcChildGroupPosMl_ssfff_(CStateInstance* entity, CScriptStack& stack)
468 stack.push((float)-1.0f);
469 newNpcChildGroupPosMl_ssffff_(entity, stack);
472 //----------------------------------------------------------------------------
473 /** @page code
475 @subsection getMidPos__ff
476 Returns the position (x, y) of the current group.
478 Arguments: -> f(x), f(y)
479 @param[out] x position of the group on x axis
480 @param[out] y position of the group on y axis
482 @code
483 (x, y)getMidPos();
484 @endcode
487 // CGroup
488 void getMidPos__ff(CStateInstance* entity, CScriptStack& stack)
490 CGroup* const group = entity->getGroup();
492 CAIVector vect;
493 if (group->isSpawned())
495 if (!group->getSpawnObj()->calcCenterPos(vect))
496 group->getSpawnObj()->calcCenterPos(vect, true);
499 float x((float)vect.x().asDouble());
500 float y((float)vect.y().asDouble());
502 stack.push(y);
503 stack.push(x);
506 //----------------------------------------------------------------------------
507 /** @page code
509 @subsection newNpcChildGroup_sssf_c
510 Used to create dynamic npc group (a parent/children relation is defined).
512 Arguments: s(GroupTemplate), s(StateMachine), s(Zone), f(Dispersion) -> c(Group)
513 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
514 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
515 @param[in] Zone is returned by the getZoneWithFlags methods
516 @param[in] Dispersion is the dispersion radius in meters when spawning a group
517 @param[out] Group is the newly created group
519 @code
520 (@grp)newNpcChildGroup("class_forager", "state_machine_1", $zone, 10);
521 @endcode
524 // CGroup not in a family behaviour
525 void newNpcChildGroup_sssf_c(CStateInstance* entity, CScriptStack& stack)
527 double dispersionRadius = (double)(float)stack.top();
528 stack.pop();
529 TStringId const zoneName = CStringMapper::map(stack.top());
530 stack.pop();
532 IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
533 CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
534 if (!aiInstance)
535 return;
537 CNpcZone const* spawnZone = aiInstance->getZone(zoneName);
538 if (!spawnZone)
540 string StateMachine = stack.top();
541 stack.pop();
542 stack.pop();
543 nlwarning("newNpcChildGroup failed : spawnZone Not Found ! for StateMachine : %s", StateMachine.c_str());
544 return;
546 if (dispersionRadius<0.)
548 dispersionRadius = 0.;
549 CNpcZonePlace const* spawnZonePlace = dynamic_cast<CNpcZonePlace const*>(spawnZone);
550 if (spawnZonePlace!=NULL)
551 dispersionRadius = spawnZonePlace->getRadius();
553 stack.push(spawnNewGroup(entity, stack, aiInstance, spawnZone->midPos(), -1, dispersionRadius));
556 //----------------------------------------------------------------------------
557 /** @page code
559 @subsection newNpcChildGroup_sssf_
560 Used to create dynamic npc group (a parent/children relation is defined).
562 Arguments: s(GroupTemplate), s(StateMachine), s(Zone), f(Dispersion) ->
563 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
564 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
565 @param[in] Zone is returned by the getZoneWithFlags methods
566 @param[in] Dispersion is the dispersion radius in meters when spawning a group
568 @code
569 ()newNpcChildGroup("class_forager", "state_machine_1", $zone, 10);
570 @endcode
573 // CGroup not in a family behaviour
574 void newNpcChildGroup_sssf_(CStateInstance* entity, CScriptStack& stack)
576 double dispersionRadius = (double)(float)stack.top();
577 stack.pop();
578 TStringId const zoneName = CStringMapper::map(stack.top());
579 stack.pop();
581 IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
582 CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
583 if (!aiInstance)
584 return;
586 CNpcZone const* spawnZone = aiInstance->getZone(zoneName);
587 if (!spawnZone)
589 string StateMachine = stack.top();
590 stack.pop();
591 stack.pop();
592 nlwarning("newNpcChildGroup failed : spawnZone Not Found ! for StateMachine : %s", StateMachine.c_str());
593 return;
595 if (dispersionRadius<0.)
597 dispersionRadius = 0.;
598 CNpcZonePlace const* spawnZonePlace = dynamic_cast<CNpcZonePlace const*>(spawnZone);
599 if (spawnZonePlace!=NULL)
600 dispersionRadius = spawnZonePlace->getRadius();
602 spawnNewGroup(entity, stack, aiInstance, spawnZone->midPos(), -1, dispersionRadius);
605 //----------------------------------------------------------------------------
606 /** @page code
608 @subsection newNpcChildGroup_sss_c
609 Used to create dynamic npc group (a parent/children relation is defined).
611 Arguments: s(GroupTemplate), s(StateMachine), s(Zone), f(Dispersion) -> c(Group)
612 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
613 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
614 @param[in] Zone is returned by the getZoneWithFlags methods
615 @param[out] Group is the newly created group
617 @code
618 (@grp)newNpcChildGroup("class_forager", "state_machine_1", $zone);
619 @endcode
622 // CGroup not in a family behaviour
623 void newNpcChildGroup_sss_c(CStateInstance* entity, CScriptStack& stack)
625 stack.push((float)-1.0f);
626 newNpcChildGroup_sssf_c(entity, stack);
629 //----------------------------------------------------------------------------
630 /** @page code
632 @subsection newNpcChildGroup_sss_
633 Used to create dynamic npc group (a parent/children relation is defined).
635 Arguments: s(GroupTemplate), s(StateMachine), s(Zone), f(Dispersion) ->
636 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
637 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
638 @param[in] Zone is returned by the getZoneWithFlags methods
640 @code
641 ()newNpcChildGroup("class_forager", "state_machine_1", $zone);
642 @endcode
645 // CGroup not in a family behaviour
646 void newNpcChildGroup_sss_(CStateInstance* entity, CScriptStack& stack)
648 stack.push((float)-1.0f);
649 newNpcChildGroup_sssf_(entity, stack);
652 //----------------------------------------------------------------------------
653 /** @page code
655 @subsection newNpcChildGroupMl_sssff_c
656 Used to create multilevel dynamic npc group (a parent/children relation is defined).
658 Arguments: s(GroupTemplate), s(StateMachine), s(Zone), f(BaseLevel), f(Dispersion) -> c(Group)
659 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
660 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
661 @param[in] Zone is returned by the getZoneWithFlags methods
662 @param[in] BaseLevel is the base level of the spawned group
663 @param[in] Dispersion is the dispersion radius in meters when spawning a group
664 @param[out] Group is the newly created group
666 @code
667 (@grp)newNpcChildGroupMl("class_forager", "state_machine_1", $zone, 2, 50);
668 @endcode
671 // CGroup not in a family behaviour
672 void newNpcChildGroupMl_sssff_c(CStateInstance* entity, CScriptStack& stack)
674 double dispersionRadius = (double)(float)stack.top();
675 stack.pop();
676 int baseLevel = (int)(float)stack.top();
677 stack.pop();
678 TStringId const zoneName = CStringMapper::map(stack.top());
679 stack.pop();
681 IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
682 CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
683 if (!aiInstance)
684 return;
686 CNpcZone const* spawnZone = aiInstance->getZone(zoneName);
687 if (!spawnZone)
689 string StateMachine = stack.top();
690 stack.pop();
691 stack.pop();
692 nlwarning("newNpcChildGroup failed : spawnZone Not Found ! for StateMachine : %s", StateMachine.c_str());
693 return;
695 if (dispersionRadius<0.)
697 dispersionRadius = 0.;
698 CNpcZonePlace const* spawnZonePlace = dynamic_cast<CNpcZonePlace const*>(spawnZone);
699 if (spawnZonePlace!=NULL)
700 dispersionRadius = spawnZonePlace->getRadius();
702 stack.push(spawnNewGroup(entity, stack, aiInstance, spawnZone->midPos(), baseLevel, dispersionRadius));
705 //----------------------------------------------------------------------------
706 /** @page code
708 @subsection newNpcChildGroupMl_sssff_
709 Used to create multilevel dynamic npc group (a parent/children relation is defined).
711 Arguments: s(GroupTemplate), s(StateMachine), s(Zone), f(BaseLevel), f(Dispersion) ->
712 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
713 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
714 @param[in] Zone is returned by the getZoneWithFlags methods
715 @param[in] BaseLevel is the base level of the spawned group
716 @param[in] Dispersion is the dispersion radius in meters when spawning a group
718 @code
719 ()newNpcChildGroupMl("class_forager", "state_machine_1", $zone, 2, 50);
720 @endcode
723 // CGroup not in a family behaviour
724 void newNpcChildGroupMl_sssff_(CStateInstance* entity, CScriptStack& stack)
726 double dispersionRadius = (double)(float)stack.top();
727 stack.pop();
728 int baseLevel = (int)(float)stack.top();
729 stack.pop();
730 TStringId const zoneName = CStringMapper::map(stack.top());
731 stack.pop();
733 IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
734 CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
735 if (!aiInstance)
736 return;
738 CNpcZone const* spawnZone = aiInstance->getZone(zoneName);
739 if (!spawnZone)
741 string StateMachine = stack.top();
742 stack.pop();
743 stack.pop();
744 nlwarning("newNpcChildGroup failed : spawnZone Not Found ! for StateMachine : %s", StateMachine.c_str());
745 return;
747 if (dispersionRadius<0.)
749 dispersionRadius = 0.;
750 CNpcZonePlace const* spawnZonePlace = dynamic_cast<CNpcZonePlace const*>(spawnZone);
751 if (spawnZonePlace!=NULL)
752 dispersionRadius = spawnZonePlace->getRadius();
754 spawnNewGroup (entity, stack, aiInstance, spawnZone->midPos(), baseLevel, dispersionRadius);
757 //----------------------------------------------------------------------------
758 /** @page code
760 @subsection newNpcChildGroupMl_sssf_c
761 Used to create multilevel dynamic npc group (a parent/children relation is defined).
763 Arguments: s(GroupTemplate), s(StateMachine), s(Zone), f(BaseLevel) -> c(Group)
764 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
765 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
766 @param[in] Zone is returned by the getZoneWithFlags methods
767 @param[in] BaseLevel is the base level of the spawned group
768 @param[out] Group is the newly created group
770 @code
771 (@grp)newNpcChildGroupMl("class_forager", "state_machine_1", $zone, 12);
772 @endcode
775 // CGroup not in a family behaviour
776 void newNpcChildGroupMl_sssf_c(CStateInstance* entity, CScriptStack& stack)
778 stack.push((float)-1.0f);
779 newNpcChildGroupMl_sssff_c(entity, stack);
782 //----------------------------------------------------------------------------
783 /** @page code
785 @subsection newNpcChildGroupMl_sssf_
786 Used to create multilevel dynamic npc group (a parent/children relation is defined).
788 Arguments: s(GroupTemplate), s(StateMachine), s(Zone), f(BaseLevel) ->
789 @param[in] GroupTemplate is the name of a template npc group defined in the same AIInstance
790 @param[in] StateMachine is the name of a state machine defined in the same AIInstance
791 @param[in] Zone is returned by the getZoneWithFlags methods
792 @param[in] BaseLevel is the base level of the spawned group
794 @code
795 ()newNpcChildGroupMl("class_forager", "state_machine_1", $zone, 12);
796 @endcode
799 // CGroup not in a family behaviour
800 void newNpcChildGroupMl_sssf_(CStateInstance* entity, CScriptStack& stack)
802 stack.push((float)-1.0f);
803 newNpcChildGroupMl_sssff_(entity, stack);
806 //----------------------------------------------------------------------------
807 /** @page code
809 @subsection spawnManager_s_
810 Spawns a manager.
812 Arguments: s(ManagerName) ->
813 @param[in] ManagerName is the name of the manager to spawn
815 @code
816 ()spawnManager("NPC Manager"); // Spawns all the NPCs in the NPC manager called "NPC Manager"
817 @endcode
820 // CGroup not in a family behaviour
821 void spawnManager_s_(CStateInstance* entity, CScriptStack& stack)
823 string ManagerName = stack.top();
824 stack.pop();
826 breakable
828 if (!entity)
830 nlwarning("SpawnManager error entity not spawned");
831 break;
834 IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
835 CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
836 if (!aiInstance)
838 nlwarning("SpawnManager error AIInstance not Found");
839 break;
841 /** :TODO: If CStringFilter is available use it here and test the whole */
842 string/*CStringFilter*/ managerFilter(ManagerName);
843 FOREACH(itManager, CAliasCont<CManager>, aiInstance->managers())
845 CManager* manager = *itManager;
846 if (manager && managerFilter==manager->getName())
848 manager->spawn();
851 return;
853 nlwarning("SpawnManager error");
856 //----------------------------------------------------------------------------
857 /** @page code
859 @subsection despawnManager_s_
860 Despawns a manager.
862 Arguments: s(ManagerName) ->
863 @param[in] ManagerName is the name of the manager to despawn
865 @code
866 ()despawnManager("NPC Manager"); // Despawns all the NPCs in the NPC manager called "NPC Manager"
867 @endcode
870 // CGroup not in a family behaviour
871 void despawnManager_s_(CStateInstance* entity, CScriptStack& stack)
873 string ManagerName = stack.top();
874 stack.pop();
876 breakable
878 if (!entity)
880 nlwarning("DespawnManager error entity not spawned");
881 break;
884 IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
885 CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
886 if (!aiInstance)
888 nlwarning("DespawnManager error AIInstance not Found");
889 break;
891 // :TODO: If CStringFilter is available use it here and test the whole
892 string/*CStringFilter*/ managerFilter(ManagerName);
893 FOREACH(itManager, CAliasCont<CManager>, aiInstance->managers())
895 CManager *manager=*itManager;
896 if (manager && managerFilter==manager->getName())
898 manager->despawnMgr();
901 return;
905 //----------------------------------------------------------------------------
906 /** @page code
908 @subsection getGroupTemplateWithFlags_sss_s
909 Returns the name of a randomly chosen group template corresponding to specified flags.
911 Arguments: s(OneOf), s(Mandatory), s(ExceptFlags) -> s(GroupTemplate)
912 @param[in] OneOf is a '|' separated list of flags
913 @param[in] Mandatory is a '|' separated list of flags
914 @param[in] ExceptFlags is a '|' separated list of flags
915 @param[out] GroupTemplate is a group template matching at least one of OneOf flags, all Manadatory flags and none of ExceptFlags
917 @code
918 ($group)getGroupTemplateWithFlags("food|rest", "invasion|outpost"); // Get a group which matches 'invasion', 'outpost' and either 'food' or 'rest' flags.
919 @endcode
922 // CGroup not in a family behaviour
923 void getGroupTemplateWithFlags_sss_s(CStateInstance* entity, CScriptStack& stack)
925 string exceptProperties = stack.top();
926 stack.pop();
927 string mandatoryProperties = stack.top();
928 stack.pop();
929 string oneOfProperties = stack.top();
930 stack.pop();
932 // If no AI instance return
933 IManagerParent* managerParent = entity->getGroup()->getOwner()->getOwner();
934 CAIInstance* aiInstance = dynamic_cast<CAIInstance*>(managerParent);
935 if (!aiInstance)
937 stack.push(string());
938 return;
941 // Fill the property sets.
942 AITYPES::CPropertySet oneOfSet = readSet(oneOfProperties);
943 AITYPES::CPropertySet mandatorySet = readSet(mandatoryProperties);
944 AITYPES::CPropertySet exceptSet = readSet(exceptProperties);
946 vector<CGroupDesc<CGroupFamily> const*> groupDescs;
947 FOREACH (itCont, CCont<CContinent>, aiInstance->continents())
949 FOREACH (itRegion, CCont<CRegion>, itCont->regions())
951 FOREACH (itFamily, CCont<CGroupFamily>, itRegion->groupFamilies())
953 FOREACH (itGroupDesc, CCont<CGroupDesc<CGroupFamily> >, itFamily->groupDescs())
955 // Skip groups not meeting the criteria
956 if (!itGroupDesc->properties().containsPartOfNotStrict(oneOfSet))
957 continue;
958 if (!itGroupDesc->properties().containsAllOf(mandatorySet))
959 continue;
960 if (itGroupDesc->properties().containsPartOfStrict(exceptSet))
961 continue;
962 groupDescs.push_back(*itGroupDesc);
968 if (groupDescs.size()==0)
970 nlwarning("getGroupTemplateWithFlags failed: no group template found that contains all of '%s' and a part of'%s' ", mandatoryProperties.c_str(), oneOfProperties.c_str());
971 stack.push(string());
972 return;
975 CGroupDesc<CGroupFamily> const* groupDesc = groupDescs[CAIS::rand16((uint32)groupDescs.size())];
976 stack.push(groupDesc->getFullName());
977 return;
980 //----------------------------------------------------------------------------
981 /** @page code
983 @subsection getGroupTemplateWithFlags_ss_s
984 Returns the name of a randomly chosen group template corresponding to specified flags.
986 Arguments: s(OneOf), s(Mandatory) -> s(GroupTemplate)
987 @param[in] OneOf is a '|' separated list of flags
988 @param[in] Mandatory is a '|' separated list of flags
989 @param[out] GroupTemplate is a group template matching at least one of OneOf flags and all Manadatory flags
991 @code
992 ($group)getGroupTemplateWithFlags("food|rest", "invasion|outpost"); // Get a group which matches 'invasion', 'outpost' and either 'food' or 'rest' flags.
993 @endcode
996 // CGroup not in a family behaviour
997 void getGroupTemplateWithFlags_ss_s(CStateInstance* entity, CScriptStack& stack)
999 stack.push(std::string(""));
1000 getGroupTemplateWithFlags_sss_s(entity, stack);
1003 //----------------------------------------------------------------------------
1004 /** @page code
1006 @subsection getZoneWithFlags_ssss_s
1007 The first parameter is a list of 'one match enough' zone flags. The zones must
1008 have at least one of these flags to be selected. The second parameter is a
1009 list of 'all required' zone flag. The zones must have all these flags to be
1010 selected. The fourth parameter is a list of 'all forbidden' zone flag. The
1011 zones must not have any of these flags to be selected. Additionnaly the
1012 returned zone cannot be ExceptZone. Last argument specifies a list of flags
1013 that the selected zone cannot have.
1015 With the list of selectable zone, the system then select a zone based on
1016 entity density in each selected zone. The system will select the least
1017 populated zone. It then returns the zone name.
1019 Priority is given to current Cell, and after that to all cells.
1021 Arguments: s(OneOf), s(Mandatory), s(ExceptZone), s(ExceptProperties) -> s(Zone)
1022 @param[in] OneOf is a '|' separated list of flags
1023 @param[in] Mandatory is a '|' separated list of flags
1024 @param[in] ExceptZone is a zone name
1025 @param[in] ExceptProperties is a '|' separated list of flags
1026 @param[out] Zone is a zone matching at least one of OneOf flags, all Manadatory flags and can't be ExceptZone
1028 @code
1029 ($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.
1030 ($zone)getZoneWithFlags("boss", "", $oldzone); // Get a zone which matches boss flag with the best score except the $oldzone
1031 @endcode
1034 // CGroup not in a family behaviour
1035 void getZoneWithFlags_ssss_s(CStateInstance* entity, CScriptStack& stack)
1037 string exceptProperties = stack.top();
1038 stack.pop();
1039 TStringId curZoneId= CStringMapper::map(stack.top());
1040 stack.pop();
1041 string mandatoryProperties = stack.top();
1042 stack.pop();
1043 string oneOfProperties = stack.top();
1044 stack.pop();
1046 // If no AI instance return
1047 IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
1048 CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
1049 if (!aiInstance)
1051 stack.push(string());
1052 return;
1055 // Fill the property sets.
1056 AITYPES::CPropertySet oneOfSet = readSet(oneOfProperties);
1057 AITYPES::CPropertySet mandatorySet = readSet(mandatoryProperties);
1058 AITYPES::CPropertySet exceptSet = readSet(exceptProperties);
1059 // Get current zone
1060 CNpcZone const* const curZone = aiInstance->getZone(curZoneId);
1061 // Create the scorer
1062 CZoneScorerMandatoryAndOneOfPlusExcept const scorer(oneOfSet, mandatorySet, exceptSet, curZone);
1064 getZoneWithFlags_helper(entity, stack, aiInstance, scorer);
1067 //----------------------------------------------------------------------------
1068 /** @page code
1070 @subsection getZoneWithFlags_sss_s
1071 @sa @ref getZoneWithFlags_ssss_s
1073 Arguments: s(OneOf), s(Mandatory), s(ExceptZone) -> s(Zone)
1074 @param[in] OneOf is a '|' separated list of flags
1075 @param[in] Mandatory is a '|' separated list of flags
1076 @param[in] ExceptZone is a zone name
1077 @param[out] Zone is a zone matching at least one of OneOf flags, all Manadatory flags and can't be ExceptZone
1079 @code
1080 ($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.
1081 ($zone)getZoneWithFlags("boss", "", $oldzone); // Get a zone which matches boss flag with the best score except the $oldzone
1082 @endcode
1085 // CGroup not in a family behaviour
1086 void getZoneWithFlags_sss_s(CStateInstance* entity, CScriptStack& stack)
1088 stack.push(std::string(""));
1089 getZoneWithFlags_ssss_s(entity, stack);
1092 //----------------------------------------------------------------------------
1093 /** @page code
1095 @subsection getNearestZoneWithFlags_ffsss_s
1096 @sa @ref getZoneWithFlags_ssss_s
1098 The zone returned by this function is the nearest from the specified point and taking into account the zone free space.
1100 Arguments: f(X), f(Y), s(OneOf), s(Mandatory), s(ExceptProperties) -> s(Zone)
1101 @param[in] X is the position of the zone we are looking for on the X axis
1102 @param[in] Y is the position of the zone we are looking for on the X axis
1103 @param[in] OneOf is a '|' separated list of flags
1104 @param[in] Mandatory is a '|' separated list of flags
1105 @param[in] ExceptProperties is a '|' separated list of flags
1106 @param[out] Zone is a zone matching at least one of OneOf flags, all Manadatory flags and can't be ExceptZone
1108 @code
1109 ($zone)getNearestZoneWithFlags(x, y, "food|rest", "invasion|outpost", "stayaway");
1110 @endcode
1113 // CGroup not in a family behaviour
1114 void getNearestZoneWithFlags_ffsss_s(CStateInstance* entity, CScriptStack& stack)
1116 string exceptProperties = stack.top();
1117 stack.pop();
1118 string mandatoryProperties = stack.top();
1119 stack.pop();
1120 string oneOfProperties = stack.top();
1121 stack.pop();
1122 float const y = stack.top();
1123 stack.pop();
1124 float const x = stack.top();
1125 stack.pop();
1127 // If no AI instance return
1128 IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
1129 CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
1130 if (!aiInstance)
1132 stack.push(string());
1133 return;
1136 // Fill the property sets.
1137 AITYPES::CPropertySet oneOfSet = readSet(oneOfProperties);
1138 AITYPES::CPropertySet mandatorySet = readSet(mandatoryProperties);
1139 AITYPES::CPropertySet exceptSet = readSet(exceptProperties);
1140 // Create the scorer
1141 CZoneScorerMandatoryAndOneOfAndDistAndSpace const scorer(oneOfSet, mandatorySet, exceptSet, CAIVector(x, y));
1143 getZoneWithFlags_helper(entity, stack, aiInstance, scorer);
1146 //----------------------------------------------------------------------------
1147 /** @page code
1149 @subsection getNearestZoneWithFlags_ffss_s
1150 @sa @ref getZoneWithFlags_sss_s
1152 The zone returned by this function is the nearest from the specified point and taking into account the zone free space.
1154 Arguments: f(X), f(Y), s(OneOf), s(Mandatory), s(ExceptProperties) -> s(Zone)
1155 @param[in] X is the position of the zone we are looking for on the X axis
1156 @param[in] Y is the position of the zone we are looking for on the X axis
1157 @param[in] OneOf is a '|' separated list of flags
1158 @param[in] Mandatory is a '|' separated list of flags
1159 @param[out] Zone is a zone matching at least one of OneOf flags, all Manadatory flags and can't be ExceptZone
1161 @code
1162 ($zone)getNearestZoneWithFlags(x, y, "food|rest", "invasion|outpost");
1163 @endcode
1166 // CGroup not in a family behaviour
1167 void getNearestZoneWithFlags_ffss_s(CStateInstance* entity, CScriptStack& stack)
1169 stack.push(std::string(""));
1170 getNearestZoneWithFlags_ffsss_s(entity, stack);
1173 //----------------------------------------------------------------------------
1174 /** @page code
1176 @subsection getNearestZoneWithFlagsStrict_ffsss_s
1177 @sa @ref getZoneWithFlags_ssss_s
1179 The zone returned by this function is the nearest from the specified point without taking into account the zone free space.
1181 Arguments: f(X), f(Y), s(OneOf), s(Mandatory), s(ExceptProperties) -> s(Zone)
1182 @param[in] X is the position of the zone we are looking for on the X axis
1183 @param[in] Y is the position of the zone we are looking for on the X axis
1184 @param[in] OneOf is a '|' separated list of flags
1185 @param[in] Mandatory is a '|' separated list of flags
1186 @param[in] ExceptProperties is a '|' separated list of flags
1187 @param[out] Zone is a zone matching at least one of OneOf flags, all Manadatory flags and can't be ExceptZone
1189 @code
1190 ($zone)getNearestZoneWithFlagsStrict(x, y, "food|rest", "invasion|outpost", "stayaway");
1191 @endcode
1194 // CGroup not in a family behaviour
1195 void getNearestZoneWithFlagsStrict_ffsss_s(CStateInstance* entity, CScriptStack& stack)
1197 string exceptProperties = stack.top();
1198 stack.pop();
1199 string mandatoryProperties = stack.top();
1200 stack.pop();
1201 string oneOfProperties = stack.top();
1202 stack.pop();
1203 float const y = stack.top();
1204 stack.pop();
1205 float const x = stack.top();
1206 stack.pop();
1208 // If no AI instance return
1209 IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
1210 CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
1211 if (!aiInstance)
1213 stack.push(string());
1214 return;
1217 // Fill the property sets.
1218 AITYPES::CPropertySet oneOfSet = readSet(oneOfProperties);
1219 AITYPES::CPropertySet mandatorySet = readSet(mandatoryProperties);
1220 AITYPES::CPropertySet exceptSet = readSet(exceptProperties);
1221 // Create the scorer
1222 const CZoneScorerMandatoryAndOneOfAndDist scorer(oneOfSet, mandatorySet, exceptSet, CAIVector(x, y));
1224 getZoneWithFlags_helper(entity, stack, aiInstance, scorer);
1227 //----------------------------------------------------------------------------
1228 /** @page code
1230 @subsection getNearestZoneWithFlagsStrict_ffss_s
1231 @sa @ref getZoneWithFlags_sss_s
1233 The zone returned by this function is the nearest from the specified point without taking into account the zone free space.
1235 Arguments: f(X), f(Y), s(OneOf), s(Mandatory), s(ExceptProperties) -> s(Zone)
1236 @param[in] X is the position of the zone we are looking for on the X axis
1237 @param[in] Y is the position of the zone we are looking for on the X axis
1238 @param[in] OneOf is a '|' separated list of flags
1239 @param[in] Mandatory is a '|' separated list of flags
1240 @param[out] Zone is a zone matching at least one of OneOf flags, all Manadatory flags and can't be ExceptZone
1242 @code
1243 ($zone)getNearestZoneWithFlagsStrict(x, y, "food|rest", "invasion|outpost");
1244 @endcode
1247 // CGroup not in a family behaviour
1248 void getNearestZoneWithFlagsStrict_ffss_s(CStateInstance* entity, CScriptStack& stack)
1250 stack.push(std::string(""));
1251 getNearestZoneWithFlagsStrict_ffsss_s(entity, stack);
1254 //----------------------------------------------------------------------------
1255 /** @page code
1257 @subsection getNeighbourZoneWithFlags_ssss_s
1258 @sa @ref getZoneWithFlags_ssss_s
1260 Here priority is given to current Cell, after that to neighbour Cells, and
1261 finally to all cells. CurrentZone cannot be returned.
1263 Arguments: s(CurrentZone), s(OneOf), s(Mandatory), s(ExceptProperties) -> s(Zone)
1264 @param[in] CurrentZone is a zone name
1265 @param[in] OneOf is a '|' separated list of flags
1266 @param[in] Mandatory is a '|' separated list of flags
1267 @param[in] ExceptProperties is a '|' separated list of flags
1268 @param[out] Zone is a zone matching the specified flags
1270 @code
1271 ($zone1)getNeighbourZoneWithFlags($zone, "boss", "", $exceptflag); // Get the zone in the neighbour cells of the one containing $zone which matches specified flags
1272 @endcode
1275 // CGroup not in a family behaviour
1276 void getNeighbourZoneWithFlags_ssss_s(CStateInstance* entity, CScriptStack& stack)
1278 string exceptProperties = stack.top();
1279 stack.pop();
1280 string mandatoryProperties = stack.top();
1281 stack.pop();
1282 string oneOfProperties = stack.top();
1283 stack.pop();
1284 TStringId curZoneId = CStringMapper::map(stack.top());
1285 stack.pop();
1287 // If no AI instance return
1288 IManagerParent* const managerParent = entity->getGroup()->getOwner()->getOwner();
1289 CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
1290 if (!aiInstance)
1292 stack.push(string());
1293 return;
1296 // If curzone is invalid return
1297 CNpcZone const* const curZone = aiInstance->getZone(curZoneId);
1298 if (!curZone)
1300 nlwarning("getNeighbourZoneWithFlags failed: current zone is invalid!");
1301 nlwarning(" - current zone: %s", CStringMapper::unmap(curZoneId).c_str());
1302 nlwarning(" - oneOfProperties: %s", oneOfProperties.c_str());
1303 nlwarning(" - mandatoryProperties: %s", mandatoryProperties.c_str());
1304 nlwarning(" - exceptProperties: %s", exceptProperties.c_str());
1305 stack.push(string());
1306 return;
1309 // Fill the property sets.
1310 AITYPES::CPropertySet oneOfSet = readSet(oneOfProperties);
1311 AITYPES::CPropertySet mandatorySet = readSet(mandatoryProperties);
1312 AITYPES::CPropertySet exceptSet = readSet(exceptProperties);
1313 // Create the scorer
1314 CZoneScorerMandatoryAndOneOfPlusExcept const scorer(oneOfSet, mandatorySet, exceptSet, curZone);
1316 vector<CCell*> cells;
1317 curZone->getOwner()->getNeighBourgCellList(cells);
1318 cells.push_back(curZone->getOwner());
1319 std::random_shuffle(cells.begin(), cells.end());
1321 CNpcZone const* const newZone = CCellZone::lookupNpcZoneScorer(cells, scorer);
1323 if (newZone)
1325 stack.push(newZone->getAliasTreeOwner().getAliasFullName());
1326 return;
1328 nlwarning("getNeighbourgZoneWithFlags failed: no zone found");
1329 nlwarning(" - current zone: %s", CStringMapper::unmap(curZoneId).c_str());
1330 nlwarning(" - oneOfProperties: %s", oneOfProperties.c_str());
1331 nlwarning(" - mandatoryProperties: %s", mandatoryProperties.c_str());
1332 nlwarning(" - exceptProperties: %s", exceptProperties.c_str());
1334 stack.push(string());
1335 return;
1338 //----------------------------------------------------------------------------
1339 /** @page code
1341 @subsection getNeighbourZoneWithFlags_sss_s
1342 @sa @ref getZoneWithFlags_sss_s
1344 Here priority is given to current Cell, after that to neighbour Cells, and
1345 finally to all cells. CurrentZone cannot be returned.
1347 Arguments: s(CurrentZone), s(OneOf), s(Mandatory) -> s(Zone)
1348 @param[in] CurrentZone is a zone name
1349 @param[in] OneOf is a '|' separated list of flags
1350 @param[in] Mandatory is a '|' separated list of flags
1351 @param[out] Zone is a zone matching the specified flags
1353 @code
1354 ($zone1)getNeighbourZoneWithFlags($zone, "boss", ""); // Get the zone in the neighbour cells of the one containing $zone which matches specified flags
1355 @endcode
1358 // CGroup not in a family behaviour
1359 void getNeighbourZoneWithFlags_sss_s(CStateInstance* entity, CScriptStack& stack)
1361 stack.push(std::string(""));
1362 getNeighbourZoneWithFlags_ssss_s(entity, stack);
1365 //----------------------------------------------------------------------------
1366 /** @page code
1368 @subsection setAggro_ff_
1369 Sets aggro parameters of current group.
1371 Arguments: f(Range), f(NbTicks) ->
1372 @param[in] Range is a aggro range in meters
1373 @param[in] NbTicks is a aggro update period in ticks
1375 @code
1376 ()setAggro(Range, NbTicks); // Sets the aggro range of the group to Range, updated every NbTicks ticks
1377 @endcode
1380 // CGroup
1381 void setAggro_ff_(CStateInstance* entity, CScriptStack& stack)
1383 sint32 updateNbTicks = (sint32)(float)stack.top();
1384 stack.pop();
1385 uint32 aggroRange = (uint32)(float)stack.top();
1386 stack.pop();
1388 CGroup* const grp = entity->getGroup();
1389 if (grp)
1391 grp->_AggroRange = aggroRange;
1392 if (updateNbTicks>0)
1393 grp->_UpdateNbTicks = updateNbTicks;
1397 //----------------------------------------------------------------------------
1398 /** @page code
1400 @subsection setCanAggro_f_
1401 Let a bot aggro or prevent it from aggroing.
1403 Arguments: f(CanAggro) ->
1404 @param[in] CanAggro tells whether the bot can aggro (!=0) or not (==0)
1406 @code
1407 ()setCanAggro(0);
1408 @endcode
1411 // CGroup
1412 void setCanAggro_f_(CStateInstance* entity, CScriptStack& stack)
1414 bool canAggro = ((float)stack.top())!=0.f;
1415 stack.pop();
1417 FOREACH(bot, CCont<CBot>, entity->getGroup()->bots())
1419 if (!bot->isSpawned())
1420 continue;
1421 CSpawnBot* spBot = bot->getSpawnObj();
1422 if (spBot)
1423 spBot->setCanAggro(canAggro);
1427 //----------------------------------------------------------------------------
1428 /** @page code
1430 @subsection clearAggroList_f_
1431 Reset the aggrolist of a bot.
1433 Arguments: f(bool don't send lost aggro message to EGS) ->
1435 @code
1436 ()clearAggroList(0/1);
1437 @endcode
1440 // CGroup
1441 void clearAggroList_f_(CStateInstance* entity, CScriptStack& stack)
1443 bool sendAggroLostMessage = ((float)stack.top())==0.f;
1444 stack.pop();
1446 FOREACH(bot, CCont<CBot>, entity->getGroup()->bots())
1448 if (!bot->isSpawned())
1449 continue;
1450 CSpawnBot* spBot = bot->getSpawnObj();
1451 if (spBot)
1452 spBot->clearAggroList(sendAggroLostMessage);
1456 //----------------------------------------------------------------------------
1457 /** @page code
1459 @subsection clearAggroList__
1460 Reset the aggrolist of a bot.
1462 Arguments: ->
1464 @code
1465 ()clearAggroList();
1466 @endcode
1469 // CGroup
1470 void clearAggroList__(CStateInstance* entity, CScriptStack& stack)
1472 stack.push((float)0.f);
1473 clearAggroList_f_(entity, stack);
1476 //----------------------------------------------------------------------------
1477 /** @page code
1479 @subsection setMode_s_
1480 Sets the mode of every bot of the group. Valid modes are:
1481 - Normal
1482 - Sit
1483 - Eat
1484 - Rest
1485 - Alert
1486 - Hungry
1487 - Death
1489 Arguments: s(Mode) ->
1490 @param[in] Mode is the mode name to set
1492 @code
1493 ()setMode("Alert");
1494 @endcode
1497 // CGroup
1498 void setMode_s_(CStateInstance* entity, CScriptStack& stack)
1500 string NewMode = stack.top();
1501 stack.pop();
1503 MBEHAV::EMode mode = MBEHAV::stringToMode(NewMode);
1504 if (mode==MBEHAV::UNKNOWN_MODE)
1505 return;
1507 FOREACH(botIt, CCont<CBot>, entity->getGroup()->bots())
1509 if (botIt->getSpawnObj())
1510 botIt->getSpawnObj()->setMode(mode);
1515 //----------------------------------------------------------------------------
1516 /** @page code
1518 @subsection setAutoSpawn_f_
1519 Determine if the current group should respawn automatically after despawn.
1521 Arguments: f(AutoSpawn) ->
1522 @param[in] AutoSpawn is whether the group automatically rewpawns (1) or not (0)
1524 @code
1525 ()setAutoSpawn(1);
1526 @endcode
1529 // CGroup
1530 void setAutoSpawn_f_(CStateInstance* entity, CScriptStack& stack)
1532 float const autoSpawn = stack.top();
1533 stack.pop();
1535 CGroup* group = entity->getGroup();
1537 group->setAutoSpawn(autoSpawn!=0.f);
1540 //----------------------------------------------------------------------------
1541 // HP related methods
1542 /** @page code
1544 @subsection setMaxHP_ff_
1545 Sets the Max HP level of each bot of the group.
1547 Arguments: f(MaxHp) f(SetFull) ->
1548 @param[in] MaxHP is the new maximum HP for each bot
1549 @param[in] SetFull if not 0, will set the HP to the new maximum
1551 @code
1552 ()setMaxHP(50000,1);
1553 @endcode
1556 // CGroup
1557 void setMaxHP_ff_(CStateInstance* entity, CScriptStack& stack)
1559 bool setFull = ((float)stack.top() != 0.f); stack.pop();
1560 float maxHp = ((float)stack.top()); stack.pop();
1562 CChangeCreatureMaxHPMsg& msgList = CAIS::instance().getCreatureChangeMaxHP();
1564 FOREACH(bot, CCont<CBot>, entity->getGroup()->bots())
1566 if (!bot->isSpawned())
1567 continue;
1569 if (maxHp > 0)
1571 CSpawnBot* const sbot = bot->getSpawnObj();
1572 msgList.Entities.push_back(sbot->dataSetRow());
1573 msgList.MaxHp.push_back((uint32)(maxHp));
1574 msgList.SetFull.push_back((uint8)(setFull?1:0));
1576 bot->setCustomMaxHp((uint32)maxHp);
1580 /** @page code
1582 @subsection setHPLevel_f_
1583 Sets the current HP level of each bot of the group.
1585 Arguments: f(Coef) ->
1586 @param[in] Coef is the percentage of its max HP each creature will have
1588 @code
1589 ()setHPLevel(0.8);
1590 @endcode
1593 // CGroup
1594 void setHPLevel_f_(CStateInstance* entity, CScriptStack& stack)
1596 float coef = stack.top();
1597 stack.pop();
1599 CChangeCreatureHPMsg& msgList = CAIS::instance().getCreatureChangeHP();
1601 FOREACH(bot, CCont<CBot>, entity->getGroup()->bots())
1603 if (!bot->isSpawned())
1604 continue;
1606 CSpawnBot* const sbot = bot->getSpawnObj();
1608 msgList.Entities.push_back(sbot->dataSetRow());
1609 msgList.DeltaHp.push_back((sint32)(sbot->maxHitPoints()*coef));
1616 //----------------------------------------------------------------------------
1617 // HP related methods
1618 /** @page code
1620 @subsection setHPScale_f__f_
1621 Sets the current HP level of level of each bot of the group. its maxHitPoints
1623 for a bot HP = 850 and MaxHP = 1000
1624 ()setHPScale_f_(0); HP will be 0 so DeltaHp = 850
1625 ()setHPScale_f_(1); HP will be 100 so DeltaHp = 150
1626 ()setHPScale_f_(0.5); HP will be 500 so DeltaHp = 350
1627 if bot HP = 840 and Max abd setHpRatio(0) HP will be 0
1630 Arguments: f(Coef) ->
1631 @param[in] Coef is the percentage of its max HP each creature will *BE*
1633 @code
1634 ()setHPLevel(0.8);
1635 @endcode
1638 // CGroup
1639 void setHPScale_f_(CStateInstance* entity, CScriptStack& stack)
1641 float coef = stack.top();
1642 stack.pop();
1644 CChangeCreatureHPMsg& msgList = CAIS::instance().getCreatureChangeHP();
1646 FOREACH(bot, CCont<CBot>, entity->getGroup()->bots())
1648 if (!bot->isSpawned())
1649 continue;
1651 CSpawnBot* const sbot = bot->getSpawnObj();
1653 msgList.Entities.push_back(sbot->dataSetRow());
1654 msgList.DeltaHp.push_back((sint32)( sbot->maxHitPoints() *coef - sbot->currentHitPoints()) );
1658 //----------------------------------------------------------------------------
1659 // Url related method
1660 /** @page code
1662 @subsection setUrl_ss_
1663 Sets the name and url of right-click action
1665 Arguments: s(actionName),s(url) ->
1666 @param[in] actionName of action when player mouse over
1667 @param[in] url of action when player mouse over
1669 @code
1670 ()setUrl("Click on Me", "http://www.domain.com/script.php");
1671 @endcode
1674 // CGroup
1675 void setUrl_ss_(CStateInstance* entity, CScriptStack& stack)
1677 CGroup* group = entity->getGroup();
1679 std::string url = (std::string)stack.top();stack.pop();
1680 std::string actionName = (std::string)stack.top();stack.pop();
1682 CCreatureSetUrlMsg msg;
1683 FOREACH(botIt, CCont<CBot>, group->bots())
1685 CSpawnBot* pbot = botIt->getSpawnObj();
1686 if (pbot!=NULL)
1688 msg.Entities.push_back(pbot->dataSetRow());
1691 CSpawnGroup* spawnGroup = group->getSpawnObj();
1692 spawnGroup->setActionName(actionName);
1693 spawnGroup->setUrl(url);
1694 msg.ActionName = actionName;
1695 msg.Url = url;
1696 msg.send(egsString);
1701 /** @page code
1703 @subsection scaleHP_f_
1704 Scales the bots HP.
1706 Arguments: f(Coef) ->
1707 @param[in] Coef is the percentage of its current HP each creature will have
1709 @code
1710 ()scaleHP(2);
1711 @endcode
1714 // CGroup
1715 void scaleHP_f_(CStateInstance* entity, CScriptStack& stack)
1717 float coef = stack.top();
1718 stack.pop();
1720 CChangeCreatureHPMsg& msgList = CAIS::instance().getCreatureChangeHP();
1722 FOREACH(bot, CCont<CBot>, entity->getGroup()->bots())
1724 if (!bot->isSpawned())
1725 continue;
1727 CSpawnBot* const sbot = bot->getSpawnObj();
1729 msgList.Entities.push_back(sbot->dataSetRow());
1730 msgList.DeltaHp.push_back((sint32)(sbot->currentHitPoints()*coef));
1735 /** @page code
1737 @subsection setBotHPScaleByAlias_fs_
1738 Same as setHpSacale but only on a specific bot of a groupe from the current group by its bot alias
1740 Arguments: f(alias),f(Coef), ->
1741 @param[in] alias is the alias of the bot
1742 @param[in] Coef is the percentage of its current HP each creature will have
1745 @code
1746 ()scaleHpByAlias(2, '(A:1000:10560)');
1747 @endcode
1750 // CGroup
1751 void setBotHPScaleByAlias_fs_(CStateInstance* entity, CScriptStack& stack)
1753 uint32 alias = LigoConfig.aliasFromString((string)stack.top()) ; stack.pop();
1755 float coef = stack.top(); stack.pop();
1757 CChangeCreatureHPMsg& msgList = CAIS::instance().getCreatureChangeHP();
1759 FOREACH(bot, CCont<CBot>, entity->getGroup()->bots())
1762 if (bot->getAlias() != alias) { continue; }
1763 if (!bot->isSpawned()) return;
1765 CSpawnBot* const sbot = bot->getSpawnObj();
1767 msgList.Entities.push_back(sbot->dataSetRow());
1768 msgList.DeltaHp.push_back((sint32)( sbot->maxHitPoints() *coef - sbot->currentHitPoints()) );
1773 /** @page code
1775 @subsection downScaleHP_f_
1776 Scales the bots HP down.
1778 Arguments: f(Coef) ->
1779 @param[in] Coef is a value
1781 @code
1782 ()downScaleHP(2);
1783 @endcode
1786 // CGroup
1787 void downScaleHP_f_(CStateInstance* entity, CScriptStack& stack)
1789 float coef = stack.top();
1790 stack.pop();
1792 CChangeCreatureHPMsg& msgList = CAIS::instance().getCreatureChangeHP();
1794 clamp(coef, 0.f, 1.f);
1795 FOREACH(bot, CCont<CBot>, entity->getGroup()->bots())
1797 if (!bot->isSpawned())
1798 continue;
1800 CSpawnBot* const sbot = bot->getSpawnObj();
1802 msgList.Entities.push_back(sbot->dataSetRow());
1803 msgList.DeltaHp.push_back((sint32)(sbot->currentHitPoints()*(coef-1)));
1807 /** @page code
1809 @subsection upScaleHP_f_
1810 Scales the bots HP up.
1812 Arguments: f(Coef) ->
1813 @param[in] Coef is a value
1815 @code
1816 ()upScaleHP(2);
1817 @endcode
1820 // CGroup
1821 void upScaleHP_f_(CStateInstance* entity, CScriptStack& stack)
1823 float coef = stack.top();
1824 stack.pop();
1826 CChangeCreatureHPMsg& msgList = CAIS::instance().getCreatureChangeHP();
1828 clamp(coef, 0.f, 1.f);
1829 FOREACH(bot, CCont<CBot>, entity->getGroup()->bots())
1831 if (!bot->isSpawned())
1832 continue;
1833 CSpawnBot* spBot = bot->getSpawnObj();
1834 if (spBot)
1836 msgList.Entities.push_back(spBot->dataSetRow());
1837 msgList.DeltaHp.push_back((sint32)((spBot->maxHitPoints()-spBot->currentHitPoints())*coef));
1842 /** @page code
1844 @subsection addHP_f_
1845 Add HP to the bots.
1847 Arguments: f(HP) ->
1848 @param[in] HP is the amount of hit points to add to each bot
1850 @code
1851 ()addHP(500);
1852 @endcode
1855 // CGroup
1856 void addHP_f_(CStateInstance* entity, CScriptStack& stack)
1858 float addHP = stack.top();
1859 stack.pop();
1861 CChangeCreatureHPMsg& msgList = CAIS::instance().getCreatureChangeHP();
1863 FOREACH(bot, CCont<CBot>, entity->getGroup()->bots())
1865 if (!bot->isSpawned())
1866 continue;
1868 CSpawnBot* const sbot = bot->getSpawnObj();
1870 msgList.Entities.push_back(sbot->dataSetRow());
1871 msgList.DeltaHp.push_back((sint32)(sbot->currentHitPoints()+addHP));
1875 void giveHP_f_(CStateInstance* entity, CScriptStack& stack)
1877 float addHP = stack.top();
1878 stack.pop();
1880 CChangeCreatureHPMsg& msgList = CAIS::instance().getCreatureChangeHP();
1882 FOREACH(bot, CCont<CBot>, entity->getGroup()->bots())
1884 if (!bot->isSpawned())
1885 continue;
1887 CSpawnBot* const sbot = bot->getSpawnObj();
1889 msgList.Entities.push_back(sbot->dataSetRow());
1890 msgList.DeltaHp.push_back((sint32)(addHP));
1894 //----------------------------------------------------------------------------
1895 /** @page code
1897 @subsection aiAction_s_
1898 Triggers an AI action, defined by its sheet name, on the current target.
1900 Arguments: s(actionSheetId) ->
1901 @param[in] actionSheetId is a the sheet name of the action
1903 @code
1904 ()aiAction("kick_his_ass.aiaction");
1905 @endcode
1908 // CGroup
1909 void aiAction_s_(CStateInstance* entity, CScriptStack& stack)
1911 std::string actionName = stack.top();
1912 stack.pop();
1913 NLMISC::CSheetId sheetId(actionName);
1914 if (sheetId==NLMISC::CSheetId::Unknown)
1916 nlwarning("Action SheetId Unknown %s", actionName.c_str());
1917 return;
1919 AISHEETS::IAIActionCPtr action = AISHEETS::CSheets::getInstance()->lookupAction(sheetId);
1920 if (action.isNull())
1922 nlwarning("Action SheetId Unknown %s", actionName.c_str());
1923 return;
1926 FOREACH(botIt, CCont<CBot>, entity->getGroup()->bots())
1928 CSpawnBot* pbot = botIt->getSpawnObj();
1929 if (pbot!=NULL)
1931 CSpawnBot& bot = *pbot;
1932 if (!bot.getAIProfile())
1933 continue; // OK
1935 CBotProfileFight* profile = dynamic_cast<CBotProfileFight*>(bot.getAIProfile());
1936 if (!profile)
1937 continue; // OK
1939 if (!profile->atAttackDist())
1940 continue; // NOT OK
1942 TDataSetRow dataSetRow;
1943 if ((CAIEntityPhysical*)bot.getTarget())
1944 dataSetRow = bot.getTarget()->dataSetRow();
1946 CEGSExecuteAiActionMsg msg(bot.dataSetRow(), dataSetRow, action->SheetId(), bot._DamageCoef, bot._DamageSpeedCoef);
1947 msg.send(egsString);
1948 bot.setActionFlags(RYZOMACTIONFLAGS::Attacks);
1949 // OK
1954 //----------------------------------------------------------------------------
1955 /** @page code
1957 @subsection aiActionSelf_s_
1958 Triggers an AI action, defined by its sheet name, on the bot itself.
1960 Arguments: s(actionSheetId) ->
1961 @param[in] actionSheetId is a the sheet name of the action
1963 @code
1964 ()aiActionSelf("defensive_aura.aiaction");
1965 @endcode
1968 // CGroup
1969 void aiActionSelf_s_(CStateInstance* entity, CScriptStack& stack)
1971 std::string actionName = stack.top();
1972 stack.pop();
1973 NLMISC::CSheetId sheetId(actionName);
1974 if (sheetId==NLMISC::CSheetId::Unknown)
1976 nlwarning("Action SheetId Unknown %s", actionName.c_str());
1977 return;
1979 AISHEETS::IAIActionCPtr action = AISHEETS::CSheets::getInstance()->lookupAction(sheetId);
1980 if (action.isNull())
1982 nlwarning("Action SheetId Unknown %s", actionName.c_str());
1983 return;
1986 FOREACH(botIt, CCont<CBot>, entity->getGroup()->bots())
1988 CSpawnBot* pbot = botIt->getSpawnObj();
1989 if (pbot!=NULL)
1991 CSpawnBot& bot = *pbot;
1992 CEGSExecuteAiActionMsg msg(bot.dataSetRow(), bot.dataSetRow(), action->SheetId(), bot._DamageCoef, bot._DamageSpeedCoef);
1993 msg.send(egsString);
1994 bot.setActionFlags(RYZOMACTIONFLAGS::Attacks);
1995 // OK
2000 //----------------------------------------------------------------------------
2001 /** @page code
2003 @subsection addProfileParameter_s_
2004 Adds a profile parameter to the current group.
2006 Arguments: s(parameterName) ->
2007 @param[in] parameterName is a the id of the parameter to add
2009 @code
2010 ()addProfileParameter("running"); // equivalent to "running" parameter in group primitive
2011 @endcode
2014 // CGroup
2015 void addProfileParameter_s_(CStateInstance* entity, CScriptStack& stack)
2017 std::string name = (std::string)stack.top();
2018 stack.pop();
2020 CGroup* group = entity->getGroup();
2022 if (group->isSpawned())
2023 group->getSpawnObj()->addProfileParameter(name, "", 0.f);
2027 //----------------------------------------------------------------------------
2028 /** @page code
2030 @subsection addProfileParameter_ss_
2031 Adds a profile parameter to the current group.
2033 Arguments: s(parameterName),s(parameterContent) ->
2034 @param[in] parameterName is a the id of the parameter to add
2035 @param[in] parameterContent is the value of the parameter
2037 @code
2038 ()addProfileParameter("foo", "bar"); // equivalent to "foo:bar" parameter in group primitive
2039 @endcode
2042 // CGroup
2043 void addProfileParameter_ss_(CStateInstance* entity, CScriptStack& stack)
2045 std::string value = (std::string)stack.top();
2046 stack.pop();
2047 std::string name = (std::string)stack.top();
2048 stack.pop();
2050 CGroup* group = entity->getGroup();
2052 if (group->isSpawned())
2053 group->getSpawnObj()->addProfileParameter(name, value, 0.f);
2056 //----------------------------------------------------------------------------
2057 /** @page code
2059 @subsection addProfileParameter_sf_
2060 Adds a profile parameter to the current group.
2062 Arguments: s(parameterName),f(parameterContent) ->
2063 @param[in] parameterName is a the id of the parameter to add
2064 @param[in] parameterContent is the value of the parameter
2066 @code
2067 ()addProfileParameter("foo", 0.5); // equivalent to "foo:0.5" parameter in group primitive
2068 @endcode
2071 // CGroup
2072 void addProfileParameter_sf_(CStateInstance* entity, CScriptStack& stack)
2074 float value = (float)stack.top();
2075 stack.pop();
2076 std::string name = (std::string)stack.top();
2077 stack.pop();
2079 CGroup* group = entity->getGroup();
2081 if (group->isSpawned())
2082 group->getSpawnObj()->addProfileParameter(name, "", value);
2085 //----------------------------------------------------------------------------
2086 /** @page code
2088 @subsection removeProfileParameter_s_
2089 removes a profile parameter from the current group.
2091 Arguments: s(parameterName) ->
2092 @param[in] parameterName is a the id of the parameter to remove
2094 @code
2095 ()removeProfileParameter("running"); // remove "running" or "running:<*>" parameter from group
2096 @endcode
2099 // CGroup
2100 void removeProfileParameter_s_(CStateInstance* entity, CScriptStack& stack)
2102 std::string name = (std::string)stack.top();
2103 stack.pop();
2105 CGroup* group = entity->getGroup();
2107 if (group->isSpawned())
2108 group->getSpawnObj()->removeProfileParameter(name);
2111 //----------------------------------------------------------------------------
2112 /** @page code
2114 @subsection addPersistentProfileParameter_s_
2115 Adds a profile parameter to the current group.
2117 Arguments: s(parameterName) ->
2118 @param[in] parameterName is a the id of the parameter to add
2120 @code
2121 ()addProfileParameter("running"); // equivalent to "running" parameter in group primitive
2122 @endcode
2125 // CGroup
2126 void addPersistentProfileParameter_s_(CStateInstance* entity, CScriptStack& stack)
2128 std::string name = (std::string)stack.top();
2129 stack.pop();
2131 CGroup* group = entity->getGroup();
2133 if (group->isSpawned())
2134 group->getSpawnObj()->addProfileParameter(name, "", 0.f);
2136 group->addProfileParameter(name, "", 0.f);
2139 //----------------------------------------------------------------------------
2140 /** @page code
2142 @subsection addPersistentProfileParameter_ss_
2143 Adds a profile parameter to the current group.
2145 Arguments: s(parameterName),s(parameterContent) ->
2146 @param[in] parameterName is a the id of the parameter to add
2147 @param[in] parameterContent is the value of the parameter
2149 @code
2150 ()addPersistentProfileParameter("foo", "bar"); // equivalent to "foo:bar" parameter in group primitive
2151 @endcode
2154 // CGroup
2155 void addPersistentProfileParameter_ss_(CStateInstance* entity, CScriptStack& stack)
2157 std::string value = (std::string)stack.top();
2158 stack.pop();
2159 std::string name = (std::string)stack.top();
2160 stack.pop();
2162 CGroup* group = entity->getGroup();
2164 if (group->isSpawned())
2165 group->getSpawnObj()->addProfileParameter(name, value, 0.f);
2167 group->addProfileParameter(name, value, 0.f);
2170 //----------------------------------------------------------------------------
2171 /** @page code
2173 @subsection addPersistentProfileParameter_sf_
2174 Adds a profile parameter to the current group.
2176 Arguments: s(parameterName),f(parameterContent) ->
2177 @param[in] parameterName is a the id of the parameter to add
2178 @param[in] parameterContent is the value of the parameter
2180 @code
2181 ()addPersistentProfileParameter("foo", 0.5); // equivalent to "foo:0.5" parameter in group primitive
2182 @endcode
2185 // CGroup
2186 void addPersistentProfileParameter_sf_(CStateInstance* entity, CScriptStack& stack)
2188 float value = (float)stack.top();
2189 stack.pop();
2190 std::string name = (std::string)stack.top();
2191 stack.pop();
2193 CGroup* group = entity->getGroup();
2194 if (group->isSpawned())
2195 group->getSpawnObj()->addProfileParameter(name, "", value);
2197 group->addProfileParameter(name, "", value);
2200 //----------------------------------------------------------------------------
2201 /** @page code
2203 @subsection removePersistentProfileParameter_s_
2204 removes a profile parameter from the current group.
2206 Arguments: s(parameterName) ->
2207 @param[in] parameterName is a the id of the parameter to remove
2209 @code
2210 ()removeProfileParameter("running"); // remove "running" or "running:<*>" parameters from group
2211 @endcode
2214 // CGroup
2215 void removePersistentProfileParameter_s_(CStateInstance* entity, CScriptStack& stack)
2217 std::string name = (std::string)stack.top();
2218 stack.pop();
2220 CGroup* group = entity->getGroup();
2221 if (group->isSpawned())
2222 group->getSpawnObj()->removeProfileParameter(name);
2224 group->removeProfileParameter(name);
2226 //----------------------------------------------------------------------------
2227 /** @page code
2229 @subsection getOutpostState__s
2230 Returns the name of the current outpost state (group must be in an outpost).
2232 Arguments: -> s(StateName)
2233 @param[out] StateName is the name of the current outpost state
2235 @code
2236 ($name)getOutpostState();
2237 @endcode
2240 // CGroup
2241 void getOutpostStateName__s(CStateInstance* si, CScriptStack& stack)
2243 string str;
2245 breakable
2247 if (!si)
2248 break;
2250 CGroup* group = si->getGroup();
2251 if (!group)
2252 break;
2254 COutpostManager* manager = dynamic_cast<COutpostManager*>(group->getOwner());
2255 if (!manager)
2256 break;
2258 str = static_cast<COutpost*>(manager->getOwner())->getStateName();
2261 stack.push(str);
2264 //----------------------------------------------------------------------------
2265 /** @page code
2267 @subsection isOutpostTribeOwner__f
2268 Returns whether the current outpost owner is a tribe (group must be in an outpost).
2270 Arguments: -> f(TribeOwner)
2271 @param[out] TribeOwner is whether the current outpost owner is a tribe (1) or not (0)
2273 @code
2274 (tribeOwner)isOutpostTribeOwner();
2275 @endcode
2278 // CGroup
2279 void isOutpostTribeOwner__f(CStateInstance* si, CScriptStack& stack)
2281 float tribeOwner = 0.f;
2283 breakable
2285 if (!si)
2286 break;
2288 CGroup* group = si->getGroup();
2289 if (!group)
2290 break;
2292 COutpostManager* manager = dynamic_cast<COutpostManager*>(group->getOwner());
2293 if (!manager)
2294 break;
2296 if (!static_cast<COutpost*>(manager->getOwner())->isBelongingToAGuild())
2297 tribeOwner = 1.f;
2300 stack.push(tribeOwner);
2303 //----------------------------------------------------------------------------
2304 /** @page code
2306 @subsection isOutpostGuildOwner__f
2307 Returns whether the current outpost owner is a guild (group must be in an outpost).
2309 Arguments: -> f(TribeOwner)
2310 @param[out] TribeOwner is whether the current outpost owner is a guild (1) or not (0)
2312 @code
2313 (guildOwner)isOutpostGuildOwner();
2314 @endcode
2317 // CGroup
2318 void isOutpostGuildOwner__f(CStateInstance* si, CScriptStack& stack)
2320 float guildOwner = 0.f;
2322 breakable
2324 if (!si)
2325 break;
2327 CGroup* group = si->getGroup();
2328 if (!group)
2329 break;
2331 COutpostManager* manager = dynamic_cast<COutpostManager*>(group->getOwner());
2332 if (!manager)
2333 break;
2335 if (static_cast<COutpost*>(manager->getOwner())->isBelongingToAGuild())
2336 guildOwner = 1.f;
2339 stack.push(guildOwner);
2342 //----------------------------------------------------------------------------
2343 /** @page code
2345 @subsection getEventParam_f_f
2346 Returns the content of a param
2348 Arguments: f(paramIndex) -> f(value)
2349 @param[in] paramIndex is the parameter index passed by EGS ai_event message
2350 @param[out] value is a the value of the parameter
2352 @code
2353 (val)getEventParam(2);
2354 @endcode
2357 // CGroup
2358 void getEventParam_f_f(CStateInstance* entity, CScriptStack& stack)
2360 uint32 varId = (uint32)((float)stack.top());
2362 CGroup* group = entity->getGroup();
2364 stack.top() = group->getEventParamFloat(varId);
2367 //----------------------------------------------------------------------------
2368 /** @page code
2370 @subsection getEventParam_f_s
2371 Returns the content of a param
2373 Arguments: f(paramIndex) -> s(value)
2374 @param[in] paramIndex is the parameter index passed by EGS ai_event message
2375 @param[out] value is a the value of the parameter
2377 @code
2378 ($val)getEventParam(2);
2379 @endcode
2382 // CGroup
2383 void getEventParam_f_s(CStateInstance* entity, CScriptStack& stack)
2385 uint32 varId = (uint32)((float)stack.top());
2387 CGroup* group = entity->getGroup();
2389 stack.top() = group->getEventParamString(varId);
2394 // -- Boss functions
2396 //----------------------------------------------------------------------------
2397 /** @page code
2399 @subsection getPlayerStat_ss_f
2400 Get some player stat.
2402 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.
2403 The player must be in the same AI Instance (same continent).
2404 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.
2405 If param is not one of "HP", "MaxHp", "RatioHp" zero is return and a warning message is printed on the log.
2406 - The "Hp" stat is the property CURRENT_HIT_POINTS as seen in the mirror.
2407 - The "MaxHp" stat is the property MAX_HIT_POINTS as seen in the mirror.
2408 - The "RatioHp" stat is (Hp * 100) / MaxHp
2409 Be careful the argument is case sensitive.
2411 Arguments: s(playerEidAsString), s(statName) -> s(result)
2412 @param[in] playerEidAsString is EntityId as string from the player we want infos
2413 @param[in] statName is the name of the property (can be "HP", "MaxHp", "RatioHp")
2414 @param[out] value is a the value of the parameter
2416 @code
2417 ($playerEid)getCurrentPlayerEid();
2418 print($playerEid); //log (0x00001fbd50:00:00:81)
2419 (maxHp)getPlayerStat($playerEid, "MaxHp");
2420 @endcode
2422 void getPlayerStat_ss_f(CStateInstance* entity, CScriptStack& stack)
2424 std::string funName = "getPlayerStat_ss_f";
2425 // reaed input
2426 std::string statName = ((std::string)stack.top()); stack.pop();
2427 std::string playerEidStr = ((std::string)stack.top()); stack.pop();
2430 // get Dataset of the player to have access to mirror values
2431 NLMISC::CEntityId playerEid;
2432 playerEid.fromString(playerEidStr.c_str());
2433 TDataSetRow playerRow = TheDataset.getDataSetRow( playerEid );
2434 if (! TheDataset.isAccessible( playerRow ) )
2436 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() );
2437 stack.push((float)0);
2438 return;
2441 if (statName == "Hp" )
2443 // return DSPropertyCURRENT_HIT_POINTS Mirror value
2444 CMirrorPropValue<sint32> mirrorSymbol( TheDataset, playerRow, DSPropertyCURRENT_HIT_POINTS );
2445 stack.push((float)mirrorSymbol.getValue());
2446 return;
2448 else if (statName == "MaxHp")
2450 // return DSPropertyMAX_HIT_POINTS Mirror value
2451 CMirrorPropValue<sint32> mirrorSymbol( TheDataset, playerRow, DSPropertyMAX_HIT_POINTS );
2452 stack.push((float)mirrorSymbol.getValue());
2453 return;
2455 else if (statName == "RatioHp")
2457 // return percentage of live (read from mirror values)
2458 CMirrorPropValue<sint32> mirrorSymbol( TheDataset, playerRow, DSPropertyCURRENT_HIT_POINTS );
2459 CMirrorPropValue<sint32> mirrorSymbol2( TheDataset, playerRow, DSPropertyMAX_HIT_POINTS );
2461 stack.push((float)(100.0*mirrorSymbol.getValue() / mirrorSymbol2.getValue()));
2462 return;
2464 else
2466 nlwarning("Try to call %s with wrong state %s", funName.c_str(), statName.c_str() );
2468 stack.push((float)0);
2469 return;
2473 //----------------------------------------------------------------------------
2474 /** @page code
2476 @subsection getPlayerPosition_ss_ff
2477 Get player position (x or y).
2479 Arguments: s(playerEidAsString), s(statName) -> s(result)
2480 @param[in] playerEidAsString is EntityId as string from the player we want infos
2481 @param[in] axis ("X" or "Y")
2482 @param[out] value is a the value of the parameter
2484 @code
2485 ($playerEid)getCurrentPlayerEid();
2486 (x, y)getPlayerPosition($playerEid);
2487 @endcode
2489 void getPlayerPosition_s_ff(CStateInstance* entity, CScriptStack& stack)
2491 std::string funName = "getPlayerPosition_s_ff";
2492 // reaed input
2493 std::string statName = ((std::string)stack.top()); stack.pop();
2494 std::string playerEidStr = ((std::string)stack.top()); stack.pop();
2497 // get Dataset of the player to have access to mirror values
2498 NLMISC::CEntityId playerEid;
2499 playerEid.fromString(playerEidStr.c_str());
2500 TDataSetRow playerRow = TheDataset.getDataSetRow( playerEid );
2501 if (! TheDataset.isAccessible( playerRow ) )
2503 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() );
2504 stack.push((float)0);
2505 return;
2508 CMirrorPropValue<sint32> mirrorSymbol( TheDataset, playerRow, DSPropertyPOSY );
2509 stack.push((float)mirrorSymbol.getValue());
2510 CMirrorPropValue<sint32> mirrorSymbol2( TheDataset, playerRow, DSPropertyPOSX );
2511 stack.push((float)mirrorSymbol2.getValue());
2512 return;
2516 /** @page code
2518 @subsection getPlayerDistance_fs_f
2519 Get the distance between a player and a bot in meters.
2521 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.
2522 The player must be in the same AI Instance (same continent).
2523 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.
2525 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.
2526 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.
2528 Arguments: s(playerEidAsString), f(botIndex) -> s(result)
2529 @param[in] playerEidAsString is EntityId as string from the player we want infos
2530 @param[in] botIndex is the index of an bot member of the current group
2531 @param[out] value is a the distance between the player on the bot (or -1 if error)
2533 @code
2534 ($playerEid)getCurrentPlayerEid();
2535 (index)getBotIndexByName("toto");
2536 (distance)getPlayerDistance(index, $playerEid);
2537 @endcode
2539 void getPlayerDistance_fs_f(CStateInstance* entity, CScriptStack& stack)
2541 std::string funName = "getPlayerDistance_is_f";
2543 // read input params
2544 std::string playerEidStr = ((std::string)stack.top()); stack.pop();
2545 sint32 botIndex = (sint32)((float)stack.top()); stack.pop();
2547 // get the player Eid
2548 NLMISC::CEntityId playerEid;
2549 playerEid.fromString(playerEidStr.c_str());
2551 // get the Spawn bot by its index
2552 CGroup* group = entity->getGroup();
2553 if (!group)
2555 nlwarning("%s on a non Npc Group, doesn't work", funName.c_str());
2556 stack.push((float) -1);
2557 return;
2559 if (!group->isSpawned() || botIndex <0 || group->bots().size() <= static_cast<uint32>(botIndex))
2561 nlwarning("%s used bad index %d/%d (or group not spawn)", funName.c_str(), botIndex, group->bots().size());
2562 stack.push((float)-1);
2563 return;
2565 CBot* bot = group->getBot(botIndex);
2566 CSpawnBot* spBot = bot?bot->getSpawnObj():0;
2567 if (!spBot)
2569 nlwarning("%s used bad index %d/%d (or bot not spawn)", funName.c_str(), botIndex, group->bots().size());
2570 stack.push((float)-1);
2571 return;
2574 // get DataSetRow of player to read mirro values
2575 TDataSetRow playerRow = TheDataset.getDataSetRow( playerEid );
2576 if (! TheDataset.isAccessible( playerRow ) )
2578 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() );
2579 stack.push((float)-1);
2580 return;
2583 // calculate the size between position of the player (from mirro) to position of the spawn bot.
2584 CMirrorPropValue<sint32> mirrorSymbol( TheDataset, playerRow, DSPropertyPOSX );
2585 CMirrorPropValue<sint32> mirrorSymbol2( TheDataset, playerRow, DSPropertyPOSY );
2586 const double dx = double (mirrorSymbol.getValue()) - double(spBot->x().asInt());
2587 const double dy = double (mirrorSymbol2.getValue()) - double(spBot->y().asInt());
2588 const double dist2 = (dx*dx + dy*dy) / 1000000.0;
2589 const double dist = sqrt(dist2);
2591 stack.push(float(dist));
2593 return;
2599 /** @page code
2601 @subsection getCurrentPlayerAggroListTarget_f_s
2602 Get the player entity id (as string) that has the most aggro in the aggro list of a bot.
2604 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.
2605 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.
2607 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)
2610 Arguments: f(botIndex) -> s(playerEidAsString)
2611 @param[in] botIndex is the index of an bot member of the current group
2612 @param[out] playerEidAsString is EntityId as string from the player we want infos
2614 @code
2615 ($playerId)getCurrentPlayerAggroListTarget(4);
2616 (distance)getPlayerDistance(4, $playerId);
2617 @endcode
2621 void getCurrentPlayerAggroListTarget_f_s(CStateInstance* entity, CScriptStack& stack)
2624 std::string funName = "getCurrentPlayerAggroListTarget_f_s";
2626 // get input params
2627 sint32 botIndex = (sint32)((float)stack.top()); stack.pop();
2629 // get spawn Bot
2630 CGroup* group = entity->getGroup();
2631 if (!group)
2633 nlwarning("%s on a non Npc Group, doesn't work", funName.c_str());
2634 stack.push(std::string(""));
2635 return;
2637 if (!group->isSpawned() || botIndex <0 || group->bots().size() <= static_cast<uint32>(botIndex))
2639 nlwarning("%s used bad index %d/%d (or group not spawn)", funName.c_str(), botIndex, group->bots().size());
2640 stack.push(std::string(""));
2642 return;
2644 CBot* bot = group->getBot(botIndex);
2645 CSpawnBot* spBot = bot?bot->getSpawnObj():0;
2646 if (!spBot)
2648 nlwarning("%s used bad index %d/%d (or bot not spawn)", funName.c_str(), botIndex, group->bots().size());
2649 stack.push(std::string(""));
2650 return;
2653 // iteratre throug aggro list to have the eid with max aggro
2654 CBotAggroOwner::TBotAggroList const& aggroList = spBot->getBotAggroList();
2655 CBotAggroOwner::TBotAggroList::const_iterator aggroIt(aggroList.begin()), aggroEnd(aggroList.end());
2656 TDataSetRow foundRow = TDataSetRow();
2657 float foundAggro = 0;
2658 for (; aggroIt != aggroEnd; ++aggroIt)
2660 float aggro = aggroIt->second->finalAggro();
2661 if (aggro > foundAggro)
2663 if (CMirrors::getEntityId(aggroIt->first).getType() != RYZOMID::player)
2665 continue;
2667 CAIEntityPhysical* ep = CAIS::instance().getEntityPhysical(aggroIt->first);
2668 if (!ep)
2670 continue;
2673 CBotPlayer const* const player = NLMISC::safe_cast<CBotPlayer const*>(ep);
2674 if (!player)
2676 continue;
2678 if (!player->isAggroable())
2680 continue;
2682 foundAggro = aggro;
2683 foundRow = aggroIt->first;
2687 if ( foundRow == TDataSetRow())
2688 { // Empty aggro list so no warning displayed
2689 stack.push(std::string(""));
2690 return;
2693 const NLMISC::CEntityId& found = CMirrors::getEntityId(foundRow);
2694 stack.push(std::string(found.toString()));
2700 /** @page code
2702 @subsection getRandomPlayerAggroListTarget_f_s
2703 Get a player entity id (as string) from the aggro list of a bot.
2705 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.
2706 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.
2708 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)
2711 Arguments: f(botIndex) -> s(playerEidAsString)
2712 @param[in] botIndex is the index of an bot member of the current group
2713 @param[out] playerEidAsString is EntityId as string from the player we want infos
2715 @code
2716 ($playerId)getRandomPlayerAggroListTarget(4);
2717 ()setAggroListTarget(4, $playerId);
2718 @endcode
2722 void getRandomPlayerAggroListTarget_f_s(CStateInstance* entity, CScriptStack& stack)
2725 std::string funName = "getRandomPlayerAggroListTarget_f_s";
2727 // test botIndex
2728 uint32 botIndex = (uint32)((float)stack.top()); stack.pop();
2730 // get Spawn bot
2731 CGroup* group = entity->getGroup();
2732 if (!group || !group->isSpawned() || botIndex <0 || group->bots().size() <= static_cast<uint32>(botIndex))
2734 nlwarning("%s used bad index %d/%d (or group not spawn)", funName.c_str(), botIndex, group->bots().size());
2735 stack.push(std::string(""));
2736 return;
2738 CBot* bot = group->getBot(botIndex);
2739 CSpawnBot* spBot = bot?bot->getSpawnObj():0;
2740 if (!spBot)
2742 nlwarning("%s used bad index %d/%d (or bot not spawn)", funName.c_str(), botIndex, group->bots().size());
2743 stack.push(std::string(""));
2744 return;
2747 // make a vector of aggroable player
2748 CBotAggroOwner::TBotAggroList const& aggroList = spBot->getBotAggroList();
2749 //typedef std::map<TDataSetRow, TAggroEntryPtr> TBotAggroList;
2750 CBotAggroOwner::TBotAggroList::const_iterator aggroIt(aggroList.begin()), aggroEnd(aggroList.end());
2751 TDataSetRow foundRow = TDataSetRow();
2752 std::vector<TDataSetRow> playerAggroable;
2753 for (; aggroIt != aggroEnd; ++aggroIt)
2755 if (CMirrors::getEntityId(aggroIt->first).getType() != RYZOMID::player)
2757 continue;
2759 CAIEntityPhysical* ep = CAIS::instance().getEntityPhysical(aggroIt->first);
2760 if (!ep)
2762 continue;
2765 CBotPlayer const* const player = NLMISC::safe_cast<CBotPlayer const*>(ep);
2766 if (!player)
2768 continue;
2770 if (!player->isAggroable())
2772 continue;
2774 playerAggroable.push_back(aggroIt->first);
2779 if ( playerAggroable.empty())
2781 stack.push(std::string(""));
2782 return;
2784 // chose a randomly a player among the container
2785 uint32 index = static_cast<uint32>( static_cast<double>(playerAggroable.size())*rand()/(RAND_MAX+1.0) );
2787 const NLMISC::CEntityId& found = CMirrors::getEntityId(playerAggroable[ index ]);
2788 stack.push(std::string(found.toString()));
2792 /** @page code
2794 @subsection getAggroListElement_ff_s
2795 Get a player entity id (as string) from the aggro list of a bot by it aggro list index.
2797 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.
2798 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.
2800 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
2804 Arguments: f(botIndex), f(aggroListIndex) -> s(playerEidAsString)
2805 @param[in] botIndex is the index of an bot member of the current group
2806 @param[in] aggroListIndex is the index of a aggroable player in the aggro list of the bot identified by botIndex
2807 @param[out] playerEidAsString is EntityId as string from the player we want infos
2809 @code
2810 (aggroSize)getAggorListSize(0);
2811 // to much player are attacking the boss
2812 if (aggoroSize > 10)
2814 ($player1)getAggroListElement(0);
2815 ($player2)getAggroListElement(1);
2816 ($player3)getAggroListElement(2);
2817 // so the boss teleport 3 person from its aggro list at the end of the world
2818 teleportPlayer($player1, 14233, 123123, 0, 0);
2819 teleportPlayer($player2, 14233, 123123, 0, 0);
2820 teleportPlayer($player2, 14233, 123123, 0, 0);
2821 clearAggroList();
2824 @endcode
2826 void getAggroListElement_ff_s(CStateInstance* entity, CScriptStack& stack)
2829 std::string funName = "getAggroListElement_ff_s";
2833 // get params
2834 uint32 elementIndex = (uint32)((float)stack.top()); stack.pop();
2835 sint32 botIndex = (uint32)((float)stack.top()); stack.pop();
2837 // get spawn bot by its index
2838 CGroup* group = entity->getGroup();
2839 if (!group || !group->isSpawned() || botIndex <0 || group->bots().size() <= static_cast<uint32>(botIndex))
2841 nlwarning("%s used bad index %d/%d (or group not spawn)", funName.c_str(), botIndex, group->bots().size());
2842 stack.push(std::string(""));
2843 return;
2845 CBot* bot = group->getBot(botIndex);
2846 CSpawnBot* spBot = bot?bot->getSpawnObj():0;
2847 if (!spBot)
2849 nlwarning("%s used bad index %d/%d (or bot not spawn)", funName.c_str(), botIndex, group->bots().size());
2850 stack.push(std::string(""));
2851 return;
2854 // make a vector of aggroable player
2855 CBotAggroOwner::TBotAggroList const& aggroList = spBot->getBotAggroList();
2856 //typedef std::map<TDataSetRow, TAggroEntryPtr> TBotAggroList;
2857 CBotAggroOwner::TBotAggroList::const_iterator aggroIt(aggroList.begin()), aggroEnd(aggroList.end());
2858 TDataSetRow foundRow = TDataSetRow();
2860 std::vector<TDataSetRow> playerAggroable;
2861 for (; aggroIt != aggroEnd; ++aggroIt)
2863 if (CMirrors::getEntityId(aggroIt->first).getType() != RYZOMID::player)
2865 continue;
2867 CAIEntityPhysical* ep = CAIS::instance().getEntityPhysical(aggroIt->first);
2868 if (!ep)
2870 continue;
2873 CBotPlayer const* const player = NLMISC::safe_cast<CBotPlayer const*>(ep);
2874 if (!player)
2876 continue;
2878 if (!player->isAggroable())
2880 continue;
2882 playerAggroable.push_back(aggroIt->first);
2887 if ( playerAggroable.empty())
2889 stack.push(std::string(""));
2890 return;
2892 // if index outside return "";
2893 if (0 > elementIndex && elementIndex >= playerAggroable.size())
2895 stack.push(std::string(""));
2896 return;
2899 const NLMISC::CEntityId& found = CMirrors::getEntityId(playerAggroable[ uint32(elementIndex) ]);
2900 stack.push(std::string(found.toString()));
2904 /** @page code
2906 @subsection getAggroListSize_f_f
2907 Get a size of the aggro lsit of a bot (list of aggroable PLAYER)
2909 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.
2910 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.
2912 A number is used to indicate the size of the aggro lsit
2914 Arguments: f(aggroListIndex) -> f(sizeOfAggroList)
2915 @param[in] botIndex is the index of an bot member of the current group.
2916 @param[out] sizeOfAggroList The size of the aggro list index.
2918 @code
2919 (aggroSize)getAggorListSize(0);
2920 // to much player are attacking the boss
2921 if (aggoroSize > 10)
2923 ($player1)getAggroListElement(0);
2924 ($player2)getAggroListElement(1);
2925 ($player3)getAggroListElement(2);
2926 // so the boss teleport 3 person from its aggro list at the end of the world
2927 teleportPlayer($player1, 14233, 123123, 0, 0);
2928 teleportPlayer($player2, 14233, 123123, 0, 0);
2929 teleportPlayer($player2, 14233, 123123, 0, 0);
2930 clearAggroList();
2933 @endcode
2935 void getAggroListSize_f_f(CStateInstance* entity, CScriptStack& stack)
2938 std::string funName = "getRandomPlayerAggroListTarget_f_s";
2942 // input params
2943 uint32 botIndex = (uint32)((float)stack.top()); stack.pop();
2945 // get spawn bot by index of the bot
2946 CGroup* group = entity->getGroup();
2947 if (!group || !group->isSpawned() || botIndex <0 || group->bots().size() <= static_cast<uint32>(botIndex))
2949 nlwarning("%s used bad index %d/%d (or group not spawn)", funName.c_str(), botIndex, group->bots().size());
2950 stack.push(float(0) );
2951 return;
2953 CBot* bot = group->getBot(botIndex);
2954 CSpawnBot* spBot = bot?bot->getSpawnObj():0;
2955 if (!spBot)
2957 nlwarning("%s used bad index %d/%d (or bot not spawn)", funName.c_str(), botIndex, group->bots().size());
2958 stack.push(float(0) );
2959 return;
2962 // make a vector of aggroable player
2963 CBotAggroOwner::TBotAggroList const& aggroList = spBot->getBotAggroList();
2964 //typedef std::map<TDataSetRow, TAggroEntryPtr> TBotAggroList;
2965 CBotAggroOwner::TBotAggroList::const_iterator aggroIt(aggroList.begin()), aggroEnd(aggroList.end());
2966 TDataSetRow foundRow = TDataSetRow();
2968 std::vector<TDataSetRow> playerAggroable;
2969 for (; aggroIt != aggroEnd; ++aggroIt)
2971 if (CMirrors::getEntityId(aggroIt->first).getType() != RYZOMID::player)
2973 continue;
2975 CAIEntityPhysical* ep = CAIS::instance().getEntityPhysical(aggroIt->first);
2976 if (!ep)
2978 continue;
2981 CBotPlayer const* const player = NLMISC::safe_cast<CBotPlayer const*>(ep);
2982 if (!player)
2984 continue;
2986 if (!player->isAggroable())
2988 continue;
2990 playerAggroable.push_back(aggroIt->first);
2995 // return the size of the aggro list
2996 stack.push(float(playerAggroable.size()));
3000 /** @page code
3002 @subsection setAggroListTarget_fs_
3004 Maximize the Aggro of a target from the Aggro list of one bot (this id can be given by getRandomPlayerAggroListTarget)..
3006 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.
3007 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.
3009 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.
3011 Arguments: f(botIndex) >s(playerEidAsString) >
3012 @param[in] botIndex is the index of an bot member of the current group
3013 @param[in] playerEidAsString is EntityId of the player that will be attacked
3015 @code
3016 ($playerId)getRandomPlayerAggroListTarget(4);
3017 ()setAggroListTarget(4, $playerId);
3018 @endcode
3021 void setAggroListTarget_fs_(CStateInstance* entity, CScriptStack& stack)
3024 std::string funName = "setAggroListTarget_fs_";
3028 std::string playerEidStr = ((std::string)stack.top()); stack.pop();
3029 sint32 botIndex = (sint32)((float)stack.top());stack.pop();
3031 // get the entity id
3032 NLMISC::CEntityId playerEid;
3033 playerEid.fromString(playerEidStr.c_str());
3035 // get the spawn bot by its indesx
3036 CGroup* group = entity->getGroup();
3037 if (!group || !group->isSpawned() || botIndex <0 || group->bots().size() <= static_cast<uint32>(botIndex))
3039 nlwarning("%s used bad index %d/%d (or group not spawn)", funName.c_str(), botIndex, group->bots().size());
3040 return;
3042 CBot* bot = group->getBot(botIndex);
3043 CSpawnBot* spBot = bot?bot->getSpawnObj():0;
3044 if (!spBot)
3046 nlwarning("%s used bad index %d/%d (or bot not spawn)", funName.c_str(), botIndex, group->bots().size());
3047 return;
3051 // test if player eid is ok
3052 if (playerEidStr.empty()) { return; }
3053 TDataSetRow playerRow = TheDataset.getDataSetRow( playerEid );
3054 bool accessible = TheDataset.isAccessible( playerRow );
3055 bool pj = playerEid.getType() == RYZOMID::player;
3056 CAIEntityPhysical* ep = accessible && pj ? CAIS::instance().getEntityPhysical(playerRow):0;
3057 CBotPlayer const* const player = ep ? NLMISC::safe_cast<CBotPlayer const*>(ep):0;
3058 if (!ep || !player ||!player->isAggroable() )
3060 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() );
3061 return;
3065 // maximize aggro from the bot for the player
3066 spBot->maximizeAggroFor(playerRow);
3070 /** @page code
3072 @subsection setGroupAggroListTarget_s_
3074 Maximize the Aggro of a target from the Aggro list of one bot to his group (this id can be given by getRandomPlayerAggroListTarget)..
3076 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.
3078 Arguments: s(playerEidAsString) >
3079 @param[in] playerEidAsString is EntityId of the player that will be attacked by the group
3081 @code
3082 ($playerId)getRandomPlayerAggroListTarget(4);
3083 ()setGroupAggroListTarget($playerId);
3084 @endcode
3087 void setGroupAggroListTarget_s_(CStateInstance* entity, CScriptStack& stack)
3090 std::string funName = "setGroupAggroListTarget_s_";
3092 // read params
3093 std::string playerEidStr = ((std::string)stack.top()); stack.pop();
3095 // read eid of the player
3096 NLMISC::CEntityId playerEid;
3097 playerEid.fromString(playerEidStr.c_str());
3100 // test if player eid is ok
3101 if (playerEidStr.empty()) { return; }
3102 TDataSetRow playerRow = TheDataset.getDataSetRow( playerEid );
3103 bool accessible = TheDataset.isAccessible( playerRow );
3104 bool pj = playerEid.getType() == RYZOMID::player;
3105 CAIEntityPhysical* ep = accessible && pj ? CAIS::instance().getEntityPhysical(playerRow):0;
3106 CBotPlayer const* const player = ep ? NLMISC::safe_cast<CBotPlayer const*>(ep):0;
3107 if (!ep || !player ||!player->isAggroable() )
3109 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() );
3110 return;
3113 // test if group is spawn
3114 CGroup* group = entity->getGroup();
3115 if (!group || !group->isSpawned() || group->bots().isEmpty() )
3117 nlwarning("Call %s on a empty/not spawned group", funName.c_str() );
3118 return;
3121 // apply maximizeAggroFor on all member of the group
3122 CCont<CBot>::iterator itBot = group->bots().begin();
3123 CCont<CBot>::iterator itEnd = group->bots().end();
3125 for (; itBot != itEnd; ++itBot)
3128 CSpawnBot* spBot = itBot->getSpawnObj();
3129 if (!spBot) { continue; }
3130 spBot->maximizeAggroFor(playerRow);
3135 /** @page code
3137 @subsection setManagerAggroListTarget_ss_
3139 Maximize the Aggro of a target of one bot to some groups of his manage.
3141 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.
3143 A string is used to select groups of the manager (groups name must contains this string)
3145 Arguments: f(botIndex), s(playerEidAsString) >
3146 @param[in] playerId is EntityId of the player
3147 @param[in] nameElement The element of the name of all group we are interest in.
3149 @code
3150 ($playerId)getRandomPlayerAggroListTarget(0);
3151 ()setManagerAggroListTarget($playerId, "group_bandit_"); // all group that have name like "group_bandit_*" will attack the player
3152 @endcode
3155 void setManagerAggroListTarget_ss_(CStateInstance* entity, CScriptStack& stack)
3158 std::string funName = "setManagerAggroListTarget_ss_";
3161 // read params
3162 std::string playerEidStr = ((std::string)stack.top()); stack.pop();
3163 std::string groupNameStr = ((std::string)stack.top()); stack.pop();
3166 // test if player eid is ok
3167 NLMISC::CEntityId playerEid;
3168 playerEid.fromString(playerEidStr.c_str());
3170 if (playerEidStr.empty()) { return; }
3171 TDataSetRow playerRow = TheDataset.getDataSetRow( playerEid );
3172 bool accessible = TheDataset.isAccessible( playerRow );
3173 bool pj = playerEid.getType() == RYZOMID::player;
3174 CAIEntityPhysical* ep = accessible && pj ? CAIS::instance().getEntityPhysical(playerRow):0;
3175 CBotPlayer const* const player = ep ? NLMISC::safe_cast<CBotPlayer const*>(ep):0;
3176 if (!ep || !player ||!player->isAggroable() )
3178 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() );
3179 return;
3183 CGroup* group = entity->getGroup();
3184 if (!group )
3186 nlwarning("Call %s on a non exisiting group", funName.c_str() );
3187 return;
3189 // get the manager of the group
3190 CManager* manager = group->getOwner();
3191 if (!manager)
3193 nlwarning("Call %s on a non exisiting manager", funName.c_str() );
3194 return;
3196 // for all group of the manager maximize aaggro *IF* the group name contains groupNameStr
3197 group=manager->getNextValidGroupChild();
3198 while (group!=NULL)
3200 if ( ! (!group || !group->isSpawned() || group->bots().isEmpty() ) && group->getName().find(groupNameStr) != std::string::npos )
3202 // apply maximizeAggroFor on all member of the group
3203 CCont<CBot>::iterator itBot = group->bots().begin();
3204 CCont<CBot>::iterator itEnd = group->bots().end();
3206 for (; itBot != itEnd; ++itBot)
3209 CSpawnBot* spBot = itBot->getSpawnObj();
3210 if (!spBot) { continue; }
3211 spBot->maximizeAggroFor(playerRow);
3214 group = manager->getNextValidGroupChild(group);
3221 /** @page code
3223 @subsection getBotIndexByName_s_f
3225 Get the index of a bot of a group by its name (or return -1). Mainly useful for scripted boss.
3227 botIndex begins at zero for the first member of the group, -1 if the bot is not found.
3229 Arguments:, s(botName) > f(botIndex)
3231 @param[in] name is the name of the bot
3232 @param[out] botIndex is the index of an bot member of the current group
3234 @code
3235 (botIndex)getBotIndexByName("boss_random_aggro");
3236 ($playerId)getRandomPlayerAggroListTarget(botIndex);
3237 ()setAggroListTarget(botIndex, $playerId);
3239 @endcode
3241 void getBotIndexByName_s_f(CStateInstance* entity, CScriptStack& stack)
3243 std::string funName = "getBotIndexByName_s_f";
3245 // read params
3246 std::string botName = (std::string)stack.top(); stack.pop();
3248 // test if group is spawned
3249 CGroup* group = entity->getGroup();
3250 if (!group || group->bots().isEmpty() )
3252 nlwarning("Call %s on a empty group", funName.c_str() );
3253 stack.push((float)-1);
3254 return;
3258 // Search on all persistent bot of the groupe the bot that have the searched name
3259 CCont<CBot>::iterator itBot = group->bots().begin();
3260 CCont<CBot>::iterator itEnd = group->bots().end();
3262 sint32 index = -1;
3263 for (; itBot != itEnd; ++itBot)
3265 ++index;
3266 const std::string& name = itBot->getName();
3267 if (name == botName)
3269 stack.push((float)index);
3270 return;
3274 // Bot not found
3275 stack.push((float)-1);
3276 return;
3280 /** @page code
3282 @subsection isGroupAlived__f
3284 Test if a group is alived (at least one member is alived)
3286 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.
3287 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.
3290 Arguments: s(playerid) > f(success)
3292 @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)
3294 @code
3295 ($alived)isGroupAlived();
3296 if ($alived == 1.0f) {
3298 @endcode
3301 void isGroupAlived__f(CStateInstance* entity, CScriptStack& stack)
3303 isAlived__f(entity, stack);
3307 /** @page code
3309 @subsection isBotAlived_f_f
3311 Test if a bot of the current group is alived. The bot is identified by its index.
3313 Arguments: f(botIndex) > f(success)
3315 @param[int] botIndex the index of the bot.
3316 @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)
3318 @code
3319 ($botIndex)getBotIndexByName("boss_3");
3320 $alived)isBotAlived($botIndex);
3321 if (alived == 1.0f) {
3323 @endcode
3326 void isBotAlived_f_f(CStateInstance* entity, CScriptStack& stack)
3328 std::string funName = "isBotAlived_f_f";
3329 // get input index
3330 sint32 botIndex = (sint32)((float)stack.top()); stack.pop();
3332 // get Spawn Bot
3333 CGroup* group = entity->getGroup();
3334 if (!group)
3336 nlwarning("%s on a non Npc Group, doesn't work", funName.c_str());
3337 stack.push((float)0);
3338 return;
3340 if (!group->isSpawned() || group->bots().isEmpty() || botIndex < 0 || group->bots().size() < static_cast<uint32>(botIndex))
3342 stack.push(0.0f);return;
3344 const CBot *const bot = group->getBot(botIndex);
3345 if ( !bot || !bot->isSpawned()) { stack.push(0.0f); return;};
3346 CAIEntityPhysical *const ep=bot->getSpawnObj();
3347 if ( !ep) { stack.push(0.0f); return;};
3349 // test if spawn bot is alive
3350 if (ep->isAlive()) { stack.push(1.0f); return;}
3352 stack.push(0.0f);
3353 return;
3357 /** @page code
3359 @subsection isPlayerAlived_s_f
3361 Test if a a player is is alived.
3363 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.
3365 Arguments: s(playerId) > f(success)
3367 @param[in] palyerId
3368 @param[out] success is 1.0f if the entity id of a player is alived.
3370 @code
3371 ($botIndex)getBotIndexByName("boss_3");
3372 ($playerId)getCurrentPlayerAggroListTarget($botIndex):
3373 (alived)isPlayerlived($playerId);
3374 if (alived == 1.0f) {
3376 @endcode
3378 void isPlayerAlived_s_f(CStateInstance* entity, CScriptStack& stack)
3380 // get input data
3381 std::string playerEidStr = (std::string)stack.top(); stack.pop();
3383 //get CAIEntityPhysical of the player
3384 NLMISC::CEntityId playerEid;
3385 playerEid.fromString(playerEidStr.c_str());
3386 TDataSetRow playeDataSetRow = TheDataset.getDataSetRow( playerEid) ;
3387 if (playerEidStr.empty() || !TheDataset.isAccessible( playeDataSetRow ) || playerEid.getType() != RYZOMID::player )
3389 stack.push(0.0f); return;
3391 CAIEntityPhysical* ep = CAIS::instance().getEntityPhysical(playeDataSetRow);
3392 if (!ep)
3395 stack.push(0.0f); return;
3397 // test if the player is alived
3398 if (ep->isAlive())
3400 stack.push(1.0f); return;
3403 stack.push(0.0f); return;
3407 /** @page code
3408 @subsection getServerTimeStr__s
3410 Gets the server time as string "eg 21:17:14 the x"
3411 This function is useful for stat purpose or debug (to know when a boss is down)
3413 Arguments: > s(serverTime)
3416 @param[out] The server time as debug string
3418 @code
3419 ($serverTime)getServerTimeAsString();
3420 @endcode
3423 void getServerTimeStr__s(CStateInstance* entity, CScriptStack& stack)
3425 //get the server time (as debug string)
3426 time_t currentTime;
3427 time( &currentTime );
3428 std::string str = NLMISC::toString("%s", asctime(localtime(&currentTime)));
3429 stack.push(str);
3432 /** @page code
3433 @subsection getServerTime__s
3435 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
3437 Arguments: > s(serverTime)
3439 @param[out] The server time as string (a float is not sharp enough
3441 @code
3442 ($serverTime)getServerTime();
3443 @endcode
3446 void getServerTime__s(CStateInstance* entity, CScriptStack& stack)
3448 //get the server time (as time stamp)
3449 time_t currentTime;
3450 time( &currentTime );
3451 std::string ret = NLMISC::toString("%d", currentTime);
3452 // convert to string
3453 stack.push((std::string)ret);
3458 /** @page code
3459 @subsection getRyzomDateStr__s
3461 Gets the ryzom date as string
3462 Arguments: > s(ryzomDateStr)
3464 @param[out] ryzomTimeAndDateAsString The time and date of the ryzom univers as debug string.
3466 @code
3467 ($ryzomDateStr)getRyzomDateStr);
3468 @endcode
3470 void getRyzomDateStr__s(CStateInstance* entity, CScriptStack& stack)
3472 // Display time using ryzom style
3473 std::string result;
3474 const CRyzomTime &rt = CTimeInterface::getRyzomTime();
3475 result = NLMISC::toString("%d:%d:00", (int) floorf(rt.getRyzomTime()) , (int) floorf(60.f * fmodf(rt.getRyzomTime(), 1.f)));
3477 uint32 month = rt.getRyzomMonth();
3478 MONTH::EMonth monthInCycle = rt.getRyzomMonthInCurrentCycle();
3479 std::string monthName = MONTH::toString((MONTH::EMonth) monthInCycle);
3480 uint32 dayOfMonth = rt.getRyzomDayOfMonth();
3481 std::string dayName = WEEKDAY::toString((WEEKDAY::EWeekDay) rt.getRyzomDayOfWeek());
3482 result += NLMISC::toString(" / %s %d %s(%d) %d",
3483 dayName.c_str(),
3484 (int) (dayOfMonth + 1),
3485 monthName.c_str(),
3486 (int) (month + 1),
3487 (int) rt.getRyzomYear());
3489 stack.push( result );
3492 /** @page code
3493 @subsection getRyzomDate__s
3495 Gets the ryzom tick game cycle. Useful for computing difference of time.
3496 The return value is a string and not a float because float is not sharp enought?
3497 Arguments: > s(tickGameCycle)
3499 @param[out] TickGameCycle The time of the ryzom univers (stops when server stops). 10 tick is 1 second.
3501 @code
3502 ($tickGameCycle)getRyzomDate();
3503 @endcode
3505 void getRyzomDate__s(CStateInstance* entity, CScriptStack& stack)
3507 //get GameTickCycle
3508 const NLMISC::TGameCycle ryzomTime= CTickEventHandler::getGameCycle();
3509 std::string ret = NLMISC::toString("%d", ryzomTime);
3510 // convert to string
3511 stack.push((std::string)ret);
3516 class CPhraseParameters
3518 public:
3519 enum TMode {NpcMsg, SystemMsg, EmoteMsg};
3520 TVectorParamCheck Values;
3523 CPhraseParameters PhraseParameters;
3525 //----------------------------------------------------------------------------
3526 /** @page code
3528 @subsection phraseBegin__
3529 Clear the parameters stack.
3531 Used when creating a customized msg via phraseEndSystemMsg_fss_, phraseEndNpcMsg_fss_, phraseEndSystemMsg_fss_.
3532 It Must be called at start of phrase if we are not sure that the parameter stack is clean.
3534 Parameter stack is unclean when someone has called a phrasePush* function but *not* a phraseEnd function before (which is *very* bad).
3536 Arguments: ->
3538 @code
3539 ()phraseBegin();
3540 ()phrasePushValue("money", 15);
3541 ()phrasePushValue("integer", 15);
3542 ()phrasePushValue("time", 15);
3543 ()phraseEndSystemMsg(0, "say", "PHRASE_FROM_PHRASE_WITH_3_PARAMETERS");
3544 @endcode
3547 // CGroup
3548 void phraseBegin__(CStateInstance* entity, CScriptStack& stack)
3550 PhraseParameters.Values.clear();
3553 //----------------------------------------------------------------------------
3554 /** @page code
3556 @subsection phrasePushValue_sf_
3557 This function push a value as number on the parameter stack. This stack is used by phraseEndSystemMsg_fss_, phraseEndNpcMsg_fss_, phraseEndSystemMsg_fss_ functions.
3558 @see phraseBegin__
3559 @see phrasePushString_ss_
3560 @see phraseEndSystemMsg_fss_
3561 @see phraseEndNpcMsg_fss_
3562 @see phraseEndSystemMsg_fss_
3565 The value *Must* be an number and only few type are handled.
3566 - money
3567 - integer
3568 - time
3570 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).
3571 - skill
3572 - faction
3573 - power_type
3574 - race
3575 - damage_type
3576 - characteristic
3577 - score
3578 - body_part
3580 Arguments: s(paramType), f(value) ->
3581 @param[in] paramType the type of the parameter
3582 @param[in] value the value of the parameter
3585 @code
3586 ()phraseBegin();
3587 ()phrasePushValue("money", 15);
3588 ()phrasePushValue("integer", 15);
3589 ()phrasePushValue("time", 15);
3590 ()phraseEndSystemMsg(0, "say", "PHRASE_WITH_3_PARAMETERS");
3591 @endcode
3594 // CGroup
3595 void phrasePushValue_sf_(CStateInstance* entity, CScriptStack& stack)
3597 float f = (float)stack.top();stack.pop(); // get the value as float
3598 std::string typeStr = (std::string)stack.top(); stack.pop(); // get the param type
3599 // create the good STRING_MANAGER::TParam in fonction of its type and is value
3600 STRING_MANAGER::TParamType type = STRING_MANAGER::stringToParamType(typeStr);
3601 STRING_MANAGER::TParam param;
3602 param.Type = type;
3603 switch( type )
3606 case STRING_MANAGER::money:
3608 param.Money = static_cast<uint64>(f);
3609 break;
3613 case STRING_MANAGER::integer:
3615 param.Int = static_cast<sint32>(f);
3616 break;
3619 case STRING_MANAGER::time:
3621 param.Time = static_cast<uint32>(f);
3622 break;
3625 case STRING_MANAGER::skill:
3626 case STRING_MANAGER::faction:
3627 case STRING_MANAGER::power_type:
3628 case STRING_MANAGER::race:
3629 case STRING_MANAGER::damage_type:
3630 case STRING_MANAGER::characteristic:
3631 case STRING_MANAGER::score:
3632 case STRING_MANAGER::body_part:
3634 param.Enum = static_cast<uint32>( f );
3635 break;
3638 default:
3639 param.Type = STRING_MANAGER::invalid_value;
3641 break;
3644 PhraseParameters.Values.push_back(param);
3648 //----------------------------------------------------------------------------
3649 /** @page code
3651 @subsection phrasePushString_ss_
3652 This function push a value as string on the parameter stack. This stack is used by phraseEndSystemMsg_fss_, phraseEndNpcMsg_fss_, phraseEndSystemMsg_fss_ functions.
3653 @see phraseBegin__
3654 @see phrasePushValue_sf_
3655 @see phraseEndSystemMsg_fss_
3656 @see phraseEndNpcMsg_fss_
3657 @see phraseEndSystemMsg_fss_
3660 The value *Must* be a string.
3661 The string is internal converted to number, sheetId, entityId when needed.
3663 Input as a number:
3664 - money
3665 - integer
3666 - time
3668 Input as string literal
3669 - literal
3671 Input as an entityId (obtains via getCurrentPlayerAggroListTarget_f_s, getRandomPlayerAggroListTarget_f_s, getBotEid_f_s, getCurrentSpeakerEid__s, getAggroListElement_ff_s)
3672 - player
3673 - bot
3674 - entity
3676 Input as sheetId name (example: "toto.sbrick", "toto.sitem", "toto.creature")
3677 - item
3678 - outpost
3679 - creature_model
3680 - creature
3681 - sphrase
3682 - sbrick
3684 Input as string identifier
3685 - place
3686 - event_faction
3687 - title
3688 - bot_name
3690 Input as stringId (number): *WARNING* LD must as coder to do function that return string_id if they want to use that type
3691 - dyn_string_id
3692 - string_id
3695 Input must be a enum value:
3696 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).
3697 - skill
3698 - faction
3699 - power_type
3700 - race
3701 - damage_type
3702 - characteristic
3703 - score
3704 - body_part
3706 Arguments: s(paramType), f(value) ->
3707 @param[in] paramType the type of the parameter
3708 @param[in] value the value of the parameter
3711 @code
3712 ($playerEid)getCurrentPlayerEid();
3713 ($botEid)group3.getBotEid(4);
3714 ()phraseBegin();
3715 ()phrasePushValue("integer", 15);
3716 ()phrasePushString("integer", "15");
3717 ()phrasePushString("literal", "Test 123");
3718 ()phrasePushString("player", $playerEid);
3719 ()phrasePushString("bot", $botEid);
3720 ()phrasePushString("item", "abc.sitem");
3721 ()phrasePushString("sbrick", "toto.sbrick");
3722 ()phrasePushString("creature_model", "toto.creature");
3723 ()phraseEndSystemMsg(0, "say", "PHRASE_WITH_SOME_PARAMETERS");
3724 @endcode
3726 void phrasePushString_ss_(CStateInstance* entity, CScriptStack& stack )
3728 std::string s = (std::string)stack.top(); stack.pop(); // get the param value
3729 std::string typeStr = (std::string)stack.top(); stack.pop(); // get the param type
3731 // construct a STRING_MANAGER::TParam in fonction of its type and its value
3732 STRING_MANAGER::TParamType type = STRING_MANAGER::stringToParamType(typeStr);
3733 STRING_MANAGER::TParam param;
3734 param.Type = type;
3735 switch( type )
3738 case STRING_MANAGER::money:
3740 NLMISC::fromString(s, param.Money);
3741 break;
3744 case STRING_MANAGER::player:
3745 case STRING_MANAGER::bot:
3746 case STRING_MANAGER::entity:
3749 NLMISC::CEntityId id;
3750 uint32 alias = 0;
3751 id.fromString(s.c_str());
3752 CAIEntityPhysical* entityPhysical=CAIS::instance().getEntityPhysical(TheDataset.getDataSetRow(id));
3753 if (entityPhysical)
3755 switch( entityPhysical->getRyzomType())
3757 case RYZOMID::creature:
3758 case RYZOMID::npc:
3761 CSpawnBot* sb = NLMISC::safe_cast<CSpawnBot*>(entityPhysical);
3762 alias = sb->getPersistent().getAlias();
3763 break;
3765 default:
3767 // player or other have no alias
3770 param.setEIdAIAlias( id, alias );
3772 break;
3774 case STRING_MANAGER::integer:
3776 NLMISC::fromString(s, param.Int);
3777 break;
3780 case STRING_MANAGER::time:
3782 NLMISC::fromString(s, param.Time);
3783 break;
3787 case STRING_MANAGER::item:
3788 case STRING_MANAGER::outpost:
3789 case STRING_MANAGER::creature_model:
3790 case STRING_MANAGER::creature:
3791 case STRING_MANAGER::sphrase:
3792 case STRING_MANAGER::sbrick:
3794 if (s.empty())
3796 nlwarning("Sheet name expected but not found in script");
3797 param.SheetId= CSheetId();
3799 else
3801 param.SheetId = CSheetId(s);
3803 break;
3807 case STRING_MANAGER::place:
3808 case STRING_MANAGER::event_faction:
3809 case STRING_MANAGER::title:
3810 case STRING_MANAGER::bot_name:
3812 param.Identifier = s;
3813 break;
3816 case STRING_MANAGER::skill:
3817 case STRING_MANAGER::faction:
3818 case STRING_MANAGER::power_type:
3819 case STRING_MANAGER::race:
3820 case STRING_MANAGER::damage_type:
3821 case STRING_MANAGER::characteristic:
3822 case STRING_MANAGER::score:
3823 case STRING_MANAGER::body_part:
3825 NLMISC::fromString(s, param.Enum);
3826 break;
3829 case STRING_MANAGER::literal:
3830 param.Literal.fromUtf8(s);
3831 break;
3833 case STRING_MANAGER::dyn_string_id:
3834 case STRING_MANAGER::string_id:
3835 NLMISC::fromString(s, param.StringId);
3836 break;
3838 case STRING_MANAGER::self:
3839 case STRING_MANAGER::role:
3840 case STRING_MANAGER::compass:
3841 case STRING_MANAGER::guild:
3842 case STRING_MANAGER::ecosystem:
3843 case STRING_MANAGER::classification_type:
3844 default:
3845 param.Type = STRING_MANAGER::invalid_value;
3847 break;
3850 PhraseParameters.Values.push_back(param);
3855 static void phraseEnd(CStateInstance* entity, CScriptStack& stack, CPhraseParameters::TMode mode)
3857 std::string funName = "phraseEnd";
3859 // get Function parameters
3861 std::string phraseId = (std::string)stack.top();stack.pop();
3862 std::string sayMode;
3863 if (mode != CPhraseParameters::EmoteMsg)
3865 sayMode = (std::string)stack.top();stack.pop();
3867 sint32 botIndex = (sint32)((float)stack.top());stack.pop();
3870 // Verify is bot is alived
3873 CGroup* group = entity->getGroup();
3874 if (!group)
3876 nlwarning("%s on a non Npc Group, doesn't work", funName.c_str());
3877 PhraseParameters.Values.clear();
3878 return;
3880 if (!group->isSpawned() || group->bots().isEmpty() || botIndex < 0 || group->bots().size() < static_cast<uint32>(botIndex))
3882 PhraseParameters.Values.clear();
3883 return;
3885 const CBot *const bot = group->getBot(botIndex);
3886 if ( !bot || !bot->isSpawned())
3888 PhraseParameters.Values.clear();
3889 return;
3891 CSpawnBot *const sp= bot->getSpawnObj();
3892 if ( !sp || !sp->isAlive() )
3894 PhraseParameters.Values.clear();
3895 return;
3898 // parse type of chat
3899 CChatGroup::TGroupType groupType;
3900 if (mode != CPhraseParameters::EmoteMsg)
3902 groupType = CChatGroup::stringToGroupType(sayMode);
3905 // verify phraseId validity
3906 if (phraseId.empty())
3908 nlwarning("%s %d: Phrase identifier is empty", funName.c_str(),static_cast<uint32>(mode));
3909 return;
3912 // send chat to client
3913 switch (mode)
3915 case CPhraseParameters::NpcMsg:
3916 npcChatParamToChannel(sp->dataSetRow(), groupType, phraseId.c_str(), PhraseParameters.Values);
3917 break;
3918 case CPhraseParameters::SystemMsg:
3919 STRING_MANAGER::sendSystemStringToClientAudience(sp->dataSetRow(),std::vector<NLMISC::CEntityId>(), groupType, phraseId.c_str(), PhraseParameters.Values);
3920 break;
3922 case CPhraseParameters::EmoteMsg:
3923 STRING_MANAGER::sendCustomEmoteTextToClientAudience(sp->dataSetRow(),std::vector<NLMISC::CEntityId>(), phraseId.c_str(), PhraseParameters.Values);
3924 break;
3927 PhraseParameters.Values.clear();
3930 //----------------------------------------------------------------------------
3931 /** @page code
3933 @subsection phraseEndNpcMsg_fss_
3934 Send a message with parameter through a bot says.
3935 Parameters are taken from the parameters stack.
3936 @see phrasePushValue_sf_
3937 @see phrasePushString_ss_
3939 Arguments: s(botIndex), s(sayType), s(phraseIdentifier) ->
3940 @param[in] botIndex the Position of the bot in the group ( see getBotIndexByName_s_f)
3941 @param[in] sayType Is the type of the say dialog ("say", "shout", "civilization", "territory", "universe", "arround", "system", "region")
3942 @param[in] phraseIdentifier Is the identifier phrase as seen in phrase_wk.uxt
3944 @code
3945 ()phrasePushString("literal", "text non traduit");
3946 ()groupOf5Bot.phraseEndNpcMsg(4, "say", "PHRASE_TOTO");
3947 @endcode
3949 WARNING
3950 In this case in the phrase_wk.txt PHRASE_TOTO must be defined as
3951 @code
3952 PHRASE_TOTO(bot b, literal l)
3954 [I am $b$, on this text is not translated $l$ ]
3956 @endcode
3958 The first parameter is ALWAYS the bot that says the text (value is automaticaly set)
3960 void phraseEndNpcMsg_fss_(CStateInstance* entity, CScriptStack& stack)
3962 phraseEnd(entity, stack, CPhraseParameters::NpcMsg);
3965 //----------------------------------------------------------------------------
3966 /** @page code
3968 @subsection phraseEndSystemMsg_fss_
3969 Send a message with parameter through system braodcast msg.
3970 Parameters are taken from the parameters stack.
3971 @see phrasePushValue_sf_
3972 @see phrasePushString_ss_
3974 Arguments: s(botIndex), s(sayType), s(phraseIdentifier) ->
3975 @param[in] botIndex the Position of the bot in the group ( see getBotIndexByName_s_f)
3976 @param[in] sayType Is the type of the say dialog ("say", "shout", "civilization", "territory", "universe", "arround", "system", "region")
3977 @param[in] phraseIdentifier Is the identifier phrase as seen in phrase_wk.uxt
3979 @code
3980 ()phrasePushString("literal", "Test des levels designer");
3981 ()groupOf5Bot.phraseEndSystemMsg(4, "say", "PHRASE_TOTO");
3982 @endcode
3984 *WARNING*
3985 In this case in the phrase_wk.txt PHRASE_TOTO must be defined as
3986 @code
3987 PHRASE_TOTO(literal l)
3989 [$l$]
3991 @endcode
3992 The first parameter is *NOT* automaticaly set to the bot that send the system msg as phraseEndNpcMsg_fss_.
3994 Because the msg can be send as "around". The broadcas msg must be send by a bot (that have a valid position)
3996 void phraseEndSystemMsg_fss_(CStateInstance* entity, CScriptStack& stack)
3998 phraseEnd(entity, stack, CPhraseParameters::SystemMsg);
4002 //----------------------------------------------------------------------------
4003 /** @page code
4005 @subsection phraseEndEmoteMsg_fs_
4006 Send a custom emote message with parameter through system braodcast msg.
4007 Parameters are taken from the parameters stack.
4008 @see phrasePushValue_sf_
4009 @see phrasePushString_ss_
4011 Arguments: s(botIndex), s(phraseIdentifier) ->
4012 @param[in] botIndex the Position of the bot in the group ( see getBotIndexByName_s_f)
4013 @param[in] phraseIdentifier Is the identifier phrase as seen in phrase_wk.uxt
4015 @code
4016 ($playerEid)getCurrentPlayerEid();
4017 ($botEid)getCurrentSpeakerEid();
4019 ()phrasePushString("player", $playerEid);
4020 ()groupOf5Bot.phraseEndEmoteMsg(,"PHRASE_TOTO1");
4022 ()phrasePushString("bot", $botEid);
4023 ()groupOf5Bot.phraseEndEmoteMsg(,"PHRASE_TOTO2");
4024 @endcode
4026 *WARNING*
4027 In this case in the phrase_wk.txt PHRASE_TOTO must be defined as
4028 @code
4029 PHRASE_TOTO1(player p)
4031 [$p$ is laughing ]
4033 PHRASE_TOTO2(bot b)
4035 [$b$ is sad ]
4037 @endcode
4038 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.
4040 The emote msg must be send by a bot (that have a valid position).
4042 void phraseEndEmoteMsg_fs_(CStateInstance* entity, CScriptStack& stack)
4044 phraseEnd(entity, stack, CPhraseParameters::EmoteMsg);
4048 //----------------------------------------------------------------------------
4049 /** @page code
4051 @subsection queryEgs_sscfs_
4052 Send a query msg to egs to know infos on a player.
4053 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
4055 Possible info to know are
4056 - Name
4057 - Hp
4058 - MaxHp
4059 - RatioHp
4060 - Sap
4061 - MaxSap
4062 - RatioSap
4063 - Focus
4064 - MaxFocus
4065 - RatioFocus
4066 - Stamina
4067 - MaxStamina
4068 - RatioStamina
4071 Arguments: s(botIndex), s(query), c(groupThatWillBeTriggered), f(idOfTheUserEvent), s(msgId)
4072 @param[in] botIndex the Position of the bot in the group ( see getBotIndexByName_s_f)
4073 @param[in] query The query we want to send
4074 @param[in] groupThatWillBeTriggered The group that will receive a user_event when the answer will come
4075 @param[in] idOfTheUserEvent The number of the user event that will be triggered
4076 @param[in] msgId The id of the msg
4078 Answer will be given by the getParam
4080 @code
4081 //Sening msg to EGS
4082 (@groupToNotify)boss_group.context();
4083 ()queryEgs("Name", $playerEid, @groupToNotify, 4, "MSG_NAME");
4084 ()queryEgs("Hp", $playerEid, @groupToNotify, 4, "msg1");
4085 ()queryEgs("MaxHp", $playerEid, @groupToNotify, 4, "msg2");
4086 ()queryEgs("RatioHp", $playerEid, @groupToNotify, 4, "msg3");
4087 ()queryEgs("Sap", $playerEid, @groupToNotify, 4, "msg4");
4088 ()queryEgs("MaxSap", $playerEid, @groupToNotify, 4, "msg5");
4089 ()queryEgs("RatioSap", $playerEid, @groupToNotify, 4, "msg6");
4090 ()queryEgs("Focus", $playerEid, @groupToNotify, 4, "msg7");
4091 ()queryEgs("MaxFocus", $playerEid, @groupToNotify, 4, "msg8");
4092 ()queryEgs("RatioFocus", $playerEid, @groupToNotify, 4, "msg9");
4093 ()queryEgs("Stamina", $playerEid, @groupToNotify, 4, "msg10");
4094 ()queryEgs("MaxStamina", $playerEid, @groupToNotify, 4, "msg11");
4095 ()queryEgs("RatioStamina", $playerEid, @groupToNotify, 4, "msg12");
4096 ()queryEgs("BestSkillLevel", $playerEid, @groupToNotify, 4, "msg13");
4097 @endcode
4098 Answer of the EGS
4099 @code
4100 // the user_event 4 of groupToNotify will be trigered
4101 ($msgName)getEventParam(0); // the msg name
4102 ($ret)getEventParam(1); // the return
4103 ($funName)getEventParam(2); // the name of the function
4104 ($playerEid)getEventParam(3); // the id of the player
4105 ($param1)getEventParam(4); // empty ot item, or sbrick or botEid
4107 if ($msgName == "MSG_NAME") {
4108 ()phrasePushString("literal", $ret);
4109 ()phrasePushString("player", $playerEid);
4110 ()boss_group.phraseEndNpcMsg(0, "say", "TEST_BOSS_TEST_MSG");
4112 else
4114 ()phrasePushString("player", $playerEid);
4115 ()phrasePushString("literal", $funName);
4116 ()phrasePushString("literal", $msgName);
4117 ()phrasePushString("integer", $ret);
4118 ()boss_group.phraseEndNpcMsg(0, "say", "TEST_BOSS_TEST_EGS_QUERY");
4121 @endcode
4124 void queryEgs_sscfs_(CStateInstance* entity, CScriptStack& stack)
4126 std::string funName = "queryEgs_sscfs_";
4127 // read input params
4128 string literal = (string)stack.top(); stack.pop();
4129 float useEventId = (float)stack.top(); stack.pop();
4130 CGroupNpc* const groupToNotify = dynamic_cast<CGroupNpc*>( (IScriptContext*)stack.top() ); stack.pop();
4131 string param1 = (string)stack.top(); stack.pop();
4132 string func = (string)stack.top(); stack.pop();
4134 // create a CUserEventMsg to send to EGS
4135 CGroup* const group = entity ? entity->getGroup() : 0;
4136 IManagerParent* const managerParent = (group&& group->getOwner()) ? group->getOwner()->getOwner():0;
4137 CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
4138 if (aiInstance == NULL)
4140 nlwarning("%s failed: the AI instance of the entity is NULL", funName.c_str());
4141 DEBUG_STOP;
4142 return;
4144 CQueryEgs msg;
4145 msg.InstanceId = aiInstance->getInstanceNumber();
4146 msg.GroupAlias = groupToNotify->getAlias();
4147 msg.EventId = (int)useEventId;
4148 msg.Params.push_back(literal);
4149 msg.Params.push_back(func);
4150 msg.Params.push_back(param1);
4151 msg.send("EGS");
4156 @subsection queryEgs_ssscfs_
4157 Send a query msg to egs to know infos on a player.
4158 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
4160 Possible info to know are:
4161 - KnowBrick (to knwo if the player know a specific brick); return value is 0 or 1 (if the player know the brick)
4162 - IsInInventory (to knwo has an item in inventory of in equipement); return value is 0, 1(item in equipment), 2(item in bag)
4163 - Target (to know if a player target a bot; return value is 0, 1(player target the bot)
4165 Arguments: s(botIndex), s(query), s(queryParam), c(groupThatWillBeTriggered), f(idOfTheUserEvent), s(msgId)
4166 @param[in] botIndex the Position of the bot in the group ( see getBotIndexByName_s_f)
4167 @param[in] query The query we want to send
4168 @param[in] queryParam Is the paramter of the query (a .creature of IsInInventory, a .sbrick for KnowBrick, a Bot EntityId for Target
4169 @param[in] groupThatWillBeTriggered The group that will receive a user_event when the answer will come
4170 @param[in] idOfTheUserEvent The number of the user event that will be triggered
4171 @param[in] msgId The id of the msg
4173 Answer will be given by the getParam
4174 @code
4175 //Sening msg to EGS
4176 //($playerEid)getCurrentPlayerEid();
4177 (@groupToNotify)boss_group.context();
4178 ()queryEgs("KnowBrick", $playerEid, "bfma01.sbrick", @groupToNotify, 4, "MSG_BRICK");
4179 ()queryEgs("IsInInventory", $playerEid, "iccm1bm.sitem", @groupToNotify, 4, "MSG_ITEM");
4180 ()queryEgs("Target", $playerEid, $botEid, @groupToNotify, 4, "msg14");
4181 @endcode
4183 Answer of the EGS
4184 @code
4185 ($msgName)getEventParam(0); // the msg name
4186 ($ret)getEventParam(1); // the return
4187 ($funName)getEventParam(2); // the name of the function
4188 ($playerEid)getEventParam(3); // the id of the player
4189 ($param1)getEventParam(4); // empty ot item, or sbrick or botEid
4191 if ($msgName == "MSG_ITEM")
4193 ()phrasePushString("item", $param1);
4194 ()phrasePushString("integer", $ret);
4195 ()boss_group.phraseEndNpcMsg(0, "say", "TEST_BOSS_TEST_EGS_QUERY_ITEM");
4196 } else if ($msgName == "MSG_BRICK") {
4197 ()phrasePushString("sbrick", $param1);
4198 ()phrasePushString("integer", $ret);
4199 ()boss_group.phraseEndNpcMsg(0, "say", "TEST_BOSS_TEST_EGS_QUERY_BRICK");
4201 } else if ($msgName == "MSG_NAME") {
4202 ()phrasePushString("literal", $ret);
4203 ()phrasePushString("player", $playerEid);
4204 ()boss_group.phraseEndNpcMsg(0, "say", "TEST_BOSS_TEST_MSG");
4206 else
4208 ()phrasePushString("player", $playerEid);
4209 ()phrasePushString("literal", $funName);
4210 ()phrasePushString("literal", $msgName);
4211 ()phrasePushString("integer", $ret);
4212 ()boss_group.phraseEndNpcMsg(0, "say", "TEST_BOSS_TEST_EGS_QUERY");
4215 @endcode
4217 void queryEgs_ssscfs_(CStateInstance* entity, CScriptStack& stack)
4219 std::string funName = "queryEgs_ssscfs_";
4220 // get input params
4221 string literal = (string)stack.top(); stack.pop();
4222 float useEventId = (float)stack.top(); stack.pop();
4223 CGroupNpc* const groupToNotify = dynamic_cast<CGroupNpc*>( (IScriptContext*)stack.top() ); stack.pop();
4224 string param2 = (string)stack.top(); stack.pop();
4225 string param1 = (string)stack.top(); stack.pop();
4226 string func = (string)stack.top(); stack.pop();
4228 // create CQueryEgs to send to egs
4229 CGroup* const group = entity ? entity->getGroup() : 0;
4230 IManagerParent* const managerParent = (group&& group->getOwner()) ? group->getOwner()->getOwner():0;
4231 CAIInstance* const aiInstance = dynamic_cast<CAIInstance*>(managerParent);
4232 if (aiInstance == NULL)
4234 nlwarning("%s failed: the AI instance of the entity is NULL", funName.c_str());
4235 DEBUG_STOP;
4236 return;
4238 CQueryEgs msg;
4239 msg.InstanceId = aiInstance->getInstanceNumber();
4240 msg.GroupAlias = groupToNotify->getAlias();
4241 msg.EventId = (int)useEventId;
4242 msg.Params.push_back(literal);
4243 msg.Params.push_back(func);
4244 msg.Params.push_back(param1);
4245 msg.Params.push_back(param2);
4246 msg.send("EGS");
4251 /** @page code
4253 @subsection summonPlayer_fs_
4255 Summon a player to a bot.
4257 Can be used by a boss to teleport a player. Or the create a teleporter.
4259 A player EntityId is used to identify the player.
4260 A index is used to identified the bot (index for the current group)
4263 Arguments: f(botIndex), s(playerEid) >
4264 @param[in] botIndex is the index of the bot in the current group(static group)
4265 @param[in] playerEid The entityId of the player
4267 @code
4268 ($playerId)getRandomPlayerAggroListTarget(0);
4269 ()teleportPlayer(0, $playerEid); // teleport player to the boss.
4270 @endcode
4272 void summonPlayer_fs_(CStateInstance* entity, CScriptStack& stack)
4275 std::string funName = "summonPlayer_fffs_";
4276 std::string playerEidStr = ((std::string)stack.top()); stack.pop();
4277 sint32 botIndex = (sint32)((float)stack.top()); stack.pop();
4280 // Verify is bot is alived
4281 CGroup* group = entity->getGroup();
4282 if (!group)
4284 nlwarning("%s on a non Npc Group, doesn't work", funName.c_str());
4285 return;
4287 if (!group->isSpawned() || group->bots().isEmpty() || botIndex < 0 || group->bots().size() < static_cast<uint32>(botIndex))
4289 return;
4291 const CBot *const bot = group->getBot(botIndex);
4292 if ( !bot || !bot->isSpawned())
4294 return;
4296 CSpawnBot *const sp= bot->getSpawnObj();
4297 if ( !sp || !sp->isAlive() )
4299 return;
4303 // Read position for mirror
4304 TDataSetRow row = sp->dataSetRow();
4305 if (! TheDataset.isAccessible( row ) )
4307 return;
4310 CMirrorPropValue<sint32> mirrorSymbolX( TheDataset, row, DSPropertyPOSX );
4311 CMirrorPropValue<sint32> mirrorSymbolY( TheDataset, row, DSPropertyPOSY );
4313 // retrieve the CBotPlayer
4314 NLMISC::CEntityId playerEid;
4315 playerEid.fromString(playerEidStr.c_str());
4316 CAIEntityPhysical *charEntity=CAIS::instance().getEntityPhysical(TheDataset.getDataSetRow(playerEid));
4317 if (!charEntity)
4318 return;
4320 // do nothing if one of them is dead
4321 if (!charEntity->isAlive() )
4323 return;
4327 // send teleport MSG
4328 TDataSetRow CharacterRowId = charEntity->dataSetRow();
4330 NLMISC::CEntityId player = CMirrors::getEntityId(CharacterRowId);
4332 if (player != NLMISC::CEntityId::Unknown)
4334 sint32 x2 = mirrorSymbolX.getValue();
4335 sint32 y2 = mirrorSymbolY.getValue();
4336 sint32 z2 = 0;
4337 float t = 0; // TODO direction to mob?
4339 NLNET::CMessage msgout( "TELEPORT_PLAYER" );
4340 nlWrite(msgout, serial, player );
4341 msgout.serial( const_cast<sint32 &>(x2) );
4342 msgout.serial( const_cast<sint32 &>(y2) );
4343 msgout.serial( const_cast<sint32 &>(z2) );
4344 msgout.serial( const_cast<float &>(t) );
4345 sendMessageViaMirror( "EGS", msgout );
4351 /** @page code
4353 @subsection teleportPlayer_sffff_
4355 Teleport a player to a position
4357 A player EntityId is used to identify the player.
4358 The position is identified by the value x,y,z and the heading
4361 Arguments: s(playerId), f(x), f(y), f(z), f(heading) >
4362 @param[in] playerId is EntityId of the player
4363 @param[in] x,y,z,heading is the new position of the player
4365 @code
4366 ($playerId)getRandomPlayerAggroListTarget(0);
4367 ()teleportPlayer($playerEid, 1000, 1000, 100, 0);
4368 @endcode
4370 void teleportPlayer_sffff_(CStateInstance* entity, CScriptStack& stack)
4372 // get player and position parameters
4373 float t = (float)stack.top(); stack.pop(); // heading
4374 float z = (float)stack.top(); stack.pop();
4375 float y = (float)stack.top(); stack.pop();
4376 float x = (float)stack.top(); stack.pop();
4377 std::string playerEidStr = (std::string)stack.top(); stack.pop();
4378 NLMISC::CEntityId playerEid;
4379 playerEid.fromString(playerEidStr.c_str());
4381 // retrieve the CBotPlayer
4382 CAIEntityPhysical *charEntity=CAIS::instance().getEntityPhysical(TheDataset.getDataSetRow(playerEid));
4383 if (!charEntity)
4384 return;
4386 // do nothing if one of them is dead
4387 if (!charEntity->isAlive() )
4389 return;
4392 // teleport player to position
4393 if (playerEid != NLMISC::CEntityId::Unknown)
4395 sint32 x2 = static_cast<sint32>(x*1000);
4396 sint32 y2 = static_cast<sint32>(y*1000);
4397 sint32 z2 = static_cast<sint32>(z*1000);
4399 NLNET::CMessage msgout( "TELEPORT_PLAYER" );
4400 msgout.serial( const_cast<CEntityId &>(playerEid) );
4401 msgout.serial( const_cast<sint32 &>(x2) );
4402 msgout.serial( const_cast<sint32 &>(y2) );
4403 msgout.serial( const_cast<sint32 &>(z2) );
4404 msgout.serial( const_cast<float &>(t) );
4405 sendMessageViaMirror( "EGS", msgout );
4409 //----------------------------------------------------------------------------
4410 /** @page code
4412 @subsection getBotEid_f_s
4413 Get the bot EntityId by its Index.
4414 Arguments: f(botIndex) -> s(botEid)
4416 @param[in] botIndex the Position of the bot in the group
4417 @param[out] botEid The entity Id given by the bot (or empty) if the indexed bot is not from the group
4419 @code
4420 (index)getBotIndexByName("bot_toto");
4421 ($botEid)getBotEid(index);
4422 if (index != -1)
4424 ()phrasePushValue("entity", $botEid);
4425 ()phraseEndEmoteMsg(index, "PHRASE_YOUR_ARE_CLICKING_ON_ME");
4427 @endcode
4430 void getBotEid_f_s(CStateInstance* entity, CScriptStack& stack)
4432 std::string funName = "getBotEid_f_s";
4433 // get spawn Bot by its index
4434 CGroup* group = entity->getGroup();
4435 if (!group)
4437 nlwarning("%s on a non Npc Group, doesn't work", funName.c_str());
4438 stack.push(std::string(CEntityId::Unknown.toString()));
4439 return;
4441 sint32 botIndex = (sint32)((float)stack.top());stack.pop();
4442 if (!group->isSpawned() || group->bots().isEmpty() || botIndex < 0 || group->bots().size() < static_cast<uint32>(botIndex))
4444 stack.push(std::string(CEntityId::Unknown.toString()));
4445 return;
4448 const CBot *const bot = group->getBot(botIndex);
4449 if ( !bot || !bot->isSpawned()) { stack.push(std::string(CEntityId::Unknown.toString())); return;}
4452 CSpawnBot *const sb= bot->getSpawnObj();
4453 if ( !sb ||!sb->isAlive()) {stack.push(std::string(CEntityId::Unknown.toString())); return;};
4455 // return the entity id of the spawn bot
4456 CEntityId id= sb->getEntityId();
4457 stack.push(std::string(id.toString()));
4461 //----------------------------------------------------------------------------
4462 /** @page code
4464 @subsection getBotIndex_s_f
4465 Get the bot Index by its entityId.
4466 Entity Id of a bot can be given via getCurrentSpeackerEid().
4467 It can be useful to Known the index of the bot in the group with the EntityId.
4469 Arguments: s(botEid) -> f(botIndex),
4471 @param[in] botEid The entity Id given by the bot
4472 @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)
4474 @code
4475 ($botEid)getCurrentSpeakerEid();
4476 (index)getBotIndex($botEid);
4477 if (index != -1)
4479 ()phrasePushValue("entity", $botEid);
4480 ()phraseEndNpcg(index, "PHRASE_YOUR_ARE_CLICKING_ON_ME");
4482 @endcode
4484 void getBotIndex_s_f(CStateInstance* entity, CScriptStack& stack)
4486 std::string funName = "getBotEid_f_s";
4487 CGroup* group = entity->getGroup();
4488 if (!group)
4490 nlwarning("%s on a non Npc Group, doesn't work", funName.c_str());
4491 stack.push(std::string(CEntityId::Unknown.toString()));
4492 return;
4494 std::string botEid = (std::string)stack.top(); stack.pop();
4496 // look in the group if the bot is alived
4497 uint32 botIndex = 0, last = group->bots().size();
4498 for ( ;botIndex != last; ++botIndex)
4500 if (!group->isSpawned() || group->bots().isEmpty() || group->bots().size() < static_cast<uint32>(botIndex))
4502 continue;
4505 const CBot *const bot = group->getBot(botIndex);
4506 if ( !bot || !bot->isSpawned()) { continue; }
4509 CSpawnBot *const sb= bot->getSpawnObj();
4510 if ( !sb ||!sb->isAlive()) {continue;};
4511 CEntityId id= sb->getEntityId();
4512 // if bot is alived return its index
4513 if (botEid == id.toString())
4515 stack.push((float)botIndex);
4516 return;
4520 stack.push((float)-1);
4521 return;
4525 /** @page code
4527 @subsection getCurrentPlayerEid__s
4528 Get the entity id of the player that is clicking on a bot.
4530 WARNING the function is only valid when called from an player_target_npc event.
4533 Arguments: -> s(playerEidAsString),
4534 @param[out] playerEidAsString is EntityId as string from the player.
4536 @code
4537 ($playerEid)getCurrentPlayerEid();
4538 (index)getBotIndexByName("toto");
4539 (distance)getPlayerDistance(index, $playerEid);
4540 phrasePushString("player", $playerEid);
4541 phrasePushValue("interger", distance);
4542 phraseEndNpcMsg(index, "say", "MSG_BOT_B_SAYS_THE_PLAYER_P_IS_AT_DISTANCE_D");\x13
4543 @endcode
4545 void getCurrentPlayerEid__s(CStateInstance* entity, CScriptStack& stack)
4547 std::string funName = "getCurrentPlayerEid__s";
4548 CEntityId id = CEntityId::Unknown;
4549 // if we are in player_target_npc event TempPlayer is valid
4550 if (!TempPlayer)
4552 //TempPlayer is invalid so return Unkwn eid
4553 std::string s = id.toString();
4554 stack.push(s);
4555 return;
4557 // TempPlayer is valid so return eid
4558 id = TempPlayer->getEntityId();
4559 std::string s = id.toString();
4560 stack.push(s);
4561 return;
4565 /** @page code
4567 @subsection getCurrentSpeakerEid__s
4568 Get the entity id of the bot at which the player as that is clicking at.
4570 WARNING the function is only valid when called from an player_target_npc event.
4573 Arguments: -> s(botEidAsString),
4574 @param[out] botEidAsString is EntityId as string from the bot.
4576 @code
4577 ($botEid)getCurrentSpeakerEid();
4578 ($playerEid)getCurrentSpeakerEid();
4580 phrasePushString("player", $playerEid);
4581 phrasePushValue("bot", $botEid);
4582 phraseEndEmotMsg(index, "EMOT_PLAYER_INSULT_BOT");
4583 @endcode
4585 void getCurrentSpeakerEid__s(CStateInstance* entity, CScriptStack& stack)
4587 std::string funName = "getCurrentSpeakerEid__s";
4588 CEntityId id = CEntityId::Unknown;
4589 // if we are in player_target_npc event TempSpeaker is valid
4590 if (!TempSpeaker)
4592 //TempSpeaker is invalid so return Unkwn eid
4593 std::string s = id.toString();
4594 stack.push(s);
4595 return;
4597 //TempSpeaker is valid so return correct eid
4598 id = TempSpeaker->getEntityId();
4599 std::string s = id.toString();
4600 stack.push(s);
4601 return;
4604 //----------------------------------------------------------------------------
4605 /** @page code
4607 @subsection setSheet_s_
4608 Change the sheet of a creature
4610 Arguments: -> s(sheetName)
4612 @code
4613 ()setSheet('ccdeb2');
4615 @endcode
4618 void setSheet_s_(CStateInstance* entity, CScriptStack& stack)
4620 string sheetname = stack.top();
4621 stack.pop();
4623 CSheetId sheetId(sheetname+".creature");
4624 if (sheetId==CSheetId::Unknown)
4625 return;
4627 FOREACH(itBot, CCont<CBot>, entity->getGroup()->bots())
4629 CBot* bot = *itBot;
4630 if (bot)
4632 AISHEETS::ICreatureCPtr const sheet = AISHEETS::CSheets::getInstance()->lookup(sheetId);
4633 if (!sheet.isNull())
4634 bot->triggerSetSheet(sheet);
4639 //----------------------------------------------------------------------------
4640 /** @page code
4642 @subsection setClientSheet_s_
4643 Change the client sheet of a creature
4645 Arguments: -> s(sheetName)
4647 @code
4648 ()setClientSheet('ccdeb2');
4650 @endcode
4653 void setClientSheet_s_(CStateInstance* entity, CScriptStack& stack)
4655 string sheetname = stack.top();
4656 stack.pop();
4658 if (sheetname.find(".creature") == string::npos)
4659 sheetname += ".creature";
4661 FOREACH(itBot, CCont<CBot>, entity->getGroup()->bots())
4663 CBot* bot = *itBot;
4664 if (bot)
4666 bot->setClientSheet(sheetname);
4671 /****************************************************************************/
4673 //----------------------------------------------------------------------------
4674 /** @page code
4676 @subsection setHealer_f_
4677 Make the group healer (need test)
4679 Arguments: -> f(isHealer)
4681 @code
4682 ()setHealer(1);
4684 @endcode
4687 void setHealer_f_(CStateInstance* entity, CScriptStack& stack)
4689 bool value = ((float)stack.top())!=0.f;
4690 stack.pop();
4692 CGroup* group = entity->getGroup();
4694 if (group->isSpawned())
4696 FOREACH(itBot, CCont<CBot>, group->bots())
4698 CBot* bot = *itBot;
4699 if (bot)
4701 bot->setHealer(value);
4702 // break; // :NOTE: Only set first bot as a healer
4708 /****************************************************************************/
4710 //----------------------------------------------------------------------------
4711 /** @page code
4713 @subsection sitDown__
4714 Make the group sit Down
4716 Arguments: ->
4718 @code
4719 ()sitDown();
4721 @endcode
4724 // CStateInstance
4725 void sitDown__(CStateInstance* entity, CScriptStack& stack)
4728 CGroup* group = entity->getGroup();
4730 if (!group)
4732 nlwarning("sitDown__ failed");
4733 return;
4736 CAILogicActionSitDownHelper::sitDown(group);
4740 //----------------------------------------------------------------------------
4741 /** @page code
4743 @subsection standUp
4744 Make the group stand up (if was previously stand down)
4746 Arguments: ->
4748 @code
4749 ()standUp();
4751 @endcode
4754 // CStateInstance
4755 void standUp__(CStateInstance* entity, CScriptStack& stack)
4757 CGroup* group = entity->getGroup();
4758 if (!group)
4760 nlwarning("standUp__ failed");
4761 return;
4764 CAILogicActionSitDownHelper::standUp(group);
4767 //----------------------------------------------------------------------------
4768 /** @page code
4770 @subsection standUp
4771 Use to implement setConditionRet
4773 Arguments: ->
4775 @code
4776 ()setConditionRet(1);
4778 @endcode
4781 // CStateInstance
4782 void setConditionSuccess_f_(CStateInstance* entity, CScriptStack& stack)
4784 bool conditionState = (uint32)((float)stack.top()) != 0;
4785 CGroup* group = entity->getGroup();
4786 if (!group)
4788 nlwarning("setConditionSuccess_f_ failed");
4789 return;
4792 CAILogicDynamicIfHelper::setConditionSuccess(conditionState);
4795 inline
4796 static float randomAngle()
4798 uint32 const maxLimit = CAngle::PI*2;
4799 float val = (float)CAIS::rand32(maxLimit);
4800 return val;
4803 //----------------------------------------------------------------------------
4804 /** @page code
4806 @subsection facing_f_
4808 The npc will face the given direction
4811 Arguments: f(direction)
4812 @param[in] direction is the new angle of the bot in radians
4814 @code
4815 ()facing(3.14);
4816 @endcode
4820 // CStateInstance
4821 void facing_f_(CStateInstance* entity, CScriptStack& stack)
4823 float const theta = (float)stack.top(); stack.pop();
4824 CGroup* group = entity->getGroup();
4826 bool bRandomAngle = false;
4827 if (theta > (NLMISC::Pi * 2.0) || theta < (-NLMISC::Pi * 2.0))
4828 bRandomAngle = true;
4830 if (group->isSpawned())
4832 FOREACH(itBot, CCont<CBot>, group->bots())
4834 CBot* bot = *itBot;
4835 if (bot)
4837 if (bot->isSpawned())
4839 CSpawnBot *spawnBot = bot->getSpawnObj();
4841 if (bRandomAngle)
4842 spawnBot->setTheta(randomAngle());
4843 else
4844 spawnBot->setTheta(theta);
4852 std::map<std::string, FScrptNativeFunc> nfGetGroupNativeFunctions()
4854 std::map<std::string, FScrptNativeFunc> functions;
4856 #define REGISTER_NATIVE_FUNC(cont, func) cont.insert(std::make_pair(std::string(#func), &func))
4858 REGISTER_NATIVE_FUNC(functions, spawn__);
4859 REGISTER_NATIVE_FUNC(functions, despawn_f_);
4860 REGISTER_NATIVE_FUNC(functions, isAlived__f);
4861 REGISTER_NATIVE_FUNC(functions, spawnBot_fsssffff_);
4862 REGISTER_NATIVE_FUNC(functions, newNpcChildGroupPos_ssfff_c);
4863 REGISTER_NATIVE_FUNC(functions, newNpcChildGroupPos_ssfff_);
4864 REGISTER_NATIVE_FUNC(functions, newNpcChildGroupPos_ssff_c);
4865 REGISTER_NATIVE_FUNC(functions, newNpcChildGroupPos_ssff_);
4866 REGISTER_NATIVE_FUNC(functions, newNpcChildGroupPosMl_ssffff_c);
4867 REGISTER_NATIVE_FUNC(functions, newNpcChildGroupPosMl_ssffff_);
4868 REGISTER_NATIVE_FUNC(functions, newNpcChildGroupPosMl_ssfff_c);
4869 REGISTER_NATIVE_FUNC(functions, newNpcChildGroupPosMl_ssfff_);
4870 REGISTER_NATIVE_FUNC(functions, newNpcChildGroup_sssf_c);
4871 REGISTER_NATIVE_FUNC(functions, newNpcChildGroup_sssf_);
4872 REGISTER_NATIVE_FUNC(functions, newNpcChildGroup_sss_c);
4873 REGISTER_NATIVE_FUNC(functions, newNpcChildGroup_sss_);
4874 REGISTER_NATIVE_FUNC(functions, newNpcChildGroupMl_sssff_c);
4875 REGISTER_NATIVE_FUNC(functions, newNpcChildGroupMl_sssff_);
4876 REGISTER_NATIVE_FUNC(functions, newNpcChildGroupMl_sssf_c);
4877 REGISTER_NATIVE_FUNC(functions, newNpcChildGroupMl_sssf_);
4878 REGISTER_NATIVE_FUNC(functions, spawnManager_s_);
4879 REGISTER_NATIVE_FUNC(functions, sitDown__);
4880 REGISTER_NATIVE_FUNC(functions, standUp__);
4881 REGISTER_NATIVE_FUNC(functions, despawnManager_s_);
4882 REGISTER_NATIVE_FUNC(functions, getMidPos__ff);
4883 REGISTER_NATIVE_FUNC(functions, getGroupTemplateWithFlags_sss_s);
4884 REGISTER_NATIVE_FUNC(functions, getGroupTemplateWithFlags_ss_s);
4885 REGISTER_NATIVE_FUNC(functions, getZoneWithFlags_ssss_s);
4886 REGISTER_NATIVE_FUNC(functions, getZoneWithFlags_sss_s);
4887 REGISTER_NATIVE_FUNC(functions, getNearestZoneWithFlags_ffsss_s);
4888 REGISTER_NATIVE_FUNC(functions, getNearestZoneWithFlags_ffss_s);
4889 REGISTER_NATIVE_FUNC(functions, getNearestZoneWithFlagsStrict_ffsss_s);
4890 REGISTER_NATIVE_FUNC(functions, getNearestZoneWithFlagsStrict_ffss_s);
4891 REGISTER_NATIVE_FUNC(functions, getNeighbourZoneWithFlags_ssss_s);
4892 REGISTER_NATIVE_FUNC(functions, getNeighbourZoneWithFlags_sss_s);
4893 REGISTER_NATIVE_FUNC(functions, setAggro_ff_);
4894 REGISTER_NATIVE_FUNC(functions, setCanAggro_f_);
4895 REGISTER_NATIVE_FUNC(functions, clearAggroList_f_);
4896 REGISTER_NATIVE_FUNC(functions, clearAggroList__);
4897 REGISTER_NATIVE_FUNC(functions, setMode_s_);
4898 REGISTER_NATIVE_FUNC(functions, setAutoSpawn_f_);
4899 REGISTER_NATIVE_FUNC(functions, setMaxHP_ff_);
4900 REGISTER_NATIVE_FUNC(functions, setHPLevel_f_);
4901 REGISTER_NATIVE_FUNC(functions, setHPScale_f_);
4902 REGISTER_NATIVE_FUNC(functions, scaleHP_f_);
4903 REGISTER_NATIVE_FUNC(functions, setBotHPScaleByAlias_fs_);
4904 REGISTER_NATIVE_FUNC(functions, downScaleHP_f_);
4905 REGISTER_NATIVE_FUNC(functions, upScaleHP_f_);
4906 REGISTER_NATIVE_FUNC(functions, addHP_f_);
4907 REGISTER_NATIVE_FUNC(functions, giveHP_f_);
4908 REGISTER_NATIVE_FUNC(functions, aiAction_s_);
4909 REGISTER_NATIVE_FUNC(functions, aiActionSelf_s_);
4910 REGISTER_NATIVE_FUNC(functions, addProfileParameter_s_);
4911 REGISTER_NATIVE_FUNC(functions, addProfileParameter_ss_);
4912 REGISTER_NATIVE_FUNC(functions, addProfileParameter_sf_);
4913 REGISTER_NATIVE_FUNC(functions, removeProfileParameter_s_);
4914 REGISTER_NATIVE_FUNC(functions, addPersistentProfileParameter_s_);
4915 REGISTER_NATIVE_FUNC(functions, addPersistentProfileParameter_ss_);
4916 REGISTER_NATIVE_FUNC(functions, addPersistentProfileParameter_sf_);
4917 REGISTER_NATIVE_FUNC(functions, removePersistentProfileParameter_s_);
4918 REGISTER_NATIVE_FUNC(functions, getOutpostStateName__s);
4919 REGISTER_NATIVE_FUNC(functions, isOutpostTribeOwner__f);
4920 REGISTER_NATIVE_FUNC(functions, isOutpostGuildOwner__f);
4921 REGISTER_NATIVE_FUNC(functions, getEventParam_f_f);
4922 REGISTER_NATIVE_FUNC(functions, getEventParam_f_s);
4923 REGISTER_NATIVE_FUNC(functions, setSheet_s_);
4924 REGISTER_NATIVE_FUNC(functions, setClientSheet_s_);
4925 REGISTER_NATIVE_FUNC(functions, setHealer_f_);
4926 REGISTER_NATIVE_FUNC(functions, setConditionSuccess_f_);
4927 REGISTER_NATIVE_FUNC(functions, facing_f_);
4928 REGISTER_NATIVE_FUNC(functions, setUrl_ss_);
4930 // Boss functions (custom text)
4931 REGISTER_NATIVE_FUNC(functions, phraseBegin__);
4932 REGISTER_NATIVE_FUNC(functions, phrasePushValue_sf_);
4933 REGISTER_NATIVE_FUNC(functions, phrasePushString_ss_);
4934 REGISTER_NATIVE_FUNC(functions, phraseEndNpcMsg_fss_);
4935 REGISTER_NATIVE_FUNC(functions, phraseEndSystemMsg_fss_);
4936 REGISTER_NATIVE_FUNC(functions, phraseEndEmoteMsg_fs_);
4938 // Boss functions (Bot infos)
4939 REGISTER_NATIVE_FUNC(functions, getBotIndex_s_f);
4940 REGISTER_NATIVE_FUNC(functions, getBotEid_f_s);
4941 REGISTER_NATIVE_FUNC(functions, getCurrentSpeakerEid__s);
4942 REGISTER_NATIVE_FUNC(functions, getBotIndexByName_s_f);
4943 REGISTER_NATIVE_FUNC(functions, isGroupAlived__f);
4944 REGISTER_NATIVE_FUNC(functions, isBotAlived_f_f);
4946 // Boss functions (Player infos)
4947 REGISTER_NATIVE_FUNC(functions, isPlayerAlived_s_f);
4948 REGISTER_NATIVE_FUNC(functions, getPlayerStat_ss_f);
4949 REGISTER_NATIVE_FUNC(functions, getPlayerPosition_s_ff);
4950 REGISTER_NATIVE_FUNC(functions, getPlayerDistance_fs_f);
4951 REGISTER_NATIVE_FUNC(functions, getCurrentPlayerEid__s);
4952 REGISTER_NATIVE_FUNC(functions, queryEgs_sscfs_);
4953 REGISTER_NATIVE_FUNC(functions, queryEgs_ssscfs_);
4955 // Boss functions (Aggro list)
4956 REGISTER_NATIVE_FUNC(functions, getCurrentPlayerAggroListTarget_f_s);
4957 REGISTER_NATIVE_FUNC(functions, getRandomPlayerAggroListTarget_f_s);
4958 REGISTER_NATIVE_FUNC(functions, getAggroListElement_ff_s);
4959 REGISTER_NATIVE_FUNC(functions, getAggroListSize_f_f);
4960 REGISTER_NATIVE_FUNC(functions, setAggroListTarget_fs_);
4961 REGISTER_NATIVE_FUNC(functions, setGroupAggroListTarget_s_);
4962 REGISTER_NATIVE_FUNC(functions, setManagerAggroListTarget_ss_);
4964 // Boss functions (Time infos)
4965 REGISTER_NATIVE_FUNC(functions, getServerTimeStr__s);
4966 REGISTER_NATIVE_FUNC(functions, getServerTime__s);
4967 REGISTER_NATIVE_FUNC(functions, getRyzomDateStr__s);
4968 REGISTER_NATIVE_FUNC(functions, getRyzomDate__s);
4970 // Boss function (teleport actions)
4971 REGISTER_NATIVE_FUNC(functions, teleportPlayer_sffff_);
4972 REGISTER_NATIVE_FUNC(functions, summonPlayer_fs_);
4975 #undef REGISTER_NATIVE_FUNC
4977 return functions;