Example #1
0
//*****************************************************************************
//
void SERVER_RCON_Tick( )
{
	// Remove timed-out candidates.
	for ( unsigned int i = 0; i < g_Candidates.Size( ); )
	{
		if (( gametic - g_Candidates[i].iLastMessageTic ) >= ( RCON_CANDIDATE_TIMEOUT_TIME * TICRATE ))
			g_Candidates.Delete( i );
		else
			i++;
	}

	// Remove timed-out clients.
	for ( unsigned int i = 0; i < g_AuthedClients.Size( ); )
	{
		if (( gametic - g_AuthedClients[i].iLastMessageTic ) >= ( RCON_CLIENT_TIMEOUT_TIME * TICRATE ))
		{
			Printf( "RCON client at %s timed out.\n", NETWORK_AddressToString( g_AuthedClients[i].Address ));
			g_AuthedClients.Delete( i );
			SERVER_RCON_UpdateInfo( SVRCU_ADMINCOUNT );
		}
		else
			i++;
	}

	g_BadRequestFloodQueue.adjustHead( gametic / 1000 );
}
	//=============================================================================
	//
	//
	//
	//=============================================================================
	void MergeLines(FGLSectionLoop *loop)
	{
		int i;
		int deleted = 0;
		FGLSectionLine *ln1;
		FGLSectionLine *ln2;
		// Merge identical lines in the list
		for(i = loop->numlines - 1; i > 0; i--)
		{
			ln1 = loop->GetLine(i);
			ln2 = loop->GetLine(i-1);

			if (ln1->sidedef == ln2->sidedef && ln1->otherside == ln2->otherside)
			{
				// identical references. These 2 lines can be merged.
				ln2->end = ln1->end;
				SectionLines.Delete(loop->startline + i);
				loop->numlines--;
				deleted++;
			}
		}

		// If we started in the middle of a sidedef the first and last lines
		// may reference the same sidedef. check that, too.

		int loopstart = 0;

		ln1 = loop->GetLine(0);
		for(i = loop->numlines - 1; i > 0; i--)
		{
			ln2 = loop->GetLine(i);
			if (ln1->sidedef != ln2->sidedef || ln1->otherside != ln2->otherside)
				break;
		}
		if (i < loop->numlines-1)
		{
			i++;
			ln2 = loop->GetLine(i);
			ln1->start = ln2->start;
			SectionLines.Delete(loop->startline + i, loop->numlines - i);
			deleted += loop->numlines - i;
			loop->numlines = i;
		}

		// Adjust all following loops
		for(unsigned ii = unsigned(loop - &SectionLoops[0]) + 1; ii < SectionLoops.Size(); ii++)
		{
			SectionLoops[ii].startline -= deleted;
		}
	}
Example #3
0
static int UseHealthItems(TArray<AInventory *> &Items, int &saveHealth)
{
	int saved = 0;

	while (Items.Size() > 0 && saveHealth > 0)
	{
		int maxhealth = 0;
		int index = -1;

		// Find the largest item in the list
		for(unsigned i = 0; i < Items.Size(); i++)
		{
			if (Items[i]->health > maxhealth)
			{
				index = i;
				maxhealth = Items[i]->health;
			}
		}

		// Now apply the health items, using the same logic as Heretic and Hexen.
		int count = (saveHealth + maxhealth-1) / maxhealth;
		for(int i = 0; i < count; i++)
		{
			saved += maxhealth;
			saveHealth -= maxhealth;
			if (--Items[index]->Amount == 0)
			{
				Items[index]->DepleteOrDestroy ();
				Items.Delete(index);
				break;
			}
		}
	}
	return saved;
}
	//=============================================================================
	//
	//
	//
	//=============================================================================
	void DeleteLine(int i)
	{
		SectionLines.Delete(i);
		for(int i = SectionLoops.Size() - 1; i >= 0; i--)
		{
			FGLSectionLoop *loop = &SectionLoops[i];
			if (loop->startline > i) loop->startline--;
		}
	}
