コード例 #1
0
ファイル: g_rail.cpp プロジェクト: BishopExile/OpenJK
	////////////////////////////////////////////////////////////////////////////////////
	// Initialize
	//
	// This function scans through the list of tracks and hooks itself up with the
	// track (and possibly lane)
	////////////////////////////////////////////////////////////////////////////////////
	void		Initialize()
	{
		mTrack	= 0;
		mLane	= 0;
		mCols	= 0;
		mRows	= 0;

		hstring	target = mEnt->target;
		for (int track=0; track<mRailTracks.size(); track++)
		{
			if (mRailTracks[track].mName==target)
			{
				mTrack = &(mRailTracks[track]);
				break;
			}
		}
		if (mTrack==0)
		{
			for (int lane=0; lane<mRailLanes.size(); lane++)
			{
				if (mRailLanes[lane].mName==target)
				{
					mLane	= &(mRailLanes[lane]);
					mTrack	= mLane->mTrack;
					break;
				}
			}
		}
		assert(mTrack!=0);
		if (mTrack)
		{
			mTrack->mMovers.push_back(this);
			mCols	= (int)((mEnt->maxs[mTrack->mWAxis] - mEnt->mins[mTrack->mWAxis]) / mTrack->mGridCellSize) + 1;
			mRows	= (int)((mEnt->maxs[mTrack->mHAxis] - mEnt->mins[mTrack->mHAxis]) / mTrack->mGridCellSize) + 1;

			// Make Sure The Mover Fits In The Track And Lane
			//------------------------------------------------
			if (mRows>mTrack->mRows)
			{
//				assert(0);
				mRows = mTrack->mRows;
			}
			if (mCols>mTrack->mCols)
			{
//				assert(0);
				mCols = mTrack->mCols;
			}
			if (mLane && mCols>(mLane->mMaxCol - mLane->mMinCol + 1))
			{
//				assert(0);
				mCols = (mLane->mMaxCol - mLane->mMinCol + 1);
			}
		}
	}
コード例 #2
0
ファイル: AI_GalakMech.cpp プロジェクト: matthewvdz/joja
////////////////////////////////////////////////////////////////////////////////////////
// Vehicle_Find
//
// Will look through all registered vehicles and choose the closest one that the given
// entity can get to.
//
////////////////////////////////////////////////////////////////////////////////////////
gentity_t*	Vehicle_Find(gentity_t *ent)
{
	gentity_t*		closest = 0;
	float			closestDist = 0;
	float			curDist = 0;


	for (int i=0; i<mRegistered.size(); i++)
	{
		if (!mRegistered[i]->owner)
		{
			curDist = Distance(mRegistered[i]->currentOrigin, ent->currentOrigin);
			if (curDist<1000 && (!closest || curDist<closestDist))
			{
				if (NAV::InSameRegion(ent, mRegistered[i]))
				{
					closest = mRegistered[i];
					closestDist = curDist;
				}
			}
		}
	}

	return closest;
}
コード例 #3
0
ファイル: g_rail.cpp プロジェクト: BishopExile/OpenJK
void SP_rail_lane(gentity_t *ent)
{
 	gi.SetBrushModel(ent, ent->model);
	G_SpawnInt("delay", "0", &ent->delay);
	mRailLanes.push_back().Setup(ent);
	G_FreeEntity(ent);
}
コード例 #4
0
ファイル: g_rail.cpp プロジェクト: BishopExile/OpenJK
	////////////////////////////////////////////////////////////////////////////////////
	// Initialize
	//
	// This function scans through the list of tracks and hooks itself up with the
	// track
	////////////////////////////////////////////////////////////////////////////////////
	void		Initialize()
	{
		mTrack		= 0;
		mMinCol		= 0;
		mMaxCol		= 0;

//		int		dummy;
		for (int i=0; i<mRailTracks.size(); i++)
		{
			if (mRailTracks[i].mName==mNameTrack)
			{
				mTrack	= &(mRailTracks[i]);
				mTrack->SnapVectorToGrid(mMins);
				mTrack->SnapVectorToGrid(mMaxs);

				mMinCol = (int)((mMins[mTrack->mWAxis] - mTrack->mMins[mTrack->mWAxis])/mTrack->mGridCellSize);
				mMaxCol = (int)((mMaxs[mTrack->mWAxis] - mTrack->mMins[mTrack->mWAxis] - (mTrack->mGridCellSize/2.0f))/mTrack->mGridCellSize);

				//if (mTrack->mNegative)
				//{
				//	mMinCol = (mTrack->mCols - mMinCol - 1);
				//	mMaxCol = (mTrack->mCols - mMaxCol - 1);
				//}


//				mTrack->mCells.get_cell_coords(mMins[mTrack->mWAxis], 0, mMinCol, dummy);
//				mTrack->mCells.get_cell_coords((mMaxs[mTrack->mWAxis]-10.0f), 0, mMaxCol, dummy);
				break;
			}
		}
		assert(mTrack!=0);
	}
