player_face.h

Go to the documentation of this file.
00001 /* $Id: player_face.h 11800 2008-01-09 21:05:03Z rubidium $ */
00002 
00005 #ifndef PLAYER_FACE_H
00006 #define PLAYER_FACE_H
00007 
00008 #include "core/random_func.hpp"
00009 #include "core/bitmath_func.hpp"
00010 
00012 enum GenderEthnicity {
00013   GENDER_FEMALE    = 0, 
00014   ETHNICITY_BLACK  = 1, 
00015 
00016   GE_WM = 0,                                         
00017   GE_WF = 1 << GENDER_FEMALE,                        
00018   GE_BM = 1 << ETHNICITY_BLACK,                      
00019   GE_BF = 1 << ETHNICITY_BLACK | 1 << GENDER_FEMALE, 
00020   GE_END,
00021 };
00022 DECLARE_ENUM_AS_BIT_SET(GenderEthnicity); 
00023 
00025 enum PlayerFaceVariable {
00026   PFV_GENDER,
00027   PFV_ETHNICITY,
00028   PFV_GEN_ETHN,
00029   PFV_HAS_MOUSTACHE,
00030   PFV_HAS_TIE_EARRING,
00031   PFV_HAS_GLASSES,
00032   PFV_EYE_COLOUR,
00033   PFV_CHEEKS,
00034   PFV_CHIN,
00035   PFV_EYEBROWS,
00036   PFV_MOUSTACHE,
00037   PFV_LIPS,
00038   PFV_NOSE,
00039   PFV_HAIR,
00040   PFV_JACKET,
00041   PFV_COLLAR,
00042   PFV_TIE_EARRING,
00043   PFV_GLASSES,
00044   PFV_END
00045 };
00046 DECLARE_POSTFIX_INCREMENT(PlayerFaceVariable);
00047 
00049 struct PlayerFaceBitsInfo {
00050   byte     offset;               
00051   byte     length;               
00052   byte     valid_values[GE_END]; 
00053   SpriteID first_sprite[GE_END]; 
00054 };
00055 
00057 static const PlayerFaceBitsInfo _pf_info[] = {
00058   /* Index                   off len   WM  WF  BM  BF         WM     WF     BM     BF */
00059   /* PFV_GENDER          */ {  0, 1, {  2,  2,  2,  2 }, {     0,     0,     0,     0 } }, 
00060   /* PFV_ETHNICITY       */ {  1, 2, {  2,  2,  2,  2 }, {     0,     0,     0,     0 } }, 
00061   /* PFV_GEN_ETHN        */ {  0, 3, {  4,  4,  4,  4 }, {     0,     0,     0,     0 } }, 
00062   /* PFV_HAS_MOUSTACHE   */ {  3, 1, {  2,  0,  2,  0 }, {     0,     0,     0,     0 } }, 
00063   /* PFV_HAS_TIE_EARRING */ {  3, 1, {  0,  2,  0,  2 }, {     0,     0,     0,     0 } }, 
00064   /* PFV_HAS_GLASSES     */ {  4, 1, {  2,  2,  2,  2 }, {     0,     0,     0,     0 } }, 
00065   /* PFV_EYE_COLOUR      */ {  5, 2, {  3,  3,  1,  1 }, {     0,     0,     0,     0 } }, 
00066   /* PFV_CHEEKS          */ {  0, 0, {  1,  1,  1,  1 }, { 0x325, 0x326, 0x390, 0x3B0 } }, 
00067   /* PFV_CHIN            */ {  7, 2, {  4,  1,  2,  2 }, { 0x327, 0x327, 0x391, 0x3B1 } },
00068   /* PFV_EYEBROWS        */ {  9, 4, { 12, 16, 11, 16 }, { 0x32B, 0x337, 0x39A, 0x3B8 } },
00069   /* PFV_MOUSTACHE       */ { 13, 2, {  3,  0,  3,  0 }, { 0x367,     0, 0x397,     0 } }, 
00070   /* PFV_LIPS            */ { 13, 4, { 12, 10,  9,  9 }, { 0x35B, 0x351, 0x3A5, 0x3C8 } }, 
00071   /* PFV_NOSE            */ { 17, 3, {  8,  4,  4,  5 }, { 0x349, 0x34C, 0x393, 0x3B3 } }, 
00072   /* PFV_HAIR            */ { 20, 4, {  9,  5,  5,  4 }, { 0x382, 0x38B, 0x3D4, 0x3D9 } },
00073   /* PFV_JACKET          */ { 24, 2, {  3,  3,  3,  3 }, { 0x36B, 0x378, 0x36B, 0x378 } },
00074   /* PFV_COLLAR          */ { 26, 2, {  4,  4,  4,  4 }, { 0x36E, 0x37B, 0x36E, 0x37B } },
00075   /* PFV_TIE_EARRING     */ { 28, 3, {  6,  3,  6,  3 }, { 0x372, 0x37F, 0x372, 0x3D1 } }, 
00076   /* PFV_GLASSES         */ { 31, 1, {  2,  2,  2,  2 }, { 0x347, 0x347, 0x3AE, 0x3AE } }  
00077 };
00078 assert_compile(lengthof(_pf_info) == PFV_END);
00079 
00088 static inline uint GetPlayerFaceBits(PlayerFace pf, PlayerFaceVariable pfv, GenderEthnicity ge)
00089 {
00090   assert(_pf_info[pfv].valid_values[ge] != 0);
00091 
00092   return GB(pf, _pf_info[pfv].offset, _pf_info[pfv].length);
00093 }
00094 
00103 static inline void SetPlayerFaceBits(PlayerFace &pf, PlayerFaceVariable pfv, GenderEthnicity ge, uint val)
00104 {
00105   assert(val < _pf_info[pfv].valid_values[ge]);
00106 
00107   SB(pf, _pf_info[pfv].offset, _pf_info[pfv].length, val);
00108 }
00109 
00122 static inline void IncreasePlayerFaceBits(PlayerFace &pf, PlayerFaceVariable pfv, GenderEthnicity ge, int8 amount)
00123 {
00124   int8 val = GetPlayerFaceBits(pf, pfv, ge) + amount; // the new value for the pfv
00125 
00126   /* scales the new value to the correct scope */
00127   if (val >= _pf_info[pfv].valid_values[ge]) {
00128     val = 0;
00129   } else if (val < 0) {
00130     val = _pf_info[pfv].valid_values[ge] - 1;
00131   }
00132 
00133   SetPlayerFaceBits(pf, pfv, ge, val); // save the new value
00134 }
00135 
00143 static inline bool ArePlayerFaceBitsValid(PlayerFace pf, PlayerFaceVariable pfv, GenderEthnicity ge)
00144 {
00145   return GB(pf, _pf_info[pfv].offset, _pf_info[pfv].length) < _pf_info[pfv].valid_values[ge];
00146 }
00147 
00156 static inline uint ScalePlayerFaceValue(PlayerFaceVariable pfv, GenderEthnicity ge, uint val)
00157 {
00158   assert(val < (1U << _pf_info[pfv].length));
00159 
00160   return (val * _pf_info[pfv].valid_values[ge]) >> _pf_info[pfv].length;
00161 }
00162 
00168 static inline void ScaleAllPlayerFaceBits(PlayerFace &pf)
00169 {
00170   IncreasePlayerFaceBits(pf, PFV_ETHNICITY, GE_WM, 0); // scales the ethnicity
00171 
00172   GenderEthnicity ge = (GenderEthnicity)GB(pf, _pf_info[PFV_GEN_ETHN].offset, _pf_info[PFV_GEN_ETHN].length); // gender & ethnicity of the face
00173 
00174   /* Is a male face with moustache. Need to reduce CPU load in the loop. */
00175   bool is_moust_male = !HasBit(ge, GENDER_FEMALE) && GetPlayerFaceBits(pf, PFV_HAS_MOUSTACHE, ge) != 0;
00176 
00177   for (PlayerFaceVariable pfv = PFV_EYE_COLOUR; pfv < PFV_END; pfv++) { // scales all other variables
00178 
00179     /* The moustache variable will be scaled only if it is a male face with has a moustache */
00180     if (pfv != PFV_MOUSTACHE || is_moust_male) {
00181       IncreasePlayerFaceBits(pf, pfv, ge, 0);
00182     }
00183   }
00184 }
00185 
00197 static inline void RandomPlayerFaceBits(PlayerFace &pf, GenderEthnicity ge, bool adv)
00198 {
00199   pf = InteractiveRandom(); // random all player face bits
00200 
00201   /* scale ge: 0 == GE_WM, 1 == GE_WF, 2 == GE_BM, 3 == GE_BF (and maybe in future: ...) */
00202   ge = (GenderEthnicity)((uint)ge % GE_END);
00203 
00204   /* set the gender (and ethnicity) for the new player face */
00205   if (adv) {
00206     SetPlayerFaceBits(pf, PFV_GEN_ETHN, ge, ge);
00207   } else {
00208     SetPlayerFaceBits(pf, PFV_GENDER, ge, HasBit(ge, GENDER_FEMALE));
00209   }
00210 
00211   /* scales all player face bits to the correct scope */
00212   ScaleAllPlayerFaceBits(pf);
00213 }
00214 
00223 static inline SpriteID GetPlayerFaceSprite(PlayerFace pf, PlayerFaceVariable pfv, GenderEthnicity ge)
00224 {
00225   assert(_pf_info[pfv].valid_values[ge] != 0);
00226 
00227   return _pf_info[pfv].first_sprite[ge] + GB(pf, _pf_info[pfv].offset, _pf_info[pfv].length);
00228 }
00229 
00230 void DrawPlayerFace(PlayerFace face, int color, int x, int y);
00231 PlayerFace ConvertFromOldPlayerFace(uint32 face);
00232 bool IsValidPlayerFace(PlayerFace pf);
00233 void DrawFaceStringLabel(const Window *w, byte widget_index, StringID str, uint8 val, bool is_bool_widget);
00234 
00235 #endif /* PLAYER_FACE_H */

Generated on Wed Oct 1 17:03:22 2008 for openttd by  doxygen 1.5.6