You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2455 lines
78 KiB
2455 lines
78 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
|
|
#include "cbase.h" |
|
#include "tf_quest_editor_panel.h" |
|
#include "econ_item_tools.h" |
|
#include "tier2/p4helpers.h" |
|
#include "tier2/fileutils.h" |
|
#include "vgui/IInput.h" |
|
|
|
#ifdef STAGING_ONLY |
|
|
|
using namespace vgui; |
|
|
|
ConVar tf_quest_editor_element_height( "tf_quest_editor_element_height", "20", FCVAR_ARCHIVE ); |
|
ConVar tf_quest_editor_indent_width( "tf_quest_editor_indent_width", "20", FCVAR_ARCHIVE ); |
|
ConVar tf_quest_editor_entry_inset( "tf_quest_editor_entry_inset", "120" ); |
|
|
|
static const char *g_skItemNameFormat = "quest%d"; |
|
static const char *g_skNameTokenFormat = "#quest%dname%d"; |
|
static const char *g_skDescTokenFormat = "#quest%ddesc%d"; |
|
static const char *g_skObjectiveDescTokenFormat = "#quest%dobjectivedesc%d"; |
|
static const char *g_skLocalizationFile = "resource/tf_quests_english.txt"; |
|
static const char *g_skQuestDefFile = "tf/scripts/items/unencrypted/_items_quests.txt"; |
|
static const char *g_skQuestObjectivesConditionsDefFile = "tf/scripts/items/unencrypted/_items_quest_objective_definitions.txt"; |
|
static const char *g_skQuestObjectivesHouseKeepingFile = "items_quest_objective_housekeeping.csv"; |
|
static const int g_nkFirstQuestDef = 25000; |
|
|
|
static const char* g_skQuestPrefabs[] = { "quest_prefab_1st_operation_pauling" |
|
, "quest_prefab_halloween_2015" |
|
, "quest_prefab_2nd_operation_pauling" }; |
|
|
|
#define FLAGS_NONE 0 |
|
#define FLAG_HIDDEN 1<<0 |
|
#define FLAG_COLLAPSED 1<<1 |
|
#define FLAG_COLLAPSABLE 1<<2 |
|
#define FLAG_MUST_BE_LAST 1<<3 |
|
#define FLAG_NOT_DELETABLE 1<<4 |
|
#define FLAG_OUTPUT_LAST 1<<5 |
|
#define FLAG_DELETED 1<<6 |
|
#define FLAG_HIGHLIGHT_MOUSEOVER 1<<7 |
|
#define FLAG_DONT_EXPORT 1<<8 |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
static CQuestEditorPanel* g_pQuestEditor = NULL; |
|
static void cc_tf_quest_editor() |
|
{ |
|
g_pQuestEditor = new CQuestEditorPanel( NULL, "QuestEditor" ); |
|
g_pQuestEditor->MakeReadyForUse(); |
|
g_pQuestEditor->Deploy(); |
|
} |
|
ConCommand tf_quest_editor( "tf_quest_editor", cc_tf_quest_editor ); |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Writes out all of the localization data for each quest intro "resource/tf_quests_english.txt" |
|
//----------------------------------------------------------------------------- |
|
void WriteLocalizationData() |
|
{ |
|
char szQuestEnglishFile[MAX_PATH]; |
|
if ( !GenerateFullPath( g_skLocalizationFile, "MOD", szQuestEnglishFile, ARRAYSIZE( szQuestEnglishFile ) ) ) |
|
{ |
|
Warning( "Failed to GenerateFullPath %s\n", g_skLocalizationFile ); |
|
return; |
|
} |
|
|
|
FOR_EACH_VEC( ILocalizationEditorParamAutoList::AutoList(), i ) |
|
{ |
|
CLocalizationEditorParam* pLocalizationEntry = static_cast< CLocalizationEditorParam* >( ILocalizationEditorParamAutoList::AutoList()[i] ); |
|
// We set the filename to "deleted" for deleted entries so that they don't get written out |
|
// into tf_quests_english.txt |
|
const char* pszFile = pLocalizationEntry->IsFlagSet( FLAG_DELETED, true ) ? "deleted" : szQuestEnglishFile; |
|
|
|
wchar_t wszLocalizedValue[MAX_QUEST_DESC_LENGTH]; |
|
g_pVGuiLocalize->ConvertANSIToUnicode( pLocalizationEntry->GetLocalizationValue(), wszLocalizedValue, sizeof( wszLocalizedValue ) ); |
|
|
|
const char *pszTokenName = pLocalizationEntry->GetValue(); |
|
if ( pszTokenName[0] == '#' ) |
|
{ |
|
pszTokenName++; |
|
} |
|
g_pVGuiLocalize->AddString( pszTokenName, wszLocalizedValue, pszFile ); |
|
} |
|
|
|
// Get the name of the file and p4 check it out |
|
char szCorrectCaseFilePath[MAX_PATH]; |
|
g_pFullFileSystem->GetCaseCorrectFullPath( szQuestEnglishFile, szCorrectCaseFilePath ); |
|
CP4AutoEditFile a( szCorrectCaseFilePath ); |
|
|
|
g_pVGuiLocalize->SaveToFile( szQuestEnglishFile ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
IEditorObject::IEditorObject( EditorObjectInitStruct init ) |
|
: EditablePanel( init.pParent, init.m_pszKeyName ) |
|
, m_Flags( init.nFlags ) |
|
, m_pOwningEditable( NULL ) |
|
, m_bHasChanges( false ) |
|
{ |
|
memset( m_szKeyName, 0, sizeof( m_szKeyName ) ); |
|
if ( init.m_pszKeyName ) |
|
{ |
|
V_sprintf_safe( m_szKeyName, "%s", init.m_pszKeyName ); |
|
} |
|
|
|
SetWide( init.pParent->GetWide() ); |
|
|
|
SetAutoResize( Panel::PIN_TOPLEFT, Panel::AUTORESIZE_RIGHT, 6, 6, -6, -6 ); |
|
} |
|
|
|
void IEditorObject::PerformLayout() |
|
{ |
|
BaseClass::PerformLayout(); |
|
|
|
SetTall( GetContentTall() ); |
|
} |
|
|
|
void IEditorObject::OnSizeChanged( int newWide, int newTall ) |
|
{ |
|
BaseClass::OnSizeChanged( newWide, newTall ); |
|
|
|
GetParent()->InvalidateLayout(); |
|
} |
|
|
|
|
|
bool IEditorObject::IsFlagSet( int nFlag, bool bCheckUpTree ) const |
|
{ |
|
bool bIsFlagSet = m_Flags & nFlag; |
|
if ( !bIsFlagSet && bCheckUpTree ) |
|
{ |
|
IEditorObject* pParent = dynamic_cast< IEditorObject* >( const_cast<IEditorObject*>(this)->GetParent() ); |
|
if ( pParent ) |
|
{ |
|
bIsFlagSet |= pParent->IsFlagSet( nFlag, bCheckUpTree ); |
|
} |
|
} |
|
return bIsFlagSet; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
IEditorObject::ESerializeAction IEditorObject::ShouldWrite( const IEditableDataType* pCallingEditable ) const |
|
{ |
|
if ( IsFlagSet( FLAG_DONT_EXPORT ) ) |
|
return SKIP_THIS_AND_CHILDREN; |
|
|
|
if ( IsFlagSet( FLAG_DELETED ) ) |
|
return SKIP_THIS_AND_CHILDREN; |
|
|
|
if ( GetOwningEditable() != pCallingEditable ) |
|
return SKIP_THIS_AND_CONTINUE; |
|
|
|
return WRITE_THIS_AND_CONTINUE; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: If we're set to highlight on mouseover, do so! |
|
//----------------------------------------------------------------------------- |
|
void IEditorObject::OnThink() |
|
{ |
|
if ( IsFlagSet( FLAG_HIGHLIGHT_MOUSEOVER, false ) ) |
|
{ |
|
if ( IsCursorOver() ) |
|
{ |
|
SetBgColor( Color( 100, 150, 100, 30 ) ); |
|
} |
|
else |
|
{ |
|
SetBgColor( Color( 235, 226, 202, 2 ) ); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CEditorObjectNode::CEditorObjectNode( EditorObjectInitStruct init ) |
|
: BaseClass( init ) |
|
{ |
|
m_pToggleCollapseButton = new Button( this, "togglecollapse", "-", this, "togglecollapse" ); |
|
m_pToggleCollapseButton->SetVisible( false ); |
|
m_pToggleCollapseButton->SetWide( 20 ); |
|
m_pToggleCollapseButton->SetZPos( 100 ); |
|
|
|
m_pDeleteButton = new Button( this, "deletebutton", "x", this, "delete" ); |
|
m_pDeleteButton->SetWide( 20 ); |
|
m_pDeleteButton->SetTall( 20 ); |
|
|
|
CEditorObjectNode* pNode = dynamic_cast< CEditorObjectNode* >( init.pParent ); |
|
if ( pNode ) |
|
{ |
|
pNode->AddChild( this ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CEditorObjectNode::~CEditorObjectNode() |
|
{ |
|
CEditorObjectNode* pEditorPanel = dynamic_cast<CEditorObjectNode*>( GetParent() ); |
|
if ( pEditorPanel ) |
|
{ |
|
pEditorPanel->RemoveChild( this ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
const IEditableDataType* IEditorObject::GetOwningEditable() const |
|
{ |
|
const IEditableDataType* pOwningEditable = NULL; |
|
const IEditorObject* pPanel = this; |
|
|
|
do |
|
{ |
|
pOwningEditable = pPanel->m_pOwningEditable; |
|
pPanel = dynamic_cast< const IEditorObject* >( const_cast< IEditorObject* >( pPanel )->GetParent() ); // Good lord, VGUI. GetParent() isn't const? Really? |
|
} |
|
while ( pOwningEditable == NULL && pPanel != NULL ); |
|
|
|
Assert( pOwningEditable != NULL ); |
|
|
|
return pOwningEditable; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void IEditorObject::InvalidateChain() |
|
{ |
|
InvalidateLayout(); |
|
|
|
Panel* pParent = this; |
|
|
|
do |
|
{ |
|
pParent = pParent->GetParent(); |
|
pParent->InvalidateLayout(); |
|
} |
|
while( dynamic_cast< IEditorObject* >( pParent ) ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void IEditorObject::ClearPendingChangesFlag() |
|
{ |
|
m_bHasChanges = false; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CEditorObjectNode::AddChild( IEditorObject* pChild ) |
|
{ |
|
m_bHasChanges = true; |
|
m_vecChildren.AddToTail( pChild ); |
|
if ( !IsFlagSet( FLAG_HIDDEN ) && IsFlagSet( FLAG_COLLAPSABLE ) ) |
|
{ |
|
m_pToggleCollapseButton->SetVisible( true ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CEditorObjectNode::RemoveChild( IEditorObject* pChild ) |
|
{ |
|
FOR_EACH_VEC( m_vecChildren, i ) |
|
{ |
|
if ( m_vecChildren[i] == pChild ) |
|
{ |
|
m_vecChildren.Remove( i ); |
|
if ( m_vecChildren.Count() == 0 ) |
|
{ |
|
m_pToggleCollapseButton->SetVisible( false ); |
|
} |
|
|
|
m_bHasChanges = true; |
|
|
|
return; |
|
} |
|
} |
|
|
|
Assert( !"Couldn't find child to remove!" ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
int CEditorObjectNode::GetNextAvailableKeyNumber() const |
|
{ |
|
int nNextAvailable = 0; |
|
|
|
FOR_EACH_VEC( m_vecChildren, i ) |
|
{ |
|
if ( !m_vecChildren[i]->IsFlagSet( FLAG_DONT_EXPORT ) ) |
|
{ |
|
nNextAvailable = Max( nNextAvailable, atoi( m_vecChildren[i]->GetName() ) ); |
|
} |
|
} |
|
|
|
return nNextAvailable; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
bool CEditorObjectNode::HasChanges( bool bCheckChildren ) const |
|
{ |
|
bool bHasChanges = m_bHasChanges; |
|
|
|
if ( bCheckChildren ) |
|
{ |
|
FOR_EACH_VEC( m_vecChildren, i ) |
|
{ |
|
bHasChanges |= m_vecChildren[i]->HasChanges( bCheckChildren ); |
|
} |
|
} |
|
|
|
return bHasChanges; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
int CEditorObjectNode::GetContentTall() const |
|
{ |
|
// Hidden panels have 0 height |
|
int nTall = IsFlagSet( FLAG_HIDDEN ) ? 0 : tf_quest_editor_element_height.GetInt(); |
|
|
|
// Collapsed panels just return their height. |
|
if ( IsFlagSet( FLAG_COLLAPSED ) ) |
|
return nTall; |
|
|
|
FOR_EACH_VEC( m_vecChildren, i ) |
|
{ |
|
nTall += m_vecChildren[i]->GetContentTall(); |
|
} |
|
|
|
return nTall; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CEditorObjectNode::SerializeToKVs( KeyValues* pKV, const IEditableDataType* pCallingEditable ) const |
|
{ |
|
m_bHasChanges = false; |
|
|
|
// End of the Line if deleted |
|
if ( IsFlagSet( FLAG_DELETED ) ) |
|
return; |
|
|
|
ESerializeAction action = ShouldWrite( pCallingEditable ); |
|
if ( action == SKIP_THIS_AND_CHILDREN ) |
|
return; |
|
|
|
if ( action != SKIP_THIS_AND_CONTINUE ) |
|
{ |
|
pKV = pKV->CreateNewKey(); |
|
pKV->SetName( GetKeyName() ); |
|
} |
|
|
|
CUtlVector< IEditorObject* > vecLastOutputs; |
|
|
|
FOR_EACH_VEC( m_vecChildren, i ) |
|
{ |
|
if ( m_vecChildren[ i ]->IsFlagSet( FLAG_OUTPUT_LAST ) ) |
|
{ |
|
vecLastOutputs.AddToTail( m_vecChildren[i] ); |
|
continue; |
|
} |
|
|
|
m_vecChildren[i]->SerializeToKVs( pKV, pCallingEditable ); |
|
|
|
} |
|
|
|
FOR_EACH_VEC( vecLastOutputs, i ) |
|
{ |
|
vecLastOutputs[ i ]->SerializeToKVs( pKV, pCallingEditable ); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CEditorObjectNode::PerformLayout() |
|
{ |
|
m_pDeleteButton->SetVisible( m_vecChildren.Count() > 0 && !IsFlagSet( FLAG_HIDDEN ) && !IsFlagSet( FLAG_NOT_DELETABLE ) ); |
|
m_pDeleteButton->SetPos( 470, 0 ); |
|
|
|
BaseClass::PerformLayout(); |
|
|
|
int nTall = IsFlagSet( FLAG_HIDDEN ) ? 0 : tf_quest_editor_element_height.GetInt(); |
|
|
|
CUtlVector< IEditorObject* > vecLastParams; |
|
|
|
FOR_EACH_VEC( m_vecChildren, i ) |
|
{ |
|
if ( IsFlagSet( FLAG_MUST_BE_LAST ) ) |
|
{ |
|
vecLastParams.AddToTail( m_vecChildren[i] ); |
|
continue; |
|
} |
|
|
|
m_vecChildren[i]->SetPos( IsFlagSet( FLAG_HIDDEN ) ? 0 : tf_quest_editor_indent_width.GetInt(), nTall ); |
|
nTall += m_vecChildren[i]->GetContentTall(); |
|
} |
|
|
|
FOR_EACH_VEC( vecLastParams, i ) |
|
{ |
|
vecLastParams[i]->SetPos( IsFlagSet( FLAG_HIDDEN ) ? 0 : tf_quest_editor_indent_width.GetInt(), nTall ); |
|
nTall += vecLastParams[i]->GetContentTall(); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CEditorObjectNode::OnCommand( const char *command ) |
|
{ |
|
if ( V_stricmp( "togglecollapse", command ) == 0 ) |
|
{ |
|
if ( IsFlagSet( FLAG_COLLAPSED ) ) |
|
{ |
|
m_pToggleCollapseButton->SetText( "-" ); |
|
} |
|
else |
|
{ |
|
m_pToggleCollapseButton->SetText( "+" ); |
|
} |
|
|
|
SetFlag( FLAG_COLLAPSED, !IsFlagSet( FLAG_COLLAPSED ) ); |
|
InvalidateChain(); |
|
|
|
return; |
|
} |
|
if ( V_stricmp( command, "delete" ) == 0 ) |
|
{ |
|
RemoveNode(); |
|
return; |
|
} |
|
|
|
BaseClass::OnCommand( command ); |
|
} |
|
|
|
void CEditorObjectNode::MarkForDeletion() |
|
{ |
|
BaseClass::MarkForDeletion(); |
|
|
|
FOR_EACH_VEC( m_vecChildren, i ) |
|
{ |
|
m_vecChildren[i]->MarkForDeletion(); |
|
} |
|
} |
|
|
|
void CEditorObjectNode::RemoveNode() |
|
{ |
|
MarkForDeletion(); |
|
|
|
InvalidateChain(); |
|
} |
|
|
|
void CEditorObjectNode::ClearPendingChangesFlag() |
|
{ |
|
BaseClass::ClearPendingChangesFlag(); |
|
|
|
FOR_EACH_VEC( m_vecChildren, i ) |
|
{ |
|
m_vecChildren[ i ]->ClearPendingChangesFlag(); |
|
} |
|
} |
|
|
|
IEditorObjectParameter::IEditorObjectParameter( EditorObjectInitStruct init, const char *pszLabelText ) |
|
: BaseClass( init ) |
|
{ |
|
memset( m_szSavedValueBuff, 0, sizeof( m_szSavedValueBuff ) ); |
|
|
|
SetTall( tf_quest_editor_element_height.GetInt() ); |
|
|
|
m_pLabel = new Label( this, "paramlabel", pszLabelText ); |
|
m_pLabel->SetWide( 100 ); |
|
m_pLabel->SetPos( 20, 0 ); |
|
m_pLabel->SetVisible( pszLabelText != NULL ); |
|
|
|
CEditorObjectNode* pNode = dynamic_cast< CEditorObjectNode* >( init.pParent ); |
|
if ( pNode ) |
|
{ |
|
pNode->AddChild( this ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
IEditorObjectParameter::~IEditorObjectParameter() |
|
{ |
|
CEditorObjectNode* pEditorPanel = dynamic_cast<CEditorObjectNode*>( GetParent() ); |
|
if ( pEditorPanel ) |
|
{ |
|
pEditorPanel->RemoveChild( this ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void IEditorObjectParameter::PerformLayout() |
|
{ |
|
BaseClass::PerformLayout(); |
|
|
|
m_pLabel->SetPos( 20, 0 ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void IEditorObjectParameter::SerializeToKVs( KeyValues* pKV, const IEditableDataType* pCallingEditable ) const |
|
{ |
|
m_bHasChanges = false; |
|
|
|
if ( ShouldWrite( pCallingEditable ) == WRITE_THIS_AND_CONTINUE ) |
|
{ |
|
KeyValues* pKVStomp = pKV->FindKey( GetKeyName() ); |
|
if ( pKVStomp ) |
|
{ |
|
AssertMsg2( false, "STOMPING existing key: %s with %s\n", pKVStomp->GetName(), GetValue() ); |
|
KeyValuesDumpAsDevMsg( pKVStomp ); |
|
} |
|
|
|
pKV->SetString( GetKeyName(), GetValue() ); |
|
|
|
UpdateSavedValue( GetValue() ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void IEditorObjectParameter::UpdateSavedValue( const char* pszNewValue ) const |
|
{ |
|
// Update saved string |
|
memset( m_szSavedValueBuff, 0, sizeof( m_szSavedValueBuff ) ); |
|
V_sprintf_safe( m_szSavedValueBuff, "%s", pszNewValue ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void IEditorObjectParameter::OnTextChanged( KeyValues *data ) |
|
{ |
|
m_bHasChanges = CheckForChanges(); |
|
|
|
IScheme *pScheme = vgui::scheme()->GetIScheme( GetScheme() ); |
|
Color labelNormalFGColor = GetSchemeColor("Label.TextColor", Color(0, 0, 0, 255), pScheme); |
|
Color labelChangesFGColor = GetSchemeColor("RichText.SelectedBgColor", Color(0, 0, 0, 255), pScheme); |
|
|
|
m_pLabel->SetFgColor( m_bHasChanges ? labelChangesFGColor : labelNormalFGColor ); |
|
|
|
g_pQuestEditor->CheckForChanges(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
bool IEditorObjectParameter::CheckForChanges() const |
|
{ |
|
return !FStrEq( GetValue(), m_szSavedValueBuff ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CTextEntryEditorParam::CTextEntryEditorParam( EditorObjectInitStruct init, const char *pszLabelText, const char *pszValue ) |
|
: BaseClass( init, pszLabelText ) |
|
{ |
|
UpdateSavedValue( pszValue ); |
|
|
|
SetTall( tf_quest_editor_element_height.GetInt() ); |
|
m_pTextEntry = new TextEntry( this, "entry" ); |
|
m_pTextEntry->SetPos( tf_quest_editor_entry_inset.GetInt(), 0 ); |
|
m_pTextEntry->SetWide( 400 ); |
|
m_pTextEntry->SetTall( tf_quest_editor_element_height.GetInt() ); |
|
m_pTextEntry->SetMultiline( true ); |
|
m_pTextEntry->SetCatchEnterKey( true ); |
|
SetTextEntryValue( pszValue ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTextEntryEditorParam::PerformLayout() |
|
{ |
|
BaseClass::PerformLayout(); |
|
|
|
m_pTextEntry->SetPos( tf_quest_editor_entry_inset.GetInt(), 0 ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
int CTextEntryEditorParam::GetContentTall() const |
|
{ |
|
return IsFlagSet( FLAG_HIDDEN ) ? 0 : m_pTextEntry->GetTall(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTextEntryEditorParam::SetTextEntryValue( const char* pszValue ) |
|
{ |
|
m_pTextEntry->SetText( pszValue ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
const char* CTextEntryEditorParam::GetValue() const |
|
{ |
|
m_pTextEntry->GetText( m_szValueBuff, sizeof( m_szValueBuff ) ); |
|
return m_szValueBuff; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
IMPLEMENT_AUTO_LIST( ILocalizationEditorParamAutoList ); |
|
CLocalizationEditorParam::CLocalizationEditorParam( EditorObjectInitStruct init, const char *pszLabelText, const char *pszLocalizationToken ) |
|
: BaseClass( init, pszLabelText, NULL ) |
|
{ |
|
char szBuff[MAX_QUEST_DESC_LENGTH]; |
|
memset( szBuff, 0, sizeof( szBuff ) ); |
|
g_pVGuiLocalize->ConvertUnicodeToANSI( g_pVGuiLocalize->Find( pszLocalizationToken ), szBuff, sizeof( szBuff ) ); |
|
SetTextEntryValue( szBuff ); |
|
UpdateSavedValue( szBuff ); |
|
|
|
V_sprintf_safe( m_szLocalizationToken, "%s", pszLocalizationToken ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
const char *CLocalizationEditorParam::GetValue() const |
|
{ |
|
// Always return the localization token |
|
return m_szLocalizationToken; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
const char* CLocalizationEditorParam::GetLocalizationValue() const |
|
{ |
|
return BaseClass::GetValue(); |
|
} |
|
|
|
bool CLocalizationEditorParam::CheckForChanges() const |
|
{ |
|
return !FStrEq( m_szSavedValueBuff, GetLocalizationValue() ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CComboBoxEditorParam::CComboBoxEditorParam( EditorObjectInitStruct init, const char *pszLabelText ) |
|
: BaseClass( init, pszLabelText ) |
|
, m_pComboBox( NULL ) |
|
{ |
|
m_pComboBox = new ComboBox( this, "combobox", 10, false ); |
|
m_pComboBox->AddActionSignalTarget( this ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CComboBoxEditorParam::PerformLayout() |
|
{ |
|
BaseClass::PerformLayout(); |
|
|
|
m_pComboBox->SetWide( 350 ); |
|
m_pComboBox->SetPos( tf_quest_editor_entry_inset.GetInt(), 0 ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
int CComboBoxEditorParam::GetContentTall() const |
|
{ |
|
return IsFlagSet( FLAG_HIDDEN ) ? 0 : m_pComboBox->GetTall(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
const char* CComboBoxEditorParam::GetValue() const |
|
{ |
|
return m_pComboBox->GetActiveItemUserData()->GetString( "write" ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CComboBoxEditorParam::AddComboBoxEntry( const char* pszText, bool bSelected, const char* pszWriteValue, const char* pszCommand ) |
|
{ |
|
KeyValues *pKVData = new KeyValues( "data" ); |
|
pKVData->SetString( "write", pszWriteValue ); |
|
pKVData->SetString( "command", pszCommand ); |
|
|
|
int nIndex = m_pComboBox->AddItem( pszText, pKVData ); |
|
|
|
if ( bSelected ) |
|
{ |
|
m_pComboBox->SilentActivateItemByRow( nIndex ); |
|
UpdateSavedValue( pszWriteValue ); |
|
} |
|
|
|
if ( pszWriteValue == NULL ) |
|
{ |
|
pszWriteValue = pszText; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CComboBoxEditorParam::OnTextChanged( KeyValues *data ) |
|
{ |
|
Panel *pPanel = reinterpret_cast<vgui::Panel *>( data->GetPtr("panel") ); |
|
vgui::ComboBox *pComboBox = dynamic_cast<vgui::ComboBox *>( pPanel ); |
|
|
|
if ( pComboBox == m_pComboBox ) |
|
{ |
|
CQuestObjectiveRestrictionNode* pParent = dynamic_cast< CQuestObjectiveRestrictionNode* >( GetParent() ); |
|
if ( pParent ) |
|
{ |
|
// What to do |
|
const char* pszCommand = m_pComboBox->GetActiveItemUserData()->GetString( "command" ); |
|
// What to write |
|
const char* pszWriteValue = m_pComboBox->GetActiveItemUserData()->GetString( "write" ); |
|
if ( V_stricmp( pszCommand, "changetype" ) == 0 ) |
|
{ |
|
pParent->SetNewType( pszWriteValue ); |
|
} |
|
else if ( V_stricmp( pszCommand, "changeevent" ) == 0 ) |
|
{ |
|
pParent->SetNewEvent( pszWriteValue ); |
|
} |
|
} |
|
} |
|
|
|
BaseClass::OnTextChanged( data ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CNewQuestObjectiveParam::CNewQuestObjectiveParam( EditorObjectInitStruct init, const char *pszLabelText ) |
|
: BaseClass( init, NULL ) |
|
{ |
|
SetFlag( FLAG_DONT_EXPORT, true ); |
|
|
|
m_pAddButton = new Button( this, "add", "Add New Filter", this, "add" ); |
|
m_pAddButton->SetTall( 20 ); |
|
m_pComboBox->SetVisible( false ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CNewQuestObjectiveParam::PerformLayout() |
|
{ |
|
BaseClass::PerformLayout(); |
|
m_pAddButton->SetWide( 200 ); |
|
m_pAddButton->SetPos( tf_quest_editor_indent_width.GetInt(), 0 ); |
|
m_pAddButton->SetContentAlignment( Label::a_center ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CNewQuestObjectiveParam::OnCommand( const char *command ) |
|
{ |
|
if ( FStrEq( command, "add" ) ) |
|
{ |
|
CQuestObjectiveRestrictionNode *pObjectiveParent = dynamic_cast< CQuestObjectiveRestrictionNode* >( GetParent() ); |
|
Assert( pObjectiveParent ); |
|
if ( pObjectiveParent ) |
|
{ |
|
const char *pszWriteValue = m_pComboBox->GetActiveItemUserData()->GetString( "write" ); |
|
CTFQuestCondition *pNewCondition = pObjectiveParent->GetCondition()->AddChildByName( pszWriteValue ); |
|
if ( pNewCondition ) |
|
{ |
|
new CQuestObjectiveRestrictionNode( { GetParent(), CFmtStr( "%d", pObjectiveParent->GetNextAvailableKeyNumber() ), FLAGS_NONE }, pNewCondition ); |
|
InvalidateChain(); |
|
} |
|
} |
|
} |
|
|
|
BaseClass::OnCommand( command ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
IOptionalExpandableBlock::IOptionalExpandableBlock( EditorObjectInitStruct init, const char* pszButtonText ) |
|
: BaseClass( init ) |
|
{ |
|
m_pAddButton = new Button( this, "add", pszButtonText, this, "add" ); |
|
} |
|
|
|
void IOptionalExpandableBlock::InitControls( KeyValues* pKVBlock ) |
|
{ |
|
int nNumControlsCreated = 0; |
|
if ( pKVBlock ) |
|
{ |
|
FOR_EACH_TRUE_SUBKEY( pKVBlock, pKVKey ) |
|
{ |
|
CreateNewControl( pKVKey ); |
|
++nNumControlsCreated; |
|
} |
|
} |
|
|
|
while( nNumControlsCreated < GetMinCount() ) |
|
{ |
|
CreateNewDefaultControl(); |
|
++nNumControlsCreated; |
|
} |
|
|
|
InvalidateChain(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void IOptionalExpandableBlock::PerformLayout() |
|
{ |
|
BaseClass::PerformLayout(); |
|
|
|
m_pAddButton->SetPos( 0, 0 ); |
|
m_pAddButton->SetWide( 200 ); |
|
m_pAddButton->SetContentAlignment(Label::a_center); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void IOptionalExpandableBlock::OnCommand( const char *command ) |
|
{ |
|
if ( FStrEq( "add", command ) ) |
|
{ |
|
CreateNewDefaultControl(); |
|
InvalidateChain(); |
|
return; |
|
} |
|
|
|
BaseClass::OnCommand( command ); |
|
} |
|
|
|
void IOptionalExpandableBlock::CreateNewControl( KeyValues* pKV ) |
|
{ |
|
SetFlag( FLAG_DONT_EXPORT, false ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CQuestObjectiveNode::CQuestObjectiveNode( CEditorObjectNode* pParentNode, KeyValues* pKVObjective ) |
|
: BaseClass( { pParentNode, pKVObjective->GetName(), FLAG_COLLAPSABLE } ) |
|
, m_pDefIndexComboBox( NULL ) |
|
, m_pSelectObjectiveButton( NULL ) |
|
{ |
|
// Create the description field |
|
new CLocalizationEditorParam( { this, "description_string", FLAGS_NONE }, "Objective Desc:", pKVObjective->GetString( "description_string" ) ); |
|
new CTextEntryEditorParam( { this, "defindex", FLAG_HIDDEN }, "Defindex", pKVObjective->GetString( "defindex" ) ); |
|
|
|
CComboBoxEditorParam * pOptionalComboBox = new CComboBoxEditorParam( { this, "optional", FLAGS_NONE }, "Optional:" ); |
|
pOptionalComboBox->AddComboBoxEntry( "False", !pKVObjective->GetBool( "optional", false ), "0", NULL ); |
|
pOptionalComboBox->AddComboBoxEntry( "True", pKVObjective->GetBool( "optional", false ), "1", NULL ); |
|
|
|
CComboBoxEditorParam * pAdvancedComboBox = new CComboBoxEditorParam( { this, "advanced", FLAGS_NONE }, "Advanced:" ); |
|
pAdvancedComboBox->AddComboBoxEntry( "False", !pKVObjective->GetBool( "advanced", false ), "0", NULL ); |
|
pAdvancedComboBox->AddComboBoxEntry( "True", pKVObjective->GetBool( "advanced", false ), "1", NULL ); |
|
|
|
CTextEntryEditorParam *pPointsNode = new CTextEntryEditorParam( { this, "points", FLAGS_NONE }, "Points:", CFmtStr( "%d", pKVObjective->GetInt( "points", 1 ) ) ); |
|
pPointsNode->GetTextEntry()->SetAllowNumericInputOnly( true ); |
|
|
|
// The condition def index this objective wants to use |
|
ObjectiveConditionDefIndex_t nConditionsDefIndex = pKVObjective->GetInt( "conditions_def_index", INVALID_QUEST_OBJECTIVE_CONDITIONS_INDEX ); |
|
Assert( nConditionsDefIndex != INVALID_QUEST_OBJECTIVE_CONDITIONS_INDEX ); |
|
|
|
m_pDefIndexComboBox = new CComboBoxEditorParam( { this, "conditions_def_index", FLAGS_NONE }, "Conditions:" ); |
|
m_pDefIndexComboBox->GetComboBox()->AddActionSignalTarget( this ); |
|
|
|
|
|
m_pSelectObjectiveButton = new Button( m_pDefIndexComboBox, "selectobjective", "Pick", this, "selectobjective" ); |
|
m_pSelectObjectiveButton->AddActionSignalTarget( this ); |
|
|
|
|
|
PopulateAndSelectConditionsCombobox( nConditionsDefIndex ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CQuestObjectiveNode::PerformLayout() |
|
{ |
|
BaseClass::PerformLayout(); |
|
|
|
m_pSelectObjectiveButton->SetPos( m_pDefIndexComboBox->GetComboBox()->GetXPos() + m_pDefIndexComboBox->GetComboBox()->GetWide(), 0 ); |
|
m_pSelectObjectiveButton->SetWide( 36 ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CQuestObjectiveNode::PopulateAndSelectConditionsCombobox( int nSelectedDefIndex ) |
|
{ |
|
// Clean out oldies |
|
m_pDefIndexComboBox->GetComboBox()->RemoveAll(); |
|
|
|
// Go through all of the current data and fill out our combo box with all of the objective conditions |
|
const CUtlVector< IEditableDataType* >& vecEditableData = g_pQuestEditor->GetEditableData(); |
|
FOR_EACH_VEC( vecEditableData, i ) |
|
{ |
|
IEditableDataType* pEditable = vecEditableData[i]; |
|
if ( pEditable->GetType() == IEditableDataType::TYPE_OBJECTIVE_CONDITIONS && !g_pQuestEditor->IsOpenForEdit( pEditable ) ) |
|
{ |
|
KeyValues* pKVData = pEditable->GetLiveData(); |
|
bool bSelected = atoi( pKVData->GetName() ) == nSelectedDefIndex; |
|
m_pDefIndexComboBox->AddComboBoxEntry( CFmtStr( "\t%s", pKVData->GetString( "name", "ERROR" ) ), bSelected, pKVData->GetName(), NULL ); |
|
} |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CQuestObjectiveNode::OnCommand( const char *command ) |
|
{ |
|
if ( FStrEq( "selectobjective", command ) ) |
|
{ |
|
KeyValues* pKV = new KeyValues( "SelectQuestObjective" ); |
|
pKV->SetPtr( "panel", this ); |
|
|
|
PostMessage( g_pQuestEditor, pKV ); |
|
} |
|
|
|
BaseClass::OnCommand( command ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Pump the command from the menu panel into us as a command |
|
//----------------------------------------------------------------------------- |
|
void CQuestObjectiveNode::OnTextChanged( KeyValues *data ) |
|
{ |
|
Panel *pPanel = reinterpret_cast<vgui::Panel *>( data->GetPtr("panel") ); |
|
|
|
ComboBox *pComboBox = dynamic_cast<ComboBox*>( pPanel ); |
|
if ( pComboBox ) |
|
{ |
|
if ( pComboBox == m_pDefIndexComboBox->GetComboBox() ) |
|
{ |
|
KeyValues* pKVUserData = pComboBox->GetActiveItemUserData(); |
|
OnCommand( pKVUserData->GetString( "command" ) ); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CQuestObjectiveNode::OnObjectiveSelected( KeyValues *data ) |
|
{ |
|
int nDesiredDefIndex = data->GetInt( "defindex", INVALID_ITEM_DEF_INDEX ); |
|
Assert( nDesiredDefIndex != INVALID_ITEM_DEF_INDEX ); |
|
|
|
ComboBox* pComboBox = m_pDefIndexComboBox->GetComboBox(); |
|
if ( pComboBox ) |
|
{ |
|
for( int i=0; i < pComboBox->GetItemCount(); ++i ) |
|
{ |
|
KeyValues* pKVUserData = pComboBox->GetItemUserData( i ); |
|
int nDefIndex = pKVUserData->GetInt( "write", INVALID_ITEM_DEF_INDEX ); |
|
|
|
if ( nDefIndex == nDesiredDefIndex ) |
|
{ |
|
pComboBox->ActivateItemByRow( i ); |
|
return; |
|
} |
|
} |
|
} |
|
|
|
// Didn't find the matching defindex! |
|
Assert( false ); |
|
} |
|
|
|
void CQuestDescriptionNode::CreateNewControl( KeyValues* pKV ) |
|
{ |
|
CEditorObjectNode* pNode = new CEditorObjectNode( EditorObjectInitStruct{ this, pKV->GetName(), FLAGS_NONE } ); |
|
CLocalizationEditorParam *pLocParam = new CLocalizationEditorParam( { pNode, "token", FLAGS_NONE }, "Description:", pKV->GetString( "token" ) ); |
|
pLocParam->GetTextEntry()->SetTall( 200 ); |
|
pLocParam->SetTall( 200 ); |
|
pLocParam->GetTextEntry()->SetVerticalScrollbar( true ); |
|
|
|
BaseClass::CreateNewControl( pKV ); |
|
} |
|
|
|
void CQuestDescriptionNode::CreateNewDefaultControl() |
|
{ |
|
int nDefindex = GetNextAvailableKeyNumber() + 1; |
|
int nObjectDefIndex = atoi( GetOwningEditable()->GetLiveData()->GetName() ); |
|
|
|
KeyValuesAD pKVDesc( CFmtStr( "%d", nDefindex ) ); |
|
pKVDesc->SetString( "token", CFmtStr( g_skDescTokenFormat, nObjectDefIndex, nDefindex ) ); |
|
|
|
CreateNewControl( pKVDesc ); |
|
} |
|
|
|
void CQuestNameNode::CreateNewControl( KeyValues* pKV ) |
|
{ |
|
CEditorObjectNode* pNode = new CEditorObjectNode( EditorObjectInitStruct{ this, pKV->GetName(), FLAGS_NONE } ); |
|
new CLocalizationEditorParam( { pNode, "token", FLAGS_NONE }, "Name:", pKV->GetString( "token" ) ); |
|
|
|
BaseClass::CreateNewControl( pKV ); |
|
} |
|
|
|
void CQuestNameNode::CreateNewDefaultControl() |
|
{ |
|
int nDefindex = GetNextAvailableKeyNumber() + 1; |
|
int nObjectDefIndex = atoi( GetOwningEditable()->GetLiveData()->GetName() ); |
|
|
|
KeyValuesAD pKVName( CFmtStr( "%d", nDefindex ) ); |
|
pKVName->SetString( "token", CFmtStr( g_skNameTokenFormat, nObjectDefIndex, nDefindex ) ); |
|
|
|
CreateNewControl( pKVName ); |
|
} |
|
|
|
|
|
CComboBoxEditorParam* CreateWeaponComboBox( EditorObjectInitStruct init, const char* pszLabelText, item_definition_index_t defIndexSelect ) |
|
{ |
|
CComboBoxEditorParam* pCombo = new CComboBoxEditorParam( init, pszLabelText ); |
|
pCombo->GetComboBox()->SetEditable( true ); // Allow for typing in the combo box. There's a lot of stuff |
|
|
|
CUtlDict< item_definition_index_t > weaponDict; |
|
const CEconItemSchema::SortedItemDefinitionMap_t& mapItemDefs = GetItemSchema()->GetSortedItemDefinitionMap(); |
|
FOR_EACH_MAP( mapItemDefs, i ) |
|
{ |
|
CTFItemDefinition* pDef = (CTFItemDefinition*)mapItemDefs[i]; |
|
|
|
int iSlot = pDef->GetDefaultLoadoutSlot(); |
|
if ( pDef->GetEquipType() == EEquipType_t::EQUIP_TYPE_ACCOUNT ) |
|
continue; |
|
|
|
if ( !( iSlot == LOADOUT_POSITION_PRIMARY |
|
|| iSlot == LOADOUT_POSITION_SECONDARY |
|
|| iSlot == LOADOUT_POSITION_MELEE |
|
|| iSlot == LOADOUT_POSITION_PDA |
|
|| iSlot == LOADOUT_POSITION_PDA2 |
|
|| iSlot == LOADOUT_POSITION_BUILDING ) ) |
|
continue; |
|
|
|
// sort weapon by name by adding to weaponDict |
|
weaponDict.Insert( pDef->GetDefinitionName(), pDef->GetDefinitionIndex() ); |
|
} |
|
|
|
// add sorted weapon to the combobox |
|
FOR_EACH_DICT( weaponDict, i ) |
|
{ |
|
item_definition_index_t weaponDefIndex = weaponDict.Element( i ); |
|
bool bSelect = defIndexSelect == weaponDefIndex; |
|
pCombo->AddComboBoxEntry( weaponDict.GetElementName( i ), bSelect, CFmtStr( "%d", weaponDefIndex ), NULL ); |
|
} |
|
|
|
return pCombo; |
|
} |
|
|
|
void CRequiredItemsParam::CreateNewControl( KeyValues* pKV ) |
|
{ |
|
CEditorObjectNode* pRoot = new CEditorObjectNode( EditorObjectInitStruct{ this, pKV->GetName(), FLAGS_NONE } ); |
|
|
|
item_definition_index_t defIndexCurrent = (item_definition_index_t)pKV->GetInt( "loaner_defindex", INVALID_ITEM_DEF_INDEX ); |
|
CreateWeaponComboBox( { pRoot, "loaner_defindex", FLAG_NOT_DELETABLE }, "Loaner Item:", defIndexCurrent ); |
|
|
|
CQualifyingItemsParam* pQualifying = new CQualifyingItemsParam( EditorObjectInitStruct{ pRoot, "qualifying_items", FLAG_NOT_DELETABLE } ); |
|
pQualifying->InitControls( pKV->FindKey( "qualifying_items" ) ); |
|
|
|
BaseClass::CreateNewControl( pKV ); |
|
} |
|
|
|
void CRequiredItemsParam::CreateNewDefaultControl() |
|
{ |
|
int nDefindex = GetNextAvailableKeyNumber() + 1; |
|
int nObjectDefIndex = atoi( GetOwningEditable()->GetLiveData()->GetName() ); |
|
|
|
KeyValuesAD pKVName( CFmtStr( "%d", nDefindex ) ); |
|
pKVName->SetString( "token", CFmtStr( g_skNameTokenFormat, nObjectDefIndex, nDefindex ) ); |
|
CreateNewControl( pKVName ); |
|
} |
|
|
|
|
|
void CQualifyingItemsParam::CreateNewControl( KeyValues* pKV ) |
|
{ |
|
CEditorObjectNode* pNode = new CEditorObjectNode( EditorObjectInitStruct{ this, pKV->GetName(), FLAGS_NONE } ); |
|
|
|
item_definition_index_t defIndexCurrent = (item_definition_index_t)pKV->GetInt( "defindex", INVALID_ITEM_DEF_INDEX ); |
|
CreateWeaponComboBox( { pNode, "defindex", FLAGS_NONE }, "Qualifying Item:", defIndexCurrent ); |
|
|
|
BaseClass::CreateNewControl( pKV ); |
|
} |
|
|
|
void CQualifyingItemsParam::CreateNewDefaultControl() |
|
{ |
|
int nDefindex = GetNextAvailableKeyNumber() + 1; |
|
|
|
KeyValuesAD pKVQualifying( CFmtStr( "%d", nDefindex ) ); |
|
pKVQualifying->SetInt( "defindex", 0 ); |
|
|
|
CreateNewControl( pKVQualifying ); |
|
} |
|
|
|
void CObjectiveExpandable::CreateNewControl( KeyValues* pKV ) |
|
{ |
|
new CQuestObjectiveNode( this, pKV ); |
|
} |
|
|
|
void CObjectiveExpandable::CreateNewDefaultControl() |
|
{ |
|
int nDefindex = GetNextAvailableKeyNumber() + 1; |
|
|
|
KeyValuesAD pKVObjective( CFmtStr( "%d", nDefindex ) ); |
|
pKVObjective->SetInt( "description_string", 0 ); |
|
|
|
const int nQuestDefIndex = atoi( GetOwningEditable()->GetLiveData()->GetName() ); |
|
const int nObjDefIndex = ( ( nQuestDefIndex - g_nkFirstQuestDef ) + 1 ) * 100 + nDefindex; |
|
pKVObjective->SetInt( "defindex", nObjDefIndex ); |
|
pKVObjective->SetString( "description_string", CFmtStr( g_skObjectiveDescTokenFormat, nQuestDefIndex, nDefindex ) ); |
|
pKVObjective->SetBool( "optional", false ); |
|
pKVObjective->SetInt( "conditions_def_index", INVALID_QUEST_OBJECTIVE_CONDITIONS_INDEX ); |
|
pKVObjective->SetInt( "advanced", 0 ); |
|
|
|
CreateNewControl( pKVObjective ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CQuestObjectiveRestrictionNode::CQuestObjectiveRestrictionNode( EditorObjectInitStruct init, CTFQuestCondition *pCondition ) |
|
: BaseClass( { init.pParent, init.m_pszKeyName, init.nFlags | FLAG_HIGHLIGHT_MOUSEOVER } ) |
|
, m_pCondition( pCondition ) |
|
, m_pNewCondition( NULL ) |
|
{ |
|
CreateControlsForCondition(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CQuestObjectiveRestrictionNode::CreateControlsForCondition() |
|
{ |
|
CComboBoxEditorParam* pTypeParam = new CComboBoxEditorParam( { this, "type", FLAGS_NONE }, "Type:" ); |
|
|
|
CUtlVector< const char* > vecValidChildren; |
|
m_pCondition->GetValidTypes( vecValidChildren ); |
|
FOR_EACH_VEC( vecValidChildren, i ) |
|
{ |
|
bool bSelected = FStrEq( m_pCondition->GetConditionName(), vecValidChildren[ i ] ); |
|
pTypeParam->AddComboBoxEntry( vecValidChildren[ i ], bSelected, vecValidChildren[ i ], "changetype" ); |
|
} |
|
|
|
// Parameters for this node |
|
KeyValuesAD KVParams( "params" ); |
|
m_pCondition->GetRequiredParamKeys( KVParams ); |
|
|
|
KeyValuesAD outputKey( "output" ); |
|
m_pCondition->GetOutputKeyValues( outputKey ); |
|
|
|
FOR_EACH_TRUE_SUBKEY( KVParams, params ) |
|
{ |
|
const char *pszParamEnglishName = params->GetString( "english_name", NULL ); |
|
const char *pszParamName = params->GetName(); |
|
const char *pszLabelText = pszParamEnglishName ? pszParamEnglishName : pszParamName; |
|
const char *pszAction = FStrEq( pszParamName, "event_name" ) ? "changeevent" : NULL; |
|
|
|
const char* pszControlType = params->GetString( "control_type", "combo_box" ); // Default to combobox |
|
|
|
if ( FStrEq( "text_entry", pszControlType ) ) |
|
{ |
|
const char *pszOutput = outputKey->GetString( pszParamName, "" ); |
|
new CTextEntryEditorParam( { this, params->GetName(), FLAGS_NONE }, pszLabelText, pszOutput ); |
|
} |
|
else if ( FStrEq( "combo_box", pszControlType ) ) |
|
{ |
|
CComboBoxEditorParam* pNewParam = new CComboBoxEditorParam( { this, params->GetName(), FLAGS_NONE }, pszLabelText ); |
|
|
|
const char *pszOutput = outputKey->GetString( pszParamName, "" ); |
|
|
|
pNewParam->ClearComboBoxEntries(); |
|
|
|
FOR_EACH_TRUE_SUBKEY( params, pChoiceKey ) |
|
{ |
|
const char *pszChoiceName = pChoiceKey->GetName(); |
|
const char *pszChoiceEnglishName = pChoiceKey->GetString( "english_name", NULL ); |
|
|
|
bool bSelect = FStrEq( pszOutput, pszChoiceName ) || pChoiceKey == params->GetFirstTrueSubKey(); |
|
|
|
pNewParam->AddComboBoxEntry( pszChoiceEnglishName ? pszChoiceEnglishName : pszChoiceName, bSelect, pszChoiceName, pszAction ); |
|
} |
|
|
|
// Hide parameters where there's only 1 option |
|
pNewParam->SetFlag( FLAG_HIDDEN, pNewParam->GetComboBox()->GetItemCount() <= 1 ); |
|
} |
|
} |
|
|
|
// Children of this node |
|
CUtlVector< CTFQuestCondition* > vecChildConditions; |
|
m_pCondition->GetChildren( vecChildConditions ); |
|
FOR_EACH_VEC( vecChildConditions, iChild ) |
|
{ |
|
CTFQuestCondition* pChildCondition = vecChildConditions[ iChild ]; |
|
new CQuestObjectiveRestrictionNode( { this, CFmtStr( "%d", iChild ), FLAGS_NONE }, pChildCondition ); |
|
} |
|
|
|
CreateAddOpportunityParam(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CQuestObjectiveRestrictionNode::CreateAddOpportunityParam() |
|
{ |
|
int nChildCount = 0; |
|
FOR_EACH_VEC( GetChildren(), i ) |
|
{ |
|
if ( dynamic_cast< CQuestObjectiveRestrictionNode* >( GetChildren()[i] ) ) |
|
{ |
|
++nChildCount; |
|
} |
|
} |
|
|
|
bool bShowAddOpportunity = m_pCondition && nChildCount < m_pCondition->GetMaxInputCount() ; |
|
if ( m_pNewCondition && !bShowAddOpportunity ) |
|
{ |
|
delete m_pNewCondition; |
|
m_pNewCondition = NULL; |
|
} |
|
else if ( !m_pNewCondition && bShowAddOpportunity ) |
|
{ |
|
// Add empty potential node |
|
CUtlVector< const char* > vecValidChildren; |
|
m_pCondition->GetValidChildren( vecValidChildren ); |
|
if ( vecValidChildren.Count() ) |
|
{ |
|
m_pNewCondition = new CNewQuestObjectiveParam( { this, NULL, FLAGS_NONE }, NULL ); |
|
FOR_EACH_VEC( vecValidChildren, i ) |
|
{ |
|
m_pNewCondition->AddComboBoxEntry( vecValidChildren[ i ], false, vecValidChildren [ i ], NULL ); |
|
} |
|
} |
|
} |
|
} |
|
|
|
void CQuestObjectiveRestrictionNode::RemoveNode() |
|
{ |
|
// tell parent to remove me and my children |
|
if ( m_pCondition ) |
|
{ |
|
CTFQuestCondition *pParentCondition = m_pCondition->GetParent(); |
|
if ( pParentCondition ) |
|
{ |
|
pParentCondition->RemoveAndDeleteChild( m_pCondition ); |
|
} |
|
} |
|
|
|
m_pCondition = NULL; |
|
|
|
BaseClass::RemoveNode(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CQuestObjectiveRestrictionNode::SetNewType( const char *pszType ) |
|
{ |
|
// Delete all children |
|
FOR_EACH_VEC_BACK( m_vecChildren, i ) |
|
{ |
|
m_vecChildren[i]->MarkForDeletion(); |
|
} |
|
|
|
m_pNewCondition = NULL; |
|
|
|
|
|
// Create new restriction |
|
CTFQuestCondition* pParent = m_pCondition->GetParent(); |
|
if ( pParent && pParent->RemoveAndDeleteChild( m_pCondition ) ) |
|
{ |
|
m_pCondition = pParent->AddChildByName( pszType ); |
|
} |
|
else |
|
{ |
|
delete m_pCondition; |
|
m_pCondition = CreateEvaluatorByName( pszType, NULL ); |
|
} |
|
|
|
CreateControlsForCondition(); |
|
InvalidateChain(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CQuestObjectiveRestrictionNode::SetNewEvent( const char *pszEvent ) |
|
{ |
|
// We only have to blow up everything if we're an evaluator |
|
if ( !m_pCondition->IsEvaluator() ) |
|
{ |
|
return; |
|
} |
|
|
|
// Delete all children |
|
FOR_EACH_VEC_BACK( m_vecChildren, i ) |
|
{ |
|
m_vecChildren[i]->MarkForDeletion(); |
|
} |
|
|
|
m_pNewCondition = NULL; |
|
|
|
char szType[256]; |
|
V_sprintf_safe( szType, "%s", m_pCondition->GetConditionName() ); |
|
|
|
// Create new restriction |
|
CTFQuestCondition* pParent = m_pCondition->GetParent(); |
|
if ( pParent && pParent->RemoveAndDeleteChild( m_pCondition ) ) |
|
{ |
|
m_pCondition = pParent->AddChildByName( szType ); |
|
} |
|
else |
|
{ |
|
delete m_pCondition; |
|
m_pCondition = CreateEvaluatorByName( szType, NULL ); |
|
} |
|
|
|
V_sprintf_safe( m_szEventName, "%s", pszEvent ); |
|
|
|
m_pCondition->SetEventName( m_szEventName ); |
|
CreateControlsForCondition(); |
|
InvalidateChain(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CQuestObjectiveRestrictionNode::PerformLayout() |
|
{ |
|
BaseClass::PerformLayout(); |
|
|
|
CreateAddOpportunityParam(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CEditorQuest::CEditorQuest( KeyValues *pKV, Panel* pParent, const IEditableDataType* pEditable ) |
|
: CEditorObjectNode( EditorObjectInitStruct{ pParent, pKV->GetName(), FLAGS_NONE } ) |
|
{ |
|
SetOwningEditable( pEditable ); |
|
|
|
new CTextEntryEditorParam( { this, "name", FLAG_HIDDEN }, "Item Def Name:", pKV->GetString( "name" ) ); |
|
new CLocalizationEditorParam( { this, "item_name", FLAGS_NONE }, "Item Name:", pKV->GetString( "item_name" ) ); |
|
|
|
CComboBoxEditorParam *pPrefabParam = new CComboBoxEditorParam( { this, "prefab", FLAGS_NONE }, "Prefab:" ); |
|
int nChosenIndex = -1; |
|
for( int i=0; i < ARRAYSIZE( g_skQuestPrefabs ); ++i ) |
|
{ |
|
if ( FStrEq( g_skQuestPrefabs[i], pKV->GetString( "prefab" ) ) ) |
|
{ |
|
nChosenIndex = i; |
|
} |
|
|
|
bool bSelect = nChosenIndex == i || ( nChosenIndex == -1 && i == 0 ); |
|
pPrefabParam->AddComboBoxEntry( g_skQuestPrefabs[i], bSelect, g_skQuestPrefabs[i], NULL ); |
|
} |
|
|
|
// Get the quest keys |
|
KeyValues *pKVQuest = pKV->FindKey( "quest" ); |
|
|
|
// Create the panels to hold the quest def |
|
CEditorObjectNode *pQuestNode = new CEditorObjectNode( EditorObjectInitStruct{ this, "quest", FLAG_HIDDEN } ); |
|
|
|
CQuestNameNode* pNameNode = new CQuestNameNode( EditorObjectInitStruct{ pQuestNode, "names", FLAG_NOT_DELETABLE | FLAG_COLLAPSABLE } ); |
|
pNameNode->InitControls( pKVQuest->FindKey( "names" ) ); |
|
|
|
new CTextEntryEditorParam( { pQuestNode, "max_standard_points", FLAGS_NONE }, "Max Standard Points:", pKVQuest->GetString( "max_standard_points" ) ); |
|
new CTextEntryEditorParam( { pQuestNode, "max_bonus_points", FLAGS_NONE }, "Max Bonus Points:", pKVQuest->GetString( "max_bonus_points" ) ); |
|
new CTextEntryEditorParam( { pQuestNode, "reward", FLAGS_NONE }, "Reward:", pKVQuest->GetString( "reward" ) ); |
|
new CTextEntryEditorParam( { pQuestNode, "objectives_to_roll", FLAGS_NONE }, "Objectives to roll:", pKVQuest->GetString( "objectives_to_roll" ) ); |
|
new CTextEntryEditorParam( { pQuestNode, "mm_map", FLAGS_NONE }, "Casual MM Map:", pKVQuest->GetString( "mm_map" ) ); |
|
CComboBoxEditorParam *pThemeParam = new CComboBoxEditorParam( { pQuestNode, "theme", FLAGS_NONE }, "Theming:" ); |
|
nChosenIndex = -1; |
|
{ |
|
const auto& mapThemes = GetItemSchema()->GetQuestThemes(); |
|
FOR_EACH_MAP( mapThemes, i ) |
|
{ |
|
if ( FStrEq( mapThemes[i]->GetName(), pKVQuest->GetString( "theme" ) ) ) |
|
{ |
|
nChosenIndex = i; |
|
} |
|
|
|
bool bSelect = nChosenIndex == i || ( nChosenIndex == -1 && i == 0 ); |
|
pThemeParam->AddComboBoxEntry( mapThemes[i]->GetName(), bSelect, mapThemes[i]->GetName(), NULL ); |
|
} |
|
} |
|
|
|
CComboBoxEditorParam *pCorrespondingOperation = new CComboBoxEditorParam( { pQuestNode, "operation", FLAGS_NONE }, "Operation:" ); |
|
nChosenIndex = -1; |
|
{ |
|
const auto& mapOperations = GetItemSchema()->GetOperationDefinitions(); |
|
FOR_EACH_MAP( mapOperations, i ) |
|
{ |
|
if ( FStrEq( mapOperations[i]->GetName(), pKVQuest->GetString( "operation" ) ) ) |
|
{ |
|
nChosenIndex = i; |
|
} |
|
|
|
bool bSelect = nChosenIndex == i || ( nChosenIndex == -1 && i == 0 ); |
|
pCorrespondingOperation->AddComboBoxEntry( mapOperations[i]->GetName(), bSelect, mapOperations[i]->GetName(), NULL ); |
|
} |
|
} |
|
|
|
CQuestDescriptionNode* pDescNode = new CQuestDescriptionNode( EditorObjectInitStruct{ pQuestNode, "descriptions", FLAG_NOT_DELETABLE | FLAG_COLLAPSABLE | FLAG_COLLAPSED } ); |
|
pDescNode->InitControls( pKVQuest->FindKey( "descriptions" ) ); |
|
|
|
CRequiredItemsParam* pRequiredExpandable = new CRequiredItemsParam( EditorObjectInitStruct{ pQuestNode, "required_items", FLAG_NOT_DELETABLE | FLAG_COLLAPSABLE | FLAG_DONT_EXPORT } ); |
|
pRequiredExpandable->InitControls( pKVQuest->FindKey( "required_items" ) ); |
|
|
|
CObjectiveExpandable* pObjectiveExpandable = new CObjectiveExpandable( EditorObjectInitStruct{ pQuestNode, "objectives", FLAG_NOT_DELETABLE | FLAG_COLLAPSABLE } ); |
|
pObjectiveExpandable->InitControls( pKVQuest->FindKey( "objectives" ) ); |
|
|
|
// Gets the scrollbar to be the right height |
|
pParent->InvalidateLayout(); |
|
} |
|
|
|
|
|
CEditorQuest::~CEditorQuest() |
|
{} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
IEditableDataType::IEditableDataType( KeyValues* pKVData ) |
|
: m_pKVLiveData( pKVData->MakeCopy() ) |
|
, m_pKVSavedData( pKVData->MakeCopy() ) |
|
, m_pCurrentObject( NULL ) |
|
, m_bHasUnsavedChanges( false ) |
|
{} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
IEditableDataType::~IEditableDataType() |
|
{ |
|
// We own the keys |
|
if ( m_pKVLiveData ) |
|
{ |
|
m_pKVLiveData->deleteThis(); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Create the panels and store a pointer to them |
|
//----------------------------------------------------------------------------- |
|
void IEditableDataType::CreatePanels( Panel* pParent ) |
|
{ |
|
Assert( m_pCurrentObject == NULL ); |
|
m_pCurrentObject = CreateEditableObject_Internal( pParent ); |
|
m_pCurrentObject->ClearPendingChangesFlag(); |
|
|
|
UpdateButton(); |
|
} |
|
|
|
void IEditableDataType::DestroyPanels() |
|
{ |
|
if ( m_pCurrentObject ) |
|
{ |
|
m_pCurrentObject->MarkForDeletion(); |
|
m_pCurrentObject = NULL; |
|
} |
|
|
|
UpdateButton(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Given a type and a name, see if we match |
|
//----------------------------------------------------------------------------- |
|
bool IEditableDataType::MatchesCriteria( EType type, const char* pszName ) const |
|
{ |
|
return GetType() == type && FStrEq( pszName, m_pKVLiveData->GetName() ); |
|
} |
|
|
|
class CKeyValuesDumpToString : public IKeyValuesDumpContextAsText |
|
{ |
|
public: |
|
// Overrides developer level to dump in DevMsg, zero to dump as Msg |
|
CKeyValuesDumpToString() {} |
|
|
|
public: |
|
|
|
virtual bool KvWriteValue( KeyValues *val, int nIndentLevel ) OVERRIDE |
|
{ |
|
if ( !val ) |
|
{ |
|
return |
|
KvWriteIndent( nIndentLevel ) && |
|
KvWriteText( "<< NULL >>\n" ); |
|
} |
|
|
|
if ( !KvWriteIndent( nIndentLevel ) ) |
|
return false; |
|
|
|
if ( !KvWriteText( val->GetName() ) ) |
|
return false; |
|
|
|
if ( !KvWriteText( " " ) ) |
|
return false; |
|
|
|
if ( !KvWriteText( val->GetString() ) ) |
|
return false; |
|
|
|
return KvWriteText( "\n" ); |
|
} |
|
|
|
virtual bool KvWriteText( char const *szText ) OVERRIDE |
|
{ |
|
m_strDump.Append( szText ); |
|
return true; |
|
} |
|
|
|
CUtlString m_strDump; |
|
}; |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Saves any changes that have been made with the controls. Does NOT write to disk. |
|
//----------------------------------------------------------------------------- |
|
void IEditableDataType::SaveEdits() |
|
{ |
|
// Get the new keys |
|
KeyValues* tempKV = new KeyValues( "edits" ); |
|
tempKV->AddSubKey( m_pKVLiveData->MakeCopy() ); |
|
|
|
WriteObjectToKeyValues( false, tempKV ); |
|
|
|
// Update the live keys |
|
m_pKVLiveData->deleteThis(); |
|
m_pKVLiveData = tempKV->GetFirstTrueSubKey()->MakeCopy(); |
|
|
|
CKeyValuesDumpToString dumpOrig; |
|
CKeyValuesDumpToString dumpNew; |
|
|
|
// Dump into strings |
|
m_pKVLiveData->Dump( &dumpNew, 0, true ); |
|
m_pKVSavedData->Dump( &dumpOrig, 0, true ); |
|
|
|
// Compare the strings to check for a difference |
|
m_bHasUnsavedChanges = !FStrEq( dumpOrig.m_strDump, dumpNew.m_strDump ); |
|
|
|
if ( m_bHasUnsavedChanges ) |
|
{ |
|
ConColorMsg( Color( 0, 173, 53, 255 ), "Old:\n%s", dumpOrig.m_strDump.String() ); |
|
ConColorMsg( Color( 218, 128, 56, 255 ), "New:\n%s", dumpNew.m_strDump.String() ); |
|
} |
|
|
|
tempKV->deleteThis(); |
|
|
|
UpdateButton(); |
|
} |
|
|
|
void IEditableDataType::UpdateButton() |
|
{ |
|
Button* pButton = g_pQuestEditor->GetButtonForEditable( this ); |
|
if ( pButton ) |
|
{ |
|
IScheme *pScheme = vgui::scheme()->GetIScheme( pButton->GetScheme() ); |
|
Color buttonBGColor = pButton->GetSchemeColor("Button.BgColor", Color(0, 0, 0, 255), pScheme); |
|
Color buttonFGColor = pButton->GetSchemeColor("Button.FGColor", Color(0, 0, 0, 255), pScheme); |
|
|
|
if ( m_pCurrentObject ) |
|
{ |
|
buttonBGColor[0] = Min( buttonBGColor[0] + 70, 255 ); |
|
buttonBGColor[1] = Min( buttonBGColor[1] + 70, 255 ); |
|
buttonBGColor[2] = Min( buttonBGColor[2] + 70, 255 ); |
|
} |
|
|
|
if ( m_bHasUnsavedChanges ) |
|
{ |
|
buttonFGColor[0] = Min( buttonFGColor[0] + 150, 255 ); // Lil more red |
|
} |
|
|
|
pButton->SetDefaultColor( buttonFGColor, buttonBGColor ); |
|
pButton->SetArmedColor( buttonFGColor, pButton->GetButtonArmedBgColor() ); |
|
|
|
if ( GetType() == IEditableDataType::TYPE_QUEST ) |
|
{ |
|
char szItemName[256]; |
|
g_pVGuiLocalize->ConvertUnicodeToANSI( g_pVGuiLocalize->Find( m_pKVLiveData->GetString( "item_name" ) ), szItemName, sizeof( szItemName ) ); |
|
pButton->SetText( CFmtStr( "%s: %s", m_pKVLiveData->GetName(), szItemName ) ); |
|
} |
|
else |
|
{ |
|
pButton->SetText( CFmtStr( "%s: %s", m_pKVLiveData->GetName(), m_pKVLiveData->GetString( "name" ) ) ); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Serialize our object and save changes to disk |
|
//----------------------------------------------------------------------------- |
|
void IEditableDataType::SaveChangesToDisk() |
|
{ |
|
SaveEdits(); |
|
|
|
WriteDataToDisk( false ); |
|
|
|
// Clean out old save data and copy the new keys |
|
if ( m_pKVSavedData ) |
|
{ |
|
m_pKVSavedData->deleteThis(); |
|
} |
|
|
|
m_pKVSavedData = m_pKVLiveData->MakeCopy(); |
|
|
|
UpdateButton(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Remove our entry from any file we exist in. Remove our panels. |
|
// Delete our button that activates us. |
|
//----------------------------------------------------------------------------- |
|
void IEditableDataType::DeleteEntry() |
|
{ |
|
WriteDataToDisk( true ); |
|
|
|
if ( m_pCurrentObject ) |
|
{ |
|
m_pCurrentObject->SetFlag( FLAG_DELETED, true ); |
|
WriteLocalizationData(); |
|
} |
|
|
|
UpdateButton(); |
|
} |
|
|
|
void IEditableDataType::RevertChanges() |
|
{ |
|
Assert( m_pCurrentObject ); |
|
if ( !m_pCurrentObject ) |
|
return; |
|
|
|
// Delete old panels |
|
Panel* pCurrentParent = m_pCurrentObject->GetParent(); |
|
m_pCurrentObject->MarkForDeletion(); |
|
m_pCurrentObject = NULL; |
|
|
|
// Delete live keys, and copy over the saved ones to live |
|
m_pKVLiveData->deleteThis(); |
|
m_pKVLiveData = m_pKVSavedData->MakeCopy(); |
|
|
|
// Recreate panels |
|
CreatePanels( pCurrentParent ); |
|
CheckForChanges(); |
|
} |
|
|
|
void IEditableDataType::CheckForChanges() |
|
{ |
|
if ( m_pCurrentObject ) |
|
{ |
|
m_bHasUnsavedChanges = m_pCurrentObject->HasChanges( true ); |
|
UpdateButton(); |
|
} |
|
} |
|
|
|
void IEditableDataType::WriteObjectToKeyValues( bool bDelete, KeyValues* pKVExistingFileData ) |
|
{ |
|
KeyValuesAD tempKV( "temp" ); |
|
m_pCurrentObject->SerializeToKVs( tempKV, this ); |
|
|
|
FOR_EACH_SUBKEY( tempKV, pNewObjectKey ) |
|
{ |
|
KeyValues *pCurrentObjectKey = pKVExistingFileData->FindKey( pNewObjectKey->GetName() ); |
|
if ( pCurrentObjectKey ) |
|
{ |
|
if ( bDelete ) |
|
{ |
|
pCurrentObjectKey->deleteThis(); |
|
} |
|
else |
|
{ |
|
// copy all elems |
|
pCurrentObjectKey->Clear(); |
|
FOR_EACH_SUBKEY( pNewObjectKey, pElem ) |
|
{ |
|
pCurrentObjectKey->AddSubKey( pElem->MakeCopy() ); |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
pKVExistingFileData->AddSubKey( pNewObjectKey->MakeCopy() ); |
|
} |
|
} |
|
} |
|
|
|
|
|
int Sort_DefIndex( KeyValues* const* p1, KeyValues* const* p2 ) |
|
{ |
|
int n1 = atoi( (*p1)->GetName() ); |
|
int n2 = atoi( (*p2)->GetName() ); |
|
|
|
return n1 - n2; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Write quest data to "tf/scripts/items/unencrypted/_items_quests.txt" |
|
//----------------------------------------------------------------------------- |
|
void CEditableQuestDataType::WriteDataToDisk( bool bDelete ) |
|
{ |
|
// Wrap all of the quest in a "quests" keyvalue |
|
CUtlBuffer bufRawData; |
|
bufRawData.SetBufferType( true, true ); |
|
bufRawData.PutString( CFmtStr( "\"%s\"\n{\n", "quests") ); |
|
|
|
bool bReadFileOK = g_pFullFileSystem->ReadFile( g_skQuestDefFile, NULL, bufRawData ); |
|
if ( !bReadFileOK ) |
|
{ |
|
AssertMsg1( false, "Couldn't load file %s for saving!", g_skQuestDefFile ); |
|
return; |
|
} |
|
|
|
bufRawData.PutString( "\n}" ); |
|
|
|
// Load the buffer into keyvalues |
|
KeyValuesAD pKVQuestItemData( "quests" ); |
|
pKVQuestItemData->LoadFromBuffer( NULL, bufRawData ); |
|
|
|
WriteObjectToKeyValues( bDelete, pKVQuestItemData ); |
|
|
|
// Sort by defindex |
|
CUtlVector< KeyValues* > vecQuests; |
|
FOR_EACH_SUBKEY( pKVQuestItemData, pItemKey ) |
|
{ |
|
vecQuests.AddToTail( pItemKey ); |
|
} |
|
vecQuests.Sort( &Sort_DefIndex ); |
|
|
|
|
|
// Write housekeeping CSV file |
|
FileHandle_t fileHandle = g_pFullFileSystem->Open( g_skQuestObjectivesHouseKeepingFile, "wt" ); |
|
|
|
// Write them out in order |
|
CUtlBuffer buffer; |
|
FOR_EACH_VEC( vecQuests, i ) |
|
{ |
|
// Write a row as we go through each quest item |
|
KeyValues* pKVQuestBlock = vecQuests[i]->FindKey( "quest" ); |
|
if ( pKVQuestBlock ) |
|
{ |
|
KeyValues* pKVObjectives = pKVQuestBlock->FindKey( "objectives" ); |
|
if ( pKVObjectives ) |
|
{ |
|
FOR_EACH_TRUE_SUBKEY( pKVObjectives, pKVEntry ) |
|
{ |
|
char szDesc[256]; |
|
g_pVGuiLocalize->ConvertUnicodeToANSI( g_pVGuiLocalize->Find( pKVEntry->GetString( "description_string" ) ), szDesc, sizeof( szDesc ) ); |
|
g_pFullFileSystem->FPrintf( fileHandle, "%d,%d,%d,%s,\n", pKVEntry->GetInt( "DefIndex" ), pKVEntry->GetInt( "points" ), pKVEntry->GetInt( "advanced" ), szDesc ); |
|
} |
|
} |
|
} |
|
|
|
vecQuests[i]->RecursiveSaveToFile( buffer, 0, false, true ); |
|
} |
|
|
|
g_pFullFileSystem->Close( fileHandle ); |
|
|
|
char szCorrectCaseFilePath[MAX_PATH]; |
|
g_pFullFileSystem->GetCaseCorrectFullPath( g_skQuestDefFile, szCorrectCaseFilePath ); |
|
CP4AutoEditFile a( szCorrectCaseFilePath ); |
|
|
|
if ( !g_pFullFileSystem->WriteFile( szCorrectCaseFilePath, NULL, buffer ) ) |
|
{ |
|
Warning( "Failed to write data to %s", g_skQuestDefFile ); |
|
} |
|
} |
|
|
|
IEditorObject* CEditableQuestDataType::CreateEditableObject_Internal( Panel* pParent ) const |
|
{ |
|
CEditorQuest* pNewQuest = new CEditorQuest( m_pKVLiveData, pParent, this ); |
|
return pNewQuest; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Write quest data to "tf/scripts/items/unencrypted/_items_quest_objective_definitions.txt" |
|
//----------------------------------------------------------------------------- |
|
void CEditableObjectiveConditionDataType::WriteDataToDisk( bool bDelete ) |
|
{ |
|
// Wrap all of the quest in a "quests" keyvalue |
|
CUtlBuffer bufRawData; |
|
bufRawData.SetBufferType( true, true ); |
|
|
|
bool bReadFileOK = g_pFullFileSystem->ReadFile( g_skQuestObjectivesConditionsDefFile, NULL, bufRawData ); |
|
if ( !bReadFileOK ) |
|
{ |
|
AssertMsg1( false, "Couldn't load file %s for saving!", g_skQuestObjectivesConditionsDefFile ); |
|
return; |
|
} |
|
|
|
// Load the buffer into keyvalues |
|
KeyValuesAD pKVQuestObjectivesData( "quest_objective_conditions" ); |
|
pKVQuestObjectivesData->LoadFromBuffer( NULL, bufRawData ); |
|
|
|
WriteObjectToKeyValues( bDelete, pKVQuestObjectivesData ); |
|
|
|
// Sort by defindex |
|
CUtlVector< KeyValues* > vecQuestObjectives; |
|
FOR_EACH_SUBKEY( pKVQuestObjectivesData, pItemKey ) |
|
{ |
|
vecQuestObjectives.AddToTail( pItemKey ); |
|
} |
|
vecQuestObjectives.Sort( &Sort_DefIndex ); |
|
|
|
KeyValuesAD pKVSorted( "quest_objective_conditions" ); |
|
|
|
// Write them out in order |
|
FOR_EACH_VEC( vecQuestObjectives, i ) |
|
{ |
|
pKVSorted->AddSubKey( vecQuestObjectives[i]->MakeCopy() ); |
|
} |
|
|
|
// Write the definitions |
|
{ |
|
CUtlBuffer buffer; |
|
pKVSorted->RecursiveSaveToFile( buffer, 0, false, true ); |
|
|
|
char szCorrectCaseFilePath[MAX_PATH]; |
|
g_pFullFileSystem->GetCaseCorrectFullPath( g_skQuestObjectivesConditionsDefFile, szCorrectCaseFilePath ); |
|
CP4AutoEditFile a( szCorrectCaseFilePath ); |
|
|
|
if ( !g_pFullFileSystem->WriteFile( szCorrectCaseFilePath, NULL, buffer ) ) |
|
{ |
|
Warning( "Failed to write data to %s", g_skQuestObjectivesConditionsDefFile ); |
|
} |
|
} |
|
} |
|
|
|
IEditorObject* CEditableObjectiveConditionDataType::CreateEditableObject_Internal( Panel* pParent ) const |
|
{ |
|
CEditorObjectNode *pConditionDef = new CEditorObjectNode( EditorObjectInitStruct{ pParent, m_pKVLiveData->GetName(), FLAG_HIDDEN } ); |
|
pConditionDef->SetOwningEditable( this ); |
|
|
|
new CTextEntryEditorParam( { pConditionDef, "name", FLAGS_NONE }, "Conditions name:", m_pKVLiveData->GetString( "name" ) ); |
|
|
|
CRequiredItemsParam* pRequiredExpandable = new CRequiredItemsParam( EditorObjectInitStruct{ pConditionDef, "required_items", FLAG_NOT_DELETABLE | FLAG_COLLAPSABLE | FLAG_DONT_EXPORT } ); |
|
pRequiredExpandable->InitControls( m_pKVLiveData->FindKey( "required_items" ) ); |
|
|
|
KeyValues* pKVConditionLogic = m_pKVLiveData->FindKey( "condition_logic" ); |
|
|
|
const char *pszType = pKVConditionLogic->GetString( "type" ); |
|
CTFQuestCondition *pCondition = CreateEvaluatorByName( pszType, NULL ); |
|
|
|
if ( !pCondition->BInitFromKV( pKVConditionLogic, NULL ) ) |
|
{ |
|
Assert( false ); |
|
} |
|
|
|
new CQuestObjectiveRestrictionNode( { pConditionDef, "condition_logic", FLAGS_NONE }, pCondition ); |
|
|
|
return pConditionDef; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CQuestEditorPanel::CQuestEditorPanel( Panel *pParent, const char *pszName ) |
|
: Frame( pParent, pszName ) |
|
, m_pCurrentOpenEdit( NULL ) |
|
, m_eCurrentSelectionMode( SELECTION_MODE_NONE ) |
|
{ |
|
SetTitle( "Quest Editor", true ); |
|
|
|
memset( m_pButtonsFilterTextEntry, NULL, sizeof( m_pButtonsFilterTextEntry ) ); |
|
m_pEditingPanel = new CExScrollingEditablePanel( this, "EditingPanel" ); |
|
m_pButtonsContainers[ IEditableDataType::TYPE_QUEST ] = new CExScrollingEditablePanel( this, "QuestListContainer" ); |
|
m_pButtonsContainers[ IEditableDataType::TYPE_OBJECTIVE_CONDITIONS ] = new CExScrollingEditablePanel( this, "QuestObjectiveConditionsContainer" ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CQuestEditorPanel::Deploy() |
|
{ |
|
PopulateExistingQuests(); |
|
|
|
SetVisible( true ); |
|
MakePopup(); |
|
MoveToFront(); |
|
SetKeyBoardInputEnabled(true); |
|
SetMouseInputEnabled(true); |
|
InvalidateLayout( true, true ); |
|
|
|
// 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)); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CQuestEditorPanel::ApplySchemeSettings( IScheme *pScheme ) |
|
{ |
|
BaseClass::ApplySchemeSettings( pScheme ); |
|
|
|
LoadControlSettings( "Resource/UI/econ/QuestEditor.res" ); |
|
|
|
m_pButtonsFilterTextEntry[ IEditableDataType::TYPE_QUEST ] = FindControl< TextEntry >( "QuestsFilter" ); |
|
if ( m_pButtonsFilterTextEntry[ IEditableDataType::TYPE_QUEST ] ) |
|
{ |
|
m_pButtonsFilterTextEntry[ IEditableDataType::TYPE_QUEST ]->AddActionSignalTarget( this ); |
|
} |
|
m_pButtonsFilterTextEntry[ IEditableDataType::TYPE_OBJECTIVE_CONDITIONS ] = FindControl< TextEntry >( "ConditionsFilter" ); |
|
if ( m_pButtonsFilterTextEntry[ IEditableDataType::TYPE_OBJECTIVE_CONDITIONS ] ) |
|
{ |
|
m_pButtonsFilterTextEntry[ IEditableDataType::TYPE_OBJECTIVE_CONDITIONS ]->AddActionSignalTarget( this ); |
|
} |
|
|
|
Label *pP4Warning = FindControl< Label >( "P4Warning" ); |
|
if ( pP4Warning ) |
|
{ |
|
pP4Warning->SetVisible( p4 == NULL ); |
|
} |
|
|
|
Button* pSaveButton = FindControl< Button >( "SaveButton" ); |
|
if ( pSaveButton ) |
|
{ |
|
pSaveButton->SetEnabled( p4 != NULL ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CQuestEditorPanel::ApplySettings( KeyValues *inResourceData ) |
|
{ |
|
BaseClass::ApplySettings( inResourceData ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CQuestEditorPanel::PerformLayout() |
|
{ |
|
BaseClass::PerformLayout(); |
|
|
|
for ( int nType = 0; nType < IEditableDataType::NUM_TYPES; ++nType ) |
|
{ |
|
UpdateButtons( (IEditableDataType::EType)nType ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CQuestEditorPanel::UpdateButtons( IEditableDataType::EType eType ) |
|
{ |
|
m_pButtonsContainers[ eType ]->ResetScrollAmount(); |
|
|
|
// Get the text out of the text entry |
|
char szFilterText[256]; |
|
m_pButtonsFilterTextEntry[ eType ]->GetText( szFilterText, sizeof( szFilterText ) ); |
|
Q_strlower( szFilterText ); |
|
|
|
int yPos = 5; |
|
FOR_EACH_VEC( m_vecEditableButtons[ eType ], i ) |
|
{ |
|
Button* pButton = m_vecEditableButtons[ eType ][ i ]; |
|
|
|
// Get the text out of the button |
|
char szButtonText[256]; |
|
pButton->GetText( szButtonText, sizeof( szButtonText ) ); |
|
Q_strlower( szButtonText ); |
|
|
|
// Substring search for the text entry text in the button text |
|
if ( V_strstr( szButtonText, szFilterText ) == NULL ) |
|
{ |
|
pButton->SetVisible( false ); |
|
continue; |
|
} |
|
|
|
pButton->SetVisible( true ); |
|
|
|
float flWideScale = 1.f; |
|
pButton->SetWide( pButton->GetParent()->GetWide() * flWideScale ); |
|
pButton->SetTall( 20 ); |
|
pButton->SetPos( 0, yPos ); |
|
yPos += pButton->GetTall() + 5 ; |
|
} |
|
|
|
m_pButtonsContainers[ eType ]->InvalidateLayout(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CQuestEditorPanel::OnCommand( const char *command ) |
|
{ |
|
if ( Q_strnicmp( "select", command, 6 ) == 0 ) |
|
{ |
|
// comes in the form "select(type) (name)" |
|
const char* pszType = command + 6; |
|
IEditableDataType::EType eType = (IEditableDataType::EType)atoi( pszType ); |
|
// Jump past the first ' ' and grab whatever is left as the name |
|
const char* pszName = strchr( pszType, ' ' ) + 1; |
|
|
|
if ( m_eCurrentSelectionMode == SELECTION_MODE_QUEST_OBJECTIVE && eType == IEditableDataType::TYPE_OBJECTIVE_CONDITIONS ) |
|
{ |
|
m_eCurrentSelectionMode = SELECTION_MODE_NONE; |
|
|
|
Panel* pSelectionpanel = m_hSelectionPanel.Get(); |
|
if ( pSelectionpanel ) |
|
{ |
|
PostMessage( pSelectionpanel, new KeyValues( "ObjectiveSelected", "defindex", pszName ) ); |
|
} |
|
} |
|
else |
|
{ |
|
if ( m_pCurrentOpenEdit ) |
|
{ |
|
// This the one that's already open? Don't do anything |
|
if ( FStrEq( pszName, m_pCurrentOpenEdit->GetLiveData()->GetName() ) ) |
|
{ |
|
return; |
|
} |
|
|
|
// We have something open. Close it down, saving live edits |
|
CloseEdit( m_pCurrentOpenEdit ); |
|
m_pCurrentOpenEdit = NULL; |
|
} |
|
|
|
m_pEditingPanel->ResetScrollAmount(); |
|
m_pCurrentOpenEdit = OpenForEdit( eType, pszName, m_pEditingPanel ); |
|
m_pEditingPanel->InvalidateLayout(); |
|
} |
|
|
|
return; |
|
} |
|
else if ( Q_stricmp( "revert", command ) == 0 ) |
|
{ |
|
if ( m_pCurrentOpenEdit ) |
|
{ |
|
m_pCurrentOpenEdit->RevertChanges(); |
|
} |
|
|
|
ResetQuestSelectionState(); |
|
} |
|
else if ( Q_stricmp( "save", command ) == 0 ) |
|
{ |
|
WriteLocalizationData(); |
|
|
|
FOR_EACH_VEC( m_vecOpenEdits, i ) |
|
{ |
|
m_vecOpenEdits[ i ]->SaveChangesToDisk(); |
|
} |
|
|
|
ResetQuestSelectionState(); |
|
|
|
return; |
|
} |
|
else if ( Q_stricmp( "newquest", command ) == 0 ) |
|
{ |
|
CloseEdit( m_pCurrentOpenEdit ); |
|
m_pEditingPanel->ResetScrollAmount(); |
|
IEditableDataType* pNewEditable = CreateNewQuest(); |
|
m_pCurrentOpenEdit = OpenForEdit( IEditableDataType::TYPE_QUEST, CFmtStr( "%s", pNewEditable->GetLiveData()->GetName() ), m_pEditingPanel ); |
|
ResetQuestSelectionState(); |
|
} |
|
else if ( Q_stricmp( "newobjcond", command ) == 0 ) |
|
{ |
|
CloseEdit( m_pCurrentOpenEdit ); |
|
m_pEditingPanel->ResetScrollAmount(); |
|
IEditableDataType* pNewEditable = CreateNewObjectiveCondition(); |
|
m_pCurrentOpenEdit = OpenForEdit( IEditableDataType::TYPE_OBJECTIVE_CONDITIONS, CFmtStr( "%s", pNewEditable->GetLiveData()->GetName() ), m_pEditingPanel ); |
|
ResetQuestSelectionState(); |
|
} |
|
else if ( Q_stricmp( "delete", command ) == 0 ) |
|
{ |
|
if ( m_pCurrentOpenEdit ) |
|
{ |
|
m_pCurrentOpenEdit->DeleteEntry(); |
|
CloseEdit( m_pCurrentOpenEdit ); |
|
|
|
Button* pButton = GetButtonForEditable( m_pCurrentOpenEdit ); |
|
Assert( pButton ); |
|
// Delete the button associated with this editable |
|
if( pButton ) |
|
{ |
|
if ( !m_vecEditableButtons[ m_pCurrentOpenEdit->GetType() ].FindAndRemove( pButton ) ) |
|
{ |
|
AssertMsg( false, "Could not find button to remove when deleting editable!" ); |
|
} |
|
pButton->MarkForDeletion(); |
|
InvalidateLayout(); |
|
} |
|
|
|
// Remove this editable from the list |
|
if ( !m_vecEditableData.FindAndRemove( m_pCurrentOpenEdit ) ) |
|
{ |
|
AssertMsg( false, "Could not find editable to remove when deleting editable!" ); |
|
} |
|
|
|
delete m_pCurrentOpenEdit; |
|
m_pCurrentOpenEdit = NULL; |
|
} |
|
ResetQuestSelectionState(); |
|
} |
|
else if ( Q_stricmp( "open_edit_context", command ) == 0 ) |
|
{ |
|
OpenEditContextMenu(); |
|
ResetQuestSelectionState(); |
|
} |
|
|
|
BaseClass::OnCommand( command ); |
|
} |
|
|
|
void CQuestEditorPanel::OnThink() |
|
{ |
|
FOR_EACH_VEC( m_vecOpenEdits, i ) |
|
{ |
|
engine->Con_NPrintf( i, CFmtStr( "%s %s", m_vecOpenEdits[i]->GetType() == IEditableDataType::TYPE_OBJECTIVE_CONDITIONS ? "Condition" : "Quest", m_vecOpenEdits[i]->GetLiveData()->GetName() ) ); |
|
} |
|
|
|
BaseClass::OnThink(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Try to find the right editable to open |
|
//----------------------------------------------------------------------------- |
|
IEditableDataType* CQuestEditorPanel::OpenForEdit( IEditableDataType::EType type, const char* pszName, Panel* pParent ) |
|
{ |
|
FOR_EACH_VEC( m_vecEditableData, i ) |
|
{ |
|
if ( m_vecEditableData[i]->MatchesCriteria( type, pszName ) ) |
|
{ |
|
m_vecEditableData[i]->CreatePanels( pParent ); |
|
|
|
FOR_EACH_VEC( m_vecOpenEdits, j ) |
|
{ |
|
if ( m_vecOpenEdits[j] == m_vecEditableData[i] ) |
|
{ |
|
AssertMsg1( false, "Editable with name %s was already open for edit!", m_vecEditableData[i]->GetLiveData()->GetName() ); |
|
m_vecOpenEdits.Remove( j ); |
|
} |
|
} |
|
|
|
m_vecOpenEdits.AddToTail( m_vecEditableData[i] ); |
|
return m_vecEditableData[i]; |
|
} |
|
} |
|
|
|
Assert( !"Failed to find editable for edit!" ); |
|
return NULL; |
|
} |
|
|
|
void CQuestEditorPanel::CloseEdit( IEditableDataType* pEditable ) |
|
{ |
|
if ( !pEditable ) |
|
return; |
|
|
|
FOR_EACH_VEC( m_vecOpenEdits, i ) |
|
{ |
|
if ( m_vecOpenEdits[i] == pEditable ) |
|
{ |
|
m_vecOpenEdits.Remove( i ); |
|
pEditable->SaveEdits(); |
|
pEditable->DestroyPanels(); |
|
return; |
|
} |
|
} |
|
|
|
AssertMsg1( false, "Editable with name %s wasn't open for edit!", pEditable->GetLiveData()->GetName() ); |
|
} |
|
|
|
bool CQuestEditorPanel::IsOpenForEdit( const IEditableDataType* pEditable ) const |
|
{ |
|
Assert( pEditable ); |
|
if ( !pEditable ) |
|
return false; |
|
|
|
FOR_EACH_VEC( m_vecOpenEdits, i ) |
|
{ |
|
if ( m_vecOpenEdits[i] == pEditable ) |
|
{ |
|
return true; |
|
} |
|
} |
|
|
|
return false; |
|
} |
|
|
|
Button* CQuestEditorPanel::GetButtonForEditable( const IEditableDataType* pEditable ) const |
|
{ |
|
IEditableDataType::EType eType = pEditable->GetType(); |
|
|
|
auto& vecButtons = m_vecEditableButtons[ eType ]; |
|
FOR_EACH_VEC( vecButtons, i ) |
|
{ |
|
if ( vecButtons[i] == pEditable->GetButton() ) |
|
{ |
|
return vecButtons[i]; |
|
} |
|
} |
|
|
|
return NULL; |
|
} |
|
|
|
template< typename T > |
|
IEditableDataType* CQuestEditorPanel::AddNewEditableKVData( KeyValues* pKVData, const char* pszName ) |
|
{ |
|
IEditableDataType* pNewEditable = new T( pKVData ); |
|
IEditableDataType::EType eType = pNewEditable->GetType(); |
|
m_vecEditableData.AddToTail( pNewEditable ); |
|
|
|
Button *pButton = new Button( m_pButtonsContainers[ eType ] |
|
, "objectivebutton" |
|
, CFmtStr( "%s: %s", pKVData->GetName(), pszName ) |
|
, this |
|
, CFmtStr( "select%d %s", eType, pKVData->GetName() ) ); |
|
|
|
pNewEditable->SetButton( pButton ); |
|
m_vecEditableButtons[ eType ].AddToTail( pButton ); |
|
|
|
InvalidateLayout(); |
|
|
|
return pNewEditable; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CQuestEditorPanel::PopulateExistingQuests() |
|
{ |
|
m_vecEditableData.PurgeAndDeleteElements(); |
|
|
|
// Quest data |
|
{ |
|
// Quests are a little strange. In the quest file, there is no root key because quests |
|
// are items and are spliced right into the middle of all the other items. To handle this |
|
// We add "quests" |
|
// { |
|
// << all the stuff from the file >> |
|
// } |
|
// To make parsing easier |
|
CUtlBuffer bufRawData; |
|
bufRawData.SetBufferType( true, true ); |
|
bufRawData.PutString( "\"quests\"\n{\n" ); |
|
bool bReadFileOK = g_pFullFileSystem->ReadFile( g_skQuestDefFile, NULL, bufRawData ); |
|
if ( !bReadFileOK ) |
|
{ |
|
AssertMsg1( false, "Couldn't load quest file %s for saving!", g_skQuestDefFile ); |
|
return; |
|
} |
|
bufRawData.PutString( "\n}" ); |
|
|
|
// Load quest data from file |
|
KeyValuesAD pKVQuestDefinitions( "quests" ); |
|
pKVQuestDefinitions->LoadFromBuffer( NULL, bufRawData ); |
|
|
|
// Create editable objects and buttons for each |
|
FOR_EACH_TRUE_SUBKEY( pKVQuestDefinitions, pKVQuest ) |
|
{ |
|
char szItemName[256]; |
|
g_pVGuiLocalize->ConvertUnicodeToANSI( g_pVGuiLocalize->Find( pKVQuest->GetString( "item_name" ) ), szItemName, sizeof( szItemName ) ); |
|
|
|
AddNewEditableKVData< CEditableQuestDataType >( pKVQuest, szItemName ); |
|
} |
|
} |
|
|
|
// Objective data |
|
{ |
|
CUtlBuffer bufRawData; |
|
bufRawData.SetBufferType( true, true ); |
|
|
|
// Now go read the objective conditions file |
|
bool bReadFileOK = g_pFullFileSystem->ReadFile( g_skQuestObjectivesConditionsDefFile, NULL, bufRawData ); |
|
if ( !bReadFileOK ) |
|
{ |
|
AssertMsg1( false, "Couldn't load quest file %s for saving!", g_skQuestObjectivesConditionsDefFile ); |
|
return; |
|
} |
|
|
|
// Load objective data from file |
|
KeyValuesAD pKVObjectiveConditions( "objectives" ); |
|
pKVObjectiveConditions->LoadFromBuffer( NULL, bufRawData ); |
|
|
|
// Create editable objects and buttons for each |
|
FOR_EACH_TRUE_SUBKEY( pKVObjectiveConditions, pKVCondition ) |
|
{ |
|
AddNewEditableKVData< CEditableObjectiveConditionDataType >( pKVCondition, pKVCondition->GetString( "name" ) ); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Create a new quest with the next available itemdefindex |
|
//----------------------------------------------------------------------------- |
|
IEditableDataType* CQuestEditorPanel::CreateNewQuest() |
|
{ |
|
// Find the next item def to use |
|
int nNextQuestDefIndex = 0; |
|
FOR_EACH_VEC( m_vecEditableData, i ) |
|
{ |
|
IEditableDataType* pData = m_vecEditableData[ i ]; |
|
if ( pData->GetType() == IEditableDataType::TYPE_QUEST ) |
|
{ |
|
nNextQuestDefIndex = Max( nNextQuestDefIndex, atoi( pData->GetLiveData()->GetName() ) ); |
|
} |
|
} |
|
|
|
++nNextQuestDefIndex; |
|
|
|
// Create keyvalues to describe a default quest |
|
KeyValuesAD pKVNewQuest( CFmtStr( "%d", nNextQuestDefIndex ) ); |
|
pKVNewQuest->SetString( "name", CFmtStr( g_skItemNameFormat, nNextQuestDefIndex ) ); |
|
pKVNewQuest->SetString( "item_name", CFmtStr( g_skNameTokenFormat, nNextQuestDefIndex ) ); |
|
pKVNewQuest->SetString( "prefab", g_skQuestPrefabs[0] ); |
|
|
|
// Tool keys |
|
KeyValues *pKeyQuestBlock = pKVNewQuest->CreateNewKey(); pKeyQuestBlock->SetName( "quest" ); |
|
pKeyQuestBlock->SetInt( "max_standard_points", 100 ); |
|
pKeyQuestBlock->SetInt( "max_bonus_points", 30 ); |
|
pKeyQuestBlock->SetInt( "objectives_to_roll", 1 ); |
|
pKeyQuestBlock->SetString( "reward", "contract_lootlist_1" ); |
|
pKeyQuestBlock->SetString( "theme", GetItemSchema()->GetQuestThemes()[0]->GetName() ); |
|
KeyValues *pKeyObjectiveBlock = pKeyQuestBlock->CreateNewKey(); pKeyObjectiveBlock->SetName( "objectives" ); |
|
|
|
return AddNewEditableKVData< CEditableQuestDataType >( pKVNewQuest, pKVNewQuest->GetString( "name" ) ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Create a new conditions with the next available defindex |
|
//----------------------------------------------------------------------------- |
|
IEditableDataType* CQuestEditorPanel::CreateNewObjectiveCondition() |
|
{ |
|
int nNextDefIndex = 0; |
|
FOR_EACH_VEC( m_vecEditableData, i ) |
|
{ |
|
IEditableDataType* pData = m_vecEditableData[ i ]; |
|
if ( pData->GetType() == IEditableDataType::TYPE_OBJECTIVE_CONDITIONS ) |
|
{ |
|
nNextDefIndex = Max( nNextDefIndex, atoi( pData->GetLiveData()->GetName() ) ); |
|
} |
|
} |
|
|
|
++nNextDefIndex; |
|
|
|
KeyValuesAD pKVNewObjCond( CFmtStr( "%d", nNextDefIndex ) ); |
|
pKVNewObjCond->SetString( "name", "*** New Objective ***" ); |
|
|
|
KeyValues* pKVConditionsBlock = pKVNewObjCond->CreateNewKey(); |
|
pKVConditionsBlock->SetName( "condition_logic" ); |
|
pKVConditionsBlock->SetString( "event_name", "player_score_changed" ); |
|
pKVConditionsBlock->SetString( "score_key_name", "delta" ); |
|
pKVConditionsBlock->SetString( "type", "event_listener" ); |
|
|
|
return AddNewEditableKVData< CEditableObjectiveConditionDataType >( pKVNewObjCond, pKVNewObjCond->GetString( "name" ) ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Open up a context menu with actions for the editing item |
|
//----------------------------------------------------------------------------- |
|
void CQuestEditorPanel::OpenEditContextMenu() |
|
{ |
|
Menu *pContextMenu = new Menu( this, "ContextMenu" ); |
|
|
|
pContextMenu->AddMenuItem( "Save", this, new KeyValues( "save" ) ); |
|
pContextMenu->AddMenuItem( "Revert", this, new KeyValues( "revert" ) ); |
|
pContextMenu->AddSeparator(); |
|
pContextMenu->AddMenuItem( "Delete", this, new KeyValues( "delete" ) ); |
|
|
|
// Position to the cursor's position |
|
int nX, nY; |
|
g_pVGuiInput->GetCursorPosition( nX, nY ); |
|
pContextMenu->SetPos( nX - 1, nY - 1 ); |
|
|
|
pContextMenu->SetVisible(true); |
|
pContextMenu->AddActionSignalTarget(this); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CQuestEditorPanel::OnTextChanged( KeyValues *data ) |
|
{ |
|
Panel *pPanel = reinterpret_cast< vgui::Panel* >( data->GetPtr( "panel" ) ); |
|
|
|
for ( int nType = 0; nType < IEditableDataType::NUM_TYPES; ++nType ) |
|
{ |
|
if ( pPanel == m_pButtonsFilterTextEntry[ nType ] ) |
|
{ |
|
UpdateButtons( (IEditableDataType::EType)nType ); |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CQuestEditorPanel::OnSelectQuestObjective( KeyValues *data ) |
|
{ |
|
m_hSelectionPanel = reinterpret_cast< vgui::Panel* >( data->GetPtr( "panel" ) ); |
|
m_eCurrentSelectionMode = SELECTION_MODE_QUEST_OBJECTIVE; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CQuestEditorPanel::CheckForChanges() |
|
{ |
|
FOR_EACH_VEC( m_vecEditableData, i ) |
|
{ |
|
m_vecEditableData[i]->CheckForChanges(); |
|
} |
|
} |
|
|
|
#endif // STAGING_ONLY
|
|
|