Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 162 additions & 1 deletion src/game/server/swarm/asw_player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
#include "missionchooser/iasw_mission_chooser_source.h"
#include "rd_vgui_vscript_shared.h"
#include "rd_crafting_defs.h"
#include <algorithm>

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
Expand Down Expand Up @@ -2173,8 +2174,168 @@ HSCRIPT CASW_Player::ScriptGetNPC() const
return ToHScript( GetNPC() );
}

CON_COMMAND( rd_set_spectate_order, "Prioritize this marines in spectate order. Example: \"4 1 7 3 0\". -1 for unset." )
{
CASW_Player *pPlayer = ToASW_Player( UTIL_GetCommandClient() );
if ( !pPlayer )
{
Warning( "rd_set_spectate_order: Not a Player (not connected to server?)\n" );
return;
}

if ( args.ArgC() == 1 )
{
Warning("rd_set_spectate_order: no args");
return;
}
if ( args.ArgC() == 2 && atoi( args[1] ) == -1 )
{
Msg("rd_set_spectate_order: unset\n");
pPlayer->UnsetSpectatingOrder();
return;
}

const int nProfiles = args.ArgC() - 1;

if ( nProfiles > ASW_NUM_MARINE_PROFILES )
{
Warning( "rd_set_spectate_order: Too many profiles (%d > %d)\n", nProfiles, ASW_NUM_MARINE_PROFILES );
return;
}

int iProfiles[ASW_NUM_MARINE_PROFILES];

// parse input
for ( int i = 0; i < nProfiles; i++ )
{
const int iProfile = atoi( args[i + 1] );

if ( iProfile < 0 || iProfile >= ASW_NUM_MARINE_PROFILES )
{
Warning( "rd_set_spectate_order: Incorrect profile number (#%d: %s)\n", i + 1, args[i + 1] );
return;
}

for ( int j = 0; j < i; j++ )
{
if ( iProfiles[j] == iProfile )
{
Warning( "rd_set_spectate_order: Duplicate profile number (#%d: %d)\n", i + 1, iProfile );
return;
}
}

iProfiles[i] = iProfile;
}

pPlayer->SetSpectatingOrder( iProfiles, nProfiles );
}

// Don't need all marine profiles; rest will have worst priority
void CASW_Player::SetSpectatingOrder( const int* iProfiles, int nProfiles )
{
// Prefill with worst priority in case a profile is not in the list or is invalid
for ( int i = 0; i < ASW_NUM_MARINE_PROFILES; i++ )
{
m_iSpectatingPrioMapping[i] = INT_MAX;
}

nProfiles = MIN( nProfiles, ASW_NUM_MARINE_PROFILES );
for ( int i = 0; i < nProfiles; i++ )
{
const int iProfile = iProfiles[i];
if ( iProfiles[i] >= 0 && iProfiles[i] < ASW_NUM_MARINE_PROFILES )
{
m_iSpectatingPrioMapping[iProfiles[i]] = i;
}
}

m_bSpectatingInOrder = true;
}

bool CASW_Player::CompareSpectatingPriority( CASW_Marine* pM1, CASW_Marine* pM2 ) const
{
// Assign worst priority if no marine or no profile index
const int iProfile1 = pM1 ? pM1->GetMarineProfile()->m_ProfileIndex : INT_MAX;
const int iProfile2 = pM2 ? pM2->GetMarineProfile()->m_ProfileIndex : INT_MAX;

const int iPriority1 = ( iProfile1 >= 0 && iProfile1 < ASW_NUM_MARINE_PROFILES ) ?
m_iSpectatingPrioMapping[iProfile1] : INT_MAX;
const int iPriority2 = ( iProfile2 >= 0 && iProfile2 < ASW_NUM_MARINE_PROFILES ) ?
m_iSpectatingPrioMapping[iProfile2] : INT_MAX;

return iPriority1 < iPriority2;
}

void CASW_Player::SpectateNextMarineInOrder()
{
CASW_Game_Resource* pGameResource = ASWGameResource();
if ( !pGameResource )
return;

int iSortedCount = 0;
CASW_Marine* pMarinesSorted[ASW_MAX_MARINE_RESOURCES] = { NULL };

// Gather all valid marines
for ( int i = 0; i < pGameResource->GetMaxMarineResources(); i++ )
{
CASW_Marine_Resource* pMR = pGameResource->GetMarineResource( i );
CASW_Marine *pMarine = pMR ? pMR->GetMarineEntity() : NULL;
if ( pMarine && pMarine->IsAlive() && pMarine->GetHealth() > 0 )
{
pMarinesSorted[iSortedCount] = pMarine;
iSortedCount++;
}
}

std::sort(
pMarinesSorted,
pMarinesSorted + iSortedCount,
[this](CASW_Marine* a, CASW_Marine* b) {
return CompareSpectatingPriority(a, b);
}
);

//Msg("CASW_Player::SpectateNextMarineInOrder\n");

//Msg(" set first guy as our first\n");
CASW_Marine *pFirst = pMarinesSorted[0];

// loop through all valid marines
for ( int i = 0; i < iSortedCount; i++ )
{
//Msg("Checking pMR %d\n", i);
CASW_Marine *pMarine = pMarinesSorted[i]; // Alive marine

if (GetSpectatingNPC() == NULL) // if we're not spectating anything yet, then spectate the first one we find
{
//Msg(" We're not spectating anyone, so we're gonna spec this dude\n");
SetSpectatingNPC(pMarine);
break;
}
if (GetSpectatingNPC() == pMarine) // if we're spectating this one, then clear it, so the next one we find will get set
{
//Msg(" we're spectating this dude, so clearing our current spectator\n");
SetSpectatingNPC(NULL);
}
}
//Msg("end\n");
// if we're still not spectating anything but we found at least marine, then that means we were spectating the last one in the list and need to set this
if (GetSpectatingNPC() == NULL && pFirst)
{
//Msg(" but we're still not speccing anyone and we have a first set, so speccing that dude\n");
SetSpectatingNPC(pFirst);
}
}

void CASW_Player::SpectateNextMarine()
{
if ( m_bSpectatingInOrder )
{
SpectateNextMarineInOrder();
return;
}

CASW_Game_Resource* pGameResource = ASWGameResource();
if (!pGameResource)
return;
Expand Down Expand Up @@ -2209,7 +2370,7 @@ void CASW_Player::SpectateNextMarine()
{
//Msg(" we're spectating this dude, so clearing our current spectator\n");
SetSpectatingNPC(NULL);
}
}
}
//Msg("end\n");
// if we're still not spectating anything but we found at least marine, then that means we were spectating the last one in the list and need to set this
Expand Down
8 changes: 8 additions & 0 deletions src/game/server/swarm/asw_player.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,14 @@ class CASW_Player : public CBaseMultiplayerPlayer, public IASWPlayerAnimStateHel
virtual bool ASWAnim_CanMove();

// spectating
private:
bool m_bSpectatingInOrder = false;
int m_iSpectatingPrioMapping[ASW_NUM_MARINE_PROFILES]; // profile -> priority; smaller number is higher priority
public:
void UnsetSpectatingOrder() { m_bSpectatingInOrder = false; }
void SetSpectatingOrder( const int* iProfiles, int nProfiles );
bool CompareSpectatingPriority( CASW_Marine* pM1, CASW_Marine* pM2 ) const;
void SpectateNextMarineInOrder();
void SpectateNextMarine();
void SetSpectatingNPC( CASW_Inhabitable_NPC *pSpectating );
CASW_Inhabitable_NPC *GetSpectatingNPC() const;
Expand Down
Loading