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/>.
23 #include "stdpch.h" // First include for pre-compiled headers.
25 #include "race_stats_sheet.h"
27 #include "game_share/characs_build.h"
29 #include "nel/georges/u_form_elm.h"
41 const string
CGenderInfo::UnknownItemName
;
43 // description of a visual slot that must be read by CGenderInfo
46 SLOTTYPE::EVisualSlot Slot
;
47 const char *Suffix
; // suffix in the sheet
50 static const CSlotInfo UsedVisualSlots
[] =
52 { SLOTTYPE::CHEST_SLOT
, "DefaultChest" },
53 { SLOTTYPE::LEGS_SLOT
, "DefaultLegs" },
54 { SLOTTYPE::HEAD_SLOT
, "DefaultHair" },
55 { SLOTTYPE::ARMS_SLOT
, "DefaultArms" },
56 { SLOTTYPE::FACE_SLOT
, "DefaultFace" },
57 { SLOTTYPE::HANDS_SLOT
, "DefaultHands" },
58 { SLOTTYPE::FEET_SLOT
, "DefaultFeet" }
60 static const uint NumUsedVisualSlots
= sizeof(UsedVisualSlots
) / sizeof(UsedVisualSlots
[0]);
66 //===============================================================
67 CGenderInfo::CGenderInfo()
69 CharacterScalePos
= 1;
70 for (uint32 i
= 0; i
< 8; ++i
)
72 BlendShapeMin
[i
] = 0.0f
;
73 BlendShapeMax
[i
] = 100.0f
;
80 //===============================================================
81 void CGenderInfo::build(const NLGEORGES::UFormElm
&item
, const std::string
&prefix
)
83 // Get equipment items
85 for(uint k
= 0; k
< NumUsedVisualSlots
; ++k
)
87 if (!item
.getValueByName(Items
[UsedVisualSlots
[k
].Slot
], (prefix
+ UsedVisualSlots
[k
].Suffix
).c_str()))
89 nlwarning("Can't get %s from race_stats sheet", UsedVisualSlots
[k
].Suffix
);
93 if (!item
.getValueByName(Skelfilename
, (prefix
+ "Skel").c_str()))
95 nlwarning("Can't get skeleton");
97 // get base animation name
98 if (!item
.getValueByName(AnimSetBaseName
, (prefix
+ "AnimSetBaseName").c_str()))
100 nlwarning("Can't get AnimSetBaseName");
104 // Load Lod character name
105 if(!item
.getValueByName(LodCharacterName
, (prefix
+ "LodCharacterName").c_str()))
106 nlwarning("CGenderInfo::build: Key 'LodCharacterName' not found.");
108 // Load Lod character apparition distance
109 if(!item
.getValueByName(LodCharacterDistance
, (prefix
+ "LodCharacterDistance").c_str()))
110 nlwarning("CGenderInfo::build: Key 'LodCharacterDistance' not found.");
113 // value to scale the "pos" channel of the animation of the player.
114 if(!item
.getValueByName(CharacterScalePos
, (prefix
+ "CharacterScalePos").c_str()))
115 nlwarning("CGenderInfo::build: Key 'CharacterScalePos' not found.");
116 for (uint32 i
= 0; i
< 8; ++i
)
118 if(!item
.getValueByName(BlendShapeMin
[i
], (prefix
+"MorphTargetMin"+NLMISC::toString(i
)).c_str()))
119 nlwarning("CGenderInfo::build: Key 'MorphTargetMin%d' not found.",i
);
120 if(!item
.getValueByName(BlendShapeMax
[i
], (prefix
+"MorphTargetMax"+NLMISC::toString(i
)).c_str()))
121 nlwarning("CGenderInfo::build: Key 'MorphTargetMax%d' not found.",i
);
124 if(!item
.getValueByName(NamePosZLow
, (prefix
+ "NamePosZLow").c_str()))
125 nlwarning("CGenderInfo::build: Key 'NamePosZLow' not found.");
126 if(!item
.getValueByName(NamePosZNormal
, (prefix
+ "NamePosZNormal").c_str()))
127 nlwarning("CGenderInfo::build: Key 'NamePosZNormal' not found.");
128 if(!item
.getValueByName(NamePosZHigh
, (prefix
+ "NamePosZHigh").c_str()))
129 nlwarning("CGenderInfo::build: Key 'NamePosZHigh' not found.");
132 //===============================================================
133 void CGenderInfo::serial(NLMISC::IStream
&f
)
136 for(uint k
= 0; k
< NumUsedVisualSlots
; ++k
)
138 f
.serial(Items
[UsedVisualSlots
[k
].Slot
]);
140 f
.serial(Skelfilename
);
141 f
.serial(AnimSetBaseName
);
142 f
.serial(LodCharacterName
);
143 f
.serial(LodCharacterDistance
);
144 f
.serial(CharacterScalePos
);
145 f
.serialCont(GroundFX
);
146 for (uint32 i
= 0; i
< 8; ++i
)
148 f
.serial(BlendShapeMin
[i
]);
149 f
.serial(BlendShapeMax
[i
]);
151 f
.serial(NamePosZLow
);
152 f
.serial(NamePosZNormal
);
153 f
.serial(NamePosZHigh
);
157 //-----------------------------------------------
159 // Get the item name for a given slot.
160 //-----------------------------------------------
161 const string
&CGenderInfo::getItemName(SLOTTYPE::EVisualSlot slot
) const
164 if(slot
>= SLOTTYPE::NB_SLOT
)
167 nlwarning("CGenderInfo::getItemName: slot '%d' invalid.", slot
);
168 return UnknownItemName
;
171 // Return the name of the default item for this slot.
179 /////////////////////
180 // CRaceStatsSheet //
181 /////////////////////
182 //===============================================================
183 CRaceStatsSheet::CRaceStatsSheet()
185 std::fill(CharacStartValue
, CharacStartValue
+ CHARACTERISTICS::NUM_CHARACTERISTICS
, 0);
186 // Initialize the type.
187 Type
= CEntitySheet::RACE_STATS
;
190 //===============================================================
191 void CRaceStatsSheet::build(const NLGEORGES::UFormElm
&item
)
193 GenderInfos
[0].build(item
, "DefaultEquipment.Male equipment.");
194 GenderInfos
[1].build(item
, "DefaultEquipment.Female equipment.");
195 // build base characs
196 loadCharacteristicsFromSheet(item
, "Characteristics.", CharacStartValue
);
199 item
.getValueByName(race
, "Race");
200 People
= EGSPD::CPeople::fromString(race
);
202 // Get the skin to use.
203 if(!item
.getValueByName(Skin
, "Skin"))
204 nlwarning("CRaceStatsSheet::build: Cannot find the key 'Skin'.");
206 buildGroundFXs(item
, "GroundFXMale", GenderInfos
[0].GroundFX
);
207 buildGroundFXs(item
, "GroundFXFemale", GenderInfos
[1].GroundFX
);
208 // get Automaton Type
209 if(!item
.getValueByName(Automaton
, "Automaton"))
210 nlwarning("CRaceStatsSheet::build: Can't get 'Automaton'.");
211 BodyToBone
.build(item
, "Localisation.");
213 for(uint k
= 0; k
< NumAttackLists
; ++k
)
215 std::string attackListName
;
216 if(item
.getValueByName(attackListName
, NLMISC::toString("attack_list%d", (int) k
).c_str()) && !attackListName
.empty())
218 AttackLists
.push_back(ClientSheetsStrings
.add(attackListName
));
224 //===============================================================
225 void CRaceStatsSheet::buildGroundFXs(const NLGEORGES::UFormElm
&item
, const std::string
&name
, std::vector
<CGroundFXSheet
> &dest
)
228 const NLGEORGES::UFormElm
*elm
;
229 if(item
.getNodeByName(&elm
, name
) && elm
)
235 uint groundFXArraySize
;
236 if(elm
->getArraySize(groundFXArraySize
))
238 if(groundFXArraySize
> 0)
240 // Adjust the array size.
241 dest
.reserve(groundFXArraySize
);
244 for(uint i
=0; i
< groundFXArraySize
; ++i
)
246 const NLGEORGES::UFormElm
*node
;
247 if (elm
->getArrayNode(&node
, i
) && node
!= NULL
)
250 if (!gfs
.build(*node
))
252 nlwarning("Error while building node %d", (int) i
);
257 for(k
= 0; k
< dest
.size(); ++k
)
259 if (dest
[k
].GroundID
== gfs
.GroundID
)
261 debug("Duplicated material");
266 if (k
== dest
.size())
276 debug(NLMISC::toString("'%s' cannot get the array size.", name
.c_str()));
279 debug(NLMISC::toString("'%s' is not an array.", name
.c_str()));
282 debug(NLMISC::toString("'%s' key not found.", name
.c_str()));
283 // sort fxs by ground type
284 std::sort(dest
.begin(), dest
.end());
287 //===============================================================
288 void CRaceStatsSheet::serial(NLMISC::IStream
&f
)
290 for(uint k
= 0; k
< CHARACTERISTICS::NUM_CHARACTERISTICS
; ++k
)
292 f
.serial(CharacStartValue
[k
]);
294 f
.serial(GenderInfos
[0], GenderInfos
[1]);
300 People
= (EGSPD::CPeople::TPeople
)people
;
304 uint8 people
= (uint8
)People
;
308 f
.serial(Skin
); // The skin
310 f
.serial(BodyToBone
);
312 uint32 size
= (uint32
)AttackLists
.size();
314 AttackLists
.resize(size
);
316 for(uint k
= 0; k
< size
; ++k
)
318 ClientSheetsStrings
.serial(f
, AttackLists
[k
]);