1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "script_compiler.h"
21 #include "ai_grp_npc.h"
22 #include "group_profile.h"
23 #include "ai_generic_fight.h"
24 #include "server_share/msg_brick_service.h"
26 #include "continent_inline.h"
27 #include "dyn_grp_inline.h"
29 #include "ai_script_data_manager.h"
31 #include "nf_helpers.h"
33 #include "game_share/send_chat.h"
34 #include "game_share/string_manager_sender.h"
40 using namespace NLMISC
;
42 using namespace AICOMP
;
43 using namespace AITYPES
;
44 using namespace RYAI_MAP_CRUNCH
;
47 //----------------------------------------------------------------------------
51 Spawns the current group.
57 void spawn__(CStateInstance
* entity
, CScriptStack
& stack
)
61 nlwarning("spawnInstance failed");
64 CGroup
const* const grp
= entity
->getGroup();
68 grp
->getSpawnObj()->spawnBots(grp
->botName
, grp
->botVpx
);
72 //----------------------------------------------------------------------------
75 @subsection despawn_f_
76 Depawns the current group.
78 Arguments: f(Immediatly) ->
79 @param Immediatly is whether the groups spawns immediatly (1) or not (0)
82 ()despawn(0); // despawn
83 ()despawn(1); // despawn immediatement
88 void despawn_f_(CStateInstance
* entity
, CScriptStack
& stack
)
90 float const immediatly
= stack
.top();
95 nlwarning("despawnInstance failed");
99 CGroup
* const grp
= entity
->getGroup();
102 nlwarning("despawn : entity '%s'%s is not a group ? ",
103 entity
->aliasTreeOwner()->getAliasFullName().c_str(),
104 entity
->aliasTreeOwner()->getAliasString().c_str());
107 grp
->despawnBots(immediatly
!=0);
110 //----------------------------------------------------------------------------
113 @subsection spawnBot_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) ->
124 void spawnBot_fsssffff_(CStateInstance
* entity
, CScriptStack
& stack
)
126 double dispersionRadius
= (double)(float)stack
.top();
128 double orientation
= (double)(float)stack
.top();
130 double y
= (double)(float)stack
.top();
132 double x
= (double)(float)stack
.top();
134 string look
= (string
)stack
.top();
136 string name
= (string
)stack
.top();
139 CSheetId
sheetId((string
)stack
.top());
141 uint nbBots
= (uint
)(float)stack
.top();
144 IManagerParent
* const managerParent
= entity
->getGroup()->getOwner()->getOwner();
145 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
149 CGroupNpc
* grp
= dynamic_cast<CGroupNpc
*>(entity
->getGroup());
151 aiInstance
->eventCreateNpcBot(grp
, nbBots
, true, sheetId
, CAIVector(x
, y
), name
, orientation
, dispersionRadius
, look
, grp
->botName
, grp
->botVpx
);
155 //----------------------------------------------------------------------------
158 @subsection isAlived__f
159 Test if the group is alived
161 Arguments: -> f(Immediatly)
162 @return 1 if group is spawned
170 void isAlived__f(CStateInstance
* entity
, CScriptStack
& stack
)
179 CGroup
* const grp
= entity
->getGroup();
182 nlwarning("isAlived__f : entity '%s'%s is not a group ? ",
183 entity
->aliasTreeOwner()->getAliasFullName().c_str(),
184 entity
->aliasTreeOwner()->getAliasString().c_str());
189 if (!grp
->isSpawned())
196 for (uint i
=0; i
<grp
->bots().size(); ++i
)
198 const CBot
*const bot
= grp
->getBot(i
);
200 || !bot
->isSpawned())
204 CAIEntityPhysical
*const ep
=bot
->getSpawnObj();
216 //----------------------------------------------------------------------------
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
231 (@grp)newNpcChildGroupPos("class_forager", "state_machine_1", x, y, 30);
235 // CGroup not in a family behaviour
236 void newNpcChildGroupPos_ssfff_c(CStateInstance
* entity
, CScriptStack
& stack
)
238 double dispersionRadius
= (double)(float)stack
.top();
240 float const y
= stack
.top();
242 float const x
= stack
.top();
245 IManagerParent
* const managerParent
= entity
->getGroup()->getOwner()->getOwner();
246 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
250 if (dispersionRadius
<0.)
251 dispersionRadius
= 0.;
252 stack
.push(spawnNewGroup(entity
, stack
, aiInstance
, CAIVector(x
, y
), -1, dispersionRadius
));
255 //----------------------------------------------------------------------------
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
269 ()newNpcChildGroupPos("class_forager", "state_machine_1", x, y, 30);
273 // CGroup not in a family behaviour
274 void newNpcChildGroupPos_ssfff_(CStateInstance
* entity
, CScriptStack
& stack
)
276 double dispersionRadius
= (double)(float)stack
.top();
278 float const y
= stack
.top();
280 float const x
= stack
.top();
283 IManagerParent
* const managerParent
= entity
->getGroup()->getOwner()->getOwner();
284 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
288 if (dispersionRadius
<0.)
289 dispersionRadius
= 0.;
290 spawnNewGroup(entity
, stack
, aiInstance
, CAIVector(x
, y
), -1, dispersionRadius
);
293 //----------------------------------------------------------------------------
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
307 (@grp)newNpcChildGroupPos("class_forager", "state_machine_1", x, y);
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 //----------------------------------------------------------------------------
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
331 ()newNpcChildGroupPos("class_forager", "state_machine_1", x, y);
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 //----------------------------------------------------------------------------
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
358 (@grp)newNpcChildGroupPosMl("class_forager", "state_machine_1", x, y, 13, 7.5);
362 // CGroup not in a family behaviour
363 void newNpcChildGroupPosMl_ssffff_c(CStateInstance
* entity
, CScriptStack
& stack
)
365 double dispersionRadius
= (double)(float)stack
.top();
367 float const y
= stack
.top();
369 float const x
= stack
.top();
372 IManagerParent
* const managerParent
= entity
->getGroup()->getOwner()->getOwner();
373 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
377 if (dispersionRadius
<0.)
378 dispersionRadius
= 0.;
379 stack
.push(spawnNewGroup(entity
, stack
, aiInstance
, CAIVector(x
,y
), -1, dispersionRadius
));
382 //----------------------------------------------------------------------------
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
397 ()newNpcChildGroupPosMl("class_forager", "state_machine_1", x, y, 13, 7.5);
401 // CGroup not in a family behaviour
402 void newNpcChildGroupPosMl_ssffff_(CStateInstance
* entity
, CScriptStack
& stack
)
404 double dispersionRadius
= (double)(float)stack
.top();
406 float const y
= stack
.top();
408 float const x
= stack
.top();
411 IManagerParent
* const managerParent
= entity
->getGroup()->getOwner()->getOwner();
412 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
416 if (dispersionRadius
<0.)
417 dispersionRadius
= 0.;
418 spawnNewGroup(entity
, stack
, aiInstance
, CAIVector(x
,y
), -1, dispersionRadius
);
421 //----------------------------------------------------------------------------
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
436 (@grp)newNpcChildGroupPosMl("class_forager", "state_machine_1", x, y, 13);
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 //----------------------------------------------------------------------------
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
461 ()newNpcChildGroupPosMl("class_forager", "state_machine_1", x, y, 13);
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 //----------------------------------------------------------------------------
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
488 void getMidPos__ff(CStateInstance
* entity
, CScriptStack
& stack
)
490 CGroup
* const group
= entity
->getGroup();
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());
506 //----------------------------------------------------------------------------
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
520 (@grp)newNpcChildGroup("class_forager", "state_machine_1", $zone, 10);
524 // CGroup not in a family behaviour
525 void newNpcChildGroup_sssf_c(CStateInstance
* entity
, CScriptStack
& stack
)
527 double dispersionRadius
= (double)(float)stack
.top();
529 TStringId
const zoneName
= CStringMapper::map(stack
.top());
532 IManagerParent
* const managerParent
= entity
->getGroup()->getOwner()->getOwner();
533 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
537 CNpcZone
const* spawnZone
= aiInstance
->getZone(zoneName
);
540 string StateMachine
= stack
.top();
543 nlwarning("newNpcChildGroup failed : spawnZone Not Found ! for StateMachine : %s", StateMachine
.c_str());
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 //----------------------------------------------------------------------------
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
569 ()newNpcChildGroup("class_forager", "state_machine_1", $zone, 10);
573 // CGroup not in a family behaviour
574 void newNpcChildGroup_sssf_(CStateInstance
* entity
, CScriptStack
& stack
)
576 double dispersionRadius
= (double)(float)stack
.top();
578 TStringId
const zoneName
= CStringMapper::map(stack
.top());
581 IManagerParent
* const managerParent
= entity
->getGroup()->getOwner()->getOwner();
582 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
586 CNpcZone
const* spawnZone
= aiInstance
->getZone(zoneName
);
589 string StateMachine
= stack
.top();
592 nlwarning("newNpcChildGroup failed : spawnZone Not Found ! for StateMachine : %s", StateMachine
.c_str());
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 //----------------------------------------------------------------------------
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
618 (@grp)newNpcChildGroup("class_forager", "state_machine_1", $zone);
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 //----------------------------------------------------------------------------
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
641 ()newNpcChildGroup("class_forager", "state_machine_1", $zone);
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 //----------------------------------------------------------------------------
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
667 (@grp)newNpcChildGroupMl("class_forager", "state_machine_1", $zone, 2, 50);
671 // CGroup not in a family behaviour
672 void newNpcChildGroupMl_sssff_c(CStateInstance
* entity
, CScriptStack
& stack
)
674 double dispersionRadius
= (double)(float)stack
.top();
676 int baseLevel
= (int)(float)stack
.top();
678 TStringId
const zoneName
= CStringMapper::map(stack
.top());
681 IManagerParent
* const managerParent
= entity
->getGroup()->getOwner()->getOwner();
682 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
686 CNpcZone
const* spawnZone
= aiInstance
->getZone(zoneName
);
689 string StateMachine
= stack
.top();
692 nlwarning("newNpcChildGroup failed : spawnZone Not Found ! for StateMachine : %s", StateMachine
.c_str());
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 //----------------------------------------------------------------------------
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
719 ()newNpcChildGroupMl("class_forager", "state_machine_1", $zone, 2, 50);
723 // CGroup not in a family behaviour
724 void newNpcChildGroupMl_sssff_(CStateInstance
* entity
, CScriptStack
& stack
)
726 double dispersionRadius
= (double)(float)stack
.top();
728 int baseLevel
= (int)(float)stack
.top();
730 TStringId
const zoneName
= CStringMapper::map(stack
.top());
733 IManagerParent
* const managerParent
= entity
->getGroup()->getOwner()->getOwner();
734 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
738 CNpcZone
const* spawnZone
= aiInstance
->getZone(zoneName
);
741 string StateMachine
= stack
.top();
744 nlwarning("newNpcChildGroup failed : spawnZone Not Found ! for StateMachine : %s", StateMachine
.c_str());
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 //----------------------------------------------------------------------------
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
771 (@grp)newNpcChildGroupMl("class_forager", "state_machine_1", $zone, 12);
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 //----------------------------------------------------------------------------
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
795 ()newNpcChildGroupMl("class_forager", "state_machine_1", $zone, 12);
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 //----------------------------------------------------------------------------
809 @subsection spawnManager_s_
812 Arguments: s(ManagerName) ->
813 @param[in] ManagerName is the name of the manager to spawn
816 ()spawnManager("NPC Manager"); // Spawns all the NPCs in the NPC manager called "NPC Manager"
820 // CGroup not in a family behaviour
821 void spawnManager_s_(CStateInstance
* entity
, CScriptStack
& stack
)
823 string ManagerName
= stack
.top();
830 nlwarning("SpawnManager error entity not spawned");
834 IManagerParent
* const managerParent
= entity
->getGroup()->getOwner()->getOwner();
835 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
838 nlwarning("SpawnManager error AIInstance not Found");
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())
853 nlwarning("SpawnManager error");
856 //----------------------------------------------------------------------------
859 @subsection despawnManager_s_
862 Arguments: s(ManagerName) ->
863 @param[in] ManagerName is the name of the manager to despawn
866 ()despawnManager("NPC Manager"); // Despawns all the NPCs in the NPC manager called "NPC Manager"
870 // CGroup not in a family behaviour
871 void despawnManager_s_(CStateInstance
* entity
, CScriptStack
& stack
)
873 string ManagerName
= stack
.top();
880 nlwarning("DespawnManager error entity not spawned");
884 IManagerParent
* const managerParent
= entity
->getGroup()->getOwner()->getOwner();
885 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
888 nlwarning("DespawnManager error AIInstance not Found");
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();
905 //----------------------------------------------------------------------------
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
918 ($group)getGroupTemplateWithFlags("food|rest", "invasion|outpost"); // Get a group which matches 'invasion', 'outpost' and either 'food' or 'rest' flags.
922 // CGroup not in a family behaviour
923 void getGroupTemplateWithFlags_sss_s(CStateInstance
* entity
, CScriptStack
& stack
)
925 string exceptProperties
= stack
.top();
927 string mandatoryProperties
= stack
.top();
929 string oneOfProperties
= stack
.top();
932 // If no AI instance return
933 IManagerParent
* managerParent
= entity
->getGroup()->getOwner()->getOwner();
934 CAIInstance
* aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
937 stack
.push(string());
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
))
958 if (!itGroupDesc
->properties().containsAllOf(mandatorySet
))
960 if (itGroupDesc
->properties().containsPartOfStrict(exceptSet
))
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());
975 CGroupDesc
<CGroupFamily
> const* groupDesc
= groupDescs
[CAIS::rand16((uint32
)groupDescs
.size())];
976 stack
.push(groupDesc
->getFullName());
980 //----------------------------------------------------------------------------
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
992 ($group)getGroupTemplateWithFlags("food|rest", "invasion|outpost"); // Get a group which matches 'invasion', 'outpost' and either 'food' or 'rest' flags.
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 //----------------------------------------------------------------------------
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
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
1034 // CGroup not in a family behaviour
1035 void getZoneWithFlags_ssss_s(CStateInstance
* entity
, CScriptStack
& stack
)
1037 string exceptProperties
= stack
.top();
1039 TStringId curZoneId
= CStringMapper::map(stack
.top());
1041 string mandatoryProperties
= stack
.top();
1043 string oneOfProperties
= stack
.top();
1046 // If no AI instance return
1047 IManagerParent
* const managerParent
= entity
->getGroup()->getOwner()->getOwner();
1048 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
1051 stack
.push(string());
1055 // Fill the property sets.
1056 AITYPES::CPropertySet oneOfSet
= readSet(oneOfProperties
);
1057 AITYPES::CPropertySet mandatorySet
= readSet(mandatoryProperties
);
1058 AITYPES::CPropertySet exceptSet
= readSet(exceptProperties
);
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 //----------------------------------------------------------------------------
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
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
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 //----------------------------------------------------------------------------
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
1109 ($zone)getNearestZoneWithFlags(x, y, "food|rest", "invasion|outpost", "stayaway");
1113 // CGroup not in a family behaviour
1114 void getNearestZoneWithFlags_ffsss_s(CStateInstance
* entity
, CScriptStack
& stack
)
1116 string exceptProperties
= stack
.top();
1118 string mandatoryProperties
= stack
.top();
1120 string oneOfProperties
= stack
.top();
1122 float const y
= stack
.top();
1124 float const x
= stack
.top();
1127 // If no AI instance return
1128 IManagerParent
* const managerParent
= entity
->getGroup()->getOwner()->getOwner();
1129 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
1132 stack
.push(string());
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 //----------------------------------------------------------------------------
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
1162 ($zone)getNearestZoneWithFlags(x, y, "food|rest", "invasion|outpost");
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 //----------------------------------------------------------------------------
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
1190 ($zone)getNearestZoneWithFlagsStrict(x, y, "food|rest", "invasion|outpost", "stayaway");
1194 // CGroup not in a family behaviour
1195 void getNearestZoneWithFlagsStrict_ffsss_s(CStateInstance
* entity
, CScriptStack
& stack
)
1197 string exceptProperties
= stack
.top();
1199 string mandatoryProperties
= stack
.top();
1201 string oneOfProperties
= stack
.top();
1203 float const y
= stack
.top();
1205 float const x
= stack
.top();
1208 // If no AI instance return
1209 IManagerParent
* const managerParent
= entity
->getGroup()->getOwner()->getOwner();
1210 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
1213 stack
.push(string());
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 //----------------------------------------------------------------------------
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
1243 ($zone)getNearestZoneWithFlagsStrict(x, y, "food|rest", "invasion|outpost");
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 //----------------------------------------------------------------------------
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
1271 ($zone1)getNeighbourZoneWithFlags($zone, "boss", "", $exceptflag); // Get the zone in the neighbour cells of the one containing $zone which matches specified flags
1275 // CGroup not in a family behaviour
1276 void getNeighbourZoneWithFlags_ssss_s(CStateInstance
* entity
, CScriptStack
& stack
)
1278 string exceptProperties
= stack
.top();
1280 string mandatoryProperties
= stack
.top();
1282 string oneOfProperties
= stack
.top();
1284 TStringId curZoneId
= CStringMapper::map(stack
.top());
1287 // If no AI instance return
1288 IManagerParent
* const managerParent
= entity
->getGroup()->getOwner()->getOwner();
1289 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
1292 stack
.push(string());
1296 // If curzone is invalid return
1297 CNpcZone
const* const curZone
= aiInstance
->getZone(curZoneId
);
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());
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
);
1325 stack
.push(newZone
->getAliasTreeOwner().getAliasFullName());
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());
1338 //----------------------------------------------------------------------------
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
1354 ($zone1)getNeighbourZoneWithFlags($zone, "boss", ""); // Get the zone in the neighbour cells of the one containing $zone which matches specified flags
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 //----------------------------------------------------------------------------
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
1376 ()setAggro(Range, NbTicks); // Sets the aggro range of the group to Range, updated every NbTicks ticks
1381 void setAggro_ff_(CStateInstance
* entity
, CScriptStack
& stack
)
1383 sint32 updateNbTicks
= (sint32
)(float)stack
.top();
1385 uint32 aggroRange
= (uint32
)(float)stack
.top();
1388 CGroup
* const grp
= entity
->getGroup();
1391 grp
->_AggroRange
= aggroRange
;
1392 if (updateNbTicks
>0)
1393 grp
->_UpdateNbTicks
= updateNbTicks
;
1397 //----------------------------------------------------------------------------
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)
1412 void setCanAggro_f_(CStateInstance
* entity
, CScriptStack
& stack
)
1414 bool canAggro
= ((float)stack
.top())!=0.f
;
1417 FOREACH(bot
, CCont
<CBot
>, entity
->getGroup()->bots())
1419 if (!bot
->isSpawned())
1421 CSpawnBot
* spBot
= bot
->getSpawnObj();
1423 spBot
->setCanAggro(canAggro
);
1427 //----------------------------------------------------------------------------
1430 @subsection clearAggroList_f_
1431 Reset the aggrolist of a bot.
1433 Arguments: f(bool don't send lost aggro message to EGS) ->
1436 ()clearAggroList(0/1);
1441 void clearAggroList_f_(CStateInstance
* entity
, CScriptStack
& stack
)
1443 bool sendAggroLostMessage
= ((float)stack
.top())==0.f
;
1446 FOREACH(bot
, CCont
<CBot
>, entity
->getGroup()->bots())
1448 if (!bot
->isSpawned())
1450 CSpawnBot
* spBot
= bot
->getSpawnObj();
1452 spBot
->clearAggroList(sendAggroLostMessage
);
1456 //----------------------------------------------------------------------------
1459 @subsection clearAggroList__
1460 Reset the aggrolist of a bot.
1470 void clearAggroList__(CStateInstance
* entity
, CScriptStack
& stack
)
1472 stack
.push((float)0.f
);
1473 clearAggroList_f_(entity
, stack
);
1476 //----------------------------------------------------------------------------
1479 @subsection setMode_s_
1480 Sets the mode of every bot of the group. Valid modes are:
1489 Arguments: s(Mode) ->
1490 @param[in] Mode is the mode name to set
1498 void setMode_s_(CStateInstance
* entity
, CScriptStack
& stack
)
1500 string NewMode
= stack
.top();
1503 MBEHAV::EMode mode
= MBEHAV::stringToMode(NewMode
);
1504 if (mode
==MBEHAV::UNKNOWN_MODE
)
1507 FOREACH(botIt
, CCont
<CBot
>, entity
->getGroup()->bots())
1509 if (botIt
->getSpawnObj())
1510 botIt
->getSpawnObj()->setMode(mode
);
1515 //----------------------------------------------------------------------------
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)
1530 void setAutoSpawn_f_(CStateInstance
* entity
, CScriptStack
& stack
)
1532 float const autoSpawn
= stack
.top();
1535 CGroup
* group
= entity
->getGroup();
1537 group
->setAutoSpawn(autoSpawn
!=0.f
);
1540 //----------------------------------------------------------------------------
1541 // HP related methods
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
1552 ()setMaxHP(50000,1);
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())
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
);
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
1594 void setHPLevel_f_(CStateInstance
* entity
, CScriptStack
& stack
)
1596 float coef
= stack
.top();
1599 CChangeCreatureHPMsg
& msgList
= CAIS::instance().getCreatureChangeHP();
1601 FOREACH(bot
, CCont
<CBot
>, entity
->getGroup()->bots())
1603 if (!bot
->isSpawned())
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
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*
1639 void setHPScale_f_(CStateInstance
* entity
, CScriptStack
& stack
)
1641 float coef
= stack
.top();
1644 CChangeCreatureHPMsg
& msgList
= CAIS::instance().getCreatureChangeHP();
1646 FOREACH(bot
, CCont
<CBot
>, entity
->getGroup()->bots())
1648 if (!bot
->isSpawned())
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
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
1670 ()setUrl("Click on Me", "http://www.domain.com/script.php");
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();
1688 msg
.Entities
.push_back(pbot
->dataSetRow());
1691 CSpawnGroup
* spawnGroup
= group
->getSpawnObj();
1692 spawnGroup
->setActionName(actionName
);
1693 spawnGroup
->setUrl(url
);
1694 msg
.ActionName
= actionName
;
1696 msg
.send(egsString
);
1703 @subsection scaleHP_f_
1706 Arguments: f(Coef) ->
1707 @param[in] Coef is the percentage of its current HP each creature will have
1715 void scaleHP_f_(CStateInstance
* entity
, CScriptStack
& stack
)
1717 float coef
= stack
.top();
1720 CChangeCreatureHPMsg
& msgList
= CAIS::instance().getCreatureChangeHP();
1722 FOREACH(bot
, CCont
<CBot
>, entity
->getGroup()->bots())
1724 if (!bot
->isSpawned())
1727 CSpawnBot
* const sbot
= bot
->getSpawnObj();
1729 msgList
.Entities
.push_back(sbot
->dataSetRow());
1730 msgList
.DeltaHp
.push_back((sint32
)(sbot
->currentHitPoints()*coef
));
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
1746 ()scaleHpByAlias(2, '(A:1000:10560)');
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()) );
1775 @subsection downScaleHP_f_
1776 Scales the bots HP down.
1778 Arguments: f(Coef) ->
1779 @param[in] Coef is a value
1787 void downScaleHP_f_(CStateInstance
* entity
, CScriptStack
& stack
)
1789 float coef
= stack
.top();
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())
1800 CSpawnBot
* const sbot
= bot
->getSpawnObj();
1802 msgList
.Entities
.push_back(sbot
->dataSetRow());
1803 msgList
.DeltaHp
.push_back((sint32
)(sbot
->currentHitPoints()*(coef
-1)));
1809 @subsection upScaleHP_f_
1810 Scales the bots HP up.
1812 Arguments: f(Coef) ->
1813 @param[in] Coef is a value
1821 void upScaleHP_f_(CStateInstance
* entity
, CScriptStack
& stack
)
1823 float coef
= stack
.top();
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())
1833 CSpawnBot
* spBot
= bot
->getSpawnObj();
1836 msgList
.Entities
.push_back(spBot
->dataSetRow());
1837 msgList
.DeltaHp
.push_back((sint32
)((spBot
->maxHitPoints()-spBot
->currentHitPoints())*coef
));
1844 @subsection addHP_f_
1848 @param[in] HP is the amount of hit points to add to each bot
1856 void addHP_f_(CStateInstance
* entity
, CScriptStack
& stack
)
1858 float addHP
= stack
.top();
1861 CChangeCreatureHPMsg
& msgList
= CAIS::instance().getCreatureChangeHP();
1863 FOREACH(bot
, CCont
<CBot
>, entity
->getGroup()->bots())
1865 if (!bot
->isSpawned())
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();
1880 CChangeCreatureHPMsg
& msgList
= CAIS::instance().getCreatureChangeHP();
1882 FOREACH(bot
, CCont
<CBot
>, entity
->getGroup()->bots())
1884 if (!bot
->isSpawned())
1887 CSpawnBot
* const sbot
= bot
->getSpawnObj();
1889 msgList
.Entities
.push_back(sbot
->dataSetRow());
1890 msgList
.DeltaHp
.push_back((sint32
)(addHP
));
1894 //----------------------------------------------------------------------------
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
1904 ()aiAction("kick_his_ass.aiaction");
1909 void aiAction_s_(CStateInstance
* entity
, CScriptStack
& stack
)
1911 std::string actionName
= stack
.top();
1913 NLMISC::CSheetId
sheetId(actionName
);
1914 if (sheetId
==NLMISC::CSheetId::Unknown
)
1916 nlwarning("Action SheetId Unknown %s", actionName
.c_str());
1919 AISHEETS::IAIActionCPtr action
= AISHEETS::CSheets::getInstance()->lookupAction(sheetId
);
1920 if (action
.isNull())
1922 nlwarning("Action SheetId Unknown %s", actionName
.c_str());
1926 FOREACH(botIt
, CCont
<CBot
>, entity
->getGroup()->bots())
1928 CSpawnBot
* pbot
= botIt
->getSpawnObj();
1931 CSpawnBot
& bot
= *pbot
;
1932 if (!bot
.getAIProfile())
1935 CBotProfileFight
* profile
= dynamic_cast<CBotProfileFight
*>(bot
.getAIProfile());
1939 if (!profile
->atAttackDist())
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
);
1954 //----------------------------------------------------------------------------
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
1964 ()aiActionSelf("defensive_aura.aiaction");
1969 void aiActionSelf_s_(CStateInstance
* entity
, CScriptStack
& stack
)
1971 std::string actionName
= stack
.top();
1973 NLMISC::CSheetId
sheetId(actionName
);
1974 if (sheetId
==NLMISC::CSheetId::Unknown
)
1976 nlwarning("Action SheetId Unknown %s", actionName
.c_str());
1979 AISHEETS::IAIActionCPtr action
= AISHEETS::CSheets::getInstance()->lookupAction(sheetId
);
1980 if (action
.isNull())
1982 nlwarning("Action SheetId Unknown %s", actionName
.c_str());
1986 FOREACH(botIt
, CCont
<CBot
>, entity
->getGroup()->bots())
1988 CSpawnBot
* pbot
= botIt
->getSpawnObj();
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
);
2000 //----------------------------------------------------------------------------
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
2010 ()addProfileParameter("running"); // equivalent to "running" parameter in group primitive
2015 void addProfileParameter_s_(CStateInstance
* entity
, CScriptStack
& stack
)
2017 std::string name
= (std::string
)stack
.top();
2020 CGroup
* group
= entity
->getGroup();
2022 if (group
->isSpawned())
2023 group
->getSpawnObj()->addProfileParameter(name
, "", 0.f
);
2027 //----------------------------------------------------------------------------
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
2038 ()addProfileParameter("foo", "bar"); // equivalent to "foo:bar" parameter in group primitive
2043 void addProfileParameter_ss_(CStateInstance
* entity
, CScriptStack
& stack
)
2045 std::string value
= (std::string
)stack
.top();
2047 std::string name
= (std::string
)stack
.top();
2050 CGroup
* group
= entity
->getGroup();
2052 if (group
->isSpawned())
2053 group
->getSpawnObj()->addProfileParameter(name
, value
, 0.f
);
2056 //----------------------------------------------------------------------------
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
2067 ()addProfileParameter("foo", 0.5); // equivalent to "foo:0.5" parameter in group primitive
2072 void addProfileParameter_sf_(CStateInstance
* entity
, CScriptStack
& stack
)
2074 float value
= (float)stack
.top();
2076 std::string name
= (std::string
)stack
.top();
2079 CGroup
* group
= entity
->getGroup();
2081 if (group
->isSpawned())
2082 group
->getSpawnObj()->addProfileParameter(name
, "", value
);
2085 //----------------------------------------------------------------------------
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
2095 ()removeProfileParameter("running"); // remove "running" or "running:<*>" parameter from group
2100 void removeProfileParameter_s_(CStateInstance
* entity
, CScriptStack
& stack
)
2102 std::string name
= (std::string
)stack
.top();
2105 CGroup
* group
= entity
->getGroup();
2107 if (group
->isSpawned())
2108 group
->getSpawnObj()->removeProfileParameter(name
);
2111 //----------------------------------------------------------------------------
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
2121 ()addProfileParameter("running"); // equivalent to "running" parameter in group primitive
2126 void addPersistentProfileParameter_s_(CStateInstance
* entity
, CScriptStack
& stack
)
2128 std::string name
= (std::string
)stack
.top();
2131 CGroup
* group
= entity
->getGroup();
2133 if (group
->isSpawned())
2134 group
->getSpawnObj()->addProfileParameter(name
, "", 0.f
);
2136 group
->addProfileParameter(name
, "", 0.f
);
2139 //----------------------------------------------------------------------------
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
2150 ()addPersistentProfileParameter("foo", "bar"); // equivalent to "foo:bar" parameter in group primitive
2155 void addPersistentProfileParameter_ss_(CStateInstance
* entity
, CScriptStack
& stack
)
2157 std::string value
= (std::string
)stack
.top();
2159 std::string name
= (std::string
)stack
.top();
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 //----------------------------------------------------------------------------
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
2181 ()addPersistentProfileParameter("foo", 0.5); // equivalent to "foo:0.5" parameter in group primitive
2186 void addPersistentProfileParameter_sf_(CStateInstance
* entity
, CScriptStack
& stack
)
2188 float value
= (float)stack
.top();
2190 std::string name
= (std::string
)stack
.top();
2193 CGroup
* group
= entity
->getGroup();
2194 if (group
->isSpawned())
2195 group
->getSpawnObj()->addProfileParameter(name
, "", value
);
2197 group
->addProfileParameter(name
, "", value
);
2200 //----------------------------------------------------------------------------
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
2210 ()removeProfileParameter("running"); // remove "running" or "running:<*>" parameters from group
2215 void removePersistentProfileParameter_s_(CStateInstance
* entity
, CScriptStack
& stack
)
2217 std::string name
= (std::string
)stack
.top();
2220 CGroup
* group
= entity
->getGroup();
2221 if (group
->isSpawned())
2222 group
->getSpawnObj()->removeProfileParameter(name
);
2224 group
->removeProfileParameter(name
);
2226 //----------------------------------------------------------------------------
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
2236 ($name)getOutpostState();
2241 void getOutpostStateName__s(CStateInstance
* si
, CScriptStack
& stack
)
2250 CGroup
* group
= si
->getGroup();
2254 COutpostManager
* manager
= dynamic_cast<COutpostManager
*>(group
->getOwner());
2258 str
= static_cast<COutpost
*>(manager
->getOwner())->getStateName();
2264 //----------------------------------------------------------------------------
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)
2274 (tribeOwner)isOutpostTribeOwner();
2279 void isOutpostTribeOwner__f(CStateInstance
* si
, CScriptStack
& stack
)
2281 float tribeOwner
= 0.f
;
2288 CGroup
* group
= si
->getGroup();
2292 COutpostManager
* manager
= dynamic_cast<COutpostManager
*>(group
->getOwner());
2296 if (!static_cast<COutpost
*>(manager
->getOwner())->isBelongingToAGuild())
2300 stack
.push(tribeOwner
);
2303 //----------------------------------------------------------------------------
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)
2313 (guildOwner)isOutpostGuildOwner();
2318 void isOutpostGuildOwner__f(CStateInstance
* si
, CScriptStack
& stack
)
2320 float guildOwner
= 0.f
;
2327 CGroup
* group
= si
->getGroup();
2331 COutpostManager
* manager
= dynamic_cast<COutpostManager
*>(group
->getOwner());
2335 if (static_cast<COutpost
*>(manager
->getOwner())->isBelongingToAGuild())
2339 stack
.push(guildOwner
);
2342 //----------------------------------------------------------------------------
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
2353 (val)getEventParam(2);
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 //----------------------------------------------------------------------------
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
2378 ($val)getEventParam(2);
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 //----------------------------------------------------------------------------
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
2417 ($playerEid)getCurrentPlayerEid();
2418 print($playerEid); //log (0x00001fbd50:00:00:81)
2419 (maxHp)getPlayerStat($playerEid, "MaxHp");
2422 void getPlayerStat_ss_f(CStateInstance
* entity
, CScriptStack
& stack
)
2424 std::string funName
= "getPlayerStat_ss_f";
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);
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());
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());
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()));
2466 nlwarning("Try to call %s with wrong state %s", funName
.c_str(), statName
.c_str() );
2468 stack
.push((float)0);
2473 //----------------------------------------------------------------------------
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
2485 ($playerEid)getCurrentPlayerEid();
2486 (x, y)getPlayerPosition($playerEid);
2489 void getPlayerPosition_s_ff(CStateInstance
* entity
, CScriptStack
& stack
)
2491 std::string funName
= "getPlayerPosition_s_ff";
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);
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());
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)
2534 ($playerEid)getCurrentPlayerEid();
2535 (index)getBotIndexByName("toto");
2536 (distance)getPlayerDistance(index, $playerEid);
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();
2555 nlwarning("%s on a non Npc Group, doesn't work", funName
.c_str());
2556 stack
.push((float) -1);
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);
2565 CBot
* bot
= group
->getBot(botIndex
);
2566 CSpawnBot
* spBot
= bot
?bot
->getSpawnObj():0;
2569 nlwarning("%s used bad index %d/%d (or bot not spawn)", funName
.c_str(), botIndex
, group
->bots().size());
2570 stack
.push((float)-1);
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);
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
));
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
2615 ($playerId)getCurrentPlayerAggroListTarget(4);
2616 (distance)getPlayerDistance(4, $playerId);
2621 void getCurrentPlayerAggroListTarget_f_s(CStateInstance
* entity
, CScriptStack
& stack
)
2624 std::string funName
= "getCurrentPlayerAggroListTarget_f_s";
2627 sint32 botIndex
= (sint32
)((float)stack
.top()); stack
.pop();
2630 CGroup
* group
= entity
->getGroup();
2633 nlwarning("%s on a non Npc Group, doesn't work", funName
.c_str());
2634 stack
.push(std::string(""));
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(""));
2644 CBot
* bot
= group
->getBot(botIndex
);
2645 CSpawnBot
* spBot
= bot
?bot
->getSpawnObj():0;
2648 nlwarning("%s used bad index %d/%d (or bot not spawn)", funName
.c_str(), botIndex
, group
->bots().size());
2649 stack
.push(std::string(""));
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
)
2667 CAIEntityPhysical
* ep
= CAIS::instance().getEntityPhysical(aggroIt
->first
);
2673 CBotPlayer
const* const player
= NLMISC::safe_cast
<CBotPlayer
const*>(ep
);
2678 if (!player
->isAggroable())
2683 foundRow
= aggroIt
->first
;
2687 if ( foundRow
== TDataSetRow())
2688 { // Empty aggro list so no warning displayed
2689 stack
.push(std::string(""));
2693 const NLMISC::CEntityId
& found
= CMirrors::getEntityId(foundRow
);
2694 stack
.push(std::string(found
.toString()));
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
2716 ($playerId)getRandomPlayerAggroListTarget(4);
2717 ()setAggroListTarget(4, $playerId);
2722 void getRandomPlayerAggroListTarget_f_s(CStateInstance
* entity
, CScriptStack
& stack
)
2725 std::string funName
= "getRandomPlayerAggroListTarget_f_s";
2728 uint32 botIndex
= (uint32
)((float)stack
.top()); stack
.pop();
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(""));
2738 CBot
* bot
= group
->getBot(botIndex
);
2739 CSpawnBot
* spBot
= bot
?bot
->getSpawnObj():0;
2742 nlwarning("%s used bad index %d/%d (or bot not spawn)", funName
.c_str(), botIndex
, group
->bots().size());
2743 stack
.push(std::string(""));
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
)
2759 CAIEntityPhysical
* ep
= CAIS::instance().getEntityPhysical(aggroIt
->first
);
2765 CBotPlayer
const* const player
= NLMISC::safe_cast
<CBotPlayer
const*>(ep
);
2770 if (!player
->isAggroable())
2774 playerAggroable
.push_back(aggroIt
->first
);
2779 if ( playerAggroable
.empty())
2781 stack
.push(std::string(""));
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()));
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
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);
2826 void getAggroListElement_ff_s(CStateInstance
* entity
, CScriptStack
& stack
)
2829 std::string funName
= "getAggroListElement_ff_s";
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(""));
2845 CBot
* bot
= group
->getBot(botIndex
);
2846 CSpawnBot
* spBot
= bot
?bot
->getSpawnObj():0;
2849 nlwarning("%s used bad index %d/%d (or bot not spawn)", funName
.c_str(), botIndex
, group
->bots().size());
2850 stack
.push(std::string(""));
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
)
2867 CAIEntityPhysical
* ep
= CAIS::instance().getEntityPhysical(aggroIt
->first
);
2873 CBotPlayer
const* const player
= NLMISC::safe_cast
<CBotPlayer
const*>(ep
);
2878 if (!player
->isAggroable())
2882 playerAggroable
.push_back(aggroIt
->first
);
2887 if ( playerAggroable
.empty())
2889 stack
.push(std::string(""));
2892 // if index outside return "";
2893 if (0 > elementIndex
&& elementIndex
>= playerAggroable
.size())
2895 stack
.push(std::string(""));
2899 const NLMISC::CEntityId
& found
= CMirrors::getEntityId(playerAggroable
[ uint32(elementIndex
) ]);
2900 stack
.push(std::string(found
.toString()));
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.
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);
2935 void getAggroListSize_f_f(CStateInstance
* entity
, CScriptStack
& stack
)
2938 std::string funName
= "getRandomPlayerAggroListTarget_f_s";
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) );
2953 CBot
* bot
= group
->getBot(botIndex
);
2954 CSpawnBot
* spBot
= bot
?bot
->getSpawnObj():0;
2957 nlwarning("%s used bad index %d/%d (or bot not spawn)", funName
.c_str(), botIndex
, group
->bots().size());
2958 stack
.push(float(0) );
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
)
2975 CAIEntityPhysical
* ep
= CAIS::instance().getEntityPhysical(aggroIt
->first
);
2981 CBotPlayer
const* const player
= NLMISC::safe_cast
<CBotPlayer
const*>(ep
);
2986 if (!player
->isAggroable())
2990 playerAggroable
.push_back(aggroIt
->first
);
2995 // return the size of the aggro list
2996 stack
.push(float(playerAggroable
.size()));
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
3016 ($playerId)getRandomPlayerAggroListTarget(4);
3017 ()setAggroListTarget(4, $playerId);
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());
3042 CBot
* bot
= group
->getBot(botIndex
);
3043 CSpawnBot
* spBot
= bot
?bot
->getSpawnObj():0;
3046 nlwarning("%s used bad index %d/%d (or bot not spawn)", funName
.c_str(), botIndex
, group
->bots().size());
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() );
3065 // maximize aggro from the bot for the player
3066 spBot
->maximizeAggroFor(playerRow
);
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
3082 ($playerId)getRandomPlayerAggroListTarget(4);
3083 ()setGroupAggroListTarget($playerId);
3087 void setGroupAggroListTarget_s_(CStateInstance
* entity
, CScriptStack
& stack
)
3090 std::string funName
= "setGroupAggroListTarget_s_";
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() );
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() );
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
);
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.
3150 ($playerId)getRandomPlayerAggroListTarget(0);
3151 ()setManagerAggroListTarget($playerId, "group_bandit_"); // all group that have name like "group_bandit_*" will attack the player
3155 void setManagerAggroListTarget_ss_(CStateInstance
* entity
, CScriptStack
& stack
)
3158 std::string funName
= "setManagerAggroListTarget_ss_";
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() );
3183 CGroup
* group
= entity
->getGroup();
3186 nlwarning("Call %s on a non exisiting group", funName
.c_str() );
3189 // get the manager of the group
3190 CManager
* manager
= group
->getOwner();
3193 nlwarning("Call %s on a non exisiting manager", funName
.c_str() );
3196 // for all group of the manager maximize aaggro *IF* the group name contains groupNameStr
3197 group
=manager
->getNextValidGroupChild();
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
);
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
3235 (botIndex)getBotIndexByName("boss_random_aggro");
3236 ($playerId)getRandomPlayerAggroListTarget(botIndex);
3237 ()setAggroListTarget(botIndex, $playerId);
3241 void getBotIndexByName_s_f(CStateInstance
* entity
, CScriptStack
& stack
)
3243 std::string funName
= "getBotIndexByName_s_f";
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);
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();
3263 for (; itBot
!= itEnd
; ++itBot
)
3266 const std::string
& name
= itBot
->getName();
3267 if (name
== botName
)
3269 stack
.push((float)index
);
3275 stack
.push((float)-1);
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)
3295 ($alived)isGroupAlived();
3296 if ($alived == 1.0f) {
3301 void isGroupAlived__f(CStateInstance
* entity
, CScriptStack
& stack
)
3303 isAlived__f(entity
, stack
);
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)
3319 ($botIndex)getBotIndexByName("boss_3");
3320 $alived)isBotAlived($botIndex);
3321 if (alived == 1.0f) {
3326 void isBotAlived_f_f(CStateInstance
* entity
, CScriptStack
& stack
)
3328 std::string funName
= "isBotAlived_f_f";
3330 sint32 botIndex
= (sint32
)((float)stack
.top()); stack
.pop();
3333 CGroup
* group
= entity
->getGroup();
3336 nlwarning("%s on a non Npc Group, doesn't work", funName
.c_str());
3337 stack
.push((float)0);
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;}
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)
3368 @param[out] success is 1.0f if the entity id of a player is alived.
3371 ($botIndex)getBotIndexByName("boss_3");
3372 ($playerId)getCurrentPlayerAggroListTarget($botIndex):
3373 (alived)isPlayerlived($playerId);
3374 if (alived == 1.0f) {
3378 void isPlayerAlived_s_f(CStateInstance
* entity
, CScriptStack
& stack
)
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
);
3395 stack
.push(0.0f
); return;
3397 // test if the player is alived
3400 stack
.push(1.0f
); return;
3403 stack
.push(0.0f
); return;
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
3419 ($serverTime)getServerTimeAsString();
3423 void getServerTimeStr__s(CStateInstance
* entity
, CScriptStack
& stack
)
3425 //get the server time (as debug string)
3427 time( ¤tTime
);
3428 std::string str
= NLMISC::toString("%s", asctime(localtime(¤tTime
)));
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
3442 ($serverTime)getServerTime();
3446 void getServerTime__s(CStateInstance
* entity
, CScriptStack
& stack
)
3448 //get the server time (as time stamp)
3450 time( ¤tTime
);
3451 std::string ret
= NLMISC::toString("%d", currentTime
);
3452 // convert to string
3453 stack
.push((std::string
)ret
);
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.
3467 ($ryzomDateStr)getRyzomDateStr);
3470 void getRyzomDateStr__s(CStateInstance
* entity
, CScriptStack
& stack
)
3472 // Display time using ryzom style
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",
3484 (int) (dayOfMonth
+ 1),
3487 (int) rt
.getRyzomYear());
3489 stack
.push( result
);
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.
3502 ($tickGameCycle)getRyzomDate();
3505 void getRyzomDate__s(CStateInstance
* entity
, CScriptStack
& stack
)
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
3519 enum TMode
{NpcMsg
, SystemMsg
, EmoteMsg
};
3520 TVectorParamCheck Values
;
3523 CPhraseParameters PhraseParameters
;
3525 //----------------------------------------------------------------------------
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).
3540 ()phrasePushValue("money", 15);
3541 ()phrasePushValue("integer", 15);
3542 ()phrasePushValue("time", 15);
3543 ()phraseEndSystemMsg(0, "say", "PHRASE_FROM_PHRASE_WITH_3_PARAMETERS");
3548 void phraseBegin__(CStateInstance
* entity
, CScriptStack
& stack
)
3550 PhraseParameters
.Values
.clear();
3553 //----------------------------------------------------------------------------
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.
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.
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).
3580 Arguments: s(paramType), f(value) ->
3581 @param[in] paramType the type of the parameter
3582 @param[in] value the value of the parameter
3587 ()phrasePushValue("money", 15);
3588 ()phrasePushValue("integer", 15);
3589 ()phrasePushValue("time", 15);
3590 ()phraseEndSystemMsg(0, "say", "PHRASE_WITH_3_PARAMETERS");
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
;
3606 case STRING_MANAGER::money
:
3608 param
.Money
= static_cast<uint64
>(f
);
3613 case STRING_MANAGER::integer
:
3615 param
.Int
= static_cast<sint32
>(f
);
3619 case STRING_MANAGER::time
:
3621 param
.Time
= static_cast<uint32
>(f
);
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
);
3639 param
.Type
= STRING_MANAGER::invalid_value
;
3644 PhraseParameters
.Values
.push_back(param
);
3648 //----------------------------------------------------------------------------
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.
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.
3668 Input as string literal
3671 Input as an entityId (obtains via getCurrentPlayerAggroListTarget_f_s, getRandomPlayerAggroListTarget_f_s, getBotEid_f_s, getCurrentSpeakerEid__s, getAggroListElement_ff_s)
3676 Input as sheetId name (example: "toto.sbrick", "toto.sitem", "toto.creature")
3684 Input as string identifier
3690 Input as stringId (number): *WARNING* LD must as coder to do function that return string_id if they want to use that type
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).
3706 Arguments: s(paramType), f(value) ->
3707 @param[in] paramType the type of the parameter
3708 @param[in] value the value of the parameter
3712 ($playerEid)getCurrentPlayerEid();
3713 ($botEid)group3.getBotEid(4);
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");
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
;
3738 case STRING_MANAGER::money
:
3740 NLMISC::fromString(s
, param
.Money
);
3744 case STRING_MANAGER::player
:
3745 case STRING_MANAGER::bot
:
3746 case STRING_MANAGER::entity
:
3749 NLMISC::CEntityId id
;
3751 id
.fromString(s
.c_str());
3752 CAIEntityPhysical
* entityPhysical
=CAIS::instance().getEntityPhysical(TheDataset
.getDataSetRow(id
));
3755 switch( entityPhysical
->getRyzomType())
3757 case RYZOMID::creature
:
3761 CSpawnBot
* sb
= NLMISC::safe_cast
<CSpawnBot
*>(entityPhysical
);
3762 alias
= sb
->getPersistent().getAlias();
3767 // player or other have no alias
3770 param
.setEIdAIAlias( id
, alias
);
3774 case STRING_MANAGER::integer
:
3776 NLMISC::fromString(s
, param
.Int
);
3780 case STRING_MANAGER::time
:
3782 NLMISC::fromString(s
, param
.Time
);
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
:
3796 nlwarning("Sheet name expected but not found in script");
3797 param
.SheetId
= CSheetId();
3801 param
.SheetId
= CSheetId(s
);
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
;
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
);
3829 case STRING_MANAGER::literal
:
3830 param
.Literal
.fromUtf8(s
);
3833 case STRING_MANAGER::dyn_string_id
:
3834 case STRING_MANAGER::string_id
:
3835 NLMISC::fromString(s
, param
.StringId
);
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
:
3845 param
.Type
= STRING_MANAGER::invalid_value
;
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();
3876 nlwarning("%s on a non Npc Group, doesn't work", funName
.c_str());
3877 PhraseParameters
.Values
.clear();
3880 if (!group
->isSpawned() || group
->bots().isEmpty() || botIndex
< 0 || group
->bots().size() < static_cast<uint32
>(botIndex
))
3882 PhraseParameters
.Values
.clear();
3885 const CBot
*const bot
= group
->getBot(botIndex
);
3886 if ( !bot
|| !bot
->isSpawned())
3888 PhraseParameters
.Values
.clear();
3891 CSpawnBot
*const sp
= bot
->getSpawnObj();
3892 if ( !sp
|| !sp
->isAlive() )
3894 PhraseParameters
.Values
.clear();
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
));
3912 // send chat to client
3915 case CPhraseParameters::NpcMsg
:
3916 npcChatParamToChannel(sp
->dataSetRow(), groupType
, phraseId
.c_str(), PhraseParameters
.Values
);
3918 case CPhraseParameters::SystemMsg
:
3919 STRING_MANAGER::sendSystemStringToClientAudience(sp
->dataSetRow(),std::vector
<NLMISC::CEntityId
>(), groupType
, phraseId
.c_str(), PhraseParameters
.Values
);
3922 case CPhraseParameters::EmoteMsg
:
3923 STRING_MANAGER::sendCustomEmoteTextToClientAudience(sp
->dataSetRow(),std::vector
<NLMISC::CEntityId
>(), phraseId
.c_str(), PhraseParameters
.Values
);
3927 PhraseParameters
.Values
.clear();
3930 //----------------------------------------------------------------------------
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
3945 ()phrasePushString("literal", "text non traduit");
3946 ()groupOf5Bot.phraseEndNpcMsg(4, "say", "PHRASE_TOTO");
3950 In this case in the phrase_wk.txt PHRASE_TOTO must be defined as
3952 PHRASE_TOTO(bot b, literal l)
3954 [I am $b$, on this text is not translated $l$ ]
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 //----------------------------------------------------------------------------
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
3980 ()phrasePushString("literal", "Test des levels designer");
3981 ()groupOf5Bot.phraseEndSystemMsg(4, "say", "PHRASE_TOTO");
3985 In this case in the phrase_wk.txt PHRASE_TOTO must be defined as
3987 PHRASE_TOTO(literal l)
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 //----------------------------------------------------------------------------
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
4016 ($playerEid)getCurrentPlayerEid();
4017 ($botEid)getCurrentSpeakerEid();
4019 ()phrasePushString("player", $playerEid);
4020 ()groupOf5Bot.phraseEndEmoteMsg(,"PHRASE_TOTO1");
4022 ()phrasePushString("bot", $botEid);
4023 ()groupOf5Bot.phraseEndEmoteMsg(,"PHRASE_TOTO2");
4027 In this case in the phrase_wk.txt PHRASE_TOTO must be defined as
4029 PHRASE_TOTO1(player p)
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 //----------------------------------------------------------------------------
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
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
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");
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");
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");
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());
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
);
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
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");
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");
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");
4217 void queryEgs_ssscfs_(CStateInstance
* entity
, CScriptStack
& stack
)
4219 std::string funName
= "queryEgs_ssscfs_";
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());
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
);
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
4268 ($playerId)getRandomPlayerAggroListTarget(0);
4269 ()teleportPlayer(0, $playerEid); // teleport player to the boss.
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();
4284 nlwarning("%s on a non Npc Group, doesn't work", funName
.c_str());
4287 if (!group
->isSpawned() || group
->bots().isEmpty() || botIndex
< 0 || group
->bots().size() < static_cast<uint32
>(botIndex
))
4291 const CBot
*const bot
= group
->getBot(botIndex
);
4292 if ( !bot
|| !bot
->isSpawned())
4296 CSpawnBot
*const sp
= bot
->getSpawnObj();
4297 if ( !sp
|| !sp
->isAlive() )
4303 // Read position for mirror
4304 TDataSetRow row
= sp
->dataSetRow();
4305 if (! TheDataset
.isAccessible( row
) )
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
));
4320 // do nothing if one of them is dead
4321 if (!charEntity
->isAlive() )
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();
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
);
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
4366 ($playerId)getRandomPlayerAggroListTarget(0);
4367 ()teleportPlayer($playerEid, 1000, 1000, 100, 0);
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
));
4386 // do nothing if one of them is dead
4387 if (!charEntity
->isAlive() )
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 //----------------------------------------------------------------------------
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
4420 (index)getBotIndexByName("bot_toto");
4421 ($botEid)getBotEid(index);
4424 ()phrasePushValue("entity", $botEid);
4425 ()phraseEndEmoteMsg(index, "PHRASE_YOUR_ARE_CLICKING_ON_ME");
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();
4437 nlwarning("%s on a non Npc Group, doesn't work", funName
.c_str());
4438 stack
.push(std::string(CEntityId::Unknown
.toString()));
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()));
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 //----------------------------------------------------------------------------
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)
4475 ($botEid)getCurrentSpeakerEid();
4476 (index)getBotIndex($botEid);
4479 ()phrasePushValue("entity", $botEid);
4480 ()phraseEndNpcg(index, "PHRASE_YOUR_ARE_CLICKING_ON_ME");
4484 void getBotIndex_s_f(CStateInstance
* entity
, CScriptStack
& stack
)
4486 std::string funName
= "getBotEid_f_s";
4487 CGroup
* group
= entity
->getGroup();
4490 nlwarning("%s on a non Npc Group, doesn't work", funName
.c_str());
4491 stack
.push(std::string(CEntityId::Unknown
.toString()));
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
))
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
);
4520 stack
.push((float)-1);
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.
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
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
4552 //TempPlayer is invalid so return Unkwn eid
4553 std::string s
= id
.toString();
4557 // TempPlayer is valid so return eid
4558 id
= TempPlayer
->getEntityId();
4559 std::string s
= id
.toString();
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.
4577 ($botEid)getCurrentSpeakerEid();
4578 ($playerEid)getCurrentSpeakerEid();
4580 phrasePushString("player", $playerEid);
4581 phrasePushValue("bot", $botEid);
4582 phraseEndEmotMsg(index, "EMOT_PLAYER_INSULT_BOT");
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
4592 //TempSpeaker is invalid so return Unkwn eid
4593 std::string s
= id
.toString();
4597 //TempSpeaker is valid so return correct eid
4598 id
= TempSpeaker
->getEntityId();
4599 std::string s
= id
.toString();
4604 //----------------------------------------------------------------------------
4607 @subsection setSheet_s_
4608 Change the sheet of a creature
4610 Arguments: -> s(sheetName)
4613 ()setSheet('ccdeb2');
4618 void setSheet_s_(CStateInstance
* entity
, CScriptStack
& stack
)
4620 string sheetname
= stack
.top();
4623 CSheetId
sheetId(sheetname
+".creature");
4624 if (sheetId
==CSheetId::Unknown
)
4627 FOREACH(itBot
, CCont
<CBot
>, entity
->getGroup()->bots())
4632 AISHEETS::ICreatureCPtr
const sheet
= AISHEETS::CSheets::getInstance()->lookup(sheetId
);
4633 if (!sheet
.isNull())
4634 bot
->triggerSetSheet(sheet
);
4639 //----------------------------------------------------------------------------
4642 @subsection setClientSheet_s_
4643 Change the client sheet of a creature
4645 Arguments: -> s(sheetName)
4648 ()setClientSheet('ccdeb2');
4653 void setClientSheet_s_(CStateInstance
* entity
, CScriptStack
& stack
)
4655 string sheetname
= stack
.top();
4658 if (sheetname
.find(".creature") == string::npos
)
4659 sheetname
+= ".creature";
4661 FOREACH(itBot
, CCont
<CBot
>, entity
->getGroup()->bots())
4666 bot
->setClientSheet(sheetname
);
4671 /****************************************************************************/
4673 //----------------------------------------------------------------------------
4676 @subsection setHealer_f_
4677 Make the group healer (need test)
4679 Arguments: -> f(isHealer)
4687 void setHealer_f_(CStateInstance
* entity
, CScriptStack
& stack
)
4689 bool value
= ((float)stack
.top())!=0.f
;
4692 CGroup
* group
= entity
->getGroup();
4694 if (group
->isSpawned())
4696 FOREACH(itBot
, CCont
<CBot
>, group
->bots())
4701 bot
->setHealer(value
);
4702 // break; // :NOTE: Only set first bot as a healer
4708 /****************************************************************************/
4710 //----------------------------------------------------------------------------
4713 @subsection sitDown__
4714 Make the group sit Down
4725 void sitDown__(CStateInstance
* entity
, CScriptStack
& stack
)
4728 CGroup
* group
= entity
->getGroup();
4732 nlwarning("sitDown__ failed");
4736 CAILogicActionSitDownHelper::sitDown(group
);
4740 //----------------------------------------------------------------------------
4744 Make the group stand up (if was previously stand down)
4755 void standUp__(CStateInstance
* entity
, CScriptStack
& stack
)
4757 CGroup
* group
= entity
->getGroup();
4760 nlwarning("standUp__ failed");
4764 CAILogicActionSitDownHelper::standUp(group
);
4767 //----------------------------------------------------------------------------
4771 Use to implement setConditionRet
4776 ()setConditionRet(1);
4782 void setConditionSuccess_f_(CStateInstance
* entity
, CScriptStack
& stack
)
4784 bool conditionState
= (uint32
)((float)stack
.top()) != 0;
4785 CGroup
* group
= entity
->getGroup();
4788 nlwarning("setConditionSuccess_f_ failed");
4792 CAILogicDynamicIfHelper::setConditionSuccess(conditionState
);
4796 static float randomAngle()
4798 uint32
const maxLimit
= CAngle::PI
*2;
4799 float val
= (float)CAIS::rand32(maxLimit
);
4803 //----------------------------------------------------------------------------
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
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())
4837 if (bot
->isSpawned())
4839 CSpawnBot
*spawnBot
= bot
->getSpawnObj();
4842 spawnBot
->setTheta(randomAngle());
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