@@ -550,7 +550,18 @@ void CKeyBinds::RemoveDeletedBinds()
550550void CKeyBinds::ClearCommandsAndControls ()
551551{
552552 const auto predicate = [](const KeyBindPtr& bind) {
553- return !bind->isBeingDeleted && bind->type != KeyBindType::FUNCTION && bind->type != KeyBindType::CONTROL_FUNCTION;
553+ if (bind->isBeingDeleted )
554+ return false ;
555+
556+ if (bind->type == KeyBindType::COMMAND)
557+ {
558+ auto commandBind = static_cast <const CCommandBind*>(bind.get ());
559+ // Only remove resource bindings, preserve user bindings
560+ return commandBind->context == BindingContext::RESOURCE;
561+ }
562+
563+ // Remove all control bindings (GTA_CONTROL)
564+ return bind->type == KeyBindType::GTA_CONTROL;
554565 };
555566 RemoveBinds (m_binds, !m_bProcessingKeyStroke, predicate);
556567}
@@ -612,9 +623,11 @@ bool CKeyBinds::AddCommand(const char* szKey, const char* szCommand, const char*
612623 CCommandBind* pUserAddedBind = FindCommandMatch (NULL , szCommand, szArguments, szResource, szKey, true , bState, true , false );
613624 if (pUserAddedBind)
614625 {
615- // Upgrade
626+ // Upgrade user binding to resource binding
616627 pUserAddedBind->wasCreatedByScript = true ;
617628 pUserAddedBind->isReplacingScriptKey = true ;
629+ pUserAddedBind->context = BindingContext::RESOURCE;
630+ pUserAddedBind->sourceResource = szResource;
618631 assert (pUserAddedBind->originalScriptKey == szKey);
619632 return true ;
620633 }
@@ -631,13 +644,20 @@ bool CKeyBinds::AddCommand(const char* szKey, const char* szCommand, const char*
631644 if (szResource)
632645 {
633646 bind->resource = szResource;
647+ bind->sourceResource = szResource;
634648 bind->wasCreatedByScript = bScriptCreated;
649+ bind->context = BindingContext::RESOURCE;
635650
636651 if (bScriptCreated)
637652 bind->originalScriptKey = szKey;
638653 else if (szOriginalScriptKey)
639654 bind->originalScriptKey = szOriginalScriptKey; // Will wait for script to addcommand before doing replace
640655 }
656+ else
657+ {
658+ // User-created binding (via /bind command)
659+ bind->context = BindingContext::USER;
660+ }
641661
642662 m_binds.emplace_back (bind.release ());
643663 return true ;
@@ -2632,3 +2652,147 @@ bool CKeyBinds::TriggerKeyStrokeHandler(const SString& strKey, bool bState, bool
26322652 }
26332653 return true ;
26342654}
2655+
2656+ bool CKeyBinds::CommandExistsInContext (const char * key, const char * command, BindingContext context, bool checkState, bool state, const char * arguments, const char * resource)
2657+ {
2658+ if (!key || !command)
2659+ return false ;
2660+
2661+ for (const KeyBindPtr& bind : m_binds)
2662+ {
2663+ if (bind->isBeingDeleted || bind->type != KeyBindType::COMMAND)
2664+ continue ;
2665+
2666+ auto commandBind = static_cast <const CCommandBind*>(bind.get ());
2667+
2668+ if (commandBind->context != context)
2669+ continue ;
2670+
2671+ if (stricmp (commandBind->boundKey ->szKey , key) != 0 )
2672+ continue ;
2673+
2674+ if (stricmp (commandBind->command .c_str (), command) != 0 )
2675+ continue ;
2676+
2677+ if (checkState && commandBind->triggerState != state)
2678+ continue ;
2679+
2680+ if (arguments && commandBind->arguments != arguments)
2681+ continue ;
2682+
2683+ if (resource && commandBind->resource != resource)
2684+ continue ;
2685+
2686+ return true ;
2687+ }
2688+
2689+ return false ;
2690+ }
2691+
2692+ bool CKeyBinds::RemoveCommandFromContext (const char * key, const char * command, BindingContext context, bool checkState, bool state, const char * arguments, const char * resource)
2693+ {
2694+ if (!key || !command)
2695+ return false ;
2696+
2697+ const auto predicate = [&](const KeyBindPtr& bind) {
2698+ if (bind->isBeingDeleted || bind->type != KeyBindType::COMMAND)
2699+ return false ;
2700+
2701+ auto commandBind = static_cast <const CCommandBind*>(bind.get ());
2702+
2703+ if (commandBind->context != context)
2704+ return false ;
2705+
2706+ if (stricmp (commandBind->boundKey ->szKey , key) != 0 )
2707+ return false ;
2708+
2709+ if (stricmp (commandBind->command .c_str (), command) != 0 )
2710+ return false ;
2711+
2712+ if (checkState && commandBind->triggerState != state)
2713+ return false ;
2714+
2715+ if (arguments && commandBind->arguments != arguments)
2716+ return false ;
2717+
2718+ if (resource && commandBind->resource != resource)
2719+ return false ;
2720+
2721+ return true ;
2722+ };
2723+
2724+ return RemoveBinds (m_binds, !m_bProcessingKeyStroke, predicate);
2725+ }
2726+
2727+ bool CKeyBinds::HasAnyBindingForKey (const char * key, bool checkState, bool state)
2728+ {
2729+ if (!key)
2730+ return false ;
2731+
2732+ for (const KeyBindPtr& bind : m_binds)
2733+ {
2734+ if (bind->isBeingDeleted )
2735+ continue ;
2736+
2737+ if (bind->type == KeyBindType::COMMAND)
2738+ {
2739+ auto commandBind = static_cast <const CCommandBind*>(bind.get ());
2740+ if (stricmp (commandBind->boundKey ->szKey , key) == 0 )
2741+ {
2742+ if (!checkState || commandBind->triggerState == state)
2743+ return true ;
2744+ }
2745+ }
2746+ else if (bind->type == KeyBindType::FUNCTION)
2747+ {
2748+ auto functionBind = static_cast <const CKeyFunctionBind*>(bind.get ());
2749+ if (stricmp (functionBind->boundKey ->szKey , key) == 0 )
2750+ {
2751+ if (!checkState || functionBind->triggerState == state)
2752+ return true ;
2753+ }
2754+ }
2755+ else if (bind->type == KeyBindType::CONTROL_FUNCTION)
2756+ {
2757+ auto controlBind = static_cast <const CControlFunctionBind*>(bind.get ());
2758+ if (stricmp (controlBind->boundKey ->szKey , key) == 0 )
2759+ {
2760+ if (!checkState || controlBind->triggerState == state)
2761+ return true ;
2762+ }
2763+ }
2764+ else if (bind->type == KeyBindType::GTA_CONTROL)
2765+ {
2766+ auto gtaBind = static_cast <const CGTAControlBind*>(bind.get ());
2767+ if (stricmp (gtaBind->boundKey ->szKey , key) == 0 )
2768+ return true ;
2769+ }
2770+ }
2771+
2772+ return false ;
2773+ }
2774+
2775+ bool CKeyBinds::HasBindingInContext (const char * key, BindingContext context, bool checkState, bool state)
2776+ {
2777+ if (!key)
2778+ return false ;
2779+
2780+ for (const KeyBindPtr& bind : m_binds)
2781+ {
2782+ if (bind->isBeingDeleted || bind->type != KeyBindType::COMMAND)
2783+ continue ;
2784+
2785+ auto commandBind = static_cast <const CCommandBind*>(bind.get ());
2786+
2787+ if (commandBind->context != context)
2788+ continue ;
2789+
2790+ if (stricmp (commandBind->boundKey ->szKey , key) != 0 )
2791+ continue ;
2792+
2793+ if (!checkState || commandBind->triggerState == state)
2794+ return true ;
2795+ }
2796+
2797+ return false ;
2798+ }
0 commit comments