Example #5
0
static void server_rcon_HandleNewConnection( NETADDRESS_s Address,  int iProtocolVersion )
{
	// Banned client? Notify him, ignore him, and get out of here.
	if ( SERVERBAN_IsIPBanned( Address ))
	{
		NETWORK_WriteByte( &g_MessageBuffer.ByteStream, SVRC_BANNED );
		NETWORK_LaunchPacket( &g_MessageBuffer, Address );
		g_BadRequestFloodQueue.addAddress( Address, gametic / 1000 );
		return;
	}

	// Old protocol version? Notify, ignore, and quit.
	if ( iProtocolVersion < MIN_PROTOCOL_VERSION )
	{
		NETWORK_WriteByte( &g_MessageBuffer.ByteStream, SVRC_OLDPROTOCOL );
		NETWORK_WriteByte( &g_MessageBuffer.ByteStream, PROTOCOL_VERSION );
		NETWORK_WriteString( &g_MessageBuffer.ByteStream, DOTVERSIONSTR );
		NETWORK_LaunchPacket( &g_MessageBuffer, Address );
		g_BadRequestFloodQueue.addAddress( Address, gametic / 1000 );
		return;
	}

	// Check if there's already a user at this address. Remove him if so (must be reconnecting).
	// This ensures that each address never has more than one entry (since this is the only function that gives out new candidate slots).
	int iIndex = server_rcon_FindCandidate( Address );
	if ( iIndex != -1 )
		g_Candidates.Delete( iIndex );
	iIndex = server_rcon_FindClient( Address );
	if ( iIndex != -1 )
		g_AuthedClients.Delete( iIndex );

	// Create a slot for him, and request his password.
	RCONCANDIDATE_s		Candidate;
	Candidate.iLastMessageTic = gametic;
	Candidate.Address = Address;
	server_rcon_CreateSalt( Candidate.szSalt );
	g_Candidates.Push( Candidate );

	NETWORK_ClearBuffer( &g_MessageBuffer );
	NETWORK_WriteByte( &g_MessageBuffer.ByteStream, SVRC_SALT );
	NETWORK_WriteString( &g_MessageBuffer.ByteStream, Candidate.szSalt );
	NETWORK_LaunchPacket( &g_MessageBuffer, Address );
}
Example #6
0
	bool Remove(ASpecialSpot *spot)
	{
		for(unsigned i = 0; i < Spots.Size(); i++)
		{
			if (Spots[i] == spot) 
			{
				Spots.Delete(i);
				if (Index > i) Index--;
				return true;
			}
		}
		return false;
	}