コード例 #5
0
ファイル: g_rail.cpp プロジェクト: BishopExile/OpenJK
void SP_rail_track(gentity_t *ent)
{
	gi.SetBrushModel(ent, ent->model);
	G_SpawnInt("delay", "0", &ent->delay);
	mRailTracks.push_back().Setup(ent);
	G_FreeEntity(ent);
	mRailSystemActive = true;
}
コード例 #6
0
ファイル: g_rail.cpp プロジェクト: BishopExile/OpenJK
void	Rail_Reset()
{
	mRailSystemActive = false;
	mRailTracks.clear();
	mRailLanes.clear();
	mRailMovers.clear();

	mWooshSml.clear();
	mWooshMed.clear();
	mWooshLar.clear();
	mWooshSup.clear();
	mWooshTun.clear();
}
コード例 #7
0
ファイル: g_rail.cpp プロジェクト: BishopExile/OpenJK
void	Rail_UnLockCenterOfTrack(const char* trackName)
{
	hstring	name = trackName;
	for (int track=0; track<mRailTracks.size(); track++)
	{
		if (mRailTracks[track].mName==name)
		{
			mRailTracks[track].mCenterLocked = false;
			return;
		}
	}
	assert(0);
}
コード例 #8
0
ファイル: g_rail.cpp プロジェクト: BishopExile/OpenJK
void	CRailTrack::RandomizeTestCols(int startCol, int stopCol)
{
	int numCols = (stopCol - startCol);
	int swapA;
	int	swapB;



	for (int swapNum=0; swapNum<numCols; swapNum++)
	{
		swapA = Q_irand(0, numCols-1);
		swapB = Q_irand(0, numCols-1);
		if (swapA!=swapB)
		{
			mTestCols.swap(swapA, swapB);
		}
	}
}
コード例 #9
0
ファイル: AI_GalakMech.cpp プロジェクト: matthewvdz/joja
void	Pilot_Update(void)
{
	mActivePilotCount = 0;
	mRegistered.clear();
	for (int i=0; i<ENTITYNUM_WORLD; i++)
	{
		if (g_entities[i].inuse && 
			g_entities[i].client &&
			g_entities[i].NPC && 
			g_entities[i].NPC->greetEnt &&
			g_entities[i].NPC->greetEnt->owner==(&g_entities[i])
			)
		{
			mActivePilotCount++;
		}
		if ( g_entities[i].inuse && 
			 g_entities[i].client &&
			 g_entities[i].m_pVehicle &&
			!g_entities[i].owner &&
			 g_entities[i].health>0 &&
			 g_entities[i].m_pVehicle->m_pVehicleInfo->type==VH_SPEEDER && 
			!mRegistered.full())
		{
			mRegistered.push_back(&g_entities[i]);
		}

	}


	if (player && 
		player->inuse && 
		TIMER_Done(player, "FlybySoundArchitectureDebounce"))
	{
    	TIMER_Set(player, "FlybySoundArchitectureDebounce", 300);

		Vehicle_t*	pVeh = G_IsRidingVehicle(player);

		if (pVeh && 
			(pVeh->m_pVehicleInfo->soundFlyBy || pVeh->m_pVehicleInfo->soundFlyBy2) &&
			//fabsf(pVeh->m_pParentEntity->currentAngles[2])<15.0f &&
			VectorLength(pVeh->m_pParentEntity->client->ps.velocity)>500.0f)
		{
			vec3_t	projectedPosition;
			vec3_t	projectedDirection;
			vec3_t	projectedRight;
			vec3_t	anglesNoRoll;

			VectorCopy(pVeh->m_pParentEntity->currentAngles, anglesNoRoll);
			anglesNoRoll[2] = 0;
			AngleVectors(anglesNoRoll, projectedDirection, projectedRight, 0);

			VectorMA(player->currentOrigin, 1.2f, pVeh->m_pParentEntity->client->ps.velocity, projectedPosition);
			VectorMA(projectedPosition, Q_flrand(-200.0f, 200.0f), projectedRight, projectedPosition); 

			gi.trace(&mPilotViewTrace, 
				player->currentOrigin, 
				0, 
				0, 
				projectedPosition, 
				player->s.number, 
 				MASK_SHOT, G2_NOCOLLIDE, 0);

			if ((mPilotViewTrace.allsolid==qfalse) && 
				(mPilotViewTrace.startsolid==qfalse) && 
				(mPilotViewTrace.fraction<0.99f) && 
				(mPilotViewTrace.plane.normal[2]<0.5f) &&
				(DotProduct(projectedDirection, mPilotViewTrace.plane.normal)<-0.5f)
				)
			{
 			//	CG_DrawEdge(player->currentOrigin, mPilotViewTrace.endpos, EDGE_IMPACT_POSSIBLE);
 		  		TIMER_Set(player, "FlybySoundArchitectureDebounce", Q_irand(1000, 2000));

				int soundFlyBy = pVeh->m_pVehicleInfo->soundFlyBy;
				if (pVeh->m_pVehicleInfo->soundFlyBy2 && (!soundFlyBy || !Q_irand(0,1)))
				{
					soundFlyBy = pVeh->m_pVehicleInfo->soundFlyBy2;
				}
				G_SoundAtSpot(mPilotViewTrace.endpos, soundFlyBy, qtrue);
			}
			else
			{
 			//	CG_DrawEdge(player->currentOrigin, mPilotViewTrace.endpos, EDGE_IMPACT_SAFE);
			}
		}
	}
}
コード例 #10
0
ファイル: AI_GalakMech.cpp プロジェクト: matthewvdz/joja
void	Pilot_Reset(void)
{
	mPilotViewTraceCount = 0;
	mActivePilotCount = 0;
	mRegistered.clear();
}
コード例 #11
0
ファイル: AI_GalakMech.cpp プロジェクト: matthewvdz/joja
bool	Pilot_AnyVehiclesRegistered()
{
	return (!mRegistered.empty());
}
コード例 #12
0
ファイル: g_rail.cpp プロジェクト: BishopExile/OpenJK
void	CRailTrack::Update()
{
	mNextUpdateTime = level.time + mNextUpdateDelay;


	// Now, Attempt To Add A Number Of Movers To The Track
	//-----------------------------------------------------
	int		attempt;
	int		startCol;
	int		stopCol;
	int		atCol;
	int		testColIndex;

	for (attempt=0; attempt<mNumMoversPerRow; attempt++)
	{
		// Randomly Select A Mover And Test To See If It Is Active
		//---------------------------------------------------------
		CRailMover*	mover = mMovers[Q_irand(0, mMovers.size()-1)];
		if (mover->Active())
		{
			continue;
		}

		// Don't Spawn Until Start Time Has Expired
		//------------------------------------------
		if (level.time < ((mover->mLane)?(mover->mLane->mStartTime):(mStartTime)))
		{
			continue;
		}

		// If Center Locked, Stop Spawning Center Track Movers
		//-----------------------------------------------------
		if (mover->mCenter && mCenterLocked)
		{
			continue;
		}
	

		// Restrict It To A Lane
		//-----------------------
		if (mover->mLane)
		{
			startCol	= mover->mLane->mMinCol;
			stopCol		= mover->mLane->mMaxCol+1;
		}

		// Or Let It Go Anywhere On The Track
		//------------------------------------
		else
		{
			startCol	= 0;
			stopCol		= mCols;
		}
		stopCol -= (mover->mCols-1);


		// If The Mover Is Too Big To Fit In The Lane, Go On To Next Attempt
		//-------------------------------------------------------------------
		if (stopCol<=startCol)
		{
			assert(0);	// Should Not Happen
			continue;
		}

		// Force It To Center
		//--------------------
		if (mover->mCenter && stopCol!=(startCol+1))
		{
			startCol	= ((mCols/2) - (mover->mCols/2));
			stopCol		= startCol+1;
		}


		// Construct A List Of Columns To Test For Insertion
		//---------------------------------------------------
		mTestCols.clear();
		for (int i=startCol; i<stopCol; i++)
		{
			mTestCols.push_back(i);
		}

		// Now Try All The Cols To See If The Building Can Fit
		//-----------------------------------------------------
		while (!mTestCols.empty())
		{
			// Randomly Pick A Column, Then Remove It From The Vector
			//--------------------------------------------------------
			testColIndex = Q_irand(0, mTestCols.size()-1);
			atCol = mTestCols[testColIndex];
			mTestCols.erase_swap(testColIndex);

			if (TestMoverInCells(mover, atCol))
			{
				// Ok, We've Found A Safe Column To Insert This Mover
				//----------------------------------------------------
				InsertMoverInCells(mover, atCol);

				// Now Transport The Actual Mover Entity Into Position, Link It & Send It Off
				//----------------------------------------------------------------------------
				CVec3	StartPos(mGridBottomLeftCorner);
				StartPos[mWAxis] += ((atCol * mGridCellSize) + ((mover->mCols/2.0f) * mGridCellSize));
				StartPos[mHAxis] += (((mover->mRows/2.0f) * mGridCellSize) * ((mNegative)?(1):(-1)));
				StartPos[2] = 0;

				// If Centered, Actually Put It At EXACTLY The Right Position On The Width Axis
				//------------------------------------------------------------------------------
				if (mover->mCenter)
				{
					StartPos[mWAxis] = mGridCenter[mWAxis];
					float	deltaOffset = mGridCenter[mWAxis] - mover->mOriginOffset[mWAxis];
					if (deltaOffset<(mGridCellSize*0.5f) )
					{
						StartPos[mWAxis] -= deltaOffset;
					}
				}

				StartPos -= mover->mOriginOffset;
				G_SetOrigin(mover->mEnt, StartPos.v);

				// Start It Moving
				//-----------------
				VectorCopy(StartPos.v, mover->mEnt->s.pos.trBase);
				VectorCopy(mVelocity.v, mover->mEnt->s.pos.trDelta);
				mover->mEnt->s.pos.trTime		= level.time;
				mover->mEnt->s.pos.trDuration	= mTravelTimeMilliseconds + (mNextUpdateDelay*mover->mRows);
				mover->mEnt->s.pos.trType		= TR_LINEAR_STOP;
				mover->mEnt->s.eFlags			&= ~EF_NODRAW;

				mover->mSoundPlayed				= false;


				// Successfully Inserted This Mover.  Now Move On To The Next Mover
				//------------------------------------------------------------------
				break;
			}
		}
	}

	// Incriment The Current Row
	//---------------------------
	mRow++;
	if (mRow>=mRows)
	{
		mRow = 0;
	}

	// Erase The Erase Row
	//---------------------
	int	EraseRow = mRow - MAX_ROW_HISTORY;
	if (EraseRow<0)
	{
		EraseRow += mRows;
	}
	for (int col=0; col<mCols; col++)
	{
		mCells.get(col, EraseRow) = 0;
	}
}
コード例 #13
0
ファイル: g_rail.cpp プロジェクト: BishopExile/OpenJK
void	Rail_Update()
{
	if (mRailSystemActive)// && false)
	{
		for (int track=0; track<mRailTracks.size(); track++)
		{
			if (level.time>mRailTracks[track].mNextUpdateTime && !mRailTracks[track].mMovers.empty())
			{
				mRailTracks[track].Update();
			}
		}

		// Is The Player Outside?
		//------------------------
 		if (player && gi.WE_IsOutside(player->currentOrigin))
		{
			int		wooshSound;
			vec3_t	wooshSoundPos;
			vec3_t	moverOrigin;
			vec3_t	playerToMover;
			float	playerToMoverDistance;
			float	playerToMoverDistanceFraction;

			// Iterate Over All The Movers
			//-----------------------------
 			for (int moverIndex=0; moverIndex<mRailMovers.size(); moverIndex++)
			{
 				CRailMover&	mover = mRailMovers[moverIndex];

				// Is It Active, And Has The Sound Already Played On It?
				//--------------------------------------------------------
   			 	if (mover.Active() && !mover.mSoundPlayed)
				{ 
 					VectorAdd(mover.mEnt->currentOrigin, mover.mOriginOffset.v, moverOrigin);
 					VectorSubtract(moverOrigin, player->currentOrigin, playerToMover);
					playerToMover[2]		= 0.0f;
 					playerToMoverDistance	= VectorNormalize(playerToMover);


					// Is It Close Enough?
					//---------------------
					if ((( mover.mLane || !mover.mCenter) &&								// Not Center Track
						 (playerToMoverDistance<WOOSH_ALL_RANGE) && 						//  And Close Enough
						 (DotProduct(playerToMover, mover.mTrack->mDirection.v)>-0.45f))	//  And On The Side
						||																	//OR
						((!mover.mLane &&  mover.mCenter) &&								// Is Center Track
						  (playerToMoverDistance<WOOSH_SUPPORT_RANGE ||						//  And Close Enough for Support
						  (playerToMoverDistance<WOOSH_TUNNEL_RANGE && mover.mRows>10))		//   Or Close Enough For Tunnel
						 ))
					{
						mover.mSoundPlayed = true;
						wooshSound = 0;

						// The Centered Entities Play Right On The Player's Head For Full Volume
						//-----------------------------------------------------------------------
						if (mover.mCenter && !mover.mLane)
						{
 							VectorCopy(player->currentOrigin, wooshSoundPos);
 							wooshSoundPos[2] += 50;

							// If It Is Very Long, Play The Tunnel Sound
							//-------------------------------------------
							if (mover.mRows>10)
							{
								wooshSound = mWooshTun[Q_irand(0, mWooshTun.size()-1)];
							}

							// Otherwise It Is A Support
							//---------------------------
							else 
							{ 
								wooshSound = mWooshSup[Q_irand(0, mWooshSup.size()-1)];
							}
						}

						// All Other Entities Play At A Fraction Of Their Normal Range
						//-------------------------------------------------------------
 						else 
						{
							// Scale The Play Pos By The Square Of The Distance
							//--------------------------------------------------
							playerToMoverDistanceFraction = playerToMoverDistance/WOOSH_ALL_RANGE;
 							playerToMoverDistanceFraction *= playerToMoverDistanceFraction;
							playerToMoverDistanceFraction *= 0.6f;
							playerToMoverDistance *= playerToMoverDistanceFraction;
 							VectorMA(player->currentOrigin, playerToMoverDistance, playerToMover, wooshSoundPos);

							// Large Building
							//----------------
							if (mover.mRows>4)
							{
								wooshSound = mWooshLar[Q_irand(0, mWooshLar.size()-1)];
							}

							// Medium Building
							//-----------------
							else if (mover.mRows>2)
							{
								wooshSound = mWooshMed[Q_irand(0, mWooshMed.size()-1)];
							}

							// Small Building
							//----------------
							else 
							{ 
								wooshSound = mWooshSml[Q_irand(0, mWooshSml.size()-1)];
							}
						}

						// If A Woosh Sound Was Selected, Play It Now
						//--------------------------------------------
						if (wooshSound)
						{
							G_SoundAtSpot(wooshSoundPos, wooshSound, qfalse);
							if (WOOSH_DEBUG)
							{
								CG_DrawEdge(player->currentOrigin, wooshSoundPos, EDGE_WHITE_TWOSECOND);
							}
						}
					}
				}
			}
		}
	}
}
コード例 #14
0
ファイル: g_rail.cpp プロジェクト: BishopExile/OpenJK
void	Rail_Initialize()
{
	for (int lane=0; lane<mRailLanes.size(); lane++)
	{
		mRailLanes[lane].Initialize();
	}

	for (int mover=0; mover<mRailMovers.size(); mover++)
	{
		mRailMovers[mover].Initialize();
	}

	// Precache All The Woosh Sounds
	//-------------------------------
	if (!mRailMovers.empty())
	{
		mWooshMed.push_back(G_SoundIndex("sound/effects/woosh1"));
		mWooshSml.push_back(G_SoundIndex("sound/effects/woosh2"));
		mWooshMed.push_back(G_SoundIndex("sound/effects/woosh3"));
		mWooshSml.push_back(G_SoundIndex("sound/effects/woosh4"));
		mWooshLar.push_back(G_SoundIndex("sound/effects/woosh5"));
		mWooshSml.push_back(G_SoundIndex("sound/effects/woosh6"));
		mWooshSup.push_back(G_SoundIndex("sound/effects/woosh7"));
		mWooshSup.push_back(G_SoundIndex("sound/effects/woosh8"));
		mWooshSup.push_back(G_SoundIndex("sound/effects/woosh9"));
		mWooshLar.push_back(G_SoundIndex("sound/effects/woosh10"));
		mWooshLar.push_back(G_SoundIndex("sound/effects/woosh11"));
		mWooshLar.push_back(G_SoundIndex("sound/effects/woosh12"));
		mWooshSml.push_back(G_SoundIndex("sound/effects/woosh13"));
		mWooshMed.push_back(G_SoundIndex("sound/effects/woosh14"));
		mWooshMed.push_back(G_SoundIndex("sound/effects/woosh15"));
		mWooshMed.push_back(G_SoundIndex("sound/effects/woosh16"));
		mWooshSml.push_back(G_SoundIndex("sound/effects/woosh17"));
		mWooshMed.push_back(G_SoundIndex("sound/effects/woosh18"));
		mWooshMed.push_back(G_SoundIndex("sound/effects/woosh19"));
		mWooshMed.push_back(G_SoundIndex("sound/effects/woosh20"));
		mWooshMed.push_back(G_SoundIndex("sound/effects/woosh21"));
		mWooshLar.push_back(G_SoundIndex("sound/effects/woosh22"));
		mWooshLar.push_back(G_SoundIndex("sound/effects/woosh23"));
		mWooshSup.push_back(G_SoundIndex("sound/effects/woosh24"));
		mWooshSup.push_back(G_SoundIndex("sound/effects/woosh25"));
		mWooshMed.push_back(G_SoundIndex("sound/effects/woosh26"));
		mWooshMed.push_back(G_SoundIndex("sound/effects/woosh27"));
		mWooshMed.push_back(G_SoundIndex("sound/effects/woosh28"));
		mWooshLar.push_back(G_SoundIndex("sound/effects/woosh29"));
		mWooshTun.push_back(G_SoundIndex("sound/effects/whoosh_tunnel"));
	}
}
コード例 #15
0
ファイル: g_rail.cpp プロジェクト: BishopExile/OpenJK
void SP_rail_mover(gentity_t *ent)
{
	gi.SetBrushModel(ent, ent->model);
	mRailMovers.push_back().Setup(ent);
}
コード例 #16
0
ファイル: AI_Animal.cpp プロジェクト: emileb/JK3
////////////////////////////////////////////////////////////////////////////////////////
// Update The Packs, Delete Dead Leaders, Join / Split Packs, Find MY Leader
////////////////////////////////////////////////////////////////////////////////////////
gentity_t* NPC_AnimalUpdateLeader(void)
{
	// Find The Closest Pack Leader, Not Counting Myself
	//---------------------------------------------------
	gentity_t*	closestLeader = 0;
	float		closestDist = 0;
	int			myLeaderNum = 0;
	
	for (int i=0; i<mPacks.size(); i++)
	{
		// Dump Dead Leaders
		//-------------------
		if (mPacks[i]==0 || mPacks[i]->health<=0)
		{
			if (mPacks[i]==NPC->client->leader)
			{
				NPC->client->leader = 0;
			}

			mPacks.erase_swap(i);

			if (i>=mPacks.size())
			{
				closestLeader = 0;
				break;
			}
		}

		// Don't Count Self
		//------------------
		if (mPacks[i]==NPC)
		{
			myLeaderNum = i;
			continue;
		}

		float	Dist = Distance(mPacks[i]->currentOrigin, NPC->currentOrigin);
		if (!closestLeader || Dist<closestDist)
		{
			closestDist = Dist;
			closestLeader = mPacks[i];
		}
	}

	// In Joining Distance?
	//----------------------
	if (closestLeader && closestDist<JOIN_PACK_DISTANCE)
	{
		// Am I Already A Leader?
		//------------------------
		if (NPC->client->leader==NPC)
		{
			mPacks.erase_swap(myLeaderNum);		// Erase Myself From The Leader List
		}

		// Join The Pack!
		//----------------
		NPC->client->leader = closestLeader;
	}


	// Do I Have A Leader?
	//---------------------
	if (NPC->client->leader)
	{
		// AM I A Leader?
		//----------------
		if (NPC->client->leader!=NPC)
		{
			// If Our Leader Is Dead, Clear Him Out

			if ( NPC->client->leader->health<=0 || NPC->client->leader->inuse == 0)
			{
				NPC->client->leader = 0;
			}
			
			// If My Leader Isn't His Own Leader, Then, Use His Leader
			//---------------------------------------------------------
			else if (NPC->client->leader->client->leader!=NPC->client->leader)
			{
				// Eh.  Can this get more confusing?
				NPC->client->leader = NPC->client->leader->client->leader;
			}

			// If Our Leader Is Too Far Away, Clear Him Out
			//------------------------------------------------------
			else if ( Distance(NPC->client->leader->currentOrigin, NPC->currentOrigin)>LEAVE_PACK_DISTANCE)
			{
				NPC->client->leader = 0;
			}
		}

	}

	// If We Couldn't Find A Leader, Then Become One
	//-----------------------------------------------
	else if (!mPacks.full())
	{
		NPC->client->leader = NPC;
		mPacks.push_back(NPC);
	}
	return NPC->client->leader;
}