950 lines
27 KiB
C++
950 lines
27 KiB
C++
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose: Generic in-game abuse reporting
|
||
|
//
|
||
|
// $NoKeywords: $
|
||
|
//=============================================================================//
|
||
|
|
||
|
#include "cbase.h"
|
||
|
#include "abuse_report_ui.h"
|
||
|
#include "econ/econ_controls.h"
|
||
|
#include "ienginevgui.h"
|
||
|
#include "vgui/ISurface.h"
|
||
|
#include <vgui_controls/TextEntry.h>
|
||
|
#include <vgui_controls/ComboBox.h>
|
||
|
#include <vgui_controls/RadioButton.h>
|
||
|
#include "vgui_bitmappanel.h"
|
||
|
#include "vgui_avatarimage.h"
|
||
|
#include "gc_clientsystem.h"
|
||
|
#include "econ/tool_items/tool_items.h"
|
||
|
#include "econ/econ_gcmessages.h"
|
||
|
#include "econ/confirm_dialog.h"
|
||
|
#include "tool_items/custom_texture_cache.h"
|
||
|
|
||
|
vgui::DHANDLE<CAbuseReportDlg> g_AbuseReportDlg;
|
||
|
|
||
|
CAbuseReportDlg::CAbuseReportDlg( vgui::Panel *parent, AbuseIncidentData_t *pIncidentData )
|
||
|
: EditablePanel( parent, "AbuseReportSubmitDialog" )
|
||
|
, m_pSubmitButton( NULL )
|
||
|
, m_pScreenShot( NULL )
|
||
|
, m_pScreenShotAttachCheckButton( NULL )
|
||
|
, m_pOffensiveImage( NULL )
|
||
|
, m_pDescriptionTextEntry( NULL )
|
||
|
, m_pPlayerLabel( NULL )
|
||
|
, m_pPlayerRadio( NULL )
|
||
|
, m_pGameServerRadio( NULL )
|
||
|
, m_pPlayerCombo( NULL )
|
||
|
, m_pAbuseContentLabel( NULL )
|
||
|
, m_pAbuseContentCombo( NULL )
|
||
|
, m_pAbuseTypeLabel( NULL )
|
||
|
, m_pAbuseTypeCombo( NULL )
|
||
|
, m_pScreenShotBitmap( NULL )
|
||
|
, m_pAvatarImage( NULL )
|
||
|
, m_pNoAvatarLabel( NULL )
|
||
|
, m_pCustomTextureImagePanel( NULL )
|
||
|
, m_pNoCustomTexturesLabel( NULL )
|
||
|
, m_pCustomTextureNextButton( NULL )
|
||
|
, m_pCustomTexturePrevButton( NULL )
|
||
|
, m_iUserImageIndex( 0 )
|
||
|
, m_pIncidentData( pIncidentData )
|
||
|
{
|
||
|
vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ClientScheme.res", "ClientScheme" );
|
||
|
SetScheme(scheme);
|
||
|
SetProportional( true );
|
||
|
//m_pContainer = new vgui::EditablePanel( this, "Container" );
|
||
|
|
||
|
Assert( g_AbuseReportDlg.Get() == NULL );
|
||
|
g_AbuseReportDlg.Set( this );
|
||
|
|
||
|
engine->ExecuteClientCmd("gameui_preventescape");
|
||
|
}
|
||
|
|
||
|
CAbuseReportDlg::~CAbuseReportDlg()
|
||
|
{
|
||
|
Assert( g_AbuseReportDlg.Get() == this );
|
||
|
if ( g_AbuseReportDlg.Get() == this )
|
||
|
{
|
||
|
engine->ExecuteClientCmd("gameui_allowescape");
|
||
|
g_AbuseReportDlg = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CAbuseReportDlg::OnCommand( const char *command )
|
||
|
{
|
||
|
if ( !Q_stricmp( command, "cancel" ) )
|
||
|
{
|
||
|
Close();
|
||
|
return;
|
||
|
}
|
||
|
if ( !Q_stricmp( command, "discard" ) )
|
||
|
{
|
||
|
Close();
|
||
|
g_AbuseReportMgr->DestroyIncidentData();
|
||
|
return;
|
||
|
}
|
||
|
if ( !Q_stricmp( command, "submit" ) )
|
||
|
{
|
||
|
OnSubmitReport();
|
||
|
return;
|
||
|
}
|
||
|
if ( !Q_stricmp( command, "nextcustomtexture" ) )
|
||
|
{
|
||
|
++m_iUserImageIndex;
|
||
|
UpdateCustomTextures();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( !Q_stricmp( command, "prevcustomtexture" ) )
|
||
|
{
|
||
|
--m_iUserImageIndex;
|
||
|
UpdateCustomTextures();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
void CAbuseReportDlg::MakeModal()
|
||
|
{
|
||
|
TFModalStack()->PushModal( this );
|
||
|
MakePopup();
|
||
|
MoveToFront();
|
||
|
SetKeyBoardInputEnabled( true );
|
||
|
SetMouseInputEnabled( true );
|
||
|
|
||
|
// !KLUDGE! Initially set the dialog to be hidden, so we can take a screenshot!
|
||
|
SetEnabled( m_pIncidentData != NULL );
|
||
|
//SetVisible( m_pIncidentData != NULL );
|
||
|
}
|
||
|
|
||
|
void CAbuseReportDlg::Close()
|
||
|
{
|
||
|
TFModalStack()->PopModal( this );
|
||
|
SetVisible( false );
|
||
|
MarkForDeletion();
|
||
|
}
|
||
|
|
||
|
const char *CAbuseReportDlg::GetResFilename()
|
||
|
{
|
||
|
return "Resource/UI/AbuseReportSubmitDialog.res";
|
||
|
//return "Resource/UI/QuickplayDialog.res";
|
||
|
}
|
||
|
|
||
|
void CAbuseReportDlg::PerformLayout()
|
||
|
{
|
||
|
BaseClass::PerformLayout();
|
||
|
|
||
|
// Center it, keeping requested size
|
||
|
int x, y, ww, wt, wide, tall;
|
||
|
vgui::surface()->GetWorkspaceBounds( x, y, ww, wt );
|
||
|
GetSize(wide, tall);
|
||
|
SetPos(x + ((ww - wide) / 2), y + ((wt - tall) / 2));
|
||
|
|
||
|
// @todo setup
|
||
|
}
|
||
|
|
||
|
class CCustomTextureImagePanel : public vgui::Panel
|
||
|
{
|
||
|
public:
|
||
|
CCustomTextureImagePanel( Panel *parent, const char *panelName ) : vgui::Panel( parent, panelName )
|
||
|
{
|
||
|
m_ugcHandle = 0;
|
||
|
}
|
||
|
|
||
|
uint64 m_ugcHandle;
|
||
|
|
||
|
virtual void Paint()
|
||
|
{
|
||
|
if ( m_ugcHandle == 0 )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
int iTextureHandle = GetCustomTextureGuiHandle( m_ugcHandle );
|
||
|
if ( iTextureHandle <= 0)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
vgui::surface()->DrawSetColor(COLOR_WHITE);
|
||
|
vgui::surface()->DrawSetTexture( iTextureHandle );
|
||
|
int iWide, iTall;
|
||
|
GetSize( iWide, iTall );
|
||
|
|
||
|
vgui::Vertex_t verts[4];
|
||
|
verts[0].Init( Vector2D( 0, 0 ), Vector2D( 0.0f, 0.0f ) );
|
||
|
verts[1].Init( Vector2D( iWide, 0 ), Vector2D( 1.0f, 0.0f ) );
|
||
|
verts[2].Init( Vector2D( iWide, iTall ), Vector2D( 1.0f, 1.0f ) );
|
||
|
verts[3].Init( Vector2D( 0, iTall ), Vector2D( 0.0f, 1.0f ) );
|
||
|
|
||
|
vgui::surface()->DrawTexturedPolygon( 4, verts );
|
||
|
vgui::surface()->DrawSetColor(COLOR_WHITE);
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
class CAbuseReportScreenShotPanel : public CBitmapPanel
|
||
|
{
|
||
|
public:
|
||
|
CAbuseReportScreenShotPanel( CAbuseReportDlg *pDlg, const char *panelName )
|
||
|
: CBitmapPanel( pDlg, panelName )
|
||
|
, m_pDlg( pDlg )
|
||
|
{}
|
||
|
|
||
|
CAbuseReportDlg *m_pDlg;
|
||
|
|
||
|
virtual void Paint()
|
||
|
{
|
||
|
CBitmapPanel::Paint();
|
||
|
|
||
|
const AbuseIncidentData_t::PlayerData_t *p = m_pDlg->GetAccusedPlayerPtr();
|
||
|
if ( p == NULL || !p->m_bRenderBoundsValid )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
int w, t;
|
||
|
GetSize( w, t );
|
||
|
|
||
|
int x0 = int( p->m_screenBoundsMin.x * (float)w );
|
||
|
int y0 = int( p->m_screenBoundsMin.y * (float)t );
|
||
|
int x1 = int( p->m_screenBoundsMax.x * (float)w );
|
||
|
int y1 = int( p->m_screenBoundsMax.y * (float)t );
|
||
|
|
||
|
vgui::surface()->DrawSetColor( Color(200, 10, 10, 200 ) );
|
||
|
vgui::surface()->DrawOutlinedRect( x0, y0, x1, y1 );
|
||
|
vgui::surface()->DrawSetColor( COLOR_WHITE );
|
||
|
}
|
||
|
};
|
||
|
|
||
|
void CAbuseReportDlg::ApplySchemeSettings( vgui::IScheme *pScheme )
|
||
|
{
|
||
|
EditablePanel::ApplySchemeSettings( pScheme );
|
||
|
|
||
|
m_pScreenShotBitmap = new CAbuseReportScreenShotPanel( this, "ScreenShotBitmap" );
|
||
|
m_pCustomTextureImagePanel = new CCustomTextureImagePanel( this, "CustomTextureImage" );
|
||
|
|
||
|
LoadControlSettings( GetResFilename() );
|
||
|
|
||
|
m_pPlayerRadio = dynamic_cast<vgui::RadioButton *>(FindChildByName( "PlayerRadio", true ));
|
||
|
Assert( m_pPlayerRadio );
|
||
|
if ( m_pPlayerRadio )
|
||
|
{
|
||
|
m_pPlayerRadio->SetVisible( m_pIncidentData->m_bCanReportGameServer );
|
||
|
}
|
||
|
|
||
|
m_pGameServerRadio = dynamic_cast<vgui::RadioButton *>(FindChildByName( "GameServerRadio", true ));
|
||
|
Assert( m_pGameServerRadio );
|
||
|
if ( m_pGameServerRadio )
|
||
|
{
|
||
|
m_pGameServerRadio->SetVisible( m_pIncidentData->m_bCanReportGameServer );
|
||
|
}
|
||
|
|
||
|
m_pPlayerLabel = FindChildByName( "PlayerLabel", true );
|
||
|
Assert( m_pPlayerLabel );
|
||
|
|
||
|
m_pScreenShotAttachCheckButton = dynamic_cast<vgui::CheckButton *>(FindChildByName( "ScreenShotAttachCheckButton", true ));
|
||
|
Assert( m_pScreenShotAttachCheckButton );
|
||
|
if ( m_pScreenShotAttachCheckButton )
|
||
|
{
|
||
|
m_pScreenShotAttachCheckButton->SetSelected( true );
|
||
|
}
|
||
|
|
||
|
m_pSubmitButton = dynamic_cast<vgui::Button *>(FindChildByName( "SubmitButton", true ));
|
||
|
Assert( m_pSubmitButton );
|
||
|
|
||
|
m_pDescriptionTextEntry = dynamic_cast<vgui::TextEntry *>(FindChildByName( "DescriptionTextEntry", true ));
|
||
|
Assert( m_pDescriptionTextEntry );
|
||
|
if ( m_pDescriptionTextEntry )
|
||
|
{
|
||
|
m_pDescriptionTextEntry->SetMultiline( true );
|
||
|
}
|
||
|
|
||
|
m_pAvatarImage = dynamic_cast<CAvatarImagePanel *>(FindChildByName( "AvatarImage", true ));
|
||
|
Assert( m_pAvatarImage );
|
||
|
|
||
|
m_pNoAvatarLabel = FindChildByName( "NoAvatarLabel", true );
|
||
|
Assert( m_pNoAvatarLabel );
|
||
|
|
||
|
m_pNoCustomTexturesLabel = FindChildByName( "NoCustomTexturesLabel", true );
|
||
|
Assert( m_pNoCustomTexturesLabel );
|
||
|
|
||
|
m_pCustomTextureNextButton = dynamic_cast<vgui::Button *>(FindChildByName( "CustomTextureNextButton", true ));
|
||
|
Assert( m_pCustomTextureNextButton );
|
||
|
|
||
|
m_pCustomTexturePrevButton = dynamic_cast<vgui::Button *>(FindChildByName( "CustomTexturePrevButton", true ));
|
||
|
Assert( m_pCustomTexturePrevButton );
|
||
|
|
||
|
m_pPlayerCombo = dynamic_cast<vgui::ComboBox *>(FindChildByName( "PlayerComboBox", true ));
|
||
|
Assert( m_pPlayerCombo );
|
||
|
|
||
|
m_pAbuseContentLabel = FindChildByName( "AbuseContentLabel", true );
|
||
|
Assert( m_pAbuseContentLabel );
|
||
|
|
||
|
m_pAbuseContentCombo = dynamic_cast<vgui::ComboBox *>(FindChildByName( "AbuseContentComboBox", true ));
|
||
|
Assert( m_pAbuseContentCombo );
|
||
|
if ( m_pAbuseContentCombo )
|
||
|
{
|
||
|
m_pAbuseContentCombo->AddItem( "#AbuseReport_SelectOne", new KeyValues( "AbuseContent", "code", k_EAbuseReportContentNoSelection ) );
|
||
|
m_pAbuseContentCombo->AddItem( "#AbuseReport_ContentAvatarImage", new KeyValues( "AbuseContent", "code", k_EAbuseReportContentAvatarImage ) );
|
||
|
m_pAbuseContentCombo->AddItem( "#AbuseReport_ContentPlayerName", new KeyValues( "AbuseContent", "code", k_EAbuseReportContentPersonaName ) );
|
||
|
m_pAbuseContentCombo->AddItem( "#AbuseReport_ContentItemDecal", new KeyValues( "AbuseContent", "code", k_EAbuseReportContentUGCImage ) );
|
||
|
m_pAbuseContentCombo->AddItem( "#AbuseReport_ContentChatText", new KeyValues( "AbuseContent", "code", k_EAbuseReportContentComments ) );
|
||
|
m_pAbuseContentCombo->AddItem( "#AbuseReport_ContentCheating", new KeyValues( "AbuseContent", "code", k_EAbuseReportContentCheating ) );
|
||
|
m_pAbuseContentCombo->AddItem( "#AbuseReport_ContentOther", new KeyValues( "AbuseContent", "code", k_EAbuseReportContentUnspecified ) );
|
||
|
m_pAbuseContentCombo->SilentActivateItemByRow( 0 );
|
||
|
m_pAbuseContentCombo->SetNumberOfEditLines( m_pAbuseContentCombo->GetItemCount() );
|
||
|
}
|
||
|
|
||
|
m_pAbuseTypeLabel = FindChildByName( "AbuseTypeLabel", true );
|
||
|
Assert( m_pAbuseTypeLabel );
|
||
|
|
||
|
m_pAbuseTypeCombo = dynamic_cast<vgui::ComboBox *>(FindChildByName( "AbuseTypeComboBox", true ));
|
||
|
Assert( m_pAbuseTypeCombo );
|
||
|
|
||
|
Assert( m_pScreenShotBitmap );
|
||
|
if ( m_pScreenShotBitmap && m_pIncidentData->m_bitmapScreenshot.IsValid() )
|
||
|
{
|
||
|
m_pScreenShotBitmap->SetBitmap( m_pIncidentData->m_bitmapScreenshot );
|
||
|
}
|
||
|
|
||
|
PopulatePlayerList();
|
||
|
SetIsAccusingGameServer( false );
|
||
|
|
||
|
SetEnabled( true );
|
||
|
SetVisible( true );
|
||
|
}
|
||
|
|
||
|
bool CAbuseReportDlg::IsAccusingGameServer()
|
||
|
{
|
||
|
return m_pIncidentData && m_pIncidentData->m_bCanReportGameServer && m_pGameServerRadio && m_pGameServerRadio->IsSelected();
|
||
|
}
|
||
|
|
||
|
EAbuseReportContentType CAbuseReportDlg::GetAbuseContentType()
|
||
|
{
|
||
|
if ( m_pAbuseContentCombo == NULL || IsAccusingGameServer() )
|
||
|
{
|
||
|
Assert( m_pAbuseContentCombo );
|
||
|
return k_EAbuseReportContentNoSelection;
|
||
|
}
|
||
|
KeyValues *pUserData = m_pAbuseContentCombo->GetActiveItemUserData();
|
||
|
if ( pUserData == NULL )
|
||
|
{
|
||
|
return k_EAbuseReportContentNoSelection;
|
||
|
}
|
||
|
return (EAbuseReportContentType)pUserData->GetInt( "code", k_EAbuseReportContentNoSelection );
|
||
|
}
|
||
|
|
||
|
EAbuseReportType CAbuseReportDlg::GetAbuseType()
|
||
|
{
|
||
|
if ( m_pAbuseTypeCombo == NULL || IsAccusingGameServer() )
|
||
|
{
|
||
|
Assert( m_pAbuseTypeCombo );
|
||
|
return k_EAbuseReportTypeNoSelection;
|
||
|
}
|
||
|
KeyValues *pUserData = m_pAbuseTypeCombo->GetActiveItemUserData();
|
||
|
if ( pUserData == NULL )
|
||
|
{
|
||
|
return k_EAbuseReportTypeNoSelection;
|
||
|
}
|
||
|
return (EAbuseReportType)pUserData->GetInt( "code", k_EAbuseReportTypeNoSelection );
|
||
|
}
|
||
|
|
||
|
CUtlString CAbuseReportDlg::GetAbuseDescription()
|
||
|
{
|
||
|
char buf[ 1024 ] = "";
|
||
|
if ( m_pDescriptionTextEntry )
|
||
|
{
|
||
|
m_pDescriptionTextEntry->GetText( buf, ARRAYSIZE(buf) );
|
||
|
}
|
||
|
|
||
|
return CUtlString( buf );
|
||
|
}
|
||
|
|
||
|
int CAbuseReportDlg::GetAccusedPlayerIndex()
|
||
|
{
|
||
|
// If accusing a game server, then there's no player
|
||
|
if ( IsAccusingGameServer() )
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if ( m_pPlayerCombo == NULL )
|
||
|
{
|
||
|
Assert( m_pPlayerCombo );
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
// Item 0 is the "<select one>" item
|
||
|
return m_pPlayerCombo->GetActiveItem() - 1;
|
||
|
}
|
||
|
|
||
|
const AbuseIncidentData_t::PlayerData_t *CAbuseReportDlg::GetAccusedPlayerPtr()
|
||
|
{
|
||
|
int iPlayerIndex = GetAccusedPlayerIndex();
|
||
|
if ( iPlayerIndex < 0 )
|
||
|
return NULL;
|
||
|
return &m_pIncidentData->m_vecPlayers[ iPlayerIndex ];
|
||
|
}
|
||
|
|
||
|
bool CAbuseReportDlg::GetAttachScreenShot()
|
||
|
{
|
||
|
if ( m_pScreenShotAttachCheckButton == NULL )
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
if ( !m_pScreenShotAttachCheckButton->IsVisible() )
|
||
|
{
|
||
|
// We hide the checkbutton when the option is not applicable
|
||
|
return false;
|
||
|
}
|
||
|
return m_pScreenShotAttachCheckButton->IsSelected();
|
||
|
}
|
||
|
|
||
|
void CAbuseReportDlg::PopulatePlayerList()
|
||
|
{
|
||
|
if ( m_pIncidentData == NULL || m_pPlayerCombo == NULL )
|
||
|
{
|
||
|
Assert( m_pIncidentData );
|
||
|
Assert( m_pPlayerCombo );
|
||
|
return;
|
||
|
}
|
||
|
m_pPlayerCombo->RemoveAll();
|
||
|
m_pPlayerCombo->AddItem( "#AbuseReport_SelectOne", NULL );
|
||
|
for ( int i = 0 ; i < m_pIncidentData->m_vecPlayers.Count() ; ++i )
|
||
|
{
|
||
|
AbuseIncidentData_t::PlayerData_t *p = &m_pIncidentData->m_vecPlayers[i];
|
||
|
m_pPlayerCombo->AddItem( p->m_sPersona, NULL );
|
||
|
}
|
||
|
m_pPlayerCombo->SilentActivateItemByRow( 0 );
|
||
|
|
||
|
m_pPlayerCombo->SetNumberOfEditLines( MIN( m_pPlayerCombo->GetItemCount()+1, 12 ) );
|
||
|
}
|
||
|
|
||
|
void CAbuseReportDlg::UpdateSubmitButton()
|
||
|
{
|
||
|
if ( !m_pSubmitButton )
|
||
|
{
|
||
|
Assert( m_pSubmitButton );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
bool bEnable = false;
|
||
|
if ( IsAccusingGameServer() )
|
||
|
{
|
||
|
bEnable = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
EAbuseReportContentType eContent = GetAbuseContentType();
|
||
|
const AbuseIncidentData_t::PlayerData_t *pAccused = GetAccusedPlayerPtr();
|
||
|
if (
|
||
|
eContent >= 0
|
||
|
&& GetAbuseType() >= 0
|
||
|
&& pAccused != NULL )
|
||
|
{
|
||
|
bEnable = true;
|
||
|
if ( eContent == k_EAbuseReportContentAvatarImage && pAccused->m_iSteamAvatarIndex <= 0 )
|
||
|
{
|
||
|
// Cannot accuse somebody of having a bad avatar image, if they
|
||
|
// don't have one set
|
||
|
bEnable = false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if ( GetAbuseDescription().IsEmpty() )
|
||
|
{
|
||
|
bEnable = false;
|
||
|
}
|
||
|
|
||
|
m_pSubmitButton->SetEnabled( bEnable );
|
||
|
}
|
||
|
|
||
|
void CAbuseReportDlg::ContentTypeChanged()
|
||
|
{
|
||
|
|
||
|
// Save current abuse type. We want to keep it the same,
|
||
|
// if possible
|
||
|
EAbuseReportType abuseType = GetAbuseType();
|
||
|
EAbuseReportContentType contentType = GetAbuseContentType();
|
||
|
|
||
|
// Show/hide screen shot / image select
|
||
|
bool bShowScreenshot = false;
|
||
|
bool bShowAttach = false;
|
||
|
switch ( contentType )
|
||
|
{
|
||
|
default:
|
||
|
Assert( false );
|
||
|
case k_EAbuseReportContentNoSelection:
|
||
|
case k_EAbuseReportContentPersonaName:
|
||
|
bShowScreenshot = true;
|
||
|
bShowAttach = false;
|
||
|
break;
|
||
|
|
||
|
case k_EAbuseReportContentUnspecified:
|
||
|
case k_EAbuseReportContentComments:
|
||
|
case k_EAbuseReportContentCheating:
|
||
|
bShowScreenshot = true;
|
||
|
bShowAttach = true;
|
||
|
break;
|
||
|
|
||
|
case k_EAbuseReportContentAvatarImage:
|
||
|
case k_EAbuseReportContentUGCImage:
|
||
|
bShowScreenshot = false;
|
||
|
bShowAttach = false;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
bShowScreenshot = bShowScreenshot && m_pIncidentData->m_bitmapScreenshot.IsValid();
|
||
|
|
||
|
// Make sure we have everything we need to upload a screenshot
|
||
|
bShowAttach = bShowAttach
|
||
|
&& bShowScreenshot
|
||
|
&& ( GetAccusedPlayerIndex() >= 0 )
|
||
|
&& m_pIncidentData->m_bufScreenshotFileData.TellPut() > 0
|
||
|
&& steamapicontext
|
||
|
&& ( steamapicontext->SteamUtils() != NULL )
|
||
|
&& ( steamapicontext->SteamRemoteStorage() != NULL );
|
||
|
|
||
|
if ( m_pScreenShotBitmap )
|
||
|
{
|
||
|
m_pScreenShotBitmap->SetVisible( bShowScreenshot );
|
||
|
}
|
||
|
if ( m_pScreenShotAttachCheckButton )
|
||
|
{
|
||
|
m_pScreenShotAttachCheckButton->SetVisible( bShowAttach );
|
||
|
}
|
||
|
|
||
|
UpdateAvatarImage();
|
||
|
UpdateCustomTextures();
|
||
|
|
||
|
// Populate abuse type
|
||
|
if ( m_pAbuseTypeCombo )
|
||
|
{
|
||
|
|
||
|
// If the combo box was invisible, then they didn't really make a purposeful decision
|
||
|
if ( !m_pAbuseTypeCombo->IsVisible() )
|
||
|
{
|
||
|
abuseType = k_EAbuseReportTypeNoSelection;
|
||
|
}
|
||
|
m_pAbuseTypeCombo->RemoveAll();
|
||
|
switch ( contentType )
|
||
|
{
|
||
|
default:
|
||
|
Assert( false );
|
||
|
case k_EAbuseReportContentNoSelection:
|
||
|
m_pAbuseTypeCombo->SetVisible( false );
|
||
|
abuseType = k_EAbuseReportTypeNoSelection;
|
||
|
m_pAbuseTypeCombo->AddItem( "#AbuseReport_SelectOne", new KeyValues( "AbuseType", "code", k_EAbuseReportTypeNoSelection ) );
|
||
|
break;
|
||
|
|
||
|
case k_EAbuseReportContentCheating:
|
||
|
m_pAbuseTypeCombo->SetVisible( false );
|
||
|
abuseType = k_EAbuseReportTypeCheating;
|
||
|
m_pAbuseTypeCombo->AddItem( "#AbuseReport_TypeCheating", new KeyValues( "AbuseType", "code", k_EAbuseReportTypeCheating ) );
|
||
|
break;
|
||
|
|
||
|
case k_EAbuseReportContentUnspecified:
|
||
|
case k_EAbuseReportContentComments:
|
||
|
case k_EAbuseReportContentPersonaName:
|
||
|
case k_EAbuseReportContentAvatarImage:
|
||
|
case k_EAbuseReportContentUGCImage:
|
||
|
m_pAbuseTypeCombo->SetVisible( true );
|
||
|
m_pAbuseTypeCombo->AddItem( "#AbuseReport_SelectOne", new KeyValues( "AbuseType", "code", k_EAbuseReportTypeNoSelection ) );
|
||
|
m_pAbuseTypeCombo->AddItem( "#AbuseReport_TypeSpam", new KeyValues( "AbuseType", "code", k_EAbuseReportTypeSpamming ) );
|
||
|
m_pAbuseTypeCombo->AddItem( "#AbuseReport_TypeAdvertisement", new KeyValues( "AbuseType", "code", k_EAbuseReportTypeAdvertisement ) );
|
||
|
m_pAbuseTypeCombo->AddItem( "#AbuseReport_TypeLanguage", new KeyValues( "AbuseType", "code", k_EAbuseReportTypeLanguage ) );
|
||
|
m_pAbuseTypeCombo->AddItem( "#AbuseReport_TypeAdultContent", new KeyValues( "AbuseType", "code", k_EAbuseReportTypeAdultContent ) );
|
||
|
m_pAbuseTypeCombo->AddItem( "#AbuseReport_TypeHarassment", new KeyValues( "AbuseType", "code", k_EAbuseReportTypeHarassment ) );
|
||
|
m_pAbuseTypeCombo->AddItem( "#AbuseReport_TypeProhibited", new KeyValues( "AbuseType", "code", k_EAbuseReportTypeProhibited ) );
|
||
|
m_pAbuseTypeCombo->AddItem( "#AbuseReport_TypeSpoofing", new KeyValues( "AbuseType", "code", k_EAbuseReportTypeSpoofing ) );
|
||
|
//m_pAbuseTypeCombo->AddItem( "#AbuseReport_TypeCheating", new KeyValues( "AbuseType", "code", k_EAbuseReportTypeCheating ) );
|
||
|
m_pAbuseTypeCombo->AddItem( "#AbuseReport_TypeInappropriate", new KeyValues( "AbuseType", "code", k_EAbuseReportTypeInappropriate ) );
|
||
|
m_pAbuseTypeCombo->AddItem( "#AbuseReport_TypeOther", new KeyValues( "AbuseType", "code", k_EAbuseReportTypeUnspecified ) );
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Now select the proper row
|
||
|
int sel = 0;
|
||
|
for ( int i = 0 ; i < m_pAbuseTypeCombo->GetItemCount() ; ++i ) {
|
||
|
if ( m_pAbuseTypeCombo->GetItemUserData(i)->GetInt("code") == abuseType )
|
||
|
{
|
||
|
sel = i;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
m_pAbuseTypeCombo->SilentActivateItemByRow( sel );
|
||
|
m_pAbuseTypeCombo->SetNumberOfEditLines( m_pAbuseTypeCombo->GetItemCount() );
|
||
|
if ( m_pAbuseTypeLabel )
|
||
|
{
|
||
|
m_pAbuseTypeLabel->SetVisible( m_pAbuseTypeCombo->IsVisible() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
UpdateSubmitButton();
|
||
|
}
|
||
|
|
||
|
void CAbuseReportDlg::OnRadioButtonChecked( vgui::Panel *panel )
|
||
|
{
|
||
|
if ( panel == m_pPlayerRadio )
|
||
|
{
|
||
|
SetIsAccusingGameServer( false );
|
||
|
}
|
||
|
else if ( panel == m_pGameServerRadio )
|
||
|
{
|
||
|
SetIsAccusingGameServer( true );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Assert( !"Clicked on unknown radio" );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CAbuseReportDlg::SetIsAccusingGameServer( bool bAccuseGameServer )
|
||
|
{
|
||
|
if ( m_pGameServerRadio && m_pGameServerRadio->IsSelected() != bAccuseGameServer )
|
||
|
{
|
||
|
m_pGameServerRadio->SetSelected( bAccuseGameServer );
|
||
|
}
|
||
|
if ( m_pPlayerRadio && m_pPlayerRadio->IsSelected() == bAccuseGameServer)
|
||
|
{
|
||
|
m_pPlayerRadio->SetSelected( !bAccuseGameServer );
|
||
|
}
|
||
|
if ( m_pPlayerLabel )
|
||
|
{
|
||
|
m_pPlayerLabel->SetVisible( !bAccuseGameServer );
|
||
|
}
|
||
|
if ( m_pPlayerCombo )
|
||
|
{
|
||
|
m_pPlayerCombo->SetVisible( !bAccuseGameServer );
|
||
|
}
|
||
|
|
||
|
PlayerChanged();
|
||
|
}
|
||
|
|
||
|
void CAbuseReportDlg::PlayerChanged()
|
||
|
{
|
||
|
m_iUserImageIndex = 0;
|
||
|
|
||
|
bool bShow = ( GetAccusedPlayerIndex() >= 0 );
|
||
|
if ( m_pAbuseContentCombo != NULL )
|
||
|
{
|
||
|
m_pAbuseContentCombo->SetVisible( bShow );
|
||
|
}
|
||
|
if ( m_pAbuseContentLabel != NULL )
|
||
|
{
|
||
|
m_pAbuseContentLabel->SetVisible( bShow );
|
||
|
}
|
||
|
|
||
|
ContentTypeChanged();
|
||
|
}
|
||
|
|
||
|
void CAbuseReportDlg::UpdateAvatarImage()
|
||
|
{
|
||
|
if ( m_pAvatarImage == NULL || m_pNoAvatarLabel == NULL )
|
||
|
{
|
||
|
Assert( m_pAvatarImage );
|
||
|
Assert( m_pNoAvatarLabel );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const AbuseIncidentData_t::PlayerData_t *pAccused = GetAccusedPlayerPtr();
|
||
|
if ( GetAbuseContentType() == k_EAbuseReportContentAvatarImage && pAccused != NULL )
|
||
|
{
|
||
|
if ( pAccused->m_iSteamAvatarIndex > 0 )
|
||
|
{
|
||
|
m_pAvatarImage->SetShouldDrawFriendIcon( false );
|
||
|
m_pAvatarImage->SetPlayer( pAccused->m_steamID, k_EAvatarSize184x184 );
|
||
|
|
||
|
m_pAvatarImage->SetVisible( true );
|
||
|
m_pNoAvatarLabel->SetVisible( false );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pAvatarImage->SetVisible( false );
|
||
|
m_pNoAvatarLabel->SetVisible( true );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pAvatarImage->SetVisible( false );
|
||
|
m_pNoAvatarLabel->SetVisible( false );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CAbuseReportDlg::UpdateCustomTextures()
|
||
|
{
|
||
|
if ( m_pCustomTextureImagePanel == NULL || m_pNoCustomTexturesLabel == NULL || m_pCustomTextureNextButton == NULL || m_pCustomTexturePrevButton == NULL )
|
||
|
{
|
||
|
Assert( m_pCustomTextureImagePanel );
|
||
|
Assert( m_pNoCustomTexturesLabel );
|
||
|
Assert( m_pCustomTextureNextButton );
|
||
|
Assert( m_pCustomTexturePrevButton );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const AbuseIncidentData_t::PlayerData_t *pAccused = GetAccusedPlayerPtr();
|
||
|
bool bShowScrollButtons = false;
|
||
|
if ( GetAbuseContentType() == k_EAbuseReportContentUGCImage && pAccused != NULL )
|
||
|
{
|
||
|
int iSelectedCustomImage = GetSelectedCustomImage();
|
||
|
|
||
|
if ( iSelectedCustomImage >= 0 )
|
||
|
{
|
||
|
|
||
|
// Currently the only thing we support...
|
||
|
Assert( pAccused->m_vecImages[ iSelectedCustomImage].m_eType == AbuseIncidentData_t::k_PlayerImageType_UGC );
|
||
|
|
||
|
m_pCustomTextureImagePanel->m_ugcHandle = pAccused->m_vecImages[ iSelectedCustomImage].m_hUGCHandle;
|
||
|
|
||
|
m_pCustomTextureImagePanel->SetVisible( true );
|
||
|
m_pNoCustomTexturesLabel->SetVisible( false );
|
||
|
|
||
|
int n = pAccused->m_vecImages.Count();
|
||
|
if ( n > 1 )
|
||
|
{
|
||
|
bShowScrollButtons = true;
|
||
|
m_pCustomTextureNextButton->SetEnabled( iSelectedCustomImage < n-1 );
|
||
|
m_pCustomTexturePrevButton->SetEnabled( iSelectedCustomImage > 0 );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pCustomTextureImagePanel->SetVisible( false );
|
||
|
m_pNoCustomTexturesLabel->SetVisible( true );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_pCustomTextureImagePanel->SetVisible( false );
|
||
|
m_pNoCustomTexturesLabel->SetVisible( false );
|
||
|
}
|
||
|
m_pCustomTextureNextButton->SetVisible( bShowScrollButtons );
|
||
|
m_pCustomTexturePrevButton->SetVisible( bShowScrollButtons );
|
||
|
}
|
||
|
|
||
|
int CAbuseReportDlg::GetSelectedCustomImage()
|
||
|
{
|
||
|
if ( GetAbuseContentType() != k_EAbuseReportContentUGCImage )
|
||
|
{
|
||
|
m_iUserImageIndex = 0;
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
const AbuseIncidentData_t::PlayerData_t *pAccused = GetAccusedPlayerPtr();
|
||
|
if ( pAccused == NULL )
|
||
|
{
|
||
|
m_iUserImageIndex = 0;
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
int n = pAccused->m_vecImages.Count();
|
||
|
if ( n < 1 )
|
||
|
{
|
||
|
m_iUserImageIndex = 0;
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
// Wrap currently selected index
|
||
|
m_iUserImageIndex = ( m_iUserImageIndex + n*10 ) % n;
|
||
|
|
||
|
// Return it
|
||
|
return m_iUserImageIndex;
|
||
|
}
|
||
|
|
||
|
void CAbuseReportDlg::OnTextChanged( vgui::Panel *panel )
|
||
|
{
|
||
|
if ( panel == m_pPlayerCombo )
|
||
|
{
|
||
|
PlayerChanged();
|
||
|
}
|
||
|
else if ( panel == m_pAbuseContentCombo )
|
||
|
{
|
||
|
ContentTypeChanged();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
UpdateSubmitButton();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Job to do the async work of submitting the report
|
||
|
//-----------------------------------------------------------------------------
|
||
|
class CSubmitAbuseReportJob : public GCSDK::CGCClientJob
|
||
|
{
|
||
|
public:
|
||
|
bool m_bGameServer;
|
||
|
|
||
|
|
||
|
CSubmitAbuseReportJob( )
|
||
|
: GCSDK::CGCClientJob( GCClientSystem()->GetGCClient() )
|
||
|
{
|
||
|
m_bGameServer = false;
|
||
|
}
|
||
|
|
||
|
virtual bool BYieldingRunGCJob()
|
||
|
{
|
||
|
EResult result = RunJob();
|
||
|
|
||
|
// Tear down our dialogs
|
||
|
CloseWaitingDialog();
|
||
|
|
||
|
CAbuseReportDlg *pDlg = g_AbuseReportDlg.Get();
|
||
|
if ( pDlg )
|
||
|
{
|
||
|
pDlg->Close();
|
||
|
pDlg = NULL;
|
||
|
}
|
||
|
|
||
|
// And destroy the queued report!
|
||
|
g_AbuseReportMgr->DestroyIncidentData();
|
||
|
|
||
|
// now show a dialog box explaining the outcome
|
||
|
switch ( result )
|
||
|
{
|
||
|
case k_EResultOK:
|
||
|
ShowMessageBox( "#AbuseReport_SucceededTitle", "#AbuseReport_SucceededMessage", "#GameUI_OK" );
|
||
|
break;
|
||
|
|
||
|
case k_EResultLimitExceeded:
|
||
|
ShowMessageBox(
|
||
|
"#AbuseReport_TooMuchFailedTitle",
|
||
|
m_bGameServer ? "#AbuseReport_TooMuchFailedMessageGameServer" : "#AbuseReport_TooMuchFailedMessage",
|
||
|
"#GameUI_OK"
|
||
|
);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
ShowMessageBox( "#AbuseReport_GenericFailureTitle", "#AbuseReport_GenericFailureMessage", "#GameUI_OK" );
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
EResult RunJob()
|
||
|
{
|
||
|
CAbuseReportDlg *pDlg = g_AbuseReportDlg.Get();
|
||
|
if ( pDlg == NULL )
|
||
|
{
|
||
|
return k_EResultFail;
|
||
|
}
|
||
|
m_bGameServer = pDlg->IsAccusingGameServer();
|
||
|
EAbuseReportContentType eContentSelected = pDlg->GetAbuseContentType();
|
||
|
EAbuseReportContentType eContentReported = eContentSelected;
|
||
|
EAbuseReportType eAbuseType = pDlg->GetAbuseType();
|
||
|
const AbuseIncidentData_t::PlayerData_t *pAccused = pDlg->GetAccusedPlayerPtr();
|
||
|
const AbuseIncidentData_t *pIncidentData = g_AbuseReportMgr->GetIncidentData();
|
||
|
CUtlString sAbuseDescription = pDlg->GetAbuseDescription();
|
||
|
netadr_t adrGameServer = pIncidentData->m_adrGameServer;
|
||
|
CSteamID steamIDGameServer = pIncidentData->m_steamIDGameServer;
|
||
|
uint64 gid = 0;
|
||
|
|
||
|
// Check if we should upload the screenshot
|
||
|
if ( pDlg->GetAttachScreenShot() && steamapicontext && steamapicontext->SteamUtils() && steamapicontext->SteamRemoteStorage() )
|
||
|
{
|
||
|
|
||
|
// Write the local copy of the file
|
||
|
if ( !steamapicontext->SteamRemoteStorage()->FileWrite( CAbuseReportManager::k_rchScreenShotFilename, pIncidentData->m_bufScreenshotFileData.Base(), pIncidentData->m_bufScreenshotFileData.TellPut() ) )
|
||
|
{
|
||
|
Warning( "Failed to save local cloud copy of %s\n", CAbuseReportManager::k_rchScreenShotFilename );
|
||
|
return k_EResultFail;
|
||
|
}
|
||
|
|
||
|
// Share it. This initiates the upload to cloud
|
||
|
Msg( "Starting upload of %s to UFS....\n", CAbuseReportManager::k_rchScreenShotFilename );
|
||
|
SteamAPICall_t hFileShareApiCall = steamapicontext->SteamRemoteStorage()->FileShare( CAbuseReportManager::k_rchScreenShotFilename );
|
||
|
if ( hFileShareApiCall == k_uAPICallInvalid )
|
||
|
{
|
||
|
Warning( "Failed to share %s\n", CAbuseReportManager::k_rchScreenShotFilename );
|
||
|
return k_EResultFail;
|
||
|
}
|
||
|
|
||
|
// Check if we're busy
|
||
|
bool bFailed;
|
||
|
RemoteStorageFileShareResult_t result;
|
||
|
while ( !steamapicontext->SteamUtils()->GetAPICallResult(hFileShareApiCall,
|
||
|
&result, sizeof(result), RemoteStorageFileShareResult_t::k_iCallback, &bFailed) )
|
||
|
{
|
||
|
BYield();
|
||
|
}
|
||
|
|
||
|
// Clear pointer, it could have been destroyed while we were yielding, make sure we don't reference it
|
||
|
pDlg = NULL;
|
||
|
|
||
|
if ( bFailed || result.m_eResult != k_EResultOK )
|
||
|
{
|
||
|
Warning( "Failed to share %s; result code %d\n", CAbuseReportManager::k_rchScreenShotFilename, result.m_eResult );
|
||
|
return result.m_eResult;
|
||
|
}
|
||
|
|
||
|
Msg( "%s shared to UGC OK\n", CAbuseReportManager::k_rchScreenShotFilename );
|
||
|
gid = result.m_hFile;
|
||
|
|
||
|
// SWitch the content type being reported, so the support tool will know what to
|
||
|
// do with the GID.
|
||
|
eContentReported = k_EAbuseReportContentActorUGCImage;
|
||
|
}
|
||
|
else if ( eContentSelected == k_EAbuseReportContentUGCImage )
|
||
|
{
|
||
|
Assert( !m_bGameServer );
|
||
|
int iImageindex = pDlg->GetSelectedCustomImage();
|
||
|
Assert( iImageindex >= 0 );
|
||
|
gid = pAccused->m_vecImages[iImageindex].m_hUGCHandle;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Fill out the report message
|
||
|
//
|
||
|
GCSDK::CProtoBufMsg<CMsgGCReportAbuse> msg( k_EMsgGC_ReportAbuse );
|
||
|
if ( m_bGameServer )
|
||
|
{
|
||
|
msg.Body().set_target_steam_id( steamIDGameServer.ConvertToUint64() );
|
||
|
msg.Body().set_target_game_server_ip( adrGameServer.GetIPHostByteOrder() );
|
||
|
msg.Body().set_target_game_server_port( adrGameServer.GetPort() );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
msg.Body().set_target_steam_id( pAccused->m_steamID.ConvertToUint64() );
|
||
|
msg.Body().set_content_type( eContentReported );
|
||
|
msg.Body().set_abuse_type( eAbuseType );
|
||
|
}
|
||
|
msg.Body().set_description( sAbuseDescription );
|
||
|
if (gid != 0 )
|
||
|
{
|
||
|
msg.Body().set_gid( gid );
|
||
|
}
|
||
|
|
||
|
// Send the message to the GC, and await the reply
|
||
|
GCSDK::CProtoBufMsg<CMsgGCReportAbuseResponse> msgReply;
|
||
|
if ( !BYldSendMessageAndGetReply( msg, 10, &msgReply, k_EMsgGC_ReportAbuseResponse ) )
|
||
|
{
|
||
|
Warning( "Abuse report failed: Did not get reply from GC\n" );
|
||
|
return k_EResultTimeout;
|
||
|
}
|
||
|
|
||
|
EResult result = (EResult)msgReply.Body().result();
|
||
|
if ( result != k_EResultOK )
|
||
|
{
|
||
|
Warning( "Abuse report failed with failure code %d. %s\n", result, msgReply.Body().error_message().c_str() );
|
||
|
}
|
||
|
|
||
|
// OK
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
void CAbuseReportDlg::OnSubmitReport()
|
||
|
{
|
||
|
// throw up a waiting dialog
|
||
|
SetEnabled( false );
|
||
|
ShowWaitingDialog( new CGenericWaitingDialog( this ), "#AbuseReport_Busy", true, false, 0.0f );
|
||
|
|
||
|
// We need to be in the global singleton handle, because that's how the job knows
|
||
|
// to get to us (and how it knows if we've died)!
|
||
|
Assert( g_AbuseReportDlg.Get() == this );
|
||
|
|
||
|
// Start a job
|
||
|
CSubmitAbuseReportJob *pJob = new CSubmitAbuseReportJob();
|
||
|
pJob->StartJob( NULL );
|
||
|
}
|