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"
33 using namespace NLMISC
;
35 using namespace AICOMP
;
36 using namespace AITYPES
;
37 using namespace RYAI_MAP_CRUNCH
;
39 AITYPES::CPropertySet
readSet(std::string strings
, std::string separator
= "|")
41 AITYPES::CPropertySet properties
;
42 CStringSeparator
const sep(strings
, separator
);
44 properties
.addProperty(AITYPES::CPropertyId::create(sep
.get()));
49 IScriptContext
* spawnNewGroup(CStateInstance
* entity
, CScriptStack
& stack
, CAIInstance
* aiInstance
, CAIVector
const& spawnPosition
, sint32 baseLevel
, double dispersionRadius
)
51 string stateMachineName
= stack
.top();
53 string dynGroupName
= stack
.top();
58 nlwarning("spawnNewGroup failed because entity==NULL");
59 return NULL
; // return a normal stack.
62 CGroupDesc
<CGroupFamily
> const* groupDesc
= NULL
;
64 // Find the group template.
65 // :TODO: Replace it with a faster map access.
66 FOREACH (itCont
, CCont
<CContinent
>, aiInstance
->continents())
68 FOREACH (itRegion
, CCont
<CRegion
>, itCont
->regions())
70 FOREACH (itFamily
, CCont
<CGroupFamily
>, itRegion
->groupFamilies())
72 FOREACH (itGroupDesc
, CCont
<CGroupDesc
<CGroupFamily
> >, itFamily
->groupDescs())
74 if (itGroupDesc
->getFullName()==dynGroupName
|| itGroupDesc
->getName()==dynGroupName
)
76 groupDesc
= *itGroupDesc
;
86 nlwarning("spawnNewGroup failed: No Group Template Found: '%s'",dynGroupName
.c_str());
90 // Find the state machine as a manager
91 CManager
* manager
=NULL
;
92 FOREACH(itCont
, CCont
<CManager
>, aiInstance
->managers())
94 if (itCont
->getFullName()==stateMachineName
|| itCont
->getName()==stateMachineName
)
102 nlwarning("spawnNpcGroup failed : Unknown stateMachine: '%s'", stateMachineName
.c_str());
105 // Find the state machine as a npc manager
106 CMgrNpc
* npcManager
= dynamic_cast<CMgrNpc
*>(manager
);
109 nlwarning("spawnNpcGroup failed : Not a npc state machine !: '%s'", stateMachineName
.c_str());
112 // Get the state machine
113 CStateMachine
const* stateMachine
= manager
->getStateMachine();
114 if (stateMachine
->cstStates().size()==0)
116 // Save the creator state
117 bool const savePlayerAttackable
= groupDesc
->getGDPlayerAttackable();
118 bool const saveBotAttackable
= groupDesc
->getGDBotAttackable();
119 // Set it to a correct value (:TODO: see why)
120 groupDesc
->setGDPlayerAttackable(true);
121 groupDesc
->setGDBotAttackable(true);
123 CGroupNpc
* const grp
= groupDesc
->createNpcGroup(npcManager
, spawnPosition
, dispersionRadius
, baseLevel
);
124 // Restore the creator state
125 groupDesc
->setGDPlayerAttackable(savePlayerAttackable
);
126 groupDesc
->setGDBotAttackable(saveBotAttackable
);
127 // Verify that the group was created
130 nlwarning("spawnNpcGroup failed : group cannot spawn !: %s", stateMachineName
.c_str());
133 // Set the new group parameters
134 grp
->autoDestroy(true);
135 grp
->getPersistentStateInstance()->setParentStateInstance(entity
->getPersistentStateInstance());
136 grp
->initDynGrp(groupDesc
, NULL
);
137 // Verify that we have a state in the state machine
139 if (!stateMachine
|| stateMachine
->cstStates().size()==0)
140 nlwarning("no state defined for StateMachine in Manager %s", manager
->getFullName().c_str());
142 // Set the group in that state
144 grp
->setStartState(stateMachine
->cstStates()[0]); // sets the first state (must exist!).
145 grp
->updateStateInstance(); // directly call his first state (to retrieve associated params).
150 void getZoneWithFlags_helper(CStateInstance
* entity
, CScriptStack
& stack
, CAIInstance
* const aiInstance
, CZoneScorer
const& scorer
)
152 // :FIXME: Copy n past from getZoneWithFlags2 begin
153 // Get all the cell-zones
154 vector
<CCellZone
*> cellZones
;
155 FOREACH(itCont
, CCont
<CContinent
>, aiInstance
->continents())
157 FOREACH(itRegion
, CCont
<CRegion
>, itCont
->regions())
159 FOREACH(itCellZone
, CCont
<CCellZone
>, itRegion
->cellZones())
161 cellZones
.push_back(*itCellZone
);
166 std::random_shuffle(cellZones
.begin(), cellZones
.end());
167 // While no zone found
168 FOREACH(itCellZone
, std::vector
<CCellZone
*>, cellZones
)
171 vector
<CCell
*> cells
;
172 FOREACH(it
, CCont
<CCell
>, (*itCellZone
)->cells())
173 cells
.push_back(*it
);
175 std::random_shuffle(cells
.begin(), cells
.end());
176 // Get a zone with a good score
177 CNpcZone
const* spawnZone
= CCellZone::lookupNpcZoneScorer(cells
, scorer
);
180 stack
.push(spawnZone
->getAliasTreeOwner().getAliasFullName());
185 nlwarning("getZoneWithFlags/getNearestZoneWithFlags No Zone Found");
186 stack
.push(string());