Linux multi-monitor fullscreen support
[ryzomcore.git] / ryzom / client / src / client_sheets / character_sheet.cpp
blobe0a0bb76cdabce718367e8dca1bf474b8ded31d7
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 //
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 /////////////
24 // INCLUDE //
25 /////////////
26 #include "stdpch.h" // First include for pre-compiled headers.
27 // Georges
28 #include "nel/georges/u_form_elm.h"
29 // Application
30 #include "character_sheet.h"
31 // Game Share
32 #include "game_share/georges_helper.h"
35 ///////////
36 // USING //
37 ///////////
38 using namespace std;
39 using namespace NLGEORGES;
40 using namespace NLMISC;
43 // ***************************************************************************
44 // Easy macro to translate value from georges
45 #define TRANSLATE_VAL( _Var_, _key_ ) \
46 if(!item.getValueByName(_Var_, _key_)) \
47 debug( string("key '") + string(_key_) + string("' not found.") );
51 /////////////
52 // METHODS //
53 /////////////
54 //-----------------------------------------------
55 // CCharacterSheet :
56 // Constructor.
57 //-----------------------------------------------
58 CCharacterSheet::CCharacterSheet()
60 CharacterScalePos = 1;
61 Scale = 1.f;
62 SoundFamily = 0;
63 SoundVariation = 0;
64 Type = CEntitySheet::FAUNA;
65 Gender = 0;
66 Race = EGSPD::CPeople::EndPeople;
67 IdSkelFilename = 0;
68 IdAnimSetBaseName = 0;
69 IdAutomaton = 0;
70 IdLodCharacterName = 0;
71 LodCharacterDistance = 0.0f;
72 IdFame = 0;
73 DisplayOSD = true;
74 DisplayInRadar = true;
75 DisplayOSDName = true;
76 DisplayOSDBars = true;
77 DisplayOSDForceOver = false;
78 Traversable = true;
79 ClipRadius= 0.f;
80 ClipHeight= 0.f;
81 R2Npc = false;
83 Selectable = false;
84 Talkable = false;
85 Attackable = false;
86 Givable = false;
87 Mountable = false;
88 Turn = false;
89 SelectableBySpace = false;
91 HLState = LHSTATE::NONE;
93 HairColor = 0;
94 Skin = 0;
95 EyesColor = 0;
97 DistToFront = 0.0f;
98 DistToBack = 0.0f;
99 DistToSide = 0.0f;
101 ColRadius = 0.0f;
102 ColHeight = 0.0f;
103 ColLength = 0.0f;
104 ColWidth = 0.0f;
106 MaxSpeed = 0.0f;
108 NamePosZLow = 0.0f;
109 NamePosZNormal = 0.0f;
110 NamePosZHigh = 0.0f;
112 IdStaticFX = 0;
114 SpellCastingPrefix = 0;
116 RegionForce = 0;
117 ForceLevel = 0;
118 Level = 0;
120 }// CCharacterSheet //
122 //-----------------------------------------------
123 // readEquipment :
124 // Read an equipment slot.
125 //-----------------------------------------------
126 void CCharacterSheet::readEquipment(const NLGEORGES::UFormElm &form, const string &key, CEquipment &slot)
128 // Get the item (or shape) name.
129 string itemName;
130 if(!form.getValueByName(itemName, string(key + ".Item").c_str() ))
131 debug(NLMISC::toString("Key '%s.Item' not found.", key.c_str()));
132 slot.IdItem = ClientSheetsStrings.add(NLMISC::toLowerAscii(itemName));
134 // Get the texture.
135 if(!form.getValueByName(slot.Texture, string(key + ".Texture").c_str() ))
136 debug(NLMISC::toString("Key '%s.Texture' not found.", key.c_str()));
138 // Get the color.
139 if(!form.getValueByName(slot.Color, string(key + ".Color").c_str() ))
140 debug(NLMISC::toString("Key '%s.Color' not found.", key.c_str()));
142 // Get the Bind point.
143 string bindPointName;
144 if(!form.getValueByName(bindPointName, string(key + ".Bind Point").c_str() ))
145 debug(NLMISC::toString("Key '%s.Bind Point' not found.", key.c_str()));
146 slot.IdBindPoint = ClientSheetsStrings.add(bindPointName);
147 }// readEquipment //
149 //-----------------------------------------------
150 // build :
151 // Build the sheet from an external script.
152 //-----------------------------------------------
153 void CCharacterSheet::build(const NLGEORGES::UFormElm &item)
155 // First Name
156 // string FirstName;
157 // if(!item.getValueByName(FirstName, "Basics.First Name"))
158 // debug("Key 'Basics.First Name' not found.");
159 // IdFirstName = ClientSheetsStrings.add(FirstName);
160 // // Character Name
161 // string LastName;
162 // if(!item.getValueByName(LastName, "Basics.CharacterName"))
163 // debug("Key 'Basics.CharacterName' not found.");
164 // IdLastName = ClientSheetsStrings.add(LastName);
166 // Fame Name
167 string FameName;
168 if(!item.getValueByName(FameName, "Basics.Fame"))
169 debug("Key 'Basics.Fame' not found.");
170 IdFame = ClientSheetsStrings.add(FameName);
172 // Character Race
173 string raceStr;
174 if(!item.getValueByName(raceStr, "Basics.Race"))
175 debug("Key 'Basics.Race' not found.");
176 else if (!raceStr.empty())
178 Race = EGSPD::CPeople::fromString(raceStr);
180 if (EGSPD::CPeople::toString(Race) != raceStr)
182 debug(toString("In sheet '%s': invalid race '%s', race is set to unknow",
183 Id.toString().c_str(),
184 raceStr.c_str()));
187 else
188 Race = EGSPD::CPeople::Unknown;
190 // Player Gender.
191 if(!item.getValueByName(Gender, "Basics.Gender"))
192 debug("Key 'Gender' not found.");
194 // Load the skel.
195 string SkelFilename;
196 if(!item.getValueByName(SkelFilename, "3d data.Skel"))
197 debug("Key '3d data.Skel' not found.");
198 IdSkelFilename = ClientSheetsStrings.add(SkelFilename);
200 // BODY
201 readEquipment(item, "Basics.Equipment.Body", Body);
202 // LEGS
203 readEquipment(item, "Basics.Equipment.Legs", Legs);
204 // ARMS
205 readEquipment(item, "Basics.Equipment.Arms", Arms);
206 // HANDS
207 readEquipment(item, "Basics.Equipment.Hands", Hands);
208 // FEET
209 readEquipment(item, "Basics.Equipment.Feet", Feet);
210 // HEAD
211 readEquipment(item, "Basics.Equipment.Head", Head);
212 // FACE
213 readEquipment(item, "Basics.Equipment.Face", Face);
214 // IN RIGHT HAND
215 readEquipment(item, "Basics.Equipment.HandR", ObjectInRightHand);
216 // IN LEFT HAND
217 readEquipment(item, "Basics.Equipment.HandL", ObjectInLeftHand);
219 if (!ObjectInRightHand.IdItem)
221 std::string right;
222 item.getValueByName(right, "item_right");
223 if (!right.empty())
224 ObjectInRightHand.IdItem = ClientSheetsStrings.add(NLMISC::toLowerAscii(right));
227 if (!ObjectInLeftHand.IdItem)
229 std::string left;
230 item.getValueByName(left, "item_left");
231 if (!left.empty())
232 ObjectInLeftHand.IdItem = ClientSheetsStrings.add(NLMISC::toLowerAscii(left));
235 // Get the animation set Base Name.
236 string AnimSetBaseName;
237 if(item.getValueByName(AnimSetBaseName, "3d data.AnimSetBaseName"))
239 if(AnimSetBaseName.empty())
240 debug("AnimSetBaseName is Empty.");
241 else
242 AnimSetBaseName = NLMISC::toLowerAscii(AnimSetBaseName); // Force the CASE in UPPER to not be CASE SENSITIVE.
244 else
245 debug("Key '3d data.AnimSetBaseName' not found.");
246 IdAnimSetBaseName = ClientSheetsStrings.add(AnimSetBaseName);
247 // AUTOMATON TYPE
248 string Automaton;
249 if(item.getValueByName(Automaton, "3d data.Automaton"))
251 // Check there is an automaton
252 if(Automaton.empty())
253 debug("Automaton is Empty.");
254 // Lower Case
255 else
256 Automaton = NLMISC::toLowerAscii(Automaton);
258 // Key not Found
259 else
260 debug("Key '3d data.Automaton' not found.");
261 IdAutomaton = ClientSheetsStrings.add(Automaton);
262 // Display OSD
263 if(!item.getValueByName(DisplayOSD, "3d data.DisplayOSD"))
265 debug("Key '3d data.DisplayOSD' not found -> set 'true'.");
266 DisplayOSD = true;
269 // New Bot Object flags
270 TRANSLATE_VAL(DisplayInRadar, "3d data.DisplayInRadar");
271 TRANSLATE_VAL(DisplayOSDName,"3d data.DisplayName");
272 TRANSLATE_VAL(DisplayOSDBars,"3d data.DisplayBars");
273 TRANSLATE_VAL(DisplayOSDForceOver, "3d data.DisplayAlwaysNameOver");
274 TRANSLATE_VAL(Traversable, "Collision.NotTraversable");
275 // invert
276 Traversable= !Traversable;
278 // CREATURE PROPERTIES (Possible Actions)
279 // Is the character selectable ?
280 if(!item.getValueByName(Selectable, "Properties.Selectable"))
282 debug("Key 'Properties.Selectable' not found -> set 'false'.");
283 Selectable = false;
285 // Is the character Talkable ?
286 if(!item.getValueByName(Talkable, "Properties.Talkable"))
288 debug("Key 'Properties.Talkable' not found -> set 'false'.");
289 Talkable = false;
291 // Is the character Attackable ?
292 if(!item.getValueByName(Attackable, "Properties.Attackable"))
294 debug("Key 'Properties.Attackable' not found -> set 'false'.");
295 Attackable = false;
297 // Is the character Givable ?
298 if(!item.getValueByName(Givable, "Properties.Givable"))
300 debug("Key 'Properties.Givable' not found -> set 'false'.");
301 Givable = false;
303 // Is the character Mountable ?
304 if(!item.getValueByName(Mountable, "Properties.Mountable"))
306 debug("Key 'Properties.Mountable' not found -> set 'false'.");
307 Mountable = false;
309 // Is the character allowed to turn ?
310 if(!item.getValueByName(Turn, "Properties.Turn"))
312 debug("Key 'Properties.Turn' not found -> set 'true'.");
313 Turn = true;
315 // Is the character selectable by pressing space (default) ?
316 if(!item.getValueByName(SelectableBySpace, "Properties.SelectableBySpace"))
318 debug("Key 'Properties.SelectableBySpace' not found -> set 'true'.");
319 SelectableBySpace = true;
321 //Get the harvest/loot state
322 string harvestLootStr;
323 if( !item.getValueByName(harvestLootStr, "Properties.LootHarvestState") )
324 debug("Key 'roperties.LootHarvestState' not found.");
325 else
326 HLState = LHSTATE::stringToLHState(harvestLootStr);
330 // Get the Hair Color.
331 if(!item.getValueByName(HairColor, "3d data.HairColor"))
332 debug("Key '3d data.HairColor' not found.");
334 // Get the Skin Texture.
335 if(!item.getValueByName(Skin, "3d data.Skin"))
336 debug("Key '3d data.Skin' not found.");
338 // Get the Eyes Color.
339 if(!item.getValueByName(EyesColor, "3d data.EyesColor"))
340 debug("Key '3d data.EyesColor' not found.");
342 // Load Lod character name
343 string LodCharacterName;
344 if(!item.getValueByName(LodCharacterName, "3d data.LodCharacterName"))
345 debug("Key '3d data.LodCharacterName' not found.");
346 IdLodCharacterName = ClientSheetsStrings.add(LodCharacterName);
348 // Load Lod character apparition distance
349 if(!item.getValueByName(LodCharacterDistance, "3d data.LodCharacterDistance"))
350 debug("Key '3d data.LodCharacterDistance' not found.");
352 // value to scale the "pos" channel of the animation of the player.
353 if(!item.getValueByName(CharacterScalePos, "3d data.CharacterScalePos"))
354 debug("Key '3d data.CharacterScalePos' not found.");
356 // value to scale the "pos" channel of the animation of the player.
357 if(!item.getValueByName(Scale, "3d data.Scale"))
358 debug("Key '3d data.Scale' not found.");
359 else
361 if(Scale <= 0.0f)
363 nlwarning("CCharacterSheet:build: Scale(%f) <= 0.0 so fix scale to 1.0", Scale);
364 Scale = 1.0f;
368 // Load name positions on Z axis
369 if(!item.getValueByName(NamePosZLow, "3d data.NamePosZLow"))
371 NamePosZLow = 0.f;
372 debug("Key '3d data.NamePosZLow' not found.");
374 if(!item.getValueByName(NamePosZNormal, "3d data.NamePosZNormal"))
376 NamePosZNormal = 0.f;
377 debug("Key '3d data.NamePosZNormal' not found.");
379 if(!item.getValueByName(NamePosZHigh, "3d data.NamePosZHigh"))
381 NamePosZHigh = 0.f;
382 debug("Key '3d data.NamePosZHigh' not found.");
385 // value to change sound familly
386 if(!item.getValueByName(SoundFamily, "3d data.SoundFamily"))
387 debug("Key '3d data.SoundFamily' not found.");
388 // value to change sound variation
389 if(!item.getValueByName(SoundVariation, "3d data.SoundVariation"))
390 debug("Key '3d data.SoundVariation' not found.");
393 // Get the dist fromm Bip to Mid
394 float tmpBip01ToMid;
395 if(!item.getValueByName(tmpBip01ToMid, "Collision.Dist Bip01 to mid"))
397 tmpBip01ToMid = 0.f;
398 debug("Key 'Collision.Dist Bip01 to mid' not found.");
400 // Get the distance from the bip01 to the front.
401 if(!item.getValueByName(DistToFront, "Collision.Dist Bip01 to front"))
403 DistToFront = 1.f;
404 debug("Key 'Collision.Dist Bip01 to front' not found.");
406 // Get the distance from the bip01 to the front.
407 if(!item.getValueByName(DistToBack, "Collision.Dist Bip01 to back"))
409 DistToBack = 1.f;
410 debug("Key 'Collision.Dist Bip01 to back' not found.");
412 // Get the creature Width.
413 if(!item.getValueByName(ColWidth, "Collision.Width"))
415 ColWidth = 1.f;
416 debug("Key 'Collision.Width' not found.");
418 DistToSide = ColWidth;
420 DistToFront = DistToFront-tmpBip01ToMid;
421 DistToBack = tmpBip01ToMid-DistToBack;
422 DistToSide = DistToSide/2.f;
424 // Get the creature collision Radius.
425 if(!item.getValueByName(ColRadius, "Collision.CollisionRadius"))
427 ColRadius = 0.5f;
428 debug("Key 'Collision.CollisionRadius' not found.");
430 // Get the creature collision Height.
431 if(!item.getValueByName(ColHeight, "Collision.Height"))
433 ColHeight = 2.f;
434 debug("Key 'Collision.Height' not found.");
436 // Get the creature collision Length.
437 if(!item.getValueByName(ColLength, "Collision.Length"))
439 ColLength = 1.f;
440 debug("Key 'Collision.Length' not found.");
444 // CLIP
445 if(!item.getValueByName(ClipRadius, "Collision.ClipRadius"))
447 ClipRadius = 0.f;
448 debug("Key 'Collision.ClipRadius' not found.");
450 if(!item.getValueByName(ClipHeight, "Collision.ClipHeight"))
452 ClipHeight = 0.f;
453 debug("Key 'Collision.ClipHeight' not found.");
457 // SPEED //
458 // Get the creature Max Speed (Run).
459 if(!item.getValueByName(MaxSpeed, "Basics.MovementSpeeds.RunSpeed"))
461 MaxSpeed = 10.f;
462 debug("Key 'Basics.MovementSpeeds.RunSpeed' not found.");
465 const UFormElm *elm = NULL;
466 // Get all alternative Clothes.
467 static const char alternativeClothesKey[] = "Basics.Alternative Clothes";
468 if(item.getNodeByName(&elm, alternativeClothesKey) && elm)
470 // Check array.
471 if(elm->isArray())
473 // Get Array Size
474 uint altClothesArraySize;
475 if(elm->getArraySize(altClothesArraySize))
477 // Get values.
478 string altClothes;
479 for(uint i=0; i<altClothesArraySize; ++i)
481 if(elm->getArrayValue(altClothes, i))
483 if(!altClothes.empty())
485 TSStringId IdAltClothes = ClientSheetsStrings.add(altClothes);
486 IdAlternativeClothes.push_back(IdAltClothes);
488 else
489 debug(toString("'%s' field empty for the index '%d'.", alternativeClothesKey, i));
491 else
492 debug(toString("'%s' cannot get the array value for the index '%d'.", alternativeClothesKey, i));
495 else
496 debug(toString("'%s' cannot get the array size.", alternativeClothesKey));
498 else
499 debug(toString("'%s' is not an array.", alternativeClothesKey));
501 else
502 debug(toString("'%s' key not found.", alternativeClothesKey));
504 // Hair item list
505 static const char hairItemList[] = "3d data.HairItem";
506 if(item.getNodeByName(&elm, hairItemList) && elm)
508 // Check array.
509 if(elm->isArray())
511 // Get Array Size
512 uint hairItemArraySize;
513 if(elm->getArraySize(hairItemArraySize))
515 if(hairItemArraySize > 0)
517 // Adjust the array size.
518 HairItemList.resize(hairItemArraySize);
520 // Get values.
521 for(uint i=0; i<hairItemArraySize; ++i)
523 string arrayNodeName;
524 if(elm->getArrayNodeName(arrayNodeName, i))
525 readEquipment(item, string(hairItemList)+"["+toString(i)+"]", HairItemList[i]);
529 else
530 debug(toString("'%s' cannot get the array size.", hairItemList));
532 else
533 debug(toString("'%s' is not an array.", hairItemList));
535 else
536 debug(toString("'%s' key not found.", hairItemList));
538 // ground fxs
539 static const char groundFXList[] = "3d data.GroundFX";
540 if(item.getNodeByName(&elm, groundFXList) && elm)
542 // Check array.
543 if(elm->isArray())
545 // Get Array Size
546 uint groundFXArraySize;
547 if(elm->getArraySize(groundFXArraySize))
549 if(groundFXArraySize > 0)
551 // Adjust the array size.
552 GroundFX.reserve(groundFXArraySize);
554 // Get values.
555 for(uint i=0; i< groundFXArraySize; ++i)
557 const UFormElm *node;
558 if (elm->getArrayNode(&node, i) && node != NULL)
560 CGroundFXSheet gfs;
561 if (!gfs.build(*node))
563 nlwarning("Error while building node %d", (int) i);
565 else
567 uint k;
568 for(k = 0; k < GroundFX.size(); ++k)
570 if (GroundFX[k].GroundID == gfs.GroundID)
572 debug("Duplicated material");
573 GroundFX[k] = gfs;
574 break;
577 if (k == GroundFX.size())
579 GroundFX.push_back(gfs);
586 else
587 debug(toString("'%s' cannot get the array size.", groundFXList));
589 else
590 debug(toString("'%s' is not an array.", groundFXList));
592 else
593 debug(toString("'%s' key not found.", groundFXList));
594 // sort fxs by ground type
595 std::sort(GroundFX.begin(), GroundFX.end());
597 // Load Ground FX
598 string staticFx;
599 if(!item.getValueByName(staticFx, "3d data.FX"))
600 debug("Key '3d data.FX' not found.");
601 IdStaticFX = ClientSheetsStrings.add(staticFx);
603 BodyToBone.build(item, "Localisation.");
605 // Attack lists
606 for(uint k = 0; k < NumAttackLists; ++k)
608 std::string attackListName;
609 if(item.getValueByName(attackListName, toString("attack_list%d", (int) k).c_str()) && !attackListName.empty())
611 AttackLists.push_back(ClientSheetsStrings.add(attackListName));
615 if(!item.getValueByName(RegionForce, "Basics.RegionForce"))
617 RegionForce = 0;
618 debug("Key 'Basics.RegionForce' not found.");
621 if(!item.getValueByName(ForceLevel, "Basics.ForceLevel"))
623 ForceLevel = 0;
624 debug("Key 'Basics.Regio Force' not found.");
627 if(!item.getValueByName(Level, "Basics.XPLevel"))
629 Level = 0;
630 debug("Key 'Basics.XPLevel' not found.");
633 // offset for projectiles
634 const UFormElm *pElt;
635 nlverify (item.getNodeByName (&pElt, "3d data.ProjectileCastRay"));
636 uint arraySize;
637 if (pElt != NULL)
639 nlverify (pElt->getArraySize (arraySize));
640 ProjectileCastRay.reserve(arraySize);
641 for (uint32 i = 0; i < arraySize; ++i)
643 const UFormElm *pEltOfList;
644 if (pElt->getArrayNode (&pEltOfList, i) && pEltOfList)
646 const UFormElm *pEltPos;
647 const UFormElm *pEltOrigin;
648 if (pEltOfList->getNodeByName(&pEltPos, "Pos") &&
649 pEltOfList->getNodeByName(&pEltOrigin, "Origin"))
651 CCharacterSheet::CCastRay cr;
652 if (pEltPos->getValueByName(cr.Pos.x, "X") &&
653 pEltPos->getValueByName(cr.Pos.y, "Y") &&
654 pEltPos->getValueByName(cr.Pos.z, "Z") &&
655 pEltOrigin->getValueByName(cr.Origin.x, "X") &&
656 pEltOrigin->getValueByName(cr.Origin.y, "Y") &&
657 pEltOrigin->getValueByName(cr.Origin.z, "Z")
660 ProjectileCastRay.push_back(cr);
667 if(!item.getValueByName(R2Npc, "r2_npc"))
669 R2Npc = false;
670 debug("Key 'R2Npc' not found.");
672 }// build //
675 //-----------------------------------------------
676 // serial :
677 // Serialize character sheet into binary data file.
678 //-----------------------------------------------
679 void CCharacterSheet::serial(NLMISC::IStream &f)
681 // Serialize class components.
682 // ClientSheetsStrings.serial(f, IdFirstName);
683 // ClientSheetsStrings.serial(f, IdLastName);
684 f.serial(Gender);
685 f.serialEnum(Race);
686 ClientSheetsStrings.serial(f, IdSkelFilename);
687 ClientSheetsStrings.serial(f, IdAnimSetBaseName);
688 ClientSheetsStrings.serial(f, IdAutomaton);
689 f.serial(Scale);
690 f.serial(SoundFamily);
691 f.serial(SoundVariation);
692 ClientSheetsStrings.serial(f, IdLodCharacterName);
694 f.serial(LodCharacterDistance);
695 f.serial(Selectable);
696 f.serial(Talkable);
697 f.serial(Attackable);
698 f.serial(Givable);
699 f.serial(Mountable);
700 f.serial(Turn);
701 f.serial(SelectableBySpace);
702 f.serialEnum(HLState);
703 f.serial(CharacterScalePos);
704 f.serial(NamePosZLow);
705 f.serial(NamePosZNormal);
706 f.serial(NamePosZHigh);
707 ClientSheetsStrings.serial(f, IdFame);
709 f.serial(Body);
710 f.serial(Legs);
711 f.serial(Arms);
712 f.serial(Hands);
713 f.serial(Feet);
714 f.serial(Head);
715 f.serial(Face);
716 f.serial(ObjectInRightHand);
717 f.serial(ObjectInLeftHand);
719 f.serial(HairColor);
720 f.serial(Skin);
721 f.serial(EyesColor);
723 f.serial(DistToFront);
724 f.serial(DistToBack);
725 f.serial(DistToSide);
727 // Collisions
728 f.serial(ColRadius);
729 f.serial(ColHeight);
730 f.serial(ColLength);
731 f.serial(ColWidth);
732 f.serial(MaxSpeed);
734 // Clip
735 f.serial(ClipRadius);
736 f.serial(ClipHeight);
738 // Alternative Look
739 ClientSheetsStrings.serial(f, IdAlternativeClothes);
741 // Hair Item List
742 f.serialCont(HairItemList);
743 // Ground fxs
744 f.serialCont(GroundFX);
745 // Display OSD
746 f.serial(DisplayOSD);
747 // static FX
748 ClientSheetsStrings.serial(f, IdStaticFX);
749 // body to bone
750 f.serial(BodyToBone);
751 // attack list
752 uint32 size = (uint32)AttackLists.size();
753 f.serial(size);
754 AttackLists.resize(size);
756 for(uint k = 0; k < size; ++k)
758 ClientSheetsStrings.serial(f, AttackLists[k]);
761 // bot object flags
762 f.serial(DisplayInRadar);
763 f.serial(DisplayOSDName);
764 f.serial(DisplayOSDBars);
765 f.serial(DisplayOSDForceOver);
766 f.serial(Traversable);
768 f.serial(RegionForce);
769 f.serial(ForceLevel);
770 f.serial(Level);
772 f.serialCont(ProjectileCastRay);
774 f.serial(R2Npc);
776 }// serial //
778 // ***************************************************************************
779 void CCharacterSheet::getWholeEquipmentList(std::vector<const CEquipment*> &equipList) const
781 equipList.clear();
782 equipList.push_back(&Body);
783 equipList.push_back(&Legs);
784 equipList.push_back(&Arms);
785 equipList.push_back(&Hands);
786 equipList.push_back(&Feet);
787 equipList.push_back(&Head);
788 equipList.push_back(&Face);
789 equipList.push_back(&ObjectInRightHand);
790 equipList.push_back(&ObjectInLeftHand);
791 for(uint i=0;i<HairItemList.size();i++)
793 equipList.push_back(&HairItemList[i]);