static void ParseArgListDef(FScanner &sc, PClassActor *cls, TArray<PType *> &args, TArray<DWORD> &argflags) { if (!sc.CheckToken(')')) { while (sc.TokenType != ')') { int flags = 0; PType *type = NULL; PClass *restrict = NULL; // Retrieve flags before type name for (;;) { if (sc.CheckToken(TK_Coerce) || sc.CheckToken(TK_Native)) { } else { break; } } // Read the variable type sc.MustGetAnyToken(); switch (sc.TokenType) { case TK_Bool: type = TypeBool; break; case TK_Int: type = TypeSInt32; break; case TK_Float: type = TypeFloat64; break; case TK_Sound: type = TypeSound; break; case TK_String: type = TypeString; break; case TK_Name: type = TypeName; break; case TK_State: type = TypeState; break; case TK_Color: type = TypeColor; break; case TK_Class: sc.MustGetToken('<'); sc.MustGetToken(TK_Identifier); // Get class name restrict = PClass::FindClass(sc.String); if (restrict == NULL) { sc.ScriptMessage("Unknown class type %s", sc.String); FScriptPosition::ErrorCounter++; } else { type = NewClassPointer(restrict); } sc.MustGetToken('>'); break; case TK_Ellipsis: // Making the final type NULL signals a varargs function. type = NULL; sc.MustGetToken(')'); sc.UnGet(); break; default: sc.ScriptMessage ("Unknown variable type %s", sc.TokenName(sc.TokenType, sc.String).GetChars()); type = TypeSInt32; FScriptPosition::ErrorCounter++; break; } // Read the optional variable name if (!sc.CheckToken(',') && !sc.CheckToken(')')) { sc.MustGetToken(TK_Identifier); } else { sc.UnGet(); } if (sc.CheckToken('=')) { flags |= VARF_Optional; FxExpression *def = ParseParameter(sc, cls, type, true); delete def; } args.Push(type); argflags.Push(flags); sc.MustGetAnyToken(); if (sc.TokenType != ',' && sc.TokenType != ')') { sc.ScriptError ("Expected ',' or ')' but got %s instead", sc.TokenName(sc.TokenType, sc.String).GetChars()); } } } sc.MustGetToken(';'); }
FCDODiffControl::FCDODiffControl( const UObject* InOldCDO , const UObject* InNewCDO , TArray< TSharedPtr<FBlueprintDifferenceTreeEntry> >& OutTreeEntries , TArray< TSharedPtr<FBlueprintDifferenceTreeEntry> >& OutRealDifferences , FOnCDODiffControlChanged SelectionCallback ) : OldDetails(InOldCDO, FDetailsDiff::FOnDisplayedPropertiesChanged() ) , NewDetails(InNewCDO, FDetailsDiff::FOnDisplayedPropertiesChanged() ) { // @todo: (doc): rename InDifferences TArray< FSingleObjectDiffEntry > DifferingProperties; OldDetails.DiffAgainst(NewDetails, DifferingProperties); // OrderedProperties will contain differences in the order they are displayed: TArray< const FSingleObjectDiffEntry* > OrderedProperties; // create differing properties list based on what is displayed by the old properties.. TArray<FPropertySoftPath> OldProperties = OldDetails.GetDisplayedProperties(); TArray<FPropertySoftPath> NewProperties = NewDetails.GetDisplayedProperties(); const auto FindDiffering = [](TArray< FSingleObjectDiffEntry > const& InDifferenceEntries, const FPropertySoftPath& PropertyIdentifer) -> const FSingleObjectDiffEntry* { for (const auto& Difference : InDifferenceEntries) { if (Difference.Identifier == PropertyIdentifer) { return &Difference; } } return nullptr; }; // zip the two sets of properties, zip iterators are not trivial to write in c++, // so this procedural stuff will have to do: int IterOld = 0; int IterNew = 0; while (IterOld != OldProperties.Num() || IterNew != NewProperties.Num()) { if (IterOld != OldProperties.Num() && IterNew != NewProperties.Num() && OldProperties[IterOld] == NewProperties[IterNew]) { if (const FSingleObjectDiffEntry* Differing = FindDiffering(DifferingProperties, OldProperties[IterOld])) { OrderedProperties.Push(Differing); } ++IterOld; ++IterNew; } else { if (IterOld != OldProperties.Num()) { bool bFoundDifference = false; if (const FSingleObjectDiffEntry* OldDiffering = FindDiffering(DifferingProperties, OldProperties[IterOld])) { bFoundDifference = true; OrderedProperties.Push(OldDiffering); ++IterOld; } else if (IterNew != NewProperties.Num()) { if (const FSingleObjectDiffEntry* NewDiffering = FindDiffering(DifferingProperties, NewProperties[IterNew])) { bFoundDifference = true; OrderedProperties.Push(NewDiffering); ++IterNew; } } if (!bFoundDifference) { ++IterOld; ++IterNew; } } else { check(IterNew != NewProperties.Num()); if (const FSingleObjectDiffEntry* Differing = FindDiffering(DifferingProperties, NewProperties[IterNew])) { OrderedProperties.Push(Differing); } ++IterNew; } } } const auto CreateCDODifferenceWidget = [](FSingleObjectDiffEntry DiffEntry, FText ObjectName) -> TSharedRef<SWidget> { return SNew(STextBlock) .Text(DiffViewUtils::PropertyDiffMessage(DiffEntry, ObjectName)) .ColorAndOpacity(DiffViewUtils::Differs()); }; const auto FocusDetailsDifferenceEntry = [](FPropertySoftPath Identifier, FCDODiffControl* Control, FOnCDODiffControlChanged InSelectionCallback) { // This allows the owning control to focus the correct tab (or do whatever else it likes): InSelectionCallback.ExecuteIfBound(); Control->HighlightDifference(Identifier); }; TArray< TSharedPtr<FBlueprintDifferenceTreeEntry> > Children; for (auto Difference : OrderedProperties) { auto Entry = TSharedPtr<FBlueprintDifferenceTreeEntry>( new FBlueprintDifferenceTreeEntry( FOnDiffEntryFocused::CreateStatic(FocusDetailsDifferenceEntry, Difference->Identifier, this, SelectionCallback) , FGenerateDiffEntryWidget::CreateStatic(CreateCDODifferenceWidget, *Difference, RightRevision) , TArray< TSharedPtr<FBlueprintDifferenceTreeEntry> >() ) ); Children.Push(Entry); OutRealDifferences.Push(Entry); } const bool bHasDiffferences = Children.Num() != 0; FLinearColor Color = bHasDiffferences ? DiffViewUtils::Differs() : DiffViewUtils::Identical(); if (!bHasDiffferences) { // make one child informing the user that there are no differences: Children.Push(FBlueprintDifferenceTreeEntry::NoDifferencesEntry() ); } const auto ForwardSelection = [](FOnCDODiffControlChanged InSelectionCallback) { // This allows the owning control to focus the correct tab (or do whatever else it likes): InSelectionCallback.ExecuteIfBound(); }; OutTreeEntries.Push(FBlueprintDifferenceTreeEntry::CreateDefaultsCategoryEntry( FOnDiffEntryFocused::CreateStatic(ForwardSelection, SelectionCallback) , Children , bHasDiffferences )); }
//***************************************************************************** // void LASTMANSTANDING_TimeExpired( void ) { LONG lHighestHealth = 0; bool bTie = false; bool bFoundPlayer = false; LONG lWinner = -1; DHUDMessageFadeOut *pMsg; char szString[64]; // Don't end the level if we're not in a game. if ( LASTMANSTANDING_GetState( ) != LMSS_INPROGRESS ) return; // Try to find the player with the highest health. if ( lastmanstanding ) { TArray<ULONG> possibleWinners; for ( unsigned int i = 0; i < MAXPLAYERS; ++i ) possibleWinners.Push ( i ); // [BB] Find the player with the most lives left. PLAYER_SelectPlayersWithHighestValue ( PLAYER_GetLivesLeft, possibleWinners ); // [BB] If more than one player has the most lives left, select the player with the highest lives. if ( possibleWinners.Size() != 1 ) PLAYER_SelectPlayersWithHighestValue ( PLAYER_GetHealth, possibleWinners ); // [BB] If more then one player have the most lives and also the same health, then the game it a tie. if ( possibleWinners.Size() == 1 ) lWinner = possibleWinners[0]; else { lWinner = MAXPLAYERS; bTie = true; } } else if ( teamlms ) { if ( LASTMANSTANDING_TeamsWithAlivePlayersOn( ) == 1 ) { for ( ULONG i = 0; i < teams.Size( ); i++ ) { if ( TEAM_CountLivingAndRespawnablePlayers( i ) ) lWinner = i; } } else { lWinner = teams.Size( ); bTie = true; } } // If for some reason we don't have any players, just end the map like normal. if ( lWinner == -1 ) { if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVER_Printf( PRINT_HIGH, "%s\n", GStrings( "TXT_TIMELIMIT" )); else Printf( "%s\n", GStrings( "TXT_TIMELIMIT" )); GAME_SetEndLevelDelay( 5 * TICRATE ); return; } // If there was a tie, then go into sudden death! if ( bTie ) { // Only print the message the instant we reach sudden death. if ( level.time == (int)( timelimit * TICRATE * 60 )) { sprintf( szString, "\\cdSUDDEN DEATH!" ); V_ColorizeString( szString ); if ( NETWORK_GetState( ) != NETSTATE_SERVER ) { // Display the HUD message. pMsg = new DHUDMessageFadeOut( BigFont, szString, 160.4f, 75.0f, 320, 200, CR_RED, 3.0f, 2.0f ); StatusBar->AttachMessage( pMsg, MAKE_ID('C','N','T','R') ); } else { SERVERCOMMANDS_PrintHUDMessageFadeOut( szString, 160.4f, 75.0f, 320, 200, CR_RED, 3.0f, 2.0f, "BigFont", false, MAKE_ID('C','N','T','R') ); } } return; } // Also, do the win sequence for the player. LASTMANSTANDING_DoWinSequence( lWinner ); // Give the winner a win. if ( lastmanstanding ) PLAYER_SetWins( &players[lWinner], players[lWinner].ulWins + 1 ); // [BB] In a team game of course give the win to the winning team. if ( teamlms ) TEAM_SetWinCount( lWinner, TEAM_GetWinCount( lWinner ) + 1, false ); if ( NETWORK_GetState( ) == NETSTATE_SERVER ) SERVER_Printf( PRINT_HIGH, "%s\n", GStrings( "TXT_TIMELIMIT" )); else Printf( "%s\n", GStrings( "TXT_TIMELIMIT" )); GAME_SetEndLevelDelay( 5 * TICRATE ); }
//***************************************************************************** // bool ZANDRONUM_ParseMasterServerResponse( BYTESTREAM_s *pByteStream, TArray<SERVER_s>&aServerInfo, TArray<QUERY_s>&aQueryInfo ) { ULONG i; LONG lCommand; SERVER_s ServerInfo; QUERY_s QueryInfo; time_t tNow; lCommand = NETWORK_ReadLong( pByteStream ); switch ( lCommand ) { case MSC_BEGINSERVERLISTPART: const ULONG ulPacketNum = NETWORK_ReadByte( pByteStream ); if ( ulPacketNum == 0 ) { // Add a new query. QueryInfo.qTotal.lNumPlayers = 0; QueryInfo.qTotal.lNumServers = 0; QueryInfo.qTotal.lNumSpectators = 0; for ( unsigned int g = 0; g < NUM_GAMETYPES; g++ ) { QueryInfo.qByGameMode[g].lNumPlayers = 0; QueryInfo.qByGameMode[g].lNumServers = 0; QueryInfo.qByGameMode[g].lNumSpectators = 0; } time( &QueryInfo.tTime ); aQueryInfo.Push( QueryInfo ); // Clear out the server list. aServerInfo.Clear( ); } time( &tNow ); while ( true ) { const LONG lCommand = NETWORK_ReadByte( pByteStream ); switch ( lCommand ) { case MSC_SERVER: { ServerInfo.ulActiveState = AS_WAITINGFORREPLY; // Read in address information. ServerInfo.Address.abIP[0] = NETWORK_ReadByte( pByteStream ); ServerInfo.Address.abIP[1] = NETWORK_ReadByte( pByteStream ); ServerInfo.Address.abIP[2] = NETWORK_ReadByte( pByteStream ); ServerInfo.Address.abIP[3] = NETWORK_ReadByte( pByteStream ); ServerInfo.Address.usPort = htons( NETWORK_ReadShort( pByteStream )); ServerInfo.tLastQuery = tNow; // Add this server's info to our list, and query it. i = aServerInfo.Push( ServerInfo ); ZANDRONUM_QueryServer( &aServerInfo[i] ); } break; case MSC_SERVERBLOCK: { // Read in address information. ULONG ulPorts = 0; while (( ulPorts = NETWORK_ReadByte( pByteStream ) )) { ServerInfo.Address.abIP[0] = NETWORK_ReadByte( pByteStream ); ServerInfo.Address.abIP[1] = NETWORK_ReadByte( pByteStream ); ServerInfo.Address.abIP[2] = NETWORK_ReadByte( pByteStream ); ServerInfo.Address.abIP[3] = NETWORK_ReadByte( pByteStream ); for ( ULONG ulIdx = 0; ulIdx < ulPorts; ++ulIdx ) { ServerInfo.ulActiveState = AS_WAITINGFORREPLY; ServerInfo.Address.usPort = htons( NETWORK_ReadShort( pByteStream )); ServerInfo.tLastQuery = tNow; // Add this server's info to our list, and query it. i = aServerInfo.Push( ServerInfo ); ZANDRONUM_QueryServer( &aServerInfo[i] ); } } } break; case MSC_ENDSERVERLISTPART: return false; case MSC_ENDSERVERLIST: Printf( "Received %d Zandronum servers.\n", aServerInfo.Size( )); // Since we got the server list, return true. return true; default: Printf( "Unknown server list command from master server: %d\n", static_cast<int> (lCommand) ); return false; } } } return true; }
void ParseTextMap(MapData *map) { char *buffer = new char[map->Size(ML_TEXTMAP)]; isTranslated = true; isExtended = false; floordrop = false; map->Read(ML_TEXTMAP, buffer); sc.OpenMem(Wads.GetLumpFullName(map->lumpnum), buffer, map->Size(ML_TEXTMAP)); delete [] buffer; sc.SetCMode(true); if (sc.CheckString("namespace")) { sc.MustGetStringName("="); sc.MustGetString(); namespc = sc.String; switch(namespc) { case NAME_ZDoom: namespace_bits = Zd; isTranslated = false; break; case NAME_ZDoomTranslated: level.flags2 |= LEVEL2_DUMMYSWITCHES; namespace_bits = Zdt; break; case NAME_Vavoom: namespace_bits = Va; isTranslated = false; break; case NAME_Hexen: namespace_bits = Hx; isTranslated = false; break; case NAME_Doom: namespace_bits = Dm; P_LoadTranslator("xlat/doom_base.txt"); level.flags2 |= LEVEL2_DUMMYSWITCHES; floordrop = true; break; case NAME_Heretic: namespace_bits = Ht; P_LoadTranslator("xlat/heretic_base.txt"); level.flags2 |= LEVEL2_DUMMYSWITCHES; floordrop = true; break; case NAME_Strife: namespace_bits = St; P_LoadTranslator("xlat/strife_base.txt"); level.flags2 |= LEVEL2_DUMMYSWITCHES|LEVEL2_RAILINGHACK; floordrop = true; break; default: Printf("Unknown namespace %s. Using defaults for %s\n", sc.String, GameTypeName()); switch (gameinfo.gametype) { default: // Shh, GCC case GAME_Doom: case GAME_Chex: namespace_bits = Dm; P_LoadTranslator("xlat/doom_base.txt"); break; case GAME_Heretic: namespace_bits = Ht; P_LoadTranslator("xlat/heretic_base.txt"); break; case GAME_Strife: namespace_bits = St; P_LoadTranslator("xlat/strife_base.txt"); break; case GAME_Hexen: namespace_bits = Hx; isTranslated = false; break; } } sc.MustGetStringName(";"); } else { Printf("Map does not define a namespace.\n"); } while (sc.GetString()) { if (sc.Compare("thing")) { FMapThing th; unsigned userdatastart = MapThingsUserData.Size(); ParseThing(&th); MapThingsConverted.Push(th); if (userdatastart < MapThingsUserData.Size()) { // User data added MapThingsUserDataIndex[MapThingsConverted.Size()-1] = userdatastart; // Mark end of the user data for this map thing FMapThingUserData ud; ud.Property = NAME_None; ud.Value = 0; MapThingsUserData.Push(ud); } } else if (sc.Compare("linedef")) { line_t li; ParseLinedef(&li, ParsedLines.Size()); ParsedLines.Push(li); } else if (sc.Compare("sidedef")) { side_t si; intmapsidedef_t st; ParseSidedef(&si, &st, ParsedSides.Size()); ParsedSides.Push(si); ParsedSideTextures.Push(st); } else if (sc.Compare("sector")) { sector_t sec; ParseSector(&sec, ParsedSectors.Size()); ParsedSectors.Push(sec); } else if (sc.Compare("vertex")) { vertex_t vt; vertexdata_t vd; ParseVertex(&vt, &vd); ParsedVertices.Push(vt); ParsedVertexDatas.Push(vd); } else { Skip(); } } // Catch bogus maps here rather than during nodebuilding if (ParsedVertices.Size() == 0) I_Error("Map has no vertices.\n"); if (ParsedSectors.Size() == 0) I_Error("Map has no sectors. \n"); if (ParsedLines.Size() == 0) I_Error("Map has no linedefs.\n"); if (ParsedSides.Size() == 0) I_Error("Map has no sidedefs.\n"); // Create the real vertices numvertexes = ParsedVertices.Size(); vertexes = new vertex_t[numvertexes]; memcpy(vertexes, &ParsedVertices[0], numvertexes * sizeof(*vertexes)); // Create the real vertex datas numvertexdatas = ParsedVertexDatas.Size(); vertexdatas = new vertexdata_t[numvertexdatas]; memcpy(vertexdatas, &ParsedVertexDatas[0], numvertexdatas * sizeof(*vertexdatas)); // Create the real sectors numsectors = ParsedSectors.Size(); sectors = new sector_t[numsectors]; memcpy(sectors, &ParsedSectors[0], numsectors * sizeof(*sectors)); sectors[0].e = new extsector_t[numsectors]; for(int i = 0; i < numsectors; i++) { sectors[i].e = §ors[0].e[i]; } // Create the real linedefs and decompress the sidedefs ProcessLineDefs(); }
void R_InitColormaps () { // [RH] Try and convert BOOM colormaps into blending values. // This is a really rough hack, but it's better than // not doing anything with them at all (right?) FakeCmap cm; R_DeinitColormaps(); cm.name[0] = 0; cm.blend = 0; fakecmaps.Push(cm); uint32_t NumLumps = Wads.GetNumLumps(); for (uint32_t i = 0; i < NumLumps; i++) { if (Wads.GetLumpNamespace(i) == ns_colormaps) { char name[9]; name[8] = 0; Wads.GetLumpName (name, i); if (Wads.CheckNumForName (name, ns_colormaps) == (int)i) { strncpy(cm.name, name, 8); cm.blend = 0; cm.lump = i; fakecmaps.Push(cm); } } } int rr = 0, gg = 0, bb = 0; for(int x=0;x<256;x++) { rr += GPalette.BaseColors[x].r; gg += GPalette.BaseColors[x].g; bb += GPalette.BaseColors[x].b; } rr >>= 8; gg >>= 8; bb >>= 8; int palette_brightness = (rr*77 + gg*143 + bb*35) / 255; // To calculate the blend it will just average the colors of the first map if (fakecmaps.Size() > 1) { uint8_t map[256]; for (unsigned j = 1; j < fakecmaps.Size(); j++) { if (Wads.LumpLength (fakecmaps[j].lump) >= 256) { int k, r, g, b; FWadLump lump = Wads.OpenLumpNum (fakecmaps[j].lump); lump.Read(map, 256); r = g = b = 0; for (k = 0; k < 256; k++) { r += GPalette.BaseColors[map[k]].r; g += GPalette.BaseColors[map[k]].g; b += GPalette.BaseColors[map[k]].b; } r /= 256; g /= 256; b /= 256; // The calculated average is too dark so brighten it according to the palettes's overall brightness int maxcol = MAX<int>(MAX<int>(palette_brightness, r), MAX<int>(g, b)); fakecmaps[j].blend = PalEntry (255, r * 255 / maxcol, g * 255 / maxcol, b * 255 / maxcol); } } } // build default special maps (e.g. invulnerability) for (unsigned i = 0; i < countof(SpecialColormapParms); ++i) { AddSpecialColormap(SpecialColormapParms[i].Start[0], SpecialColormapParms[i].Start[1], SpecialColormapParms[i].Start[2], SpecialColormapParms[i].End[0], SpecialColormapParms[i].End[1], SpecialColormapParms[i].End[2]); } // desaturated colormaps. These are used for texture composition for(int m = 0; m < 31; m++) { uint8_t *shade = DesaturateColormap[m]; for (int c = 0; c < 256; c++) { int intensity = (GPalette.BaseColors[c].r * 77 + GPalette.BaseColors[c].g * 143 + GPalette.BaseColors[c].b * 37) / 256; int r = (GPalette.BaseColors[c].r * (31-m) + intensity *m) / 31; int g = (GPalette.BaseColors[c].g * (31-m) + intensity *m) / 31; int b = (GPalette.BaseColors[c].b * (31-m) + intensity *m) / 31; shade[c] = ColorMatcher.Pick(r, g, b); } } }
void ParseCompatibility() { TArray<FMD5Holder> md5array; FMD5Holder md5; FCompatValues flags; int i, x; unsigned int j; BCompatMap.Clear(); CompatParams.Clear(); // The contents of this file are not cumulative, as it should not // be present in user-distributed maps. FScanner sc(Wads.GetNumForFullName("compatibility.txt")); while (sc.GetString()) // Get MD5 signature { do { if (strlen(sc.String) != 32) { sc.ScriptError("MD5 signature must be exactly 32 characters long"); } for (i = 0; i < 32; ++i) { if (sc.String[i] >= '0' && sc.String[i] <= '9') { x = sc.String[i] - '0'; } else { sc.String[i] |= 'a' ^ 'A'; if (sc.String[i] >= 'a' && sc.String[i] <= 'f') { x = sc.String[i] - 'a' + 10; } else { x = 0; sc.ScriptError("MD5 signature must be a hexadecimal value"); } } if (!(i & 1)) { md5.Bytes[i / 2] = x << 4; } else { md5.Bytes[i / 2] |= x; } } md5array.Push(md5); sc.MustGetString(); } while (!sc.Compare("{")); memset(flags.CompatFlags, 0, sizeof(flags.CompatFlags)); flags.ExtCommandIndex = ~0u; while (sc.GetString()) { if ((i = sc.MatchString(&Options[0].Name, sizeof(*Options))) >= 0) { flags.CompatFlags[Options[i].WhichSlot] |= Options[i].CompatFlags; } else if (sc.Compare("clearlineflags")) { if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size(); CompatParams.Push(CP_CLEARFLAGS); sc.MustGetNumber(); CompatParams.Push(sc.Number); sc.MustGetNumber(); CompatParams.Push(sc.Number); } else if (sc.Compare("setlineflags")) { if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size(); CompatParams.Push(CP_SETFLAGS); sc.MustGetNumber(); CompatParams.Push(sc.Number); sc.MustGetNumber(); CompatParams.Push(sc.Number); } else if (sc.Compare("setlinespecial")) { if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size(); CompatParams.Push(CP_SETSPECIAL); sc.MustGetNumber(); CompatParams.Push(sc.Number); sc.MustGetString(); CompatParams.Push(P_FindLineSpecial(sc.String, NULL, NULL)); for (int i = 0; i < 5; i++) { sc.MustGetNumber(); CompatParams.Push(sc.Number); } } else if (sc.Compare("clearlinespecial")) { if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size(); CompatParams.Push(CP_CLEARSPECIAL); sc.MustGetNumber(); CompatParams.Push(sc.Number); } else if (sc.Compare("setactivation")) { if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size(); CompatParams.Push(CP_SETACTIVATION); sc.MustGetNumber(); CompatParams.Push(sc.Number); sc.MustGetNumber(); CompatParams.Push(sc.Number); } else if (sc.Compare("sectorflooroffset")) { if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size(); CompatParams.Push(CP_SECTORFLOOROFFSET); sc.MustGetNumber(); CompatParams.Push(sc.Number); sc.MustGetFloat(); CompatParams.Push(FLOAT2FIXED(sc.Float)); } else if (sc.Compare("setwallyscale")) { if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size(); CompatParams.Push(CP_SETWALLYSCALE); sc.MustGetNumber(); CompatParams.Push(sc.Number); sc.MustGetString(); CompatParams.Push(sc.MustMatchString(LineSides)); sc.MustGetString(); CompatParams.Push(sc.MustMatchString(WallTiers)); sc.MustGetFloat(); CompatParams.Push(FLOAT2FIXED(sc.Float)); } else if (sc.Compare("setthingz")) { if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size(); CompatParams.Push(CP_SETTHINGZ); sc.MustGetNumber(); CompatParams.Push(sc.Number); sc.MustGetFloat(); CompatParams.Push(FLOAT2FIXED(sc.Float)); } else if (sc.Compare("setsectortag")) { if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size(); CompatParams.Push(CP_SETTAG); sc.MustGetNumber(); CompatParams.Push(sc.Number); sc.MustGetNumber(); CompatParams.Push(sc.Number); } else if (sc.Compare("setthingflags")) { if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size(); CompatParams.Push(CP_SETTHINGFLAGS); sc.MustGetNumber(); CompatParams.Push(sc.Number); sc.MustGetNumber(); CompatParams.Push(sc.Number); } else { sc.UnGet(); break; } } if (flags.ExtCommandIndex != ~0u) { CompatParams.Push(CP_END); } sc.MustGetStringName("}"); for (j = 0; j < md5array.Size(); ++j) { BCompatMap[md5array[j]] = flags; } md5array.Clear(); } }
/** * Assigns a group index to each triangle such that it's the same group as its adjacent triangles. * The group indices are between zero and the minimum number of indices needed. * @return The number of groups used. */ static uint32 AssignMinimalAdjacencyGroups(const TArray<uint32>& Adjacency,TArray<int32>& OutTriangleGroups) { const uint32 NumTriangles = Adjacency.Num() / 3; check(Adjacency.Num() == NumTriangles * 3); // Initialize the triangle group array. OutTriangleGroups.Empty(NumTriangles); for(uint32 TriangleIndex = 0;TriangleIndex < NumTriangles;TriangleIndex++) { OutTriangleGroups.Add(INDEX_NONE); } uint32 NumGroups = 0; while(true) { const uint32 CurrentGroupIndex = NumGroups; TArray<uint32> PendingGroupTriangles; // Find the next ungrouped triangle to start the group with. for(uint32 TriangleIndex = 0;TriangleIndex < NumTriangles;TriangleIndex++) { if(OutTriangleGroups[TriangleIndex] == INDEX_NONE) { PendingGroupTriangles.Push(TriangleIndex); break; } } if(!PendingGroupTriangles.Num()) { break; } else { // Recursively expand the group to include all triangles adjacent to the group's triangles. while(PendingGroupTriangles.Num()) { const uint32 TriangleIndex = PendingGroupTriangles.Pop(); OutTriangleGroups[TriangleIndex] = CurrentGroupIndex; for(int32 EdgeIndex = 0;EdgeIndex < 3;EdgeIndex++) { const int32 AdjacentTriangleIndex = Adjacency[TriangleIndex * 3 + EdgeIndex]; if(AdjacentTriangleIndex != INDEX_NONE) { const int32 AdjacentTriangleGroupIndex = OutTriangleGroups[AdjacentTriangleIndex]; check(AdjacentTriangleGroupIndex == INDEX_NONE || AdjacentTriangleGroupIndex == CurrentGroupIndex); if(AdjacentTriangleGroupIndex == INDEX_NONE) { PendingGroupTriangles.Push(AdjacentTriangleIndex); } } } }; NumGroups++; } }; return NumGroups; }
static void server_rcon_HandleLogin( int iCandidateIndex, const char *pszHash ) { // If there's no slot, the candidate must have timed out, or is hacking. Bye! if ( iCandidateIndex == -1 ) return; // Combine the salt and password, and hash it. FString fsString, fsCorrectHash; fsString.Format( "%s%s", g_Candidates[iCandidateIndex].szSalt, sv_rconpassword.GetGenericRep(CVAR_String).String ); CMD5Checksum::GetMD5( reinterpret_cast<const BYTE *>(fsString.GetChars()), fsString.Len(), fsCorrectHash ); // Compare that to what he sent us. // Printf("Mine: %s\nTheirs: %s\n", fsCorrectHash, pszHash ); NETWORK_ClearBuffer( &g_MessageBuffer ); // [BB] Do not allow the server to let anybody use RCON in case sv_rconpassword is empty. if ( fsCorrectHash.Compare( pszHash ) || ( strlen( sv_rconpassword.GetGenericRep(CVAR_String).String ) == 0 ) ) { // Wrong password. NETWORK_WriteByte( &g_MessageBuffer.ByteStream, SVRC_INVALIDPASSWORD ); NETWORK_LaunchPacket( &g_MessageBuffer, g_Candidates[iCandidateIndex].Address ); // [RC] Note: Be sure to finish any packets before calling Printf(). Otherwise SERVER_RCON_Print will clear your buffer. // To prevent mass password flooding, ignore the IP for a few seconds. g_BadRequestFloodQueue.addAddress( g_Candidates[iCandidateIndex].Address, gametic / 1000 ); Printf( "Failed RCON login from %s. Ignoring IP for 10 seconds...\n", NETWORK_AddressToString( g_Candidates[iCandidateIndex].Address )); } else { // [BB] Since we log when RCON clients disconnect, we should also log when they connect. // Do this before we do anything else so that this message is sent to the new RCON client // with the console history. Printf( "RCON client at %s connected.\n", NETWORK_AddressToString( g_Candidates[iCandidateIndex].Address )); // Correct password. Promote him to an authed client. RCONCLIENT_s Client; Client.Address = g_Candidates[iCandidateIndex].Address; Client.iLastMessageTic = gametic; g_AuthedClients.Push( Client ); NETWORK_ClearBuffer( &g_MessageBuffer ); NETWORK_WriteByte( &g_MessageBuffer.ByteStream, SVRC_LOGGEDIN ); // Tell him some info about the server. NETWORK_WriteByte( &g_MessageBuffer.ByteStream, PROTOCOL_VERSION ); NETWORK_WriteString( &g_MessageBuffer.ByteStream, sv_hostname.GetGenericRep( CVAR_String ).String ); // Send updates. NETWORK_WriteByte( &g_MessageBuffer.ByteStream, NUM_RCON_UPDATES ); for ( int i = 0; i < NUM_RCON_UPDATES; i++ ) server_WriteUpdateInfo( &g_MessageBuffer.ByteStream, i ); // Send the console history. NETWORK_WriteByte( &g_MessageBuffer.ByteStream, g_RecentConsoleLines.size() ); for( std::list<FString>::iterator i = g_RecentConsoleLines.begin(); i != g_RecentConsoleLines.end(); ++i ) NETWORK_WriteString( &g_MessageBuffer.ByteStream, *i ); NETWORK_LaunchPacket( &g_MessageBuffer, g_Candidates[iCandidateIndex].Address ); SERVER_RCON_UpdateInfo( SVRCU_ADMINCOUNT ); } // Remove his temporary slot. g_Candidates.Delete( iCandidateIndex ); }
void InitThingdef() { PType *TypeActor = NewPointer(RUNTIME_CLASS(AActor)); PStruct *sstruct = NewNativeStruct("Sector", nullptr); auto sptr = NewPointer(sstruct); sstruct->AddNativeField("soundtarget", TypeActor, myoffsetof(sector_t, SoundTarget)); // expose the global validcount variable. PField *vcf = new PField("validcount", TypeSInt32, VARF_Native | VARF_Static, (intptr_t)&validcount); GlobalSymbols.AddSymbol(vcf); // expose the global Multiplayer variable. PField *multif = new PField("multiplayer", TypeBool, VARF_Native | VARF_ReadOnly | VARF_Static, (intptr_t)&multiplayer); GlobalSymbols.AddSymbol(multif); // set up a variable for the global level data structure PStruct *lstruct = NewNativeStruct("LevelLocals", nullptr); PField *levelf = new PField("level", lstruct, VARF_Native | VARF_Static, (intptr_t)&level); GlobalSymbols.AddSymbol(levelf); // set up a variable for the DEH data PStruct *dstruct = NewNativeStruct("DehInfo", nullptr); PField *dehf = new PField("deh", dstruct, VARF_Native | VARF_Static, (intptr_t)&deh); GlobalSymbols.AddSymbol(dehf); // set up a variable for the global players array. PStruct *pstruct = NewNativeStruct("PlayerInfo", nullptr); pstruct->Size = sizeof(player_t); pstruct->Align = alignof(player_t); PArray *parray = NewArray(pstruct, MAXPLAYERS); PField *playerf = new PField("players", parray, VARF_Native | VARF_Static, (intptr_t)&players); GlobalSymbols.AddSymbol(playerf); // set up the lines array in the sector struct. This is a bit messy because the type system is not prepared to handle a pointer to an array of pointers to a native struct even remotely well... // As a result, the size has to be set to something large and arbritrary because it can change between maps. This will need some serious improvement when things get cleaned up. pstruct = NewNativeStruct("Sector", nullptr); pstruct->AddNativeField("lines", NewPointer(NewArray(NewPointer(NewNativeStruct("line", nullptr), false), 0x40000), false), myoffsetof(sector_t, lines), VARF_Native); parray = NewArray(TypeBool, MAXPLAYERS); playerf = new PField("playeringame", parray, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&playeringame); GlobalSymbols.AddSymbol(playerf); playerf = new PField("gameaction", TypeUInt8, VARF_Native | VARF_Static, (intptr_t)&gameaction); GlobalSymbols.AddSymbol(playerf); playerf = new PField("consoleplayer", TypeSInt32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&consoleplayer); GlobalSymbols.AddSymbol(playerf); // Argh. It sucks when bad hacks need to be supported. WP_NOCHANGE is just a bogus pointer but it used everywhere as a special flag. // It cannot be defined as constant because constants can either be numbers or strings but nothing else, so the only 'solution' // is to create a static variable from it and reference that in the script. Yuck!!! static AWeapon *wpnochg = WP_NOCHANGE; playerf = new PField("WP_NOCHANGE", NewPointer(RUNTIME_CLASS(AWeapon), false), VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&wpnochg); GlobalSymbols.AddSymbol(playerf); // this needs to be done manually until it can be given a proper type. RUNTIME_CLASS(AActor)->AddNativeField("DecalGenerator", NewPointer(TypeVoid), myoffsetof(AActor, DecalGenerator)); // synthesize a symbol for each flag from the flag name tables to avoid redundant declaration of them. for (auto &fl : FlagLists) { if (fl.Use & 2) { for(int i=0;i<fl.NumDefs;i++) { if (fl.Defs[i].structoffset > 0) // skip the deprecated entries in this list { const_cast<PClass*>(*fl.Type)->AddNativeField(FStringf("b%s", fl.Defs[i].name), (fl.Defs[i].fieldsize == 4 ? TypeSInt32 : TypeSInt16), fl.Defs[i].structoffset, fl.Defs[i].varflags, fl.Defs[i].flagbit); } } } } FAutoSegIterator probe(CRegHead, CRegTail); while (*++probe != NULL) { if (((ClassReg *)*probe)->InitNatives) ((ClassReg *)*probe)->InitNatives(); } // Sort the flag lists for (size_t i = 0; i < NUM_FLAG_LISTS; ++i) { qsort (FlagLists[i].Defs, FlagLists[i].NumDefs, sizeof(FFlagDef), flagcmp); } // Create a sorted list of properties if (properties.Size() == 0) { FAutoSegIterator probe(GRegHead, GRegTail); while (*++probe != NULL) { properties.Push((FPropertyInfo *)*probe); } properties.ShrinkToFit(); qsort(&properties[0], properties.Size(), sizeof(properties[0]), propcmp); } // Create a sorted list of native action functions AFTable.Clear(); if (AFTable.Size() == 0) { FAutoSegIterator probe(ARegHead, ARegTail); while (*++probe != NULL) { AFuncDesc *afunc = (AFuncDesc *)*probe; assert(afunc->VMPointer != NULL); *(afunc->VMPointer) = new VMNativeFunction(afunc->Function, afunc->FuncName); (*(afunc->VMPointer))->PrintableName.Format("%s.%s [Native]", afunc->ClassName+1, afunc->FuncName); AFTable.Push(*afunc); } AFTable.ShrinkToFit(); qsort(&AFTable[0], AFTable.Size(), sizeof(AFTable[0]), funccmp); } FieldTable.Clear(); if (FieldTable.Size() == 0) { FAutoSegIterator probe(FRegHead, FRegTail); while (*++probe != NULL) { FieldDesc *afield = (FieldDesc *)*probe; FieldTable.Push(*afield); } FieldTable.ShrinkToFit(); qsort(&FieldTable[0], FieldTable.Size(), sizeof(FieldTable[0]), fieldcmp); } }
/** Creates a vertex element list for the D3D9MeshUtils vertex format. */ static void GetD3D9MeshVertexDeclarations(TArray<D3DVERTEXELEMENT9>& OutVertexElements) { OutVertexElements.Push(ConstructD3DVertexElement(0, STRUCT_OFFSET(FUtilVertex,Position), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0)); OutVertexElements.Push(ConstructD3DVertexElement(0, STRUCT_OFFSET(FUtilVertex,UVs[0]), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0)); OutVertexElements.Push(ConstructD3DVertexElement(0, STRUCT_OFFSET(FUtilVertex,UVs[1]), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1)); OutVertexElements.Push(ConstructD3DVertexElement(0, STRUCT_OFFSET(FUtilVertex,UVs[2]), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2)); OutVertexElements.Push(ConstructD3DVertexElement(0, STRUCT_OFFSET(FUtilVertex,UVs[3]), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3)); OutVertexElements.Push(ConstructD3DVertexElement(0, STRUCT_OFFSET(FUtilVertex,UVs[4]), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4)); OutVertexElements.Push(ConstructD3DVertexElement(0, STRUCT_OFFSET(FUtilVertex,UVs[5]), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 5)); OutVertexElements.Push(ConstructD3DVertexElement(0, STRUCT_OFFSET(FUtilVertex,UVs[6]), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 6)); OutVertexElements.Push(ConstructD3DVertexElement(0, STRUCT_OFFSET(FUtilVertex,UVs[7]), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 7)); OutVertexElements.Push(ConstructD3DVertexElement(0, STRUCT_OFFSET(FUtilVertex,Color), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0)); OutVertexElements.Push(ConstructD3DVertexElement(0, STRUCT_OFFSET(FUtilVertex,SmoothingMask), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1)); OutVertexElements.Push(ConstructD3DVertexElement(0, STRUCT_OFFSET(FUtilVertex,TangentX), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0)); OutVertexElements.Push(ConstructD3DVertexElement(0, STRUCT_OFFSET(FUtilVertex,TangentY), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL, 0)); OutVertexElements.Push(ConstructD3DVertexElement(0, STRUCT_OFFSET(FUtilVertex,TangentZ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0)); OutVertexElements.Push(ConstructD3DVertexElement(0xFF,0,D3DDECLTYPE_UNUSED,0,0,0)); }
void FTeam::ParseTeamDefinition (FScanner &Scan) { FTeam Team; int valid = -1; Scan.MustGetString (); Team.m_Name = Scan.String; Scan.MustGetStringName ("{"); while (!Scan.CheckString ("}")) { Scan.MustGetString (); switch (Scan.MatchString (TeamInfoOptions)) { case TEAMINFO_Game: Scan.MustGetString (); if (Scan.Compare("Any")) valid = 1; else if (CheckGame(Scan.String, false)) valid = 1; else if (valid == -1) valid = 0; break; case TEAMINFO_PlayerColor: Scan.MustGetString (); Team.m_iPlayerColor = V_GetColor (NULL, Scan.String); break; case TEAMINFO_TextColor: Scan.MustGetString (); Team.m_TextColor.AppendFormat ("[%s]", Scan.String); break; case TEAMINFO_Logo: Scan.MustGetString (); Team.m_Logo = Scan.String; break; case TEAMINFO_AllowCustomPlayerColor: Team.m_bAllowCustomPlayerColor = true; break; case TEAMINFO_PlayerStartThingNumber: Scan.MustGetNumber (); break; case TEAMINFO_RailColor: case TEAMINFO_FlagItem: case TEAMINFO_SkullItem: case TEAMINFO_SmallFlagHUDIcon: case TEAMINFO_SmallSkullHUDIcon: case TEAMINFO_LargeFlagHUDIcon: case TEAMINFO_LargeSkullHUDIcon: case TEAMINFO_WinnerPic: case TEAMINFO_LoserPic: case TEAMINFO_WinnerTheme: case TEAMINFO_LoserTheme: Scan.MustGetString (); break; default: Scan.ScriptError ("ParseTeamDefinition: Unknown team option '%s'.\n", Scan.String); break; } } if (valid) Teams.Push (Team); }
void FMapInfoParser::ParseSkill () { FSkillInfo skill; skill.AmmoFactor = FRACUNIT; skill.DoubleAmmoFactor = 2*FRACUNIT; skill.DropAmmoFactor = -1; skill.DamageFactor = FRACUNIT; skill.FastMonsters = false; skill.DisableCheats = false; skill.EasyBossBrain = false; skill.AutoUseHealth = false; skill.RespawnCounter = 0; skill.RespawnLimit = 0; skill.Aggressiveness = FRACUNIT; skill.SpawnFilter = 0; skill.ACSReturn = AllSkills.Size(); skill.MenuNameIsLump = false; skill.MustConfirm = false; skill.Shortcut = 0; skill.TextColor = ""; sc.MustGetString(); skill.Name = sc.String; ParseOpenBrace(); while (sc.GetString ()) { if (sc.Compare ("ammofactor")) { ParseAssign(); sc.MustGetFloat (); skill.AmmoFactor = FLOAT2FIXED(sc.Float); } else if (sc.Compare ("doubleammofactor")) { ParseAssign(); sc.MustGetFloat (); skill.DoubleAmmoFactor = FLOAT2FIXED(sc.Float); } else if (sc.Compare ("dropammofactor")) { ParseAssign(); sc.MustGetFloat (); skill.DropAmmoFactor = FLOAT2FIXED(sc.Float); } else if (sc.Compare ("damagefactor")) { ParseAssign(); sc.MustGetFloat (); skill.DamageFactor = FLOAT2FIXED(sc.Float); } else if (sc.Compare ("fastmonsters")) { skill.FastMonsters = true; } else if (sc.Compare ("disablecheats")) { skill.DisableCheats = true; } else if (sc.Compare ("easybossbrain")) { skill.EasyBossBrain = true; } else if (sc.Compare("autousehealth")) { skill.AutoUseHealth = true; } else if (sc.Compare("respawntime")) { ParseAssign(); sc.MustGetFloat (); skill.RespawnCounter = int(sc.Float*TICRATE); } else if (sc.Compare("respawnlimit")) { ParseAssign(); sc.MustGetNumber (); skill.RespawnLimit = sc.Number; } else if (sc.Compare("Aggressiveness")) { ParseAssign(); sc.MustGetFloat (); skill.Aggressiveness = FRACUNIT - FLOAT2FIXED(clamp(sc.Float, 0.,1.)); } else if (sc.Compare("SpawnFilter")) { ParseAssign(); if (sc.CheckNumber()) { if (sc.Number > 0) skill.SpawnFilter |= (1<<(sc.Number-1)); } else { sc.MustGetString (); if (sc.Compare("baby")) skill.SpawnFilter |= 1; else if (sc.Compare("easy")) skill.SpawnFilter |= 2; else if (sc.Compare("normal")) skill.SpawnFilter |= 4; else if (sc.Compare("hard")) skill.SpawnFilter |= 8; else if (sc.Compare("nightmare")) skill.SpawnFilter |= 16; } } else if (sc.Compare("ACSReturn")) { ParseAssign(); sc.MustGetNumber (); skill.ACSReturn = sc.Number; } else if (sc.Compare("Name")) { ParseAssign(); sc.MustGetString (); skill.MenuName = sc.String; skill.MenuNameIsLump = false; } else if (sc.Compare("PlayerClassName")) { ParseAssign(); sc.MustGetString (); FName pc = sc.String; ParseComma(); sc.MustGetString (); skill.MenuNamesForPlayerClass[pc]=sc.String; } else if (sc.Compare("PicName")) { ParseAssign(); sc.MustGetString (); skill.MenuName = sc.String; skill.MenuNameIsLump = true; } else if (sc.Compare("MustConfirm")) { skill.MustConfirm = true; if (format_type == FMT_New) { if (CheckAssign()) { sc.MustGetString(); skill.MustConfirmText = sc.String; } } else { if (sc.CheckToken(TK_StringConst)) { skill.MustConfirmText = sc.String; } } } else if (sc.Compare("Key")) { ParseAssign(); sc.MustGetString(); skill.Shortcut = tolower(sc.String[0]); } else if (sc.Compare("TextColor")) { ParseAssign(); sc.MustGetString(); skill.TextColor.Format("[%s]", sc.String); } else if (!ParseCloseBrace()) { // Unknown sc.ScriptMessage("Unknown property '%s' found in skill definition\n", sc.String); SkipToNext(); } else { break; } } CheckEndOfFile("skill"); for(unsigned int i = 0; i < AllSkills.Size(); i++) { if (AllSkills[i].Name == skill.Name) { AllSkills[i] = skill; return; } } AllSkills.Push(skill); }
static bool ParsePropertyParams(FScanner &sc, FPropertyInfo *prop, AActor *defaults, Baggage &bag) { static TArray<FPropParam> params; static TArray<FString> strings; params.Clear(); strings.Clear(); params.Reserve(1); params[0].i = 0; if (prop->params[0] != '0') { const char * p = prop->params; bool nocomma; bool optcomma; while (*p) { FPropParam conv; FPropParam pref; nocomma = false; conv.s = NULL; pref.s = NULL; pref.i = -1; bag.ScriptPosition = sc; switch ((*p) & 223) { case 'X': // Expression in parentheses or number. { FxExpression *x = NULL; if (sc.CheckString ("(")) { x = new FxDamageValue(new FxIntCast(ParseExpression(sc, bag.Info)), true); sc.MustGetStringName(")"); } else { sc.MustGetNumber(); if (sc.Number != 0) { x = new FxDamageValue(new FxConstant(sc.Number, bag.ScriptPosition), false); } } conv.exp = x; params.Push(conv); } break; case 'I': sc.MustGetNumber(); conv.i = sc.Number; break; case 'F': sc.MustGetFloat(); conv.d = sc.Float; break; case 'Z': // an optional string. Does not allow any numerical value. if (sc.CheckFloat()) { nocomma = true; sc.UnGet(); break; } // fall through case 'S': sc.MustGetString(); conv.s = strings[strings.Reserve(1)] = sc.String; break; case 'T': sc.MustGetString(); conv.s = strings[strings.Reserve(1)] = strbin1(sc.String); break; case 'C': if (sc.CheckNumber ()) { int R, G, B; R = clamp (sc.Number, 0, 255); sc.CheckString (","); sc.MustGetNumber (); G = clamp (sc.Number, 0, 255); sc.CheckString (","); sc.MustGetNumber (); B = clamp (sc.Number, 0, 255); conv.i = MAKERGB(R, G, B); pref.i = 0; } else { sc.MustGetString (); conv.s = strings[strings.Reserve(1)] = sc.String; pref.i = 1; } break; case 'M': // special case. An expression-aware parser will not need this. conv.i = ParseMorphStyle(sc); break; case 'N': // special case. An expression-aware parser will not need this. conv.i = ParseThingActivation(sc); break; case 'L': // Either a number or a list of strings if (sc.CheckNumber()) { pref.i = 0; conv.i = sc.Number; } else { pref.i = 1; params.Push(pref); params[0].i++; do { sc.MustGetString (); conv.s = strings[strings.Reserve(1)] = sc.String; params.Push(conv); params[0].i++; } while (sc.CheckString(",")); goto endofparm; } break; default: assert(false); break; } if (pref.i != -1) { params.Push(pref); params[0].i++; } params.Push(conv); params[0].i++; endofparm: p++; // Hack for some properties that have to allow comma less // parameter lists for compatibility. if ((optcomma = (*p == '_'))) p++; if (nocomma) { continue; } else if (*p == 0) { break; } else if (*p >= 'a') { if (!sc.CheckString(",")) { if (optcomma) { if (!sc.CheckFloat()) break; else sc.UnGet(); } else break; } } else { if (!optcomma) sc.MustGetStringName(","); else sc.CheckString(","); } } } // call the handler try { prop->Handler(defaults, bag.Info, bag, ¶ms[0]); } catch (CRecoverableError &error) { sc.ScriptError("%s", error.GetMessage()); } return true; }
void gl_InitPortals() { FPortalMap collection; if (level.nodes.Size() == 0) return; CollectPortalSectors(collection); glSectorPortals.Clear(); FPortalMap::Iterator it(collection); FPortalMap::Pair *pair; int c = 0; int planeflags = 0; while (it.NextPair(pair)) { for(unsigned i=0;i<pair->Value.Size(); i++) { if (pair->Value[i].mPlane == sector_t::floor) planeflags |= 1; else if (pair->Value[i].mPlane == sector_t::ceiling) planeflags |= 2; } for (int i=1;i<=2;i<<=1) { // add separate glSectorPortals for floor and ceiling. if (planeflags & i) { FPortal *portal = new FPortal; portal->mDisplacement = pair->Key.mDisplacement; portal->plane = (i==1? sector_t::floor : sector_t::ceiling); /**/ portal->glportal = NULL; glSectorPortals.Push(portal); for(unsigned j=0;j<pair->Value.Size(); j++) { sector_t *sec = pair->Value[j].mSub; int plane = pair->Value[j].mPlane; if (portal->plane == plane) { for(int k=0;k<sec->subsectorcount; k++) { subsector_t *sub = sec->subsectors[k]; gl_BuildPortalCoverage(&sub->portalcoverage[plane], sub, pair->Key.mDisplacement); } sec->portals[plane] = portal; } } } } } // Now group the line glSectorPortals (each group must be a continuous set of colinear linedefs with no gaps) glLinePortals.Clear(); linePortalToGL.Clear(); TArray<int> tempindex; tempindex.Reserve(linePortals.Size()); memset(&tempindex[0], -1, linePortals.Size() * sizeof(int)); for (unsigned i = 0; i < linePortals.Size(); i++) { auto port = linePortals[i]; bool gotsome; if (tempindex[i] == -1) { tempindex[i] = glLinePortals.Size(); line_t *pSrcLine = linePortals[i].mOrigin; line_t *pLine = linePortals[i].mDestination; FGLLinePortal &glport = glLinePortals[glLinePortals.Reserve(1)]; glport.lines.Push(&linePortals[i]); // We cannot do this grouping for non-linked glSectorPortals because they can be changed at run time. if (linePortals[i].mType == PORTT_LINKED && pLine != nullptr) { glport.v1 = pLine->v1; glport.v2 = pLine->v2; do { // now collect all other colinear lines connected to this one. We run this loop as long as it still finds a match gotsome = false; for (unsigned j = 0; j < linePortals.Size(); j++) { if (tempindex[j] == -1) { line_t *pSrcLine2 = linePortals[j].mOrigin; line_t *pLine2 = linePortals[j].mDestination; // angular precision is intentionally reduced to 32 bit BAM to account for precision problems (otherwise many not perfectly horizontal or vertical glSectorPortals aren't found here.) unsigned srcang = pSrcLine->Delta().Angle().BAMs(); unsigned dstang = pLine->Delta().Angle().BAMs(); if ((pSrcLine->v2 == pSrcLine2->v1 && pLine->v1 == pLine2->v2) || (pSrcLine->v1 == pSrcLine2->v2 && pLine->v2 == pLine2->v1)) { // The line connects, now check the translation unsigned srcang2 = pSrcLine2->Delta().Angle().BAMs(); unsigned dstang2 = pLine2->Delta().Angle().BAMs(); if (srcang == srcang2 && dstang == dstang2) { // The lines connect and both source and destination are colinear, so this is a match gotsome = true; tempindex[j] = tempindex[i]; if (pLine->v1 == pLine2->v2) glport.v1 = pLine2->v1; else glport.v2 = pLine2->v2; glport.lines.Push(&linePortals[j]); } } } } } while (gotsome); } } } linePortalToGL.Resize(linePortals.Size()); for (unsigned i = 0; i < linePortals.Size(); i++) { linePortalToGL[i] = &glLinePortals[tempindex[i]]; /* Printf("portal at line %d translates to GL portal %d, range = %f,%f to %f,%f\n", int(linePortals[i].mOrigin - lines), tempindex[i], linePortalToGL[i]->v1->fixX() / 65536., linePortalToGL[i]->v1->fixY() / 65536., linePortalToGL[i]->v2->fixX() / 65536., linePortalToGL[i]->v2->fixY() / 65536.); */ } }
void MapLoader::PO_Init (void) { int NumPolyobjs = 0; TArray<FMapThing *> polythings; for (auto &mthing : MapThingsConverted) { if (mthing.EdNum == 0 || mthing.EdNum == -1 || mthing.info == nullptr) continue; FDoomEdEntry *mentry = mthing.info; switch (mentry->Special) { case SMT_PolyAnchor: case SMT_PolySpawn: case SMT_PolySpawnCrush: case SMT_PolySpawnHurt: polythings.Push(&mthing); if (mentry->Special != SMT_PolyAnchor) NumPolyobjs++; } } int polyIndex; // [RH] Make this faster InitSideLists (); Level->Polyobjects.Resize(NumPolyobjs); for (auto &po : Level->Polyobjects) po.Level = Level; // must be done before the init loop below. polyIndex = 0; // index polyobj number // Find the startSpot points, and spawn each polyobj for (int i=polythings.Size()-1; i >= 0; i--) { // 9301 (3001) = no crush, 9302 (3002) = crushing, 9303 = hurting touch int type = polythings[i]->info->Special; if (type >= SMT_PolySpawn && type <= SMT_PolySpawnHurt) { // Polyobj StartSpot Pt. Level->Polyobjects[polyIndex].StartSpot.pos = polythings[i]->pos; SpawnPolyobj(polyIndex, polythings[i]->angle, type); polyIndex++; } } for (int i = polythings.Size() - 1; i >= 0; i--) { int type = polythings[i]->info->Special; if (type == SMT_PolyAnchor) { // Polyobj Anchor Pt. TranslateToStartSpot (polythings[i]->angle, polythings[i]->pos); } } // check for a startspot without an anchor point for (auto &poly : Level->Polyobjects) { if (poly.OriginalPts.Size() == 0) { Printf (TEXTCOLOR_RED "PO_Init: StartSpot located without an Anchor point: %d\n", poly.tag); } } InitPolyBlockMap(); // [RH] Don't need the side lists anymore KnownPolySides.Reset(); // mark all subsectors which have a seg belonging to a polyobj // These ones should not be rendered on the textured automap. for (auto &ss : Level->subsectors) { for(uint32_t j=0;j<ss.numlines; j++) { if (ss.firstline[j].sidedef != NULL && ss.firstline[j].sidedef->Flags & WALLF_POLYOBJ) { ss.flags |= SSECF_POLYORG; break; } } } // clear all polyobj specials so that they do not obstruct using other lines. for (auto &line : Level->lines) { if (line.special == Polyobj_ExplicitLine || line.special == Polyobj_StartLine) { line.special = 0; } } }
void USoundCue::PostLoad() { Super::PostLoad(); // Game doesn't care if there are NULL graph nodes #if WITH_EDITOR if (GIsEditor ) { if (SoundCueGraph) { // Deal with SoundNode types being removed - iterate in reverse as nodes may be removed for (int32 idx = SoundCueGraph->Nodes.Num() - 1; idx >= 0; --idx) { USoundCueGraphNode* Node = Cast<USoundCueGraphNode>(SoundCueGraph->Nodes[idx]); if (Node && Node->SoundNode == NULL) { FBlueprintEditorUtils::RemoveNode(NULL, Node, true); } } } else { // we should have a soundcuegraph unless we are contained in a package which is missing editor only data check( GetOutermost()->HasAnyPackageFlags(PKG_FilterEditorOnly) ); } // Always load all sound waves in the editor for (USoundNode* SoundNode : AllNodes) { if (USoundNodeAssetReferencer* AssetReferencerNode = Cast<USoundNodeAssetReferencer>(SoundNode)) { AssetReferencerNode->LoadAsset(); } } } else #endif { TArray<USoundNode*> NodesToEvaluate; NodesToEvaluate.Push(FirstNode); while (NodesToEvaluate.Num() > 0) { if (USoundNode* SoundNode = NodesToEvaluate.Pop(false)) { if (USoundNodeAssetReferencer* AssetReferencerNode = Cast<USoundNodeAssetReferencer>(SoundNode)) { AssetReferencerNode->LoadAsset(); } else if (USoundNodeQualityLevel* QualityLevelNode = Cast<USoundNodeQualityLevel>(SoundNode)) { // Only pick the node connected for current quality, currently don't support changing audio quality on the fly static const int32 CachedQualityLevel = GEngine->GetGameUserSettings()->GetAudioQualityLevel(); if (CachedQualityLevel < QualityLevelNode->ChildNodes.Num()) { NodesToEvaluate.Add(QualityLevelNode->ChildNodes[CachedQualityLevel]); } } else { NodesToEvaluate.Append(SoundNode->ChildNodes); } } } } }
static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls) { FScriptPosition scpos(sc); if (sc.CheckToken('(')) { FxExpression *data = ParseExpressionM (sc, cls); sc.MustGetToken(')'); return data; } else if (sc.CheckToken(TK_True)) { return new FxConstant(1, scpos); } else if (sc.CheckToken(TK_False)) { return new FxConstant(0, scpos); } else if (sc.CheckToken(TK_IntConst)) { return new FxConstant(sc.Number, scpos); } else if (sc.CheckToken(TK_FloatConst)) { return new FxConstant(sc.Float, scpos); } else if (sc.CheckToken(TK_NameConst)) { return new FxConstant(sc.Name, scpos); } else if (sc.CheckToken(TK_StringConst)) { // String parameters are converted to names. Technically, this should be // done at a higher level, as needed, but since no functions take string // arguments and ACS_NamedExecuteWithResult/CallACS need names, this is // a cheap way to get them working when people use "name" instead of 'name'. return new FxConstant(FName(sc.String), scpos); } else if (sc.CheckToken(TK_Random)) { FRandom *rng; if (sc.CheckToken('[')) { sc.MustGetToken(TK_Identifier); rng = FRandom::StaticFindRNG(sc.String); sc.MustGetToken(']'); } else { rng = &pr_exrandom; } sc.MustGetToken('('); FxExpression *min = ParseExpressionM (sc, cls); sc.MustGetToken(','); FxExpression *max = ParseExpressionM (sc, cls); sc.MustGetToken(')'); return new FxRandom(rng, min, max, sc); } else if (sc.CheckToken(TK_RandomPick) || sc.CheckToken(TK_FRandomPick)) { bool floaty = sc.TokenType == TK_FRandomPick; FRandom *rng; TArray<FxExpression*> list; list.Clear(); int index = 0; if (sc.CheckToken('[')) { sc.MustGetToken(TK_Identifier); rng = FRandom::StaticFindRNG(sc.String); sc.MustGetToken(']'); } else { rng = &pr_exrandom; } sc.MustGetToken('('); for (;;) { FxExpression *expr = ParseExpressionM(sc, cls); list.Push(expr); if (sc.CheckToken(')')) break; sc.MustGetToken(','); } return new FxRandomPick(rng, list, floaty, sc); } else if (sc.CheckToken(TK_FRandom)) { FRandom *rng; if (sc.CheckToken('[')) { sc.MustGetToken(TK_Identifier); rng = FRandom::StaticFindRNG(sc.String); sc.MustGetToken(']'); } else { rng = &pr_exrandom; } sc.MustGetToken('('); FxExpression *min = ParseExpressionM (sc, cls); sc.MustGetToken(','); FxExpression *max = ParseExpressionM (sc, cls); sc.MustGetToken(')'); return new FxFRandom(rng, min, max, sc); } else if (sc.CheckToken(TK_Random2)) { FRandom *rng; if (sc.CheckToken('[')) { sc.MustGetToken(TK_Identifier); rng = FRandom::StaticFindRNG(sc.String); sc.MustGetToken(']'); } else { rng = &pr_exrandom; } sc.MustGetToken('('); FxExpression *mask = NULL; if (!sc.CheckToken(')')) { mask = ParseExpressionM(sc, cls); sc.MustGetToken(')'); } return new FxRandom2(rng, mask, sc); } else if (sc.CheckToken(TK_Abs)) { sc.MustGetToken('('); FxExpression *x = ParseExpressionM (sc, cls); sc.MustGetToken(')'); return new FxAbs(x); } else if (sc.CheckToken(TK_Identifier)) { FName identifier = FName(sc.String); if (sc.CheckToken('(')) { FArgumentList *args = new FArgumentList; PFunction *func = dyn_cast<PFunction>(cls->Symbols.FindSymbol(identifier, true)); try { if (func != NULL) { sc.UnGet(); ParseFunctionParameters(sc, cls, *args, func, "", NULL); return new FxVMFunctionCall(func, args, sc); } else if (!sc.CheckToken(')')) { do { args->Push(ParseExpressionM (sc, cls)); } while (sc.CheckToken(',')); sc.MustGetToken(')'); } return new FxFunctionCall(NULL, identifier, args, sc); } catch (...) { delete args; throw; } } else { return new FxIdentifier(identifier, sc); } } else { FString tokname = sc.TokenName(sc.TokenType, sc.String); sc.ScriptError ("Unexpected token %s", tokname.GetChars()); } return NULL; }
void FTextureManager::ParseAnimatedDoor(FScanner &sc) { const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny; FDoorAnimation anim; TArray<FTextureID> frames; bool error = false; FTextureID v; sc.MustGetString(); anim.BaseTexture = CheckForTexture (sc.String, FTexture::TEX_Wall, texflags); if (!anim.BaseTexture.Exists()) { error = true; } else { Texture(anim.BaseTexture)->bNoDecals = true; } while (sc.GetString()) { if (sc.Compare ("opensound")) { sc.MustGetString (); anim.OpenSound = sc.String; } else if (sc.Compare ("closesound")) { sc.MustGetString (); anim.CloseSound = sc.String; } else if (sc.Compare ("pic")) { sc.MustGetString (); if (IsNum (sc.String)) { v = anim.BaseTexture + (atoi(sc.String) - 1); } else { v = CheckForTexture (sc.String, FTexture::TEX_Wall, texflags); if (!v.Exists() && anim.BaseTexture.Exists() && !error) { sc.ScriptError ("Unknown texture %s", sc.String); } } frames.Push(v); } else if (sc.Compare("allowdecals")) { if (anim.BaseTexture.Exists()) Texture(anim.BaseTexture)->bNoDecals = false; } else { sc.UnGet (); break; } } if (!error) { anim.TextureFrames = new FTextureID[frames.Size()]; memcpy (anim.TextureFrames, &frames[0], sizeof(FTextureID) * frames.Size()); anim.NumTextureFrames = frames.Size(); mAnimatedDoors.Push (anim); } }
FExpressionResult Evaluate(const TArray<FCompiledToken>& CompiledTokens, const IOperatorEvaluationEnvironment& InEnvironment) { // Evaluation strategy: the supplied compiled tokens are const. To avoid copying the whole array, we store a separate array of // any tokens that are generated at runtime by the evaluator. The operand stack will consist of indices into either the CompiledTokens // array, or the RuntimeGeneratedTokens (where Index >= CompiledTokens.Num()) TArray<FExpressionToken> RuntimeGeneratedTokens; TArray<int32> OperandStack; /** Get the token pertaining to the specified operand index */ auto GetToken = [&](int32 Index) -> const FExpressionToken& { if (Index < CompiledTokens.Num()) { return CompiledTokens[Index]; } return RuntimeGeneratedTokens[Index - CompiledTokens.Num()]; }; /** Add a new token to the runtime generated array */ auto AddToken = [&](FExpressionToken&& In) -> int32 { auto Index = CompiledTokens.Num() + RuntimeGeneratedTokens.Num(); RuntimeGeneratedTokens.Emplace(MoveTemp(In)); return Index; }; for (int32 Index = 0; Index < CompiledTokens.Num(); ++Index) { const auto& Token = CompiledTokens[Index]; switch(Token.Type) { case FCompiledToken::Benign: continue; case FCompiledToken::Operand: OperandStack.Push(Index); continue; case FCompiledToken::BinaryOperator: if (OperandStack.Num() >= 2) { // Binary const auto& R = GetToken(OperandStack.Pop()); const auto& L = GetToken(OperandStack.Pop()); auto OpResult = InEnvironment.ExecBinary(Token, L, R); if (OpResult.IsValid()) { // Inherit the LHS context OperandStack.Push(AddToken(FExpressionToken(L.Context, MoveTemp(OpResult.GetValue())))); } else { return MakeError(OpResult.GetError()); } } else { FFormatOrderedArguments Args; Args.Add(FText::FromString(Token.Context.GetString())); return MakeError(FText::Format(LOCTEXT("SyntaxError_NotEnoughOperandsBinary", "Not enough operands for binary operator {0}"), Args)); } break; case FCompiledToken::PostUnaryOperator: case FCompiledToken::PreUnaryOperator: if (OperandStack.Num() >= 1) { const auto& Operand = GetToken(OperandStack.Pop()); FExpressionResult OpResult = (Token.Type == FCompiledToken::PreUnaryOperator) ? InEnvironment.ExecPreUnary(Token, Operand) : InEnvironment.ExecPostUnary(Token, Operand); if (OpResult.IsValid()) { // Inherit the LHS context OperandStack.Push(AddToken(FExpressionToken(Operand.Context, MoveTemp(OpResult.GetValue())))); } else { return MakeError(OpResult.GetError()); } } else { FFormatOrderedArguments Args; Args.Add(FText::FromString(Token.Context.GetString())); return MakeError(FText::Format(LOCTEXT("SyntaxError_NoUnaryOperand", "No operand for unary operator {0}"), Args)); } break; } } if (OperandStack.Num() == 1) { return MakeValue(GetToken(OperandStack[0]).Node.Copy()); } return MakeError(LOCTEXT("SyntaxError_InvalidExpression", "Could not evaluate expression")); }
void CollectNode(void *node, TArray<FCoverageVertex> &shape) { static TArray<FCoverageLine> lists[2]; const double COVERAGE_EPSILON = 6.; // same epsilon as the node builder if (!((size_t)node & 1)) // Keep going until found a subsector { node_t *bsp = (node_t *)node; int centerside = R_PointOnSide(center.x, center.y, bsp); lists[0].Clear(); lists[1].Clear(); for(unsigned i=0;i<shape.Size(); i++) { FCoverageVertex *v1 = &shape[i]; FCoverageVertex *v2 = &shape[(i+1) % shape.Size()]; FCoverageLine vl = {{*v1, *v2}}; double dist_v1 = PartitionDistance(v1, bsp); double dist_v2 = PartitionDistance(v2, bsp); if(dist_v1 <= COVERAGE_EPSILON) { if (dist_v2 <= COVERAGE_EPSILON) { lists[centerside].Push(vl); } else { int side = PointOnSide(v2, bsp); lists[side].Push(vl); } } else if (dist_v2 <= COVERAGE_EPSILON) { int side = PointOnSide(v1, bsp); lists[side].Push(vl); } else { int side1 = PointOnSide(v1, bsp); int side2 = PointOnSide(v2, bsp); if(side1 != side2) { // if the partition line crosses this seg, we must split it. FCoverageVertex vert; if (GetIntersection(v1, v2, bsp, &vert)) { lists[0].Push(vl); lists[1].Push(vl); lists[side1].Last().v[1] = vert; lists[side2].Last().v[0] = vert; } else { // should never happen lists[side1].Push(vl); } } else { // both points on the same side. lists[side1].Push(vl); } } } if (lists[1].Size() == 0) { CollectNode(bsp->children[0], shape); } else if (lists[0].Size() == 0) { CollectNode(bsp->children[1], shape); } else { // copy the static arrays into local ones TArray<FCoverageVertex> locallists[2]; for(int l=0;l<2;l++) { for (unsigned i=0;i<lists[l].Size(); i++) { locallists[l].Push(lists[l][i].v[0]); unsigned i1= (i+1)%lists[l].Size(); if (lists[l][i1].v[0] != lists[l][i].v[1]) { locallists[l].Push(lists[l][i].v[1]); } } } CollectNode(bsp->children[0], locallists[0]); CollectNode(bsp->children[1], locallists[1]); } } else { // we reached a subsector so we can link the node with this subsector subsector_t *sub = (subsector_t *)((BYTE *)node - 1); collect.Push(int(sub-subsectors)); } }
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 ProcessLineDefs() { int sidecount = 0; for(unsigned i = 0, skipped = 0; i < ParsedLines.Size();) { // Relocate the vertices intptr_t v1i = intptr_t(ParsedLines[i].v1); intptr_t v2i = intptr_t(ParsedLines[i].v2); if (v1i >= numvertexes || v2i >= numvertexes || v1i < 0 || v2i < 0) { I_Error ("Line %d has invalid vertices: %zd and/or %zd.\nThe map only contains %d vertices.", i+skipped, v1i, v2i, numvertexes); } else if (v1i == v2i || (vertexes[v1i].x == vertexes[v2i].x && vertexes[v1i].y == vertexes[v2i].y)) { Printf ("Removing 0-length line %d\n", i+skipped); ParsedLines.Delete(i); ForceNodeBuild = true; skipped++; } else { ParsedLines[i].v1 = &vertexes[v1i]; ParsedLines[i].v2 = &vertexes[v2i]; if (ParsedLines[i].sidedef[0] != NULL) sidecount++; if (ParsedLines[i].sidedef[1] != NULL) sidecount++; linemap.Push(i+skipped); i++; } } numlines = ParsedLines.Size(); numsides = sidecount; lines = new line_t[numlines]; sides = new side_t[numsides]; int line, side; for(line = 0, side = 0; line < numlines; line++) { short tempalpha[2] = { SHRT_MIN, SHRT_MIN }; lines[line] = ParsedLines[line]; for(int sd = 0; sd < 2; sd++) { if (lines[line].sidedef[sd] != NULL) { int mapside = int(intptr_t(lines[line].sidedef[sd]))-1; if (mapside < sidecount) { sides[side] = ParsedSides[mapside]; sides[side].linedef = &lines[line]; sides[side].sector = §ors[intptr_t(sides[side].sector)]; lines[line].sidedef[sd] = &sides[side]; P_ProcessSideTextures(!isExtended, &sides[side], sides[side].sector, &ParsedSideTextures[mapside], lines[line].special, lines[line].args[0], &tempalpha[sd], missingTex); side++; } else { lines[line].sidedef[sd] = NULL; } } } P_AdjustLine(&lines[line]); P_FinishLoadingLineDef(&lines[line], tempalpha[0]); } assert(side <= numsides); if (side < numsides) { Printf("Map had %d invalid side references\n", numsides - side); numsides = side; } }
void InitThingdef() { // Sort the flag lists for (size_t i = 0; i < NUM_FLAG_LISTS; ++i) { qsort (FlagLists[i].Defs, FlagLists[i].NumDefs, sizeof(FFlagDef), flagcmp); } // Create a sorted list of properties if (properties.Size() == 0) { FAutoSegIterator probe(GRegHead, GRegTail); while (*++probe != NULL) { properties.Push((FPropertyInfo *)*probe); } properties.ShrinkToFit(); qsort(&properties[0], properties.Size(), sizeof(properties[0]), propcmp); } // Create a sorted list of native action functions AFTable.Clear(); if (AFTable.Size() == 0) { FAutoSegIterator probe(ARegHead, ARegTail); while (*++probe != NULL) { AFuncDesc *afunc = (AFuncDesc *)*probe; assert(afunc->VMPointer != NULL); *(afunc->VMPointer) = new VMNativeFunction(afunc->Function, afunc->Name); AFTable.Push(*afunc); } AFTable.ShrinkToFit(); qsort(&AFTable[0], AFTable.Size(), sizeof(AFTable[0]), funccmp); } // Define some member variables we feel like exposing to the user PSymbolTable &symt = RUNTIME_CLASS(AActor)->Symbols; PType *array5 = NewArray(TypeSInt32, 5); symt.AddSymbol(new PField(NAME_Alpha, TypeFloat64, VARF_Native, myoffsetof(AActor,Alpha))); symt.AddSymbol(new PField(NAME_Angle, TypeFloat64, VARF_Native, myoffsetof(AActor,Angles.Yaw))); symt.AddSymbol(new PField(NAME_Args, array5, VARF_Native, myoffsetof(AActor,args))); symt.AddSymbol(new PField(NAME_CeilingZ, TypeFloat64, VARF_Native, myoffsetof(AActor,ceilingz))); symt.AddSymbol(new PField(NAME_FloorZ, TypeFloat64, VARF_Native, myoffsetof(AActor,floorz))); symt.AddSymbol(new PField(NAME_Health, TypeSInt32, VARF_Native, myoffsetof(AActor,health))); symt.AddSymbol(new PField(NAME_Mass, TypeSInt32, VARF_Native, myoffsetof(AActor,Mass))); symt.AddSymbol(new PField(NAME_Pitch, TypeFloat64, VARF_Native, myoffsetof(AActor,Angles.Pitch))); symt.AddSymbol(new PField(NAME_Roll, TypeFloat64, VARF_Native, myoffsetof(AActor,Angles.Roll))); symt.AddSymbol(new PField(NAME_Special, TypeSInt32, VARF_Native, myoffsetof(AActor,special))); symt.AddSymbol(new PField(NAME_TID, TypeSInt32, VARF_Native, myoffsetof(AActor,tid))); symt.AddSymbol(new PField(NAME_TIDtoHate, TypeSInt32, VARF_Native, myoffsetof(AActor,TIDtoHate))); symt.AddSymbol(new PField(NAME_WaterLevel, TypeSInt32, VARF_Native, myoffsetof(AActor,waterlevel))); symt.AddSymbol(new PField(NAME_X, TypeFloat64, VARF_Native, myoffsetof(AActor,__Pos.X))); // must remain read-only! symt.AddSymbol(new PField(NAME_Y, TypeFloat64, VARF_Native, myoffsetof(AActor,__Pos.Y))); // must remain read-only! symt.AddSymbol(new PField(NAME_Z, TypeFloat64, VARF_Native, myoffsetof(AActor,__Pos.Z))); // must remain read-only! symt.AddSymbol(new PField(NAME_VelX, TypeFloat64, VARF_Native, myoffsetof(AActor,Vel.X))); symt.AddSymbol(new PField(NAME_VelY, TypeFloat64, VARF_Native, myoffsetof(AActor, Vel.Y))); symt.AddSymbol(new PField(NAME_VelZ, TypeFloat64, VARF_Native, myoffsetof(AActor, Vel.Z))); symt.AddSymbol(new PField(NAME_MomX, TypeFloat64, VARF_Native, myoffsetof(AActor, Vel.X))); symt.AddSymbol(new PField(NAME_MomY, TypeFloat64, VARF_Native, myoffsetof(AActor, Vel.Y))); symt.AddSymbol(new PField(NAME_MomZ, TypeFloat64, VARF_Native, myoffsetof(AActor, Vel.Z))); symt.AddSymbol(new PField(NAME_ScaleX, TypeFloat64, VARF_Native, myoffsetof(AActor, Scale.X))); symt.AddSymbol(new PField(NAME_ScaleY, TypeFloat64, VARF_Native, myoffsetof(AActor, Scale.Y))); symt.AddSymbol(new PField(NAME_Score, TypeSInt32, VARF_Native, myoffsetof(AActor,Score))); symt.AddSymbol(new PField(NAME_Accuracy, TypeSInt32, VARF_Native, myoffsetof(AActor,accuracy))); symt.AddSymbol(new PField(NAME_Stamina, TypeSInt32, VARF_Native, myoffsetof(AActor,stamina))); symt.AddSymbol(new PField(NAME_Height, TypeFloat64, VARF_Native, myoffsetof(AActor,Height))); symt.AddSymbol(new PField(NAME_Radius, TypeFloat64, VARF_Native, myoffsetof(AActor,radius))); symt.AddSymbol(new PField(NAME_ReactionTime,TypeSInt32, VARF_Native, myoffsetof(AActor,reactiontime))); symt.AddSymbol(new PField(NAME_MeleeRange, TypeFloat64, VARF_Native, myoffsetof(AActor,meleerange))); symt.AddSymbol(new PField(NAME_Speed, TypeFloat64, VARF_Native, myoffsetof(AActor,Speed))); symt.AddSymbol(new PField(NAME_Threshold, TypeSInt32, VARF_Native, myoffsetof(AActor,threshold))); symt.AddSymbol(new PField(NAME_DefThreshold,TypeSInt32, VARF_Native, myoffsetof(AActor,DefThreshold))); }
void ParseCompatibility() { TArray<FMD5Holder> md5array; FMD5Holder md5; FCompatValues flags; int i, x; unsigned int j; BCompatMap.Clear(); CompatParams.Clear(); // The contents of this file are not cumulative, as it should not // be present in user-distributed maps. FScanner sc(Wads.GetNumForFullName("compatibility.txt")); while (sc.GetString()) // Get MD5 signature { do { if (strlen(sc.String) != 32) { sc.ScriptError("MD5 signature must be exactly 32 characters long"); } for (i = 0; i < 32; ++i) { if (sc.String[i] >= '0' && sc.String[i] <= '9') { x = sc.String[i] - '0'; } else { sc.String[i] |= 'a' ^ 'A'; if (sc.String[i] >= 'a' && sc.String[i] <= 'f') { x = sc.String[i] - 'a' + 10; } else { x = 0; sc.ScriptError("MD5 signature must be a hexadecimal value"); } } if (!(i & 1)) { md5.Bytes[i / 2] = x << 4; } else { md5.Bytes[i / 2] |= x; } } md5array.Push(md5); sc.MustGetString(); } while (!sc.Compare("{")); memset(flags.CompatFlags, 0, sizeof(flags.CompatFlags)); flags.ExtCommandIndex = ~0u; while (sc.GetString()) { if ((i = sc.MatchString(&Options[0].Name, sizeof(*Options))) >= 0) { flags.CompatFlags[Options[i].WhichSlot] |= Options[i].CompatFlags; } else if (sc.Compare("clearlineflags")) { if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size(); CompatParams.Push(CP_CLEARFLAGS); sc.MustGetNumber(); CompatParams.Push(sc.Number); sc.MustGetNumber(); CompatParams.Push(sc.Number); } else if (sc.Compare("setlineflags")) { if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size(); CompatParams.Push(CP_SETFLAGS); sc.MustGetNumber(); CompatParams.Push(sc.Number); sc.MustGetNumber(); CompatParams.Push(sc.Number); } else if (sc.Compare("setlinespecial")) { if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size(); CompatParams.Push(CP_SETSPECIAL); sc.MustGetNumber(); CompatParams.Push(sc.Number); sc.MustGetString(); CompatParams.Push(P_FindLineSpecial(sc.String, NULL, NULL)); for (int i = 0; i < 5; i++) { sc.MustGetNumber(); CompatParams.Push(sc.Number); } } else if (sc.Compare("clearlinespecial")) { if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size(); CompatParams.Push(CP_CLEARSPECIAL); sc.MustGetNumber(); CompatParams.Push(sc.Number); } else if (sc.Compare("setactivation")) { if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size(); CompatParams.Push(CP_SETACTIVATION); sc.MustGetNumber(); CompatParams.Push(sc.Number); sc.MustGetNumber(); CompatParams.Push(sc.Number); } else if (sc.Compare("setsectoroffset")) { if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size(); CompatParams.Push(CP_SETSECTOROFFSET); sc.MustGetNumber(); CompatParams.Push(sc.Number); sc.MustGetString(); CompatParams.Push(sc.MustMatchString(SectorPlanes)); sc.MustGetFloat(); CompatParams.Push(int(sc.Float*65536.)); } else if (sc.Compare("setsectorspecial")) { if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size(); CompatParams.Push(CP_SETSECTORSPECIAL); sc.MustGetNumber(); CompatParams.Push(sc.Number); sc.MustGetNumber(); CompatParams.Push(sc.Number); } else if (sc.Compare("setwallyscale")) { if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size(); CompatParams.Push(CP_SETWALLYSCALE); sc.MustGetNumber(); CompatParams.Push(sc.Number); sc.MustGetString(); CompatParams.Push(sc.MustMatchString(LineSides)); sc.MustGetString(); CompatParams.Push(sc.MustMatchString(WallTiers)); sc.MustGetFloat(); CompatParams.Push(int(sc.Float*65536.)); } else if (sc.Compare("setwalltexture")) { if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size(); CompatParams.Push(CP_SETWALLTEXTURE); sc.MustGetNumber(); CompatParams.Push(sc.Number); sc.MustGetString(); CompatParams.Push(sc.MustMatchString(LineSides)); sc.MustGetString(); CompatParams.Push(sc.MustMatchString(WallTiers)); sc.MustGetString(); const FString texName = sc.String; const unsigned int texIndex = TexNames.Find(texName); const unsigned int texCount = TexNames.Size(); if (texIndex == texCount) { TexNames.Push(texName); } CompatParams.Push(texIndex); } else if (sc.Compare("setthingz")) { if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size(); CompatParams.Push(CP_SETTHINGZ); sc.MustGetNumber(); CompatParams.Push(sc.Number); sc.MustGetFloat(); CompatParams.Push(int(sc.Float*256)); // do not use full fixed here so that it can eventually handle larger levels } else if (sc.Compare("setsectortag")) { if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size(); CompatParams.Push(CP_SETTAG); sc.MustGetNumber(); CompatParams.Push(sc.Number); sc.MustGetNumber(); CompatParams.Push(sc.Number); } else if (sc.Compare("setthingflags")) { if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size(); CompatParams.Push(CP_SETTHINGFLAGS); sc.MustGetNumber(); CompatParams.Push(sc.Number); sc.MustGetNumber(); CompatParams.Push(sc.Number); } else if (sc.Compare("setvertex")) { if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size(); CompatParams.Push(CP_SETVERTEX); sc.MustGetNumber(); CompatParams.Push(sc.Number); sc.MustGetFloat(); CompatParams.Push(int(sc.Float * 256)); // do not use full fixed here so that it can eventually handle larger levels sc.MustGetFloat(); CompatParams.Push(int(sc.Float * 256)); // do not use full fixed here so that it can eventually handle larger levels flags.CompatFlags[SLOT_BCOMPAT] |= BCOMPATF_REBUILDNODES; } else if (sc.Compare("setthingskills")) { if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size(); CompatParams.Push(CP_SETTHINGSKILLS); sc.MustGetNumber(); CompatParams.Push(sc.Number); sc.MustGetNumber(); CompatParams.Push(sc.Number); } else if (sc.Compare("setsectortexture")) { if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size(); CompatParams.Push(CP_SETSECTORTEXTURE); sc.MustGetNumber(); CompatParams.Push(sc.Number); sc.MustGetString(); CompatParams.Push(sc.MustMatchString(SectorPlanes)); sc.MustGetString(); const FString texName = sc.String; const unsigned int texIndex = TexNames.Find(texName); const unsigned int texCount = TexNames.Size(); if (texIndex == texCount) { TexNames.Push(texName); } CompatParams.Push(texIndex); } else if (sc.Compare("setsectorlight")) { if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size(); CompatParams.Push(CP_SETSECTORLIGHT); sc.MustGetNumber(); CompatParams.Push(sc.Number); sc.MustGetNumber(); CompatParams.Push(sc.Number); } else { sc.UnGet(); break; } } if (flags.ExtCommandIndex != ~0u) { CompatParams.Push(CP_END); } sc.MustGetStringName("}"); for (j = 0; j < md5array.Size(); ++j) { BCompatMap[md5array[j]] = flags; } md5array.Clear(); } }
FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, ETextureType usetype) : Pixels (0), Spans(0), Parts(0), bRedirect(false), bTranslucentPatches(false) { TArray<TexPart> parts; TArray<TexInit> inits; bool bSilent = false; bMultiPatch = true; sc.SetCMode(true); sc.MustGetString(); const char* textureName = NULL; if (sc.Compare("optional")) { bSilent = true; sc.MustGetString(); if (sc.Compare(",")) { // this is not right. Apparently a texture named 'optional' is being defined right now... sc.UnGet(); textureName = "optional"; bSilent = false; } } Name = !textureName ? sc.String : textureName; Name.ToUpper(); sc.MustGetStringName(","); sc.MustGetNumber(); Width = sc.Number; sc.MustGetStringName(","); sc.MustGetNumber(); Height = sc.Number; UseType = usetype; bool offset2set = false; if (sc.CheckString("{")) { while (!sc.CheckString("}")) { sc.MustGetString(); if (sc.Compare("XScale")) { sc.MustGetFloat(); Scale.X = sc.Float; if (Scale.X == 0) sc.ScriptError("Texture %s is defined with null x-scale\n", Name.GetChars()); } else if (sc.Compare("YScale")) { sc.MustGetFloat(); Scale.Y = sc.Float; if (Scale.Y == 0) sc.ScriptError("Texture %s is defined with null y-scale\n", Name.GetChars()); } else if (sc.Compare("WorldPanning")) { bWorldPanning = true; } else if (sc.Compare("NullTexture")) { UseType = ETextureType::Null; } else if (sc.Compare("NoDecals")) { bNoDecals = true; } else if (sc.Compare("Patch")) { TexPart part; TexInit init; ParsePatch(sc, part, init); if (init.TexName.IsNotEmpty()) { parts.Push(part); init.UseType = ETextureType::WallPatch; init.Silent = bSilent; init.HasLine = true; init.sc = sc; inits.Push(init); } part.Texture = NULL; part.Translation = NULL; } else if (sc.Compare("Sprite")) { TexPart part; TexInit init; ParsePatch(sc, part, init); if (init.TexName.IsNotEmpty()) { parts.Push(part); init.UseType = ETextureType::Sprite; init.Silent = bSilent; init.HasLine = true; init.sc = sc; inits.Push(init); } part.Texture = NULL; part.Translation = NULL; } else if (sc.Compare("Graphic")) { TexPart part; TexInit init; ParsePatch(sc, part, init); if (init.TexName.IsNotEmpty()) { parts.Push(part); init.UseType = ETextureType::MiscPatch; init.Silent = bSilent; init.HasLine = true; init.sc = sc; inits.Push(init); } part.Texture = NULL; part.Translation = NULL; } else if (sc.Compare("Offset")) { sc.MustGetNumber(); _LeftOffset[0] = sc.Number; sc.MustGetStringName(","); sc.MustGetNumber(); _TopOffset[0] = sc.Number; if (!offset2set) { _LeftOffset[1] = _LeftOffset[0]; _TopOffset[1] = _TopOffset[0]; } } else if (sc.Compare("Offset2")) { sc.MustGetNumber(); _LeftOffset[1] = sc.Number; sc.MustGetStringName(","); sc.MustGetNumber(); _TopOffset[1] = sc.Number; offset2set = true; } else { sc.ScriptError("Unknown texture property '%s'", sc.String); } } NumParts = parts.Size(); Parts = new TexPart[NumParts]; memcpy(Parts, &parts[0], NumParts * sizeof(*Parts)); Inits = new TexInit[NumParts]; for (int i = 0; i < NumParts; i++) { Inits[i] = inits[i]; } } if (Width <= 0 || Height <= 0) { UseType = ETextureType::Null; Printf("Texture %s has invalid dimensions (%d, %d)\n", Name.GetChars(), Width, Height); Width = Height = 1; } CalcBitSize (); sc.SetCMode(false); }
FSCSDiffControl::FSCSDiffControl( const UBlueprint* InOldBlueprint , const UBlueprint* InNewBlueprint , TArray< TSharedPtr<FBlueprintDifferenceTreeEntry> >& OutTreeEntries , TArray< TSharedPtr<FBlueprintDifferenceTreeEntry> >& OutRealDifferences , FOnSCSDiffControlChanged SelectionCallback ) : DifferingProperties() , OldSCS( InOldBlueprint ) , NewSCS( InNewBlueprint ) { TArray< FSCSResolvedIdentifier > OldHierarchy = OldSCS.GetDisplayedHierarchy(); TArray< FSCSResolvedIdentifier > NewHierarchy = NewSCS.GetDisplayedHierarchy(); DiffUtils::CompareUnrelatedSCS(InOldBlueprint, OldHierarchy, InNewBlueprint, NewHierarchy, DifferingProperties); const auto FocusSCSDifferenceEntry = [](FSCSDiffEntry Entry, FOnSCSDiffControlChanged InSelectionCallback, FSCSDiffControl* Owner) { InSelectionCallback.ExecuteIfBound(); if (Entry.TreeIdentifier.Name != NAME_None) { Owner->OldSCS.HighlightProperty(Entry.TreeIdentifier.Name, FPropertyPath()); Owner->NewSCS.HighlightProperty(Entry.TreeIdentifier.Name, FPropertyPath()); } }; const auto CreateSCSDifferenceWidget = [](FSCSDiffEntry Entry, FText ObjectName) -> TSharedRef<SWidget> { return SNew(STextBlock) .Text(DiffViewUtils::SCSDiffMessage(Entry,ObjectName)) .ColorAndOpacity(DiffViewUtils::Differs()); }; TArray< TSharedPtr<FBlueprintDifferenceTreeEntry> > Children; for( auto Difference : DifferingProperties.Entries ) { auto Entry = TSharedPtr<FBlueprintDifferenceTreeEntry>( new FBlueprintDifferenceTreeEntry( FOnDiffEntryFocused::CreateStatic(FocusSCSDifferenceEntry, Difference, SelectionCallback, this) , FGenerateDiffEntryWidget::CreateStatic(CreateSCSDifferenceWidget, Difference, RightRevision) , TArray< TSharedPtr<FBlueprintDifferenceTreeEntry> >() ) ); Children.Push(Entry); OutRealDifferences.Push(Entry); } const bool bHasDiffferences = Children.Num() != 0; if (!bHasDiffferences) { // make one child informing the user that there are no differences: Children.Push(FBlueprintDifferenceTreeEntry::NoDifferencesEntry()); } const auto ForwardSelection = [](FOnSCSDiffControlChanged InSelectionCallback) { // This allows the owning control to focus the correct tab (or do whatever else it likes): InSelectionCallback.ExecuteIfBound(); }; OutTreeEntries.Push(FBlueprintDifferenceTreeEntry::CreateComponentsCategoryEntry( FOnDiffEntryFocused::CreateStatic(ForwardSelection, SelectionCallback), Children, bHasDiffferences )); }
static bool LoadScriptFile(int lumpnum, FileReader *lump, int numnodes, bool include, int type) { int i; DWORD prevSpeakerType; FStrifeDialogueNode *node; char buffer[4]; lump->Read(buffer, 4); lump->Seek(-4, SEEK_CUR); // The binary format is so primitive that this check is enough to detect it. bool isbinary = (buffer[0] == 0 || buffer[1] == 0 || buffer[2] == 0 || buffer[3] == 0); if ((type == 1 && !isbinary) || (type == 2 && isbinary)) { DPrintf("Incorrect data format for %s.", Wads.GetLumpFullName(lumpnum)); return false; } if (!isbinary) { P_ParseUSDF(lumpnum, lump, numnodes); } else { if (!include) { LoadScriptFile("SCRIPT00", true, 1); } if (!(gameinfo.flags & GI_SHAREWARE)) { // Strife scripts are always a multiple of 1516 bytes because each entry // is exactly 1516 bytes long. if (numnodes % 1516 != 0) { DPrintf("Incorrect data format for %s.", Wads.GetLumpFullName(lumpnum)); return false; } numnodes /= 1516; } else { // And the teaser version has 1488-byte entries. if (numnodes % 1488 != 0) { DPrintf("Incorrect data format for %s.", Wads.GetLumpFullName(lumpnum)); return false; } numnodes /= 1488; } prevSpeakerType = 0; for (i = 0; i < numnodes; ++i) { if (!(gameinfo.flags & GI_SHAREWARE)) { node = ReadRetailNode (lump, prevSpeakerType); } else { node = ReadTeaserNode (lump, prevSpeakerType); } node->ThisNodeNum = StrifeDialogues.Push(node); } } return true; }
void gl_InitModels() { int Lump, lastLump; FString path; int index, surface; int i; FSpriteModelFrame smf; lastLump = 0; for(unsigned i=0;i<Models.Size();i++) { delete Models[i]; } Models.Clear(); SpriteModelFrames.Clear(); DeleteModelHash(); // First, create models for each voxel for (unsigned i = 0; i < Voxels.Size(); i++) { FVoxelModel *md = new FVoxelModel(Voxels[i], false); Voxels[i]->VoxelIndex = Models.Push(md); } // now create GL model frames for the voxeldefs for (unsigned i = 0; i < VoxelDefs.Size(); i++) { FVoxelModel *md = (FVoxelModel*)Models[VoxelDefs[i]->Voxel->VoxelIndex]; memset(&smf, 0, sizeof(smf)); smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1; smf.modelIDs[0] = VoxelDefs[i]->Voxel->VoxelIndex; smf.skinIDs[0] = md->GetPaletteTexture(); smf.xscale = smf.yscale = smf.zscale = VoxelDefs[i]->Scale; smf.angleoffset = VoxelDefs[i]->AngleOffset.Degrees; if (VoxelDefs[i]->PlacedSpin != 0) { smf.yrotate = 1.f; smf.rotationSpeed = VoxelDefs[i]->PlacedSpin / 55.55f; smf.flags |= MDL_ROTATING; } VoxelDefs[i]->VoxeldefIndex = SpriteModelFrames.Push(smf); if (VoxelDefs[i]->PlacedSpin != VoxelDefs[i]->DroppedSpin) { if (VoxelDefs[i]->DroppedSpin != 0) { smf.yrotate = 1.f; smf.rotationSpeed = VoxelDefs[i]->DroppedSpin / 55.55f; smf.flags |= MDL_ROTATING; } else { smf.yrotate = 0; smf.rotationSpeed = 0; smf.flags &= ~MDL_ROTATING; } SpriteModelFrames.Push(smf); } } memset(&smf, 0, sizeof(smf)); smf.modelIDs[0] = smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1; while ((Lump = Wads.FindLump("MODELDEF", &lastLump)) != -1) { FScanner sc(Lump); while (sc.GetString()) { if (sc.Compare("model")) { path = ""; sc.MustGetString(); memset(&smf, 0, sizeof(smf)); smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1; smf.xscale=smf.yscale=smf.zscale=1.f; smf.type = PClass::FindClass(sc.String); if (!smf.type || smf.type->Defaults == nullptr) { sc.ScriptError("MODELDEF: Unknown actor type '%s'\n", sc.String); } sc.MustGetStringName("{"); while (!sc.CheckString("}")) { sc.MustGetString(); if (sc.Compare("path")) { sc.MustGetString(); FixPathSeperator(sc.String); path = sc.String; if (path[(int)path.Len()-1]!='/') path+='/'; } else if (sc.Compare("model")) { sc.MustGetNumber(); index = sc.Number; if (index < 0 || index >= MAX_MODELS_PER_FRAME) { sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars()); } sc.MustGetString(); FixPathSeperator(sc.String); smf.modelIDs[index] = FindModel(path.GetChars(), sc.String); if (smf.modelIDs[index] == -1) { Printf("%s: model not found in %s\n", sc.String, path.GetChars()); } } else if (sc.Compare("scale")) { sc.MustGetFloat(); smf.xscale = sc.Float; sc.MustGetFloat(); smf.yscale = sc.Float; sc.MustGetFloat(); smf.zscale = sc.Float; } // [BB] Added zoffset reading. // Now it must be considered deprecated. else if (sc.Compare("zoffset")) { sc.MustGetFloat(); smf.zoffset=sc.Float; } // Offset reading. else if (sc.Compare("offset")) { sc.MustGetFloat(); smf.xoffset = sc.Float; sc.MustGetFloat(); smf.yoffset = sc.Float; sc.MustGetFloat(); smf.zoffset = sc.Float; } // angleoffset, pitchoffset and rolloffset reading. else if (sc.Compare("angleoffset")) { sc.MustGetFloat(); smf.angleoffset = sc.Float; } else if (sc.Compare("pitchoffset")) { sc.MustGetFloat(); smf.pitchoffset = sc.Float; } else if (sc.Compare("rolloffset")) { sc.MustGetFloat(); smf.rolloffset = sc.Float; } // [BB] Added model flags reading. else if (sc.Compare("ignoretranslation")) { smf.flags |= MDL_IGNORETRANSLATION; } else if (sc.Compare("pitchfrommomentum")) { smf.flags |= MDL_PITCHFROMMOMENTUM; } else if (sc.Compare("inheritactorpitch")) { smf.flags |= MDL_USEACTORPITCH | MDL_BADROTATION; } else if (sc.Compare("inheritactorroll")) { smf.flags |= MDL_USEACTORROLL; } else if (sc.Compare("useactorpitch")) { smf.flags |= MDL_USEACTORPITCH; } else if (sc.Compare("useactorroll")) { smf.flags |= MDL_USEACTORROLL; } else if (sc.Compare("rotating")) { smf.flags |= MDL_ROTATING; smf.xrotate = 0.; smf.yrotate = 1.; smf.zrotate = 0.; smf.rotationCenterX = 0.; smf.rotationCenterY = 0.; smf.rotationCenterZ = 0.; smf.rotationSpeed = 1.; } else if (sc.Compare("rotation-speed")) { sc.MustGetFloat(); smf.rotationSpeed = sc.Float; } else if (sc.Compare("rotation-vector")) { sc.MustGetFloat(); smf.xrotate = sc.Float; sc.MustGetFloat(); smf.yrotate = sc.Float; sc.MustGetFloat(); smf.zrotate = sc.Float; } else if (sc.Compare("rotation-center")) { sc.MustGetFloat(); smf.rotationCenterX = sc.Float; sc.MustGetFloat(); smf.rotationCenterY = sc.Float; sc.MustGetFloat(); smf.rotationCenterZ = sc.Float; } else if (sc.Compare("interpolatedoubledframes")) { smf.flags |= MDL_INTERPOLATEDOUBLEDFRAMES; } else if (sc.Compare("nointerpolation")) { smf.flags |= MDL_NOINTERPOLATION; } else if (sc.Compare("skin")) { sc.MustGetNumber(); index=sc.Number; if (index<0 || index>=MAX_MODELS_PER_FRAME) { sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars()); } sc.MustGetString(); FixPathSeperator(sc.String); if (sc.Compare("")) { smf.skinIDs[index]=FNullTextureID(); } else { smf.skinIDs[index] = LoadSkin(path.GetChars(), sc.String); if (!smf.skinIDs[index].isValid()) { Printf("Skin '%s' not found in '%s'\n", sc.String, smf.type->TypeName.GetChars()); } } } else if (sc.Compare("surfaceskin")) { sc.MustGetNumber(); index = sc.Number; sc.MustGetNumber(); surface = sc.Number; if (index<0 || index >= MAX_MODELS_PER_FRAME) { sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars()); } if (surface<0 || surface >= MD3_MAX_SURFACES) { sc.ScriptError("Invalid MD3 Surface %d in %s", MD3_MAX_SURFACES, smf.type->TypeName.GetChars()); } sc.MustGetString(); FixPathSeperator(sc.String); if (sc.Compare("")) { smf.surfaceskinIDs[index][surface] = FNullTextureID(); } else { smf.surfaceskinIDs[index][surface] = LoadSkin(path.GetChars(), sc.String); if (!smf.surfaceskinIDs[index][surface].isValid()) { Printf("Surface Skin '%s' not found in '%s'\n", sc.String, smf.type->TypeName.GetChars()); } } } else if (sc.Compare("frameindex") || sc.Compare("frame")) { bool isframe=!!sc.Compare("frame"); sc.MustGetString(); smf.sprite = -1; for (i = 0; i < (int)sprites.Size (); ++i) { if (strnicmp (sprites[i].name, sc.String, 4) == 0) { if (sprites[i].numframes==0) { //sc.ScriptError("Sprite %s has no frames", sc.String); } smf.sprite = i; break; } } if (smf.sprite==-1) { sc.ScriptError("Unknown sprite %s in model definition for %s", sc.String, smf.type->TypeName.GetChars()); } sc.MustGetString(); FString framechars = sc.String; sc.MustGetNumber(); index=sc.Number; if (index<0 || index>=MAX_MODELS_PER_FRAME) { sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars()); } if (isframe) { sc.MustGetString(); if (smf.modelIDs[index] != -1) { FModel *model = Models[smf.modelIDs[index]]; smf.modelframes[index] = model->FindFrame(sc.String); if (smf.modelframes[index]==-1) sc.ScriptError("Unknown frame '%s' in %s", sc.String, smf.type->TypeName.GetChars()); } else smf.modelframes[index] = -1; } else { sc.MustGetNumber(); smf.modelframes[index] = sc.Number; } for(i=0; framechars[i]>0; i++) { char map[29]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; int c = toupper(framechars[i])-'A'; if (c<0 || c>=29) { sc.ScriptError("Invalid frame character %c found", c+'A'); } if (map[c]) continue; smf.frame=c; SpriteModelFrames.Push(smf); GetDefaultByType(smf.type)->hasmodel = true; map[c]=1; } } else { sc.ScriptMessage("Unrecognized string \"%s\"", sc.String); } } } } } // create a hash table for quick access SpriteModelHash = new int[SpriteModelFrames.Size ()]; atterm(DeleteModelHash); memset(SpriteModelHash, 0xff, SpriteModelFrames.Size () * sizeof(int)); for (i = 0; i < (int)SpriteModelFrames.Size (); i++) { int j = ModelFrameHash(&SpriteModelFrames[i]) % SpriteModelFrames.Size (); SpriteModelFrames[i].hashnext = SpriteModelHash[j]; SpriteModelHash[j]=i; } }
TArray<FString> I_GetSteamPath() { TArray<FString> result; TArray<FString> SteamInstallFolders; // Linux and OS X actually allow the user to install to any location, so // we need to figure out on an app-by-app basis where the game is installed. // To do so, we read the virtual registry. #ifdef __APPLE__ const FString appSupportPath = M_GetMacAppSupportPath(); FString regPath = appSupportPath + "/Steam/config/config.vdf"; try { SteamInstallFolders = ParseSteamRegistry(regPath); } catch(class CDoomError &error) { // If we can't parse for some reason just pretend we can't find anything. return result; } SteamInstallFolders.Push(appSupportPath + "/Steam/SteamApps/common"); #else char* home = getenv("HOME"); if(home != NULL && *home != '\0') { FString regPath; regPath.Format("%s/.steam/config/config.vdf", home); // [BL] The config seems to have moved from the more modern .local to // .steam at some point. Not sure if it's just my setup so I guess we // can fall back on it? if(!FileExists(regPath)) regPath.Format("%s/.local/share/Steam/config/config.vdf", home); try { SteamInstallFolders = ParseSteamRegistry(regPath); } catch(class CDoomError &error) { // If we can't parse for some reason just pretend we can't find anything. return result; } regPath.Format("%s/.local/share/Steam/SteamApps/common", home); SteamInstallFolders.Push(regPath); } #endif for(unsigned int i = 0;i < SteamInstallFolders.Size();++i) { for(unsigned int app = 0;app < countof(AppInfo);++app) { struct stat st; FString candidate(SteamInstallFolders[i] + "/" + AppInfo[app].BasePath); if(DirExists(candidate)) result.Push(candidate); } } return result; }