Merge pull request #182 from Petercov/mapbase-feature/dynint-loader-enhancement

NPCs can load dynamic interactions from all animation MDLs
This commit is contained in:
Blixibon 2022-04-26 14:44:18 -05:00 committed by GitHub
commit d525ca02b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -14719,326 +14719,356 @@ bool CAI_BaseNPC::IsAllowedToDodge( void )
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: // Purpose:
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CAI_BaseNPC::ParseScriptedNPCInteractions( void ) void CAI_BaseNPC::ParseScriptedNPCInteractions(void)
{ {
// Already parsed them? // Already parsed them?
if ( m_ScriptedInteractions.Count() ) if (m_ScriptedInteractions.Count())
return; return;
// Parse the model's key values and find any dynamic interactions // Parse the model's key values and find any dynamic interactions
KeyValues *modelKeyValues = new KeyValues(""); KeyValues* modelKeyValues = new KeyValues("");
CUtlBuffer buf( 1024, 0, CUtlBuffer::TEXT_BUFFER ); CUtlBuffer buf(1024, 0, CUtlBuffer::TEXT_BUFFER);
if (! modelinfo->GetModelKeyValue( GetModel(), buf )) if (!modelinfo->GetModelKeyValue(GetModel(), buf))
return; return;
if ( modelKeyValues->LoadFromBuffer( modelinfo->GetModelName( GetModel() ), buf ) ) if (modelKeyValues->LoadFromBuffer(modelinfo->GetModelName(GetModel()), buf))
{ {
// Do we have a dynamic interactions section?
KeyValues *pkvInteractions = modelKeyValues->FindKey("dynamic_interactions");
if ( pkvInteractions )
{
KeyValues *pkvNode = pkvInteractions->GetFirstSubKey();
while ( pkvNode )
{
ScriptedNPCInteraction_t sInteraction;
sInteraction.iszInteractionName = AllocPooledString( pkvNode->GetName() );
#ifdef MAPBASE #ifdef MAPBASE
// The method for parsing dynamic interactions has been reworked. CUtlVector<string_t> iszUsedNames;
// Unknown values are now stored as response contexts to test against response criteria. for (KeyValues* pkvModelBlock = modelKeyValues; pkvModelBlock != nullptr; pkvModelBlock = pkvModelBlock->GetNextKey())
{
bool bValidInteraction = true; // Do we have a dynamic interactions section?
KeyValues* pkvInteractions = pkvModelBlock->FindKey("dynamic_interactions");
// Default values if (pkvInteractions)
UTIL_StringToVector( sInteraction.vecRelativeOrigin.Base(), "0 0 0" ); {
sInteraction.flDelay = 10.0; KeyValues* pkvNode = pkvInteractions->GetFirstSubKey();
sInteraction.flDistSqr = (DSS_MAX_DIST * DSS_MAX_DIST); while (pkvNode)
// Misc. response criteria
char *szCriteria = "";
KeyValues *pCurNode = pkvNode->GetFirstSubKey();
const char *szName = NULL;
const char *szValue = NULL;
while (pCurNode)
{ {
szName = pCurNode->GetName(); ScriptedNPCInteraction_t sInteraction;
szValue = pCurNode->GetString(); sInteraction.iszInteractionName = AllocPooledString(pkvNode->GetName());
if (!szName || !szValue) if (iszUsedNames.Find(sInteraction.iszInteractionName) != iszUsedNames.InvalidIndex())
{ {
DevWarning("ERROR: Invalid dynamic interaction string\n"); DevMsg(2, "Scripted interaction %s already defined on %s\n", pkvNode->GetName(), GetClassname());
pkvNode = pkvNode->GetNextKey();
continue;
}
// The method for parsing dynamic interactions has been reworked.
// Unknown values are now stored as response contexts to test against response criteria.
bool bValidInteraction = true;
// Default values
UTIL_StringToVector(sInteraction.vecRelativeOrigin.Base(), "0 0 0");
sInteraction.flDelay = 10.0;
sInteraction.flDistSqr = (DSS_MAX_DIST * DSS_MAX_DIST);
// Misc. response criteria
char* szCriteria = "";
KeyValues* pCurNode = pkvNode->GetFirstSubKey();
const char* szName = NULL;
const char* szValue = NULL;
while (pCurNode)
{
szName = pCurNode->GetName();
szValue = pCurNode->GetString();
if (!szName || !szValue)
{
DevWarning("ERROR: Invalid dynamic interaction string\n");
pCurNode = pCurNode->GetNextKey();
}
if (!Q_strncmp(szName, "classname", 9))
{
bool pass = false;
if (Q_strstr(szValue, "!="))
{
szValue += 2;
pass = true;
}
if (!FStrEq(GetClassname(), szValue))
pass = !pass;
}
else if (!Q_strncmp(szName, "mapbase", 7))
{
sInteraction.iFlags |= SCNPC_FLAG_MAPBASE_ADDITION;
}
else if (!Q_strncmp(szName, "trigger", 7))
{
if (!Q_strncmp(szValue, "auto_in_combat", 14))
sInteraction.iTriggerMethod = SNPCINT_AUTOMATIC_IN_COMBAT;
}
else if (!Q_strncmp(szValue, "loop_break_trigger", 18))
{
char szTrigger[256];
Q_strncpy(szTrigger, szValue, sizeof(szTrigger));
char* pszParam = strtok(szTrigger, " ");
while (pszParam)
{
if (!Q_strncmp(pszParam, "on_damage", 9))
{
sInteraction.iLoopBreakTriggerMethod |= SNPCINT_LOOPBREAK_ON_DAMAGE;
}
else if (!Q_strncmp(pszParam, "on_flashlight_illum", 19))
{
sInteraction.iLoopBreakTriggerMethod |= SNPCINT_LOOPBREAK_ON_FLASHLIGHT_ILLUM;
}
pszParam = strtok(NULL, " ");
}
}
else if (!Q_strncmp(szName, "origin_relative", 15))
UTIL_StringToVector(sInteraction.vecRelativeOrigin.Base(), szValue);
else if (!Q_strncmp(szName, "angles_relative", 15))
{
sInteraction.iFlags |= SCNPC_FLAG_TEST_OTHER_ANGLES;
UTIL_StringToVector(sInteraction.angRelativeAngles.Base(), szValue);
}
else if (!Q_strncmp(szName, "velocity_relative", 17))
{
sInteraction.iFlags |= SCNPC_FLAG_TEST_OTHER_VELOCITY;
UTIL_StringToVector(sInteraction.vecRelativeVelocity.Base(), szValue);
}
else if (!Q_strncmp(szName, "end_position", 12))
{
sInteraction.iFlags |= SCNPC_FLAG_TEST_END_POSITION;
UTIL_StringToVector(sInteraction.vecRelativeEndPos.Base(), szValue);
}
else if (!Q_strncmp(szName, "entry_sequence", 14))
sInteraction.sPhases[SNPCINT_ENTRY].iszSequence = AllocPooledString(szValue);
else if (!Q_strncmp(szName, "entry_activity", 14))
sInteraction.sPhases[SNPCINT_ENTRY].iActivity = GetActivityID(szValue);
else if (!Q_strncmp(szName, "sequence", 8))
sInteraction.sPhases[SNPCINT_SEQUENCE].iszSequence = AllocPooledString(szValue);
else if (!Q_strncmp(szName, "activity", 8))
sInteraction.sPhases[SNPCINT_SEQUENCE].iActivity = GetActivityID(szValue);
else if (!Q_strncmp(szName, "exit_sequence", 13))
sInteraction.sPhases[SNPCINT_EXIT].iszSequence = AllocPooledString(szValue);
else if (!Q_strncmp(szName, "exit_activity", 13))
sInteraction.sPhases[SNPCINT_EXIT].iActivity = GetActivityID(szValue);
else if (!Q_strncmp(szName, "delay", 5))
sInteraction.flDelay = atof(szValue);
else if (!Q_strncmp(szName, "origin_max_delta", 16))
sInteraction.flDistSqr = atof(szValue);
else if (!Q_strncmp(szName, "loop_in_action", 14) && !FStrEq(szValue, "0"))
sInteraction.iFlags |= SCNPC_FLAG_LOOP_IN_ACTION;
else if (!Q_strncmp(szName, "dont_teleport_at_end", 20))
{
if (!Q_stricmp(szValue, "me") || !Q_stricmp(szValue, "both"))
sInteraction.iFlags |= SCNPC_FLAG_DONT_TELEPORT_AT_END_ME;
else if (!Q_stricmp(szValue, "them") || !Q_stricmp(szValue, "both"))
sInteraction.iFlags |= SCNPC_FLAG_DONT_TELEPORT_AT_END_THEM;
}
else if (!Q_strncmp(szName, "needs_weapon", 12))
{
if (!Q_strncmp(szValue, "ME", 2))
sInteraction.iFlags |= SCNPC_FLAG_NEEDS_WEAPON_ME;
else if (!Q_strncmp(szValue, "THEM", 4))
sInteraction.iFlags |= SCNPC_FLAG_NEEDS_WEAPON_THEM;
else if (!Q_strncmp(szValue, "BOTH", 4))
{
sInteraction.iFlags |= SCNPC_FLAG_NEEDS_WEAPON_ME;
sInteraction.iFlags |= SCNPC_FLAG_NEEDS_WEAPON_THEM;
}
}
else if (!Q_strncmp(szName, "weapon_mine", 11))
{
sInteraction.iFlags |= SCNPC_FLAG_NEEDS_WEAPON_ME;
sInteraction.iszMyWeapon = AllocPooledString(szValue);
}
else if (!Q_strncmp(szName, "weapon_theirs", 13))
{
sInteraction.iFlags |= SCNPC_FLAG_NEEDS_WEAPON_THEM;
sInteraction.iszTheirWeapon = AllocPooledString(szValue);
}
// Add anything else to our miscellaneous criteria
else
{
szCriteria = UTIL_VarArgs("%s,%s:%s", szCriteria, szName, szValue);
}
pCurNode = pCurNode->GetNextKey(); pCurNode = pCurNode->GetNextKey();
} }
if (!Q_strncmp(szName, "classname", 9)) if (!bValidInteraction)
{ {
bool pass = false; DevMsg("Scripted interaction %s rejected by %s\n", pkvNode->GetName(), GetClassname());
if (Q_strstr(szValue, "!=")) pkvNode = pkvNode->GetNextKey();
{ continue;
szValue += 2;
pass = true;
}
if (!FStrEq(GetClassname(), szValue))
pass = !pass;
}
else if (!Q_strncmp(szName, "mapbase", 7))
{
sInteraction.iFlags |= SCNPC_FLAG_MAPBASE_ADDITION;
}
else if (!Q_strncmp(szName, "trigger", 7))
{
if (!Q_strncmp(szValue, "auto_in_combat", 14))
sInteraction.iTriggerMethod = SNPCINT_AUTOMATIC_IN_COMBAT;
}
else if (!Q_strncmp(szValue, "loop_break_trigger", 18))
{
char szTrigger[256];
Q_strncpy( szTrigger, szValue, sizeof(szTrigger) );
char *pszParam = strtok( szTrigger, " " );
while (pszParam)
{
if ( !Q_strncmp( pszParam, "on_damage", 9) )
{
sInteraction.iLoopBreakTriggerMethod |= SNPCINT_LOOPBREAK_ON_DAMAGE;
}
else if ( !Q_strncmp( pszParam, "on_flashlight_illum", 19) )
{
sInteraction.iLoopBreakTriggerMethod |= SNPCINT_LOOPBREAK_ON_FLASHLIGHT_ILLUM;
}
pszParam = strtok(NULL," ");
}
}
else if (!Q_strncmp(szName, "origin_relative", 15))
UTIL_StringToVector( sInteraction.vecRelativeOrigin.Base(), szValue );
else if (!Q_strncmp(szName, "angles_relative", 15))
{
sInteraction.iFlags |= SCNPC_FLAG_TEST_OTHER_ANGLES;
UTIL_StringToVector( sInteraction.angRelativeAngles.Base(), szValue );
}
else if (!Q_strncmp(szName, "velocity_relative", 17))
{
sInteraction.iFlags |= SCNPC_FLAG_TEST_OTHER_VELOCITY;
UTIL_StringToVector( sInteraction.vecRelativeVelocity.Base(), szValue );
}
#ifdef MAPBASE
else if (!Q_strncmp(szName, "end_position", 12))
{
sInteraction.iFlags |= SCNPC_FLAG_TEST_END_POSITION;
UTIL_StringToVector( sInteraction.vecRelativeEndPos.Base(), szValue );
}
#endif
else if (!Q_strncmp(szName, "entry_sequence", 14))
sInteraction.sPhases[SNPCINT_ENTRY].iszSequence = AllocPooledString( szValue );
else if (!Q_strncmp(szName, "entry_activity", 14))
sInteraction.sPhases[SNPCINT_ENTRY].iActivity = GetActivityID( szValue );
else if (!Q_strncmp(szName, "sequence", 8))
sInteraction.sPhases[SNPCINT_SEQUENCE].iszSequence = AllocPooledString( szValue );
else if (!Q_strncmp(szName, "activity", 8))
sInteraction.sPhases[SNPCINT_SEQUENCE].iActivity = GetActivityID( szValue );
else if (!Q_strncmp(szName, "exit_sequence", 13))
sInteraction.sPhases[SNPCINT_EXIT].iszSequence = AllocPooledString( szValue );
else if (!Q_strncmp(szName, "exit_activity", 13))
sInteraction.sPhases[SNPCINT_EXIT].iActivity = GetActivityID(szValue);
else if (!Q_strncmp(szName, "delay", 5))
sInteraction.flDelay = atof(szValue);
else if (!Q_strncmp(szName, "origin_max_delta", 16))
sInteraction.flDistSqr = atof(szValue);
else if (!Q_strncmp(szName, "loop_in_action", 14) && !FStrEq(szValue, "0"))
sInteraction.iFlags |= SCNPC_FLAG_LOOP_IN_ACTION;
else if (!Q_strncmp(szName, "dont_teleport_at_end", 20))
{
if ( !Q_stricmp( szValue, "me" ) || !Q_stricmp( szValue, "both" ) )
sInteraction.iFlags |= SCNPC_FLAG_DONT_TELEPORT_AT_END_ME;
else if ( !Q_stricmp( szValue, "them" ) || !Q_stricmp( szValue, "both" ) )
sInteraction.iFlags |= SCNPC_FLAG_DONT_TELEPORT_AT_END_THEM;
} }
else if (!Q_strncmp(szName, "needs_weapon", 12)) if (szCriteria[0] == ',')
{ {
if ( !Q_strncmp( szValue, "ME", 2 ) ) szCriteria += 1;
sInteraction.iFlags |= SCNPC_FLAG_NEEDS_WEAPON_ME; sInteraction.MiscCriteria = AllocPooledString(szCriteria);
else if ( !Q_strncmp( szValue, "THEM", 4 ) )
sInteraction.iFlags |= SCNPC_FLAG_NEEDS_WEAPON_THEM;
else if ( !Q_strncmp( szValue, "BOTH", 4 ) )
{
sInteraction.iFlags |= SCNPC_FLAG_NEEDS_WEAPON_ME;
sInteraction.iFlags |= SCNPC_FLAG_NEEDS_WEAPON_THEM;
}
} }
else if (!Q_strncmp(szName, "weapon_mine", 11))
{
sInteraction.iFlags |= SCNPC_FLAG_NEEDS_WEAPON_ME;
sInteraction.iszMyWeapon = AllocPooledString( szValue );
}
else if (!Q_strncmp(szName, "weapon_theirs", 13))
{
sInteraction.iFlags |= SCNPC_FLAG_NEEDS_WEAPON_THEM;
sInteraction.iszTheirWeapon = AllocPooledString( szValue );
}
// Add anything else to our miscellaneous criteria // Add it to the list
else AddScriptedNPCInteraction(&sInteraction);
{ iszUsedNames.AddToTail(sInteraction.iszInteractionName);
szCriteria = UTIL_VarArgs("%s,%s:%s", szCriteria, szName, szValue);
}
pCurNode = pCurNode->GetNextKey(); // Move to next interaction
}
if (!bValidInteraction)
{
DevMsg("Scripted interaction %s rejected by %s\n", pkvNode->GetName(), GetClassname());
pkvNode = pkvNode->GetNextKey(); pkvNode = pkvNode->GetNextKey();
continue;
}
if (szCriteria[0] == ',')
{
szCriteria += 1;
sInteraction.MiscCriteria = AllocPooledString(szCriteria);
} }
}
}
#else #else
// Do we have a dynamic interactions section?
KeyValues* pkvInteractions = modelKeyValues->FindKey("dynamic_interactions");
if (pkvInteractions)
{
KeyValues* pkvNode = pkvInteractions->GetFirstSubKey();
while (pkvNode)
{
ScriptedNPCInteraction_t sInteraction;
sInteraction.iszInteractionName = AllocPooledString(pkvNode->GetName());
// Trigger method // Trigger method
const char *pszTrigger = pkvNode->GetString( "trigger", NULL ); const char* pszTrigger = pkvNode->GetString("trigger", NULL);
if ( pszTrigger ) if (pszTrigger)
{ {
if ( !Q_strncmp( pszTrigger, "auto_in_combat", 14) ) if (!Q_strncmp(pszTrigger, "auto_in_combat", 14))
{ {
sInteraction.iTriggerMethod = SNPCINT_AUTOMATIC_IN_COMBAT; sInteraction.iTriggerMethod = SNPCINT_AUTOMATIC_IN_COMBAT;
} }
} }
// Loop Break trigger method // Loop Break trigger method
pszTrigger = pkvNode->GetString( "loop_break_trigger", NULL ); pszTrigger = pkvNode->GetString("loop_break_trigger", NULL);
if ( pszTrigger ) if (pszTrigger)
{ {
char szTrigger[256]; char szTrigger[256];
Q_strncpy( szTrigger, pszTrigger, sizeof(szTrigger) ); Q_strncpy(szTrigger, pszTrigger, sizeof(szTrigger));
char *pszParam = strtok( szTrigger, " " ); char* pszParam = strtok(szTrigger, " ");
while (pszParam) while (pszParam)
{ {
if ( !Q_strncmp( pszParam, "on_damage", 9) ) if (!Q_strncmp(pszParam, "on_damage", 9))
{ {
sInteraction.iLoopBreakTriggerMethod |= SNPCINT_LOOPBREAK_ON_DAMAGE; sInteraction.iLoopBreakTriggerMethod |= SNPCINT_LOOPBREAK_ON_DAMAGE;
} }
if ( !Q_strncmp( pszParam, "on_flashlight_illum", 19) ) if (!Q_strncmp(pszParam, "on_flashlight_illum", 19))
{ {
sInteraction.iLoopBreakTriggerMethod |= SNPCINT_LOOPBREAK_ON_FLASHLIGHT_ILLUM; sInteraction.iLoopBreakTriggerMethod |= SNPCINT_LOOPBREAK_ON_FLASHLIGHT_ILLUM;
} }
pszParam = strtok(NULL," "); pszParam = strtok(NULL, " ");
} }
} }
// Origin // Origin
const char *pszOrigin = pkvNode->GetString( "origin_relative", "0 0 0" ); const char* pszOrigin = pkvNode->GetString("origin_relative", "0 0 0");
UTIL_StringToVector( sInteraction.vecRelativeOrigin.Base(), pszOrigin ); UTIL_StringToVector(sInteraction.vecRelativeOrigin.Base(), pszOrigin);
// Angles // Angles
const char *pszAngles = pkvNode->GetString( "angles_relative", NULL ); const char* pszAngles = pkvNode->GetString("angles_relative", NULL);
if ( pszAngles ) if (pszAngles)
{ {
sInteraction.iFlags |= SCNPC_FLAG_TEST_OTHER_ANGLES; sInteraction.iFlags |= SCNPC_FLAG_TEST_OTHER_ANGLES;
UTIL_StringToVector( sInteraction.angRelativeAngles.Base(), pszAngles ); UTIL_StringToVector(sInteraction.angRelativeAngles.Base(), pszAngles);
} }
// Velocity // Velocity
const char *pszVelocity = pkvNode->GetString( "velocity_relative", NULL ); const char* pszVelocity = pkvNode->GetString("velocity_relative", NULL);
if ( pszVelocity ) if (pszVelocity)
{ {
sInteraction.iFlags |= SCNPC_FLAG_TEST_OTHER_VELOCITY; sInteraction.iFlags |= SCNPC_FLAG_TEST_OTHER_VELOCITY;
UTIL_StringToVector( sInteraction.vecRelativeVelocity.Base(), pszVelocity ); UTIL_StringToVector(sInteraction.vecRelativeVelocity.Base(), pszVelocity);
} }
// Entry Sequence // Entry Sequence
const char *pszSequence = pkvNode->GetString( "entry_sequence", NULL ); const char* pszSequence = pkvNode->GetString("entry_sequence", NULL);
if ( pszSequence ) if (pszSequence)
{ {
sInteraction.sPhases[SNPCINT_ENTRY].iszSequence = AllocPooledString( pszSequence ); sInteraction.sPhases[SNPCINT_ENTRY].iszSequence = AllocPooledString(pszSequence);
} }
// Entry Activity // Entry Activity
const char *pszActivity = pkvNode->GetString( "entry_activity", NULL ); const char* pszActivity = pkvNode->GetString("entry_activity", NULL);
if ( pszActivity ) if (pszActivity)
{ {
sInteraction.sPhases[SNPCINT_ENTRY].iActivity = GetActivityID( pszActivity ); sInteraction.sPhases[SNPCINT_ENTRY].iActivity = GetActivityID(pszActivity);
} }
// Sequence // Sequence
pszSequence = pkvNode->GetString( "sequence", NULL ); pszSequence = pkvNode->GetString("sequence", NULL);
if ( pszSequence ) if (pszSequence)
{ {
sInteraction.sPhases[SNPCINT_SEQUENCE].iszSequence = AllocPooledString( pszSequence ); sInteraction.sPhases[SNPCINT_SEQUENCE].iszSequence = AllocPooledString(pszSequence);
} }
// Activity // Activity
pszActivity = pkvNode->GetString( "activity", NULL ); pszActivity = pkvNode->GetString("activity", NULL);
if ( pszActivity ) if (pszActivity)
{ {
sInteraction.sPhases[SNPCINT_SEQUENCE].iActivity = GetActivityID( pszActivity ); sInteraction.sPhases[SNPCINT_SEQUENCE].iActivity = GetActivityID(pszActivity);
} }
// Exit Sequence // Exit Sequence
pszSequence = pkvNode->GetString( "exit_sequence", NULL ); pszSequence = pkvNode->GetString("exit_sequence", NULL);
if ( pszSequence ) if (pszSequence)
{ {
sInteraction.sPhases[SNPCINT_EXIT].iszSequence = AllocPooledString( pszSequence ); sInteraction.sPhases[SNPCINT_EXIT].iszSequence = AllocPooledString(pszSequence);
} }
// Exit Activity // Exit Activity
pszActivity = pkvNode->GetString( "exit_activity", NULL ); pszActivity = pkvNode->GetString("exit_activity", NULL);
if ( pszActivity ) if (pszActivity)
{ {
sInteraction.sPhases[SNPCINT_EXIT].iActivity = GetActivityID( pszActivity ); sInteraction.sPhases[SNPCINT_EXIT].iActivity = GetActivityID(pszActivity);
} }
// Delay // Delay
sInteraction.flDelay = pkvNode->GetFloat( "delay", 10.0 ); sInteraction.flDelay = pkvNode->GetFloat("delay", 10.0);
// Delta // Delta
sInteraction.flDistSqr = pkvNode->GetFloat( "origin_max_delta", (DSS_MAX_DIST * DSS_MAX_DIST) ); sInteraction.flDistSqr = pkvNode->GetFloat("origin_max_delta", (DSS_MAX_DIST * DSS_MAX_DIST));
// Loop? // Loop?
if ( pkvNode->GetFloat( "loop_in_action", 0 ) ) if (pkvNode->GetFloat("loop_in_action", 0))
{ {
sInteraction.iFlags |= SCNPC_FLAG_LOOP_IN_ACTION; sInteraction.iFlags |= SCNPC_FLAG_LOOP_IN_ACTION;
} }
// Fixup position? // Fixup position?
const char *pszDontFixup = pkvNode->GetString( "dont_teleport_at_end", NULL ); const char* pszDontFixup = pkvNode->GetString("dont_teleport_at_end", NULL);
if ( pszDontFixup ) if (pszDontFixup)
{ {
if ( !Q_stricmp( pszDontFixup, "me" ) || !Q_stricmp( pszDontFixup, "both" ) ) if (!Q_stricmp(pszDontFixup, "me") || !Q_stricmp(pszDontFixup, "both"))
{ {
sInteraction.iFlags |= SCNPC_FLAG_DONT_TELEPORT_AT_END_ME; sInteraction.iFlags |= SCNPC_FLAG_DONT_TELEPORT_AT_END_ME;
} }
else if ( !Q_stricmp( pszDontFixup, "them" ) || !Q_stricmp( pszDontFixup, "both" ) ) else if (!Q_stricmp(pszDontFixup, "them") || !Q_stricmp(pszDontFixup, "both"))
{ {
sInteraction.iFlags |= SCNPC_FLAG_DONT_TELEPORT_AT_END_THEM; sInteraction.iFlags |= SCNPC_FLAG_DONT_TELEPORT_AT_END_THEM;
} }
} }
// Needs a weapon? // Needs a weapon?
const char *pszNeedsWeapon = pkvNode->GetString( "needs_weapon", NULL ); const char* pszNeedsWeapon = pkvNode->GetString("needs_weapon", NULL);
if ( pszNeedsWeapon ) if (pszNeedsWeapon)
{ {
if ( !Q_strncmp( pszNeedsWeapon, "ME", 2 ) ) if (!Q_strncmp(pszNeedsWeapon, "ME", 2))
{ {
sInteraction.iFlags |= SCNPC_FLAG_NEEDS_WEAPON_ME; sInteraction.iFlags |= SCNPC_FLAG_NEEDS_WEAPON_ME;
} }
else if ( !Q_strncmp( pszNeedsWeapon, "THEM", 4 ) ) else if (!Q_strncmp(pszNeedsWeapon, "THEM", 4))
{ {
sInteraction.iFlags |= SCNPC_FLAG_NEEDS_WEAPON_THEM; sInteraction.iFlags |= SCNPC_FLAG_NEEDS_WEAPON_THEM;
} }
else if ( !Q_strncmp( pszNeedsWeapon, "BOTH", 4 ) ) else if (!Q_strncmp(pszNeedsWeapon, "BOTH", 4))
{ {
sInteraction.iFlags |= SCNPC_FLAG_NEEDS_WEAPON_ME; sInteraction.iFlags |= SCNPC_FLAG_NEEDS_WEAPON_ME;
sInteraction.iFlags |= SCNPC_FLAG_NEEDS_WEAPON_THEM; sInteraction.iFlags |= SCNPC_FLAG_NEEDS_WEAPON_THEM;
@ -15046,27 +15076,28 @@ void CAI_BaseNPC::ParseScriptedNPCInteractions( void )
} }
// Specific weapon types // Specific weapon types
const char *pszWeaponName = pkvNode->GetString( "weapon_mine", NULL ); const char* pszWeaponName = pkvNode->GetString("weapon_mine", NULL);
if ( pszWeaponName ) if (pszWeaponName)
{ {
sInteraction.iFlags |= SCNPC_FLAG_NEEDS_WEAPON_ME; sInteraction.iFlags |= SCNPC_FLAG_NEEDS_WEAPON_ME;
sInteraction.iszMyWeapon = AllocPooledString( pszWeaponName ); sInteraction.iszMyWeapon = AllocPooledString(pszWeaponName);
} }
pszWeaponName = pkvNode->GetString( "weapon_theirs", NULL ); pszWeaponName = pkvNode->GetString("weapon_theirs", NULL);
if ( pszWeaponName ) if (pszWeaponName)
{ {
sInteraction.iFlags |= SCNPC_FLAG_NEEDS_WEAPON_THEM; sInteraction.iFlags |= SCNPC_FLAG_NEEDS_WEAPON_THEM;
sInteraction.iszTheirWeapon = AllocPooledString( pszWeaponName ); sInteraction.iszTheirWeapon = AllocPooledString(pszWeaponName);
} }
#endif
// Add it to the list // Add it to the list
AddScriptedNPCInteraction( &sInteraction ); AddScriptedNPCInteraction(&sInteraction);
// Move to next interaction // Move to next interaction
pkvNode = pkvNode->GetNextKey(); pkvNode = pkvNode->GetNextKey();
} }
} }
#endif // MAPBASE
} }
modelKeyValues->deleteThis(); modelKeyValues->deleteThis();