Example #7
0
void SkylineBinPack::Insert(TArray<RectSize> &rects, TArray<Rect> &dst)
{
	dst.Clear();

	while(rects.Size() > 0)
	{
		Rect bestNode;
		int bestScore1 = INT_MAX;
		int bestScore2 = INT_MAX;
		int bestSkylineIndex = -1;
		int bestRectIndex = -1;
		for(unsigned i = 0; i < rects.Size(); ++i)
		{
			Rect newNode;
			int score1;
			int score2;
			int index;
			newNode = FindPositionForNewNodeMinWaste(rects[i].width, rects[i].height, score2, score1, index);
			assert(disjointRects.Disjoint(newNode));
			if (newNode.height != 0)
			{
				if (score1 < bestScore1 || (score1 == bestScore1 && score2 < bestScore2))
				{
					bestNode = newNode;
					bestScore1 = score1;
					bestScore2 = score2;
					bestSkylineIndex = index;
					bestRectIndex = i;
				}
			}
		}

		if (bestRectIndex == -1)
			return;

		// Perform the actual packing.
		assert(disjointRects.Disjoint(bestNode));
#ifdef _DEBUG
		disjointRects.Add(bestNode);
#endif
		AddSkylineLevel(bestSkylineIndex, bestNode);
		usedSurfaceArea += rects[bestRectIndex].width * rects[bestRectIndex].height;
		rects.Delete(bestRectIndex);
		dst.Push(bestNode);
	}
}
void gl_AddLightDefaults(FLightDefaults *defaults)
{
   FLightDefaults *temp;
   unsigned int i;

   // remove duplicates
   for (i = 0; i < LightDefaults.Size(); i++)
   {
      temp = LightDefaults[i];
	  if (temp->GetName() == defaults->GetName())
      {
         delete temp;
         LightDefaults.Delete(i);
         break;
      }
   }

   LightDefaults.Push(defaults);
}
Example #9
0
void P_AutoUseStrifeHealth (player_t *player)
{
	TArray<AInventory *> Items;

	for(AInventory *inv = player->mo->Inventory; inv != NULL; inv = inv->Inventory)
	{
		if (inv->Amount > 0 && inv->IsKindOf(RUNTIME_CLASS(AHealthPickup)))
		{
			int mode = static_cast<AHealthPickup*>(inv)->autousemode;

			if (mode == 3) Items.Push(inv);
		}
	}

	if (!sv_disableautohealth)
	{
		while (Items.Size() > 0)
		{
			int maxhealth = 0;
			int index = -1;

			// Find the largest item in the list
			for(unsigned i = 0; i < Items.Size(); i++)
			{
				if (Items[i]->health > maxhealth)
				{
					index = i;
					maxhealth = Items[i]->Amount;
				}
			}

			while (player->health < 50)
			{
				if (!player->mo->UseInventory (Items[index]))
					break;
			}
			if (player->health >= 50) return;
			// Using all of this item was not enough so delete it and restart with the next best one
			Items.Delete(index);
		}
	}
}
Example #10
0
void WordGenerator (CXMLElement *pCmdLine)
{
    int i;

    //	Load input file

    CString sFilespec = pCmdLine->GetAttribute(CONSTLIT("input"));
    if (sFilespec.IsBlank())
    {
        printf("ERROR: input filename expected.\n");
        return;
    }

    CFileReadBlock InputFile(sFilespec);
    if (InputFile.Open() != NOERROR)
    {
        printf("ERROR: Unable to open file: %s\n", sFilespec.GetASCIIZPointer());
        return;
    }

    //	"Novel" means that we only generate words that are not
    //	in the input file.

    bool bNovelWordsOnly = pCmdLine->GetAttributeBool(NOVEL_ATTRIB);

    //	Build up a word generator

    CMarkovWordGenerator Generator;
    TMap<CString, DWORD> InputWords;

    //	Read each line of the file

    char *pPos = InputFile.GetPointer(0);
    char *pEndPos = pPos + InputFile.GetLength();
    while (pPos < pEndPos)
    {
        //	Skip whitespace

        while (pPos < pEndPos && (strIsWhitespace(pPos) || *pPos < ' '))
            pPos++;

        //	Parse the line

        char *pStart = pPos;
        while (pPos < pEndPos && *pPos != '\r' && *pPos != '\n' && *pPos >= ' ')
            pPos++;

        CString sWord(pStart, pPos - pStart);

        //	Add the word to the generator

        if (!sWord.IsBlank())
        {
            Generator.AddSample(strTrimWhitespace(sWord));

            //	If we are looking for novel words we need to keep a map
            //	of all words in the input file.

            if (bNovelWordsOnly)
                InputWords.Insert(sWord);
        }
    }

    //	If we have a count, then output a list of random words

    int iCount;
    if (pCmdLine->FindAttributeInteger(COUNT_ATTRIB, &iCount))
    {
        if (iCount > 0)
        {
            TArray<CString> Result;
            Generator.GenerateUnique(iCount, &Result);

            for (i = 0; i < Result.GetCount(); i++)
                if (InputWords.Find(Result[i]))
                {
                    Result.Delete(i);
                    i--;
                }

            Result.Sort();

            for (i = 0; i < Result.GetCount(); i++)
                printf("%s\n", Result[i].GetASCIIZPointer());
        }
    }

    //	Otherwise, output the generator as XML

    else
    {
        CMemoryWriteStream Output;
        if (Output.Create() != NOERROR)
        {
            printf("ERROR: Out of memory.\n");
            return;
        }

        if (Generator.WriteAsXML(&Output) != NOERROR)
        {
            printf("ERROR: Unable to output generator as XML.\n");
            return;
        }

        Output.Write("\0", 1);
        printf(Output.GetPointer());
    }
}
Example #11
0
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 );
}
Example #12
0
void SERVER_RCON_ParseMessage( NETADDRESS_s Address, LONG lMessage, BYTESTREAM_s *pByteStream )
{
	int iIndex = -1;

	switch ( lMessage )
	{
	case CLRC_BEGINCONNECTION:

		server_rcon_HandleNewConnection( Address, NETWORK_ReadByte( pByteStream ));
		break;
	case CLRC_PASSWORD:

		server_rcon_HandleLogin( server_rcon_FindCandidate( Address ), NETWORK_ReadString( pByteStream ));
		break;	
	case CLRC_PONG:

		iIndex = server_rcon_FindClient( Address );
		if ( iIndex != -1 )	
			g_AuthedClients[iIndex].iLastMessageTic = gametic;
		break;
	case CLRC_COMMAND:

		// Execute the command (if this came from an admin).
		iIndex = server_rcon_FindClient( Address );
		if ( iIndex != -1 )
		{
			const char *szCommand = NETWORK_ReadString( pByteStream );
			// [BB] Log the command before adding it. If we don't have a server GUI, the command
			// is executed immediately and may cause Skulltag to exit before the command is logged.
			Printf( "-> %s (RCON by %s)\n", szCommand, NETWORK_AddressToString( Address ) );
			SERVER_AddCommand( szCommand );
			g_AuthedClients[iIndex].iLastMessageTic = gametic;
		}
		break;
	case CLRC_DISCONNECT:
		
		iIndex = server_rcon_FindClient( Address );
		if ( iIndex != -1 )	
		{
			g_AuthedClients.Delete( iIndex );
			SERVER_RCON_UpdateInfo( SVRCU_ADMINCOUNT );
			Printf( "RCON client at %s disconnected.\n", NETWORK_AddressToString( Address ));
		}
		break;
	case CLRC_TABCOMPLETE:

		// [TP] RCON client wishes to tab-complete
		iIndex = server_rcon_FindClient( Address );
		if ( iIndex != -1 )
		{
			const char* part = NETWORK_ReadString( pByteStream );
			TArray<FString> list = C_GetTabCompletes( part );
			NETWORK_ClearBuffer( &g_MessageBuffer );

			// [TP] Let's not send too many of these though
			if ( list.Size() < 50 )
			{
				NETWORK_WriteByte( &g_MessageBuffer.ByteStream, SVRC_TABCOMPLETE );
				NETWORK_WriteByte( &g_MessageBuffer.ByteStream, list.Size() );

				for ( unsigned i = 0; i < list.Size(); ++i )
					NETWORK_WriteString( &g_MessageBuffer.ByteStream, list[i] );
			}
			else
			{
				NETWORK_WriteByte( &g_MessageBuffer.ByteStream, SVRC_TOOMANYTABCOMPLETES );
				NETWORK_WriteShort( &g_MessageBuffer.ByteStream, list.Size() );
			}

			NETWORK_LaunchPacket( &g_MessageBuffer, g_AuthedClients[iIndex].Address );
		}
		break;
	}
}
Example #13
0
void P_Recalculate3DFloors(sector_t * sector)
{
	F3DFloor *		rover;
	F3DFloor *		pick;
	unsigned		pickindex;
	F3DFloor *		clipped=NULL;
	F3DFloor *		solid=NULL;
	double			solid_bottom=0;
	double			clipped_top;
	double			clipped_bottom=0;
	double			maxheight, minheight;
	unsigned		i, j;
	lightlist_t newlight;
	lightlist_t resetlight;	// what it goes back to after FF_DOUBLESHADOW

	TArray<F3DFloor*> & ffloors=sector->e->XFloor.ffloors;
	TArray<lightlist_t> & lightlist = sector->e->XFloor.lightlist;

	// Sort the floors top to bottom for quicker access here and later
	// Translucent and swimmable floors are split if they overlap with solid ones.
	if (ffloors.Size()>1)
	{
		TArray<F3DFloor*> oldlist;
		
		oldlist = ffloors;
		ffloors.Clear();

		// first delete the old dynamic stuff
		for(i=0;i<oldlist.Size();i++)
		{
			F3DFloor * rover=oldlist[i];

			if (rover->flags&FF_DYNAMIC)
			{
				delete rover;
				oldlist.Delete(i);
				i--;
				continue;
			}
			if (rover->flags&FF_CLIPPED)
			{
				rover->flags&=~FF_CLIPPED;
				rover->flags|=FF_EXISTS;
			}
		}

		while (oldlist.Size())
		{
			pick=oldlist[0];
			double height=pick->top.plane->ZatPoint(sector->centerspot);

			// find highest starting ffloor - intersections are not supported!
			pickindex=0;
			for (j=1;j<oldlist.Size();j++)
			{
				double h2=oldlist[j]->top.plane->ZatPoint(sector->centerspot);

				if (h2>height)
				{
					pick=oldlist[j];
					pickindex=j;
					height=h2;
				}
			}

			oldlist.Delete(pickindex);
			double pick_bottom=pick->bottom.plane->ZatPoint(sector->centerspot);

			if (pick->flags & FF_THISINSIDE)
			{
				// These have the floor higher than the ceiling and cannot be processed
				// by the clipping code below.
				ffloors.Push(pick);
			}
			else if ((pick->flags&(FF_SWIMMABLE|FF_TRANSLUCENT) || (!(pick->flags&FF_RENDERALL))) && pick->flags&FF_EXISTS)
			{
				// We must check if this nonsolid segment gets clipped from the top by another 3D floor
				if (solid != NULL && solid_bottom < height)
				{
					ffloors.Push(pick);
					if (solid_bottom < pick_bottom)
					{
						// this one is fully covered
						pick->flags|=FF_CLIPPED;
						pick->flags&=~FF_EXISTS;
					}
					else
					{
						F3DFloor * dyn=new F3DFloor;
						*dyn=*pick;
						pick->flags|=FF_CLIPPED;
						pick->flags&=~FF_EXISTS;
						dyn->flags|=FF_DYNAMIC;
						dyn->top.copyPlane(&solid->bottom);
						ffloors.Push(dyn);

						clipped = dyn;
						clipped_top = solid_bottom;
						clipped_bottom = pick_bottom;
					}
				}
				else if (pick_bottom > height)	// do not allow inverted planes
				{
					F3DFloor * dyn = new F3DFloor;
					*dyn = *pick;
					pick->flags |= FF_CLIPPED;
					pick->flags &= ~FF_EXISTS;
					dyn->flags |= FF_DYNAMIC;
					dyn->bottom.copyPlane(&pick->top);
					ffloors.Push(pick);
					ffloors.Push(dyn);
				}
				else
				{
					clipped = pick;
					clipped_top = height;
					clipped_bottom = pick_bottom;
					ffloors.Push(pick);
				}
			}
			else if (clipped && clipped_bottom<height)
			{
				// translucent floor above must be clipped to this one!
				F3DFloor * dyn=new F3DFloor;
				*dyn=*clipped;
				clipped->flags|=FF_CLIPPED;
				clipped->flags&=~FF_EXISTS;
				dyn->flags|=FF_DYNAMIC;
				dyn->bottom.copyPlane(&pick->top);
				ffloors.Push(dyn);
				ffloors.Push(pick);

				if (pick_bottom<=clipped_bottom)
				{
					clipped=NULL;
				}
				else
				{
					// the translucent part extends below the clipper
					dyn=new F3DFloor;
					*dyn=*clipped;
					dyn->flags|=FF_DYNAMIC|FF_EXISTS;
					dyn->top.copyPlane(&pick->bottom);
					ffloors.Push(dyn);
					clipped = dyn;
					clipped_top = pick_bottom;
				}
				solid = pick;
				solid_bottom = pick_bottom;
			}
			else
			{
				clipped = NULL;
				if (solid == NULL || solid_bottom > pick_bottom)
				{
					// only if this one is lower
					solid = pick;
					solid_bottom = pick_bottom;
				}
				ffloors.Push(pick);

			}

		}
	}

	// having the floors sorted makes this routine significantly simpler
	// Only some overlapping cases with FF_DOUBLESHADOW might create anomalies
	// but these are clearly undefined.
	if(ffloors.Size())
	{
		lightlist.Resize(1);
		lightlist[0].plane = sector->ceilingplane;
		lightlist[0].p_lightlevel = &sector->lightlevel;
		lightlist[0].caster = NULL;
		lightlist[0].lightsource = NULL;
		lightlist[0].extra_colormap = sector->ColorMap;
		lightlist[0].blend = 0;
		lightlist[0].flags = 0;

		resetlight = lightlist[0];

		maxheight = sector->ceilingplane.ZatPoint(sector->centerspot);
		minheight = sector->floorplane.ZatPoint(sector->centerspot);
		for(i = 0; i < ffloors.Size(); i++)
		{
			rover=ffloors[i];

			if ( !(rover->flags & FF_EXISTS) || rover->flags & FF_NOSHADE )
				continue;
				
			double ff_top=rover->top.plane->ZatPoint(sector->centerspot);
			if (ff_top < minheight) break;	// reached the floor
			if (ff_top < maxheight)
			{
				newlight.plane = *rover->top.plane;
				newlight.p_lightlevel = rover->toplightlevel;
				newlight.caster = rover;
				newlight.lightsource = rover;
				newlight.extra_colormap = rover->GetColormap();
				newlight.blend = rover->GetBlend();
				newlight.flags = rover->flags;
				lightlist.Push(newlight);
			}
			else
			{
				double ff_bottom=rover->bottom.plane->ZatPoint(sector->centerspot);
				if (ff_bottom<maxheight)
				{
					// this segment begins over the ceiling and extends beyond it
					lightlist[0].p_lightlevel = rover->toplightlevel;
					lightlist[0].caster = rover;
					lightlist[0].lightsource = rover;
					lightlist[0].extra_colormap = rover->GetColormap();
					lightlist[0].blend = rover->GetBlend();
					lightlist[0].flags = rover->flags;
				}
			}
			if (!(rover->flags & (FF_DOUBLESHADOW | FF_RESET)))
			{
				resetlight = lightlist.Last();
			}
			else if (rover->flags & FF_RESET)
			{
				resetlight.p_lightlevel = &sector->lightlevel;
				resetlight.lightsource = NULL;
				resetlight.extra_colormap = sector->ColorMap;
				resetlight.blend = 0;
			}

			if (rover->flags&FF_DOUBLESHADOW)
			{
				double ff_bottom=rover->bottom.plane->ZatPoint(sector->centerspot);
				if(ff_bottom < maxheight && ff_bottom>minheight)
				{
					newlight.caster = rover;
					newlight.plane = *rover->bottom.plane;
					newlight.lightsource = resetlight.lightsource;
					newlight.p_lightlevel = resetlight.p_lightlevel;
					newlight.extra_colormap = resetlight.extra_colormap;
					newlight.blend = resetlight.blend;
					newlight.flags = rover->flags;
					lightlist.Push(newlight);
				}
			}
		}
	}
}
Example #14
0
void CIntGraph::GenerateRandomConnections (DWORD dwStartNode, int iMinConnections, int iMaxConnections)

//	GenerateRandomConnections
//
//	Generate random connection across all nodes.

	{
	int i, j;

	//	We start by making sure every node is connected with one other node.
	//	We keep track of the nodes that are connected and those that are not.

	TArray<int> Connected;
	TArray<int> NotConnected;

	//	All the nodes are part of the not-connected group
	//	(except for the start node)

	for (i = 0; i < m_Nodes.GetCount(); i++)
		if (i != dwStartNode && !NodeIsFree(GetNode(i)))
			NotConnected.Insert(i);

	Connected.Insert((int)dwStartNode);

	//	Loop until all nodes are connected

	while (NotConnected.GetCount() > 0)
		{
		//	Look for the shortest, non-overlapping distance
		//	between a node in the connected list and a node in the
		//	not-connected list.

		int iBestDist2 = MAX_DIST2;
		int iBestFrom = -1;
		int iBestTo = -1;

		for (i = 0; i < Connected.GetCount(); i++)
			{
			int iFrom = i;
			SNode *pFrom = GetNode(Connected[iFrom]);

			for (j = 0; j < NotConnected.GetCount(); j++)
				{
				int iTo = j;
				SNode *pTo = GetNode(NotConnected[iTo]);

				int xDist = pTo->x - pFrom->x;
				int yDist = pTo->y - pFrom->y;
				int iDist2 = xDist * xDist + yDist * yDist;
				if (iDist2 < iBestDist2
						&& !IsCrossingConnection(Connected[iFrom], NotConnected[iTo]))
					{
					iBestDist2 = iDist2;
					iBestFrom = iFrom;
					iBestTo = iTo;
					}
				}
			}

		//	If we found a best distance, connect the two nodes

		if (iBestFrom != -1)
			{
			Connect(Connected[iBestFrom], NotConnected[iBestTo]);
			Connected.Insert(NotConnected[iBestTo]);
			NotConnected.Delete(iBestTo);
			}

		//	If we did not find the best distance, then it means that we could not
		//	connect without overlapping. In that case, just connect all the unconnected

		else
			{
			for (i = 0; i < NotConnected.GetCount(); i++)
				Connect(Connected[0], NotConnected[i]);

			NotConnected.DeleteAll();
			}
		}
	}