void D_SetupUserInfo () { int i; userinfo_t *coninfo = &players[consoleplayer].userinfo; for (i = 0; i < MAXPLAYERS; i++) memset (&players[i].userinfo, 0, sizeof(userinfo_t)); strncpy (coninfo->netname, name, MAXPLAYERNAME); if (teamplay && !TeamLibrary.IsValidTeam (team)) { coninfo->team = D_PickRandomTeam (); } else { coninfo->team = team; } if (autoaim > 35.f || autoaim < 0.f) { coninfo->aimdist = ANGLE_1*35; } else { coninfo->aimdist = abs ((int)(autoaim * (float)ANGLE_1)); } coninfo->color = color; coninfo->skin = R_FindSkin (skin, 0); coninfo->gender = D_GenderToInt (gender); coninfo->neverswitch = neverswitchonpickup; coninfo->MoveBob = (fixed_t)(65536.f * movebob); coninfo->StillBob = (fixed_t)(65536.f * stillbob); coninfo->PlayerClass = D_PlayerClassToInt (playerclass); R_BuildPlayerTranslation (consoleplayer); }
int userinfo_t::PlayerClassChanged(const char *classname) { int classnum = D_PlayerClassToInt(classname); *static_cast<FIntCVar *>((*this)[NAME_PlayerClass]) = classnum; return classnum; }
void R_InitSkins (void) { FSoundID playersoundrefs[NUMSKINSOUNDS]; spritedef_t temp; int sndlumps[NUMSKINSOUNDS]; char key[65]; DWORD intname, crouchname; size_t i; int j, k, base; int lastlump; int aliasid; bool remove; PClassPlayerPawn *basetype, *transtype; key[sizeof(key)-1] = 0; i = PlayerClasses.Size () - 1; lastlump = 0; for (j = 0; j < NUMSKINSOUNDS; ++j) { playersoundrefs[j] = skinsoundnames[j][1]; } while ((base = Wads.FindLump ("S_SKIN", &lastlump, true)) != -1) { // The player sprite has 23 frames. This means that the S_SKIN // marker needs a minimum of 23 lumps after it. if (base >= Wads.GetNumLumps() - 23 || base == -1) continue; i++; for (j = 0; j < NUMSKINSOUNDS; j++) sndlumps[j] = -1; skins[i].namespc = Wads.GetLumpNamespace (base); FScanner sc(base); intname = 0; crouchname = 0; remove = false; basetype = NULL; transtype = NULL; // Data is stored as "key = data". while (sc.GetString ()) { strncpy (key, sc.String, sizeof(key)-1); if (!sc.GetString() || sc.String[0] != '=') { Printf (PRINT_BOLD, "Bad format for skin %d: %s\n", (int)i, key); break; } sc.GetString (); if (0 == stricmp (key, "name")) { strncpy (skins[i].name, sc.String, 16); for (j = 0; (size_t)j < i; j++) { if (stricmp (skins[i].name, skins[j].name) == 0) { mysnprintf (skins[i].name, countof(skins[i].name), "skin%d", (int)i); Printf (PRINT_BOLD, "Skin %s duplicated as %s\n", skins[j].name, skins[i].name); break; } } } else if (0 == stricmp (key, "sprite")) { for (j = 3; j >= 0; j--) sc.String[j] = toupper (sc.String[j]); intname = *((DWORD *)sc.String); } else if (0 == stricmp (key, "crouchsprite")) { for (j = 3; j >= 0; j--) sc.String[j] = toupper (sc.String[j]); crouchname = *((DWORD *)sc.String); } else if (0 == stricmp (key, "face")) { for (j = 2; j >= 0; j--) skins[i].face[j] = toupper (sc.String[j]); skins[i].face[3] = '\0'; } else if (0 == stricmp (key, "gender")) { skins[i].gender = D_GenderToInt (sc.String); } else if (0 == stricmp (key, "scale")) { skins[i].Scale.X = clamp(atof (sc.String), 1./65536, 256.); skins[i].Scale.Y = skins[i].Scale.X; } else if (0 == stricmp (key, "game")) { if (gameinfo.gametype == GAME_Heretic) basetype = dyn_cast<PClassPlayerPawn>(PClass::FindActor(NAME_HereticPlayer)); else if (gameinfo.gametype == GAME_Strife) basetype = dyn_cast<PClassPlayerPawn>(PClass::FindActor(NAME_StrifePlayer)); else basetype = dyn_cast<PClassPlayerPawn>(PClass::FindActor(NAME_DoomPlayer)); transtype = basetype; if (stricmp (sc.String, "heretic") == 0) { if (gameinfo.gametype & GAME_DoomChex) { transtype = dyn_cast<PClassPlayerPawn>(PClass::FindActor(NAME_HereticPlayer)); skins[i].othergame = true; } else if (gameinfo.gametype != GAME_Heretic) { remove = true; } } else if (stricmp (sc.String, "strife") == 0) { if (gameinfo.gametype != GAME_Strife) { remove = true; } } else { if (gameinfo.gametype == GAME_Heretic) { transtype = dyn_cast<PClassPlayerPawn>(PClass::FindActor(NAME_DoomPlayer)); skins[i].othergame = true; } else if (!(gameinfo.gametype & GAME_DoomChex)) { remove = true; } } if (remove) break; } else if (0 == stricmp (key, "class")) { // [GRB] Define the skin for a specific player class int pclass = D_PlayerClassToInt (sc.String); if (pclass < 0) { remove = true; break; } basetype = transtype = PlayerClasses[pclass].Type; } else if (key[0] == '*') { // Player sound replacment (ZDoom extension) int lump = Wads.CheckNumForName (sc.String, skins[i].namespc); if (lump == -1) { lump = Wads.CheckNumForFullName (sc.String, true, ns_sounds); } if (lump != -1) { if (stricmp (key, "*pain") == 0) { // Replace all pain sounds in one go aliasid = S_AddPlayerSound (skins[i].name, skins[i].gender, playersoundrefs[0], lump, true); for (int l = 3; l > 0; --l) { S_AddPlayerSoundExisting (skins[i].name, skins[i].gender, playersoundrefs[l], aliasid, true); } } else { int sndref = S_FindSoundNoHash (key); if (sndref != 0) { S_AddPlayerSound (skins[i].name, skins[i].gender, sndref, lump, true); } } } } else { for (j = 0; j < NUMSKINSOUNDS; j++) { if (stricmp (key, skinsoundnames[j][0]) == 0) { sndlumps[j] = Wads.CheckNumForName (sc.String, skins[i].namespc); if (sndlumps[j] == -1) { // Replacement not found, try finding it in the global namespace sndlumps[j] = Wads.CheckNumForFullName (sc.String, true, ns_sounds); } } } //if (j == 8) // Printf ("Funny info for skin %i: %s = %s\n", i, key, sc.String); } } // [GRB] Assume Doom skin by default if (!remove && basetype == NULL) { if (gameinfo.gametype & GAME_DoomChex) { basetype = transtype = dyn_cast<PClassPlayerPawn>(PClass::FindActor(NAME_DoomPlayer)); } else if (gameinfo.gametype == GAME_Heretic) { basetype = dyn_cast<PClassPlayerPawn>(PClass::FindActor(NAME_HereticPlayer)); transtype = dyn_cast<PClassPlayerPawn>(PClass::FindActor(NAME_DoomPlayer)); skins[i].othergame = true; } else { remove = true; } } if (!remove) { skins[i].range0start = transtype->ColorRangeStart; skins[i].range0end = transtype->ColorRangeEnd; remove = true; for (j = 0; j < (int)PlayerClasses.Size (); j++) { PClassPlayerPawn *type = PlayerClasses[j].Type; if (type->IsDescendantOf (basetype) && GetDefaultByType(type)->SpawnState->sprite == GetDefaultByType(basetype)->SpawnState->sprite && type->ColorRangeStart == basetype->ColorRangeStart && type->ColorRangeEnd == basetype->ColorRangeEnd) { PlayerClasses[j].Skins.Push ((int)i); remove = false; } } } if (!remove) { if (skins[i].name[0] == 0) mysnprintf (skins[i].name, countof(skins[i].name), "skin%d", (int)i); // Now collect the sprite frames for this skin. If the sprite name was not // specified, use whatever immediately follows the specifier lump. if (intname == 0) { char name[9]; Wads.GetLumpName (name, base+1); memcpy(&intname, name, 4); } int basens = Wads.GetLumpNamespace(base); for(int spr = 0; spr<2; spr++) { spriteframewithrotate sprtemp[MAX_SPRITE_FRAMES]; memset (sprtemp, 0xFFFF, sizeof(sprtemp)); for (k = 0; k < MAX_SPRITE_FRAMES; ++k) { sprtemp[k].Flip = 0; sprtemp[k].Voxel = NULL; } int maxframe = -1; if (spr == 1) { if (crouchname !=0 && crouchname != intname) { intname = crouchname; } else { skins[i].crouchsprite = -1; break; } } for (k = base + 1; Wads.GetLumpNamespace(k) == basens; k++) { char lname[9]; DWORD lnameint; Wads.GetLumpName (lname, k); memcpy(&lnameint, lname, 4); if (lnameint == intname) { FTextureID picnum = TexMan.CreateTexture(k, FTexture::TEX_SkinSprite); bool res = R_InstallSpriteLump (picnum, lname[4] - 'A', lname[5], false, sprtemp, maxframe); if (lname[6] && res) R_InstallSpriteLump (picnum, lname[6] - 'A', lname[7], true, sprtemp, maxframe); } } if (spr == 0 && maxframe <= 0) { Printf (PRINT_BOLD, "Skin %s (#%d) has no frames. Removing.\n", skins[i].name, (int)i); remove = true; break; } Wads.GetLumpName (temp.name, base+1); temp.name[4] = 0; int sprno = (int)sprites.Push (temp); if (spr==0) skins[i].sprite = sprno; else skins[i].crouchsprite = sprno; R_InstallSprite (sprno, sprtemp, maxframe); } } if (remove) { if (i < numskins-1) memmove (&skins[i], &skins[i+1], sizeof(skins[0])*(numskins-i-1)); i--; continue; } // Register any sounds this skin provides aliasid = 0; for (j = 0; j < NUMSKINSOUNDS; j++) { if (sndlumps[j] != -1) { if (j == 0 || sndlumps[j] != sndlumps[j-1]) { aliasid = S_AddPlayerSound (skins[i].name, skins[i].gender, playersoundrefs[j], sndlumps[j], true); } else { S_AddPlayerSoundExisting (skins[i].name, skins[i].gender, playersoundrefs[j], aliasid, true); } } } // Make sure face prefix is a full 3 chars if (skins[i].face[1] == 0 || skins[i].face[2] == 0) { skins[i].face[0] = 0; } } if (numskins > PlayerClasses.Size ()) { // The sound table may have changed, so rehash it. S_HashSounds (); S_ShrinkPlayerSoundLists (); } }
void D_ReadUserInfoStrings (int i, BYTE **stream, bool update) { userinfo_t *info = &players[i].userinfo; const char *ptr = *((const char **)stream); const char *breakpt; FString value; bool compact; int infotype = -1; if (*ptr++ != '\\') return; compact = (*ptr == '\\') ? ptr++, true : false; if (i < MAXPLAYERS) { for (;;) { int j; breakpt = strchr (ptr, '\\'); if (compact) { value = D_UnescapeUserInfo(ptr, breakpt != NULL ? breakpt - ptr : strlen(ptr)); infotype++; } else { assert(breakpt != NULL); // A malicious remote machine could invalidate the above assert. if (breakpt == NULL) { break; } const char *valstart = breakpt + 1; if ( (breakpt = strchr (valstart, '\\')) != NULL ) { value = D_UnescapeUserInfo(valstart, breakpt - valstart); } else { value = D_UnescapeUserInfo(valstart, strlen(valstart)); } for (j = 0; UserInfoStrings[j] && strnicmp (UserInfoStrings[j], ptr, valstart - ptr - 1) != 0; ++j) { } if (UserInfoStrings[j] == NULL) { infotype = -1; } else { infotype = j; } } switch (infotype) { case INFO_Autoaim: { double angles; angles = atof (value); if (angles > 35.f || angles < 0.f) { info->aimdist = ANGLE_1*35; } else { info->aimdist = abs ((int)(angles * (float)ANGLE_1)); } } break; case INFO_Name: { char oldname[MAXPLAYERNAME+1]; strcpy (oldname, info->netname); strncpy (info->netname, value, MAXPLAYERNAME); info->netname[MAXPLAYERNAME] = 0; CleanseString(info->netname); if (update && strcmp (oldname, info->netname) != 0) { Printf ("%s is now known as %s\n", oldname, info->netname); } } break; case INFO_Team: UpdateTeam (i, atoi(value), update); break; case INFO_Color: info->color = V_GetColorFromString (NULL, value); R_BuildPlayerTranslation (i); if (StatusBar != NULL && i == StatusBar->GetPlayer()) { StatusBar->AttachToPlayer (&players[i]); } break; case INFO_Skin: info->skin = R_FindSkin (value, players[i].CurrentPlayerClass); if (players[i].mo != NULL) { if (players[i].cls != NULL && players[i].mo->state->sprite == GetDefaultByType (players[i].cls)->SpawnState->sprite) { // Only change the sprite if the player is using a standard one players[i].mo->sprite = skins[info->skin].sprite; players[i].mo->scaleX = skins[info->skin].ScaleX; players[i].mo->scaleY = skins[info->skin].ScaleY; } } // Rebuild translation in case the new skin uses a different range // than the old one. R_BuildPlayerTranslation (i); if (StatusBar != NULL && i == StatusBar->GetPlayer()) { StatusBar->SetFace (&skins[info->skin]); } break; case INFO_Gender: info->gender = D_GenderToInt (value); break; case INFO_NeverSwitchOnPickup: if (value[0] >= '0' && value[0] <= '9') { info->neverswitch = atoi (value) ? true : false; } else if (stricmp (value, "true") == 0) { info->neverswitch = 1; } else { info->neverswitch = 0; } break; case INFO_MoveBob: info->MoveBob = (fixed_t)(atof (value) * 65536.f); break; case INFO_StillBob: info->StillBob = (fixed_t)(atof (value) * 65536.f); break; case INFO_PlayerClass: info->PlayerClass = D_PlayerClassToInt (value); break; default: break; } if (breakpt) { ptr = breakpt + 1; } else { break; } } } *stream += strlen (*((char **)stream)) + 1; }