Binding
Binding is OpenBOR's one-way synchronization system for attaching one entity to another. The binding entity can follow a target's position, drawing order, direction, animation, and indexed animation position while retaining its own model, scripts, collision data, state, and other entity properties.
Binding is essential for layered visual effects, weapon trails, carried objects, grappling sequences, synchronized helpers, multipart enemies, modular costumes, mounted characters, status graphics, composite entities, and any system where one independent entity must remain aligned with another in real time.
The relationship is always described from the binding entity's perspective:
- The binding entity owns the bind properties.
- The binding entity attaches itself to one target.
- One entity can have only one bind target at a time.
- Any number of entities may bind themselves to the same target.
- The target does not gain ownership or native control of the binding entity.
Binding is separate from owner, parent, child, grabbing, link, and platform relationships. Setting a bind target does not establish any of those other relationships.
Core Concept
Every entity contains one bind-property object. The object exists for the entity's lifetime, even when binding is inactive. BIND_PROPERTY_TARGET activates the relationship by holding another entity pointer.
When the target is empty or null, OpenBOR performs no binding update. Configuration, offsets, animation selections, metadata, direction adjustment, and relative sort ID remain stored, allowing them to be reused when another target is assigned.
Destroying a target automatically clears every active entity bind pointing to it. Clearing the target manually cancels binding without removing either entity.
Self-targeting and cyclic binds should be avoided. Relative offsets and sort adjustments can accumulate or oscillate when an entity ultimately targets itself, while cycles do not provide a stable parent-child hierarchy.
Script Access
Use the entity property interface to retrieve an entity's bind pointer:
void bind = get_entity_property(
entity,
ENTITY_PROPERTY_BIND
);
Once retrieved, the same pointer is used with the bind-property functions:
void value = get_bind_property(bind, property);
set_bind_property(bind, property, value);
Changing a property does not immediately run the complete binding calculation. Normal binding resolution occurs near the end of the logical entity-update process. Call update_bind(entity) when the change must be applied at the current script location:
update_bind(entity);
Manual updates execute the same bind callbacks, matching, removal, direction, sorting, and positioning logic as the normal pass. Calling update_bind() does not suppress the normal later update, so a still-active bind may resolve twice during that logical tick.
Property List
| Property | Type | Default | Purpose |
|---|---|---|---|
BIND_PROPERTY_ANIMATION_FRAME
|
Integer | 0
|
Indexed animation position used when BIND_CONFIG_ANIMATION_FRAME_DEFINED is active.
|
BIND_PROPERTY_ANIMATION_ID
|
Integer | 0
|
Animation ID used when BIND_CONFIG_ANIMATION_DEFINED is active.
|
BIND_PROPERTY_CONFIG
|
Unsigned 64-bit integer | BIND_CONFIG_NONE
|
Bitmask selecting animation matching, axis sources, failure removal, and native-behavior overrides. See Configuration Flags. |
BIND_PROPERTY_DIRECTION_ADJUST
|
Integer | DIRECTION_ADJUST_NONE
|
Direction rule applied in relation to the target. |
BIND_PROPERTY_META_DATA
|
Pointer | Empty | Creator-managed metadata pointer. Native binding logic does not interpret it. |
BIND_PROPERTY_META_TAG
|
Integer | 0
|
Creator-managed numeric tag. Native binding logic does not interpret it. |
BIND_PROPERTY_OFFSET_X
|
Integer | 0
|
X offset from the target or absolute X coordinate, according to configuration. |
BIND_PROPERTY_OFFSET_Y
|
Integer | 0
|
Y offset from the target or absolute Y coordinate, according to configuration. |
BIND_PROPERTY_OFFSET_Z
|
Integer | 0
|
Z offset from the target or absolute Z coordinate, according to configuration. |
BIND_PROPERTY_SORT_ID
|
Integer | 0
|
Drawing sort adjustment added to the target's current sort ID during each bind update. |
BIND_PROPERTY_TARGET
|
Entity pointer | Empty | Entity to which the property owner binds itself. Empty or null disables all native binding logic. |
Several API constants retain the legacy word FRAME. Within OpenBOR's data model, these values refer to an indexed animation position rather than a separate frame object.
Activating and Cancelling Binding
Assigning the target activates the bind object:
void bind = get_entity_property(
follower,
ENTITY_PROPERTY_BIND
);
set_bind_property(
bind,
BIND_PROPERTY_TARGET,
target
);
Cancel the relationship by clearing the target:
set_bind_property(
bind,
BIND_PROPERTY_TARGET,
NULL()
);
Setting BIND_PROPERTY_CONFIG to BIND_CONFIG_NONE does not unbind the entity. Target, relative sort ID, direction adjustment, callbacks, and any other behavior independent of configuration remain active. Clear BIND_PROPERTY_TARGET when the relationship itself should end.
Configuration Flags
BIND_PROPERTY_CONFIG is a 64-bit bitmask. Combine independent behaviors with bitwise OR:
int config = BIND_CONFIG_AXIS_X_TARGET
| BIND_CONFIG_AXIS_Y_TARGET
| BIND_CONFIG_AXIS_Z_TARGET;
set_bind_property(
bind,
BIND_PROPERTY_CONFIG,
config
);
Assign BIND_CONFIG_NONE directly to clear all flags.
Animation Matching
| Flag | Effect |
|---|---|
BIND_CONFIG_ANIMATION_TARGET
|
Match the target's current animation ID. |
BIND_CONFIG_ANIMATION_DEFINED
|
Match BIND_PROPERTY_ANIMATION_ID instead of the target's current animation.
|
BIND_CONFIG_ANIMATION_REMOVE
|
Remove the binding entity when the requested animation is unavailable. Without this flag, an unavailable animation clears the bind target instead. |
BIND_CONFIG_ANIMATION_FRAME_TARGET
|
Match the target's current indexed animation position. |
BIND_CONFIG_ANIMATION_FRAME_DEFINED
|
Match BIND_PROPERTY_ANIMATION_FRAME instead of the target's current position.
|
BIND_CONFIG_ANIMATION_FRAME_REMOVE
|
Remove the binding entity when a requested indexed position does not exist in its selected animation. |
Defined selection takes precedence when both defined and target flags are present. BIND_CONFIG_ANIMATION_DEFINED wins over BIND_CONFIG_ANIMATION_TARGET, while BIND_CONFIG_ANIMATION_FRAME_DEFINED wins over BIND_CONFIG_ANIMATION_FRAME_TARGET.
Animation matching occurs before indexed-position matching. Target matching uses the target's numeric animation ID, so the binding model must provide a valid animation in the corresponding slot. Position matching then uses the binding entity's selected animation.
Pair removal flags with the matching behavior they protect. Typical visual helpers combine target matching with both removal flags, allowing the helper to remove itself cleanly when its model cannot represent the target's state.
Entering a matched animation or indexed position follows the normal animation-entry path. Animationscript and other entry behavior may consequently execute during binding resolution.
Axis Sources
| Flag | Result |
|---|---|
BIND_CONFIG_AXIS_X_TARGET
|
Set binding entity X to target X plus the configured X offset. Offset direction mirrors with target facing. |
BIND_CONFIG_AXIS_X_LEVEL
|
Set binding entity X directly to the configured X value. |
BIND_CONFIG_AXIS_Y_TARGET
|
Set binding entity Y to target Y plus the configured Y offset. |
BIND_CONFIG_AXIS_Y_LEVEL
|
Set binding entity Y directly to the configured Y value. |
BIND_CONFIG_AXIS_Z_TARGET
|
Set binding entity Z to target Z plus the configured Z offset. |
BIND_CONFIG_AXIS_Z_LEVEL
|
Set binding entity Z directly to the configured Z value. |
Target mode takes precedence when both target and level flags are set for the same axis. Axes without either flag remain unchanged by binding.
Level-axis flags make the offset property an absolute level coordinate. They do not remove the requirement for a valid bind target. Binding resolution always returns immediately when BIND_PROPERTY_TARGET is empty.
Native-Behavior Overrides
Override flags remain effective only while a valid bind target exists.
| Flag | Suppressed native behavior |
|---|---|
BIND_CONFIG_OVERRIDE_FALL_LAND
|
Normal falling-state landing resolution when the entity reaches its base. |
BIND_CONFIG_OVERRIDE_DROPFRAME
|
Configured drop-position transition and its associated effect. |
BIND_CONFIG_OVERRIDE_LANDFRAME
|
Configured land-position transition and its associated effect. |
BIND_CONFIG_OVERRIDE_SPECIAL_AI
|
Special activation for enemy and NPC entities through the native energy-check path. |
BIND_CONFIG_OVERRIDE_SPECIAL_PLAYER
|
Special activation for player entities through the native energy-check path. |
Override flags are especially useful for custom grapples, carries, throws, and slams. Native landing or special behavior can otherwise interrupt a scripted sequence even while position and animation are being synchronized.
Positioning Rules
X Offset and Facing
Target-relative X offset mirrors according to the target's direction:
- Target faces right - binding X is
target X + offset X. - Target faces left - binding X is
target X - offset X.
Positive X therefore means forward from the target's facing, while negative X means behind it. Absolute level X does not mirror.
Target facing controls this offset even when the binding entity uses a different direction-adjustment rule.
Y and Z Offsets
Target-relative Y and Z offsets do not mirror:
- Positive Y places the binding entity higher than the target.
- Negative Y places it lower.
- Positive Z places it at a greater world-depth coordinate, generally toward the camera.
- Negative Z places it toward the background.
Binding does not perform collision correction for the final assignment. Selected axes are written after ordinary entity movement, so target-relative values can place the binding entity through walls, platforms, or other obstacles when that is what the configured relationship requires.
Direction Adjustment
BIND_PROPERTY_DIRECTION_ADJUST accepts the following constants:
| Constant | Result |
|---|---|
DIRECTION_ADJUST_NONE
|
Preserve the binding entity's current direction. |
DIRECTION_ADJUST_SAME
|
Match the target's direction. |
DIRECTION_ADJUST_OPPOSITE
|
Face opposite the target's direction. |
DIRECTION_ADJUST_RIGHT
|
Always face right. |
DIRECTION_ADJUST_LEFT
|
Always face left. |
DIRECTION_ADJUST_TOWARD
|
Face toward the target according to their current X positions. |
DIRECTION_ADJUST_AWAY
|
Face away from the target according to their current X positions. |
Toward and away preserve the binding entity's current direction when both entities occupy the same X coordinate. Their comparison occurs before axis positioning for the current bind pass.
Drawing Sort
Every active bind update assigns:
binding entity sort ID = target sort ID + bind sort adjustment
Relative value -1 normally places the binding entity immediately behind its target when both share the same drawing Z. Value 1 normally places it immediately in front. Value 0 matches the target's sort ID.
World Z and drawing sort ID both participate in display order. Relative sort adjustment alone does not guarantee front or back placement when the entities occupy different Z positions. Binding Z to the target is the usual choice for tightly layered composite visuals.
Items with identical Z and sort values should not depend on incidental insertion order. Give layered components distinct relative sort values when their relationship must remain stable.
Runtime Timing
Normal binding resolves once during each logical entity-update cycle:
- OpenBOR performs the main update for eligible entities.
- Gravity and pending movement are resolved for every existing entity.
- Once all entity movement is complete, OpenBOR visits existing entities for binding.
- The target-side bind callback executes.
- The binding-entity callback executes.
- OpenBOR rechecks whether the bind still has a target.
- Animation and indexed-position matching are applied.
- Relative sort ID is applied.
- Direction adjustment is applied.
- Configured X, Y, and Z axes are applied.
- Removed entities are compacted from the active list.
Post-movement placement is an important part of binding behavior. The system is not a physical parent constraint evaluated during collision movement. The binding entity undergoes its ordinary update first, then selected properties are synchronized after movement finishes.
Binding updates are not gated by viewport visibility or the binding entity's frozen state. Frozen entities still receive bind placement and bind callbacks during an advancing logical cycle. Pausing the logical engine stops the normal update pass.
Freshly spawned entities are skipped by the main entity update during their spawn tick, though they can still participate in the later binding pass when a target was assigned during creation or Onspawnscript.
Binding Chains
Direct bindings observe target movement completed earlier in the same logical cycle. Binding itself is resolved in one active entity-list pass, not as a dependency tree.
For a chain where C binds to B and B binds to A, C sees B's newly bound result during the same cycle only when B happens to resolve first. Reverse ordering leaves C using B's pre-bind result until the next cycle. Entity allocation and removal may change that ordering.
Use one direct target for multiple components when exact same-cycle composition matters. Project-managed ordering or explicit update_bind() calls can coordinate intentional chains, though manual updates also execute callbacks and should be guarded against recursion.
Bind Update Scripts
Two optional model scripts execute before native matching and placement during every active bind update.
| Model command | Executes on | Purpose |
|---|---|---|
on_bind_update_other_to_self_script
|
The current bind target. | Inspect or modify an entity binding itself to self.
|
on_bind_update_self_to_other_script
|
The binding entity. | Inspect or modify self's relationship with its target.
|
Example model declarations:
on_bind_update_other_to_self_script data/scripts/bind_target_update.c
on_bind_update_self_to_other_script data/scripts/bind_follower_update.c
Both callbacks receive the same bind object, which belongs to the binding entity:
| Callback | self
|
other
|
bind
|
|---|---|---|---|
on_bind_update_other_to_self_script
|
Bind target | Entity binding itself to the target | Binding entity's bind pointer |
on_bind_update_self_to_other_script
|
Binding entity | Current bind target | Binding entity's bind pointer |
The target callback runs first. Changes to configuration, offsets, matching, sort ID, direction, metadata, or target can affect the same bind pass because OpenBOR reads the working properties afterward.
The binding-entity callback runs second. If the target callback redirected the bind, other reflects the new target. If the target callback cleared the target, the binding-entity callback still executes with an empty other, then native binding exits.
Return values are ignored. Clear BIND_PROPERTY_TARGET to cancel the native adjustment for the current pass.
Calling update_bind() from either bind callback re-enters the same callback sequence. Unguarded use can recurse indefinitely.
Quick Examples
Target-Relative Visual Component
This helper binds a visual component to a target, places it 24 units forward and 36 units above, matches facing, and draws it one sort step behind:
void attach_visual_component(void component, void target)
{
void bind = get_entity_property(
component,
ENTITY_PROPERTY_BIND
);
int config = BIND_CONFIG_AXIS_X_TARGET
| BIND_CONFIG_AXIS_Y_TARGET
| BIND_CONFIG_AXIS_Z_TARGET;
set_bind_property(bind, BIND_PROPERTY_OFFSET_X, 24);
set_bind_property(bind, BIND_PROPERTY_OFFSET_Y, 36);
set_bind_property(bind, BIND_PROPERTY_OFFSET_Z, 0);
set_bind_property(bind, BIND_PROPERTY_SORT_ID, -1);
set_bind_property(
bind,
BIND_PROPERTY_DIRECTION_ADJUST,
DIRECTION_ADJUST_SAME
);
set_bind_property(bind, BIND_PROPERTY_CONFIG, config);
set_bind_property(bind, BIND_PROPERTY_TARGET, target);
update_bind(component);
}
The component remains an independent entity. Binding supplies synchronized placement, facing, and sort order without transferring ownership or collision behavior.
Animation-Synchronized Effect
This configuration follows the target's animation and indexed position, then removes the effect if its model lacks the required match:
int config = BIND_CONFIG_AXIS_X_TARGET
| BIND_CONFIG_AXIS_Y_TARGET
| BIND_CONFIG_AXIS_Z_TARGET
| BIND_CONFIG_ANIMATION_TARGET
| BIND_CONFIG_ANIMATION_FRAME_TARGET
| BIND_CONFIG_ANIMATION_REMOVE
| BIND_CONFIG_ANIMATION_FRAME_REMOVE;
This pattern suits trails, aura layers, alternate body parts, and other components built with animation tables corresponding to their targets.
Grapples and Slams
Binding is an essential component in constructing sequence-heavy grapple attacks such as piledrivers, backbreakers, carries, and throws. Grapples can be understood much like professional wrestling - the attacker initiates and directs the maneuver, while the victim performs most of the technical work.
Typically, the attacker places the victim into a dedicated reaction animation and binds it to the attacker. The victim's animation supplies the poses and adjusts its bind offsets as the maneuver progresses. Damage may be applied at selected indexed animation positions. Once the sequence finishes, the victim is unbound and usually receives final damage with a knockdown effect.
This victim-led arrangement allows each model to provide poses suited to its own proportions while the attacker only needs to select the victim and initiate the sequence. It also allows one attacker to coordinate multiple bound victims at once. Since each victim maintains its own bind and sequence, careful setup can produce awe-inspiring multi-part, multi-target grapples that fill the screen with synchronized motion and pain.
Binding provides several flags particularly useful for grapple construction:
BIND_CONFIG_OVERRIDE_FALL_LANDprevents native landing behavior from interrupting the sequence.BIND_CONFIG_OVERRIDE_DROPFRAMEsuppresses the normal drop-position transition.BIND_CONFIG_OVERRIDE_LANDFRAMEsuppresses the normal land-position transition.BIND_CONFIG_OVERRIDE_SPECIAL_AIandBIND_CONFIG_OVERRIDE_SPECIAL_PLAYERcan prevent native special activation while the victim remains bound.
The following abbreviated example binds a victim to an attacker and places the victim in its first follow animation. The victim's Animationscript can call the impact and finishing functions at the appropriate indexed animation positions.
void begin_slam(void attacker, void victim)
{
void bind = get_entity_property(
victim,
ENTITY_PROPERTY_BIND
);
void config = BIND_CONFIG_AXIS_X_TARGET
| BIND_CONFIG_AXIS_Y_TARGET
| BIND_CONFIG_AXIS_Z_TARGET
| BIND_CONFIG_OVERRIDE_FALL_LAND
| BIND_CONFIG_OVERRIDE_DROPFRAME
| BIND_CONFIG_OVERRIDE_LANDFRAME;
set_bind_property(bind, BIND_PROPERTY_OFFSET_X, 0);
set_bind_property(bind, BIND_PROPERTY_OFFSET_Y, 0);
set_bind_property(bind, BIND_PROPERTY_OFFSET_Z, 0);
set_bind_property(bind, BIND_PROPERTY_SORT_ID, -1);
set_bind_property(
bind,
BIND_PROPERTY_DIRECTION_ADJUST,
DIRECTION_ADJUST_SAME
);
set_bind_property(bind, BIND_PROPERTY_CONFIG, config);
set_bind_property(bind, BIND_PROPERTY_TARGET, attacker);
performattack(victim, ANI_FOLLOW1);
update_bind(victim);
}
void slam_impact(void victim, void attacker)
{
damageentity(
victim,
attacker,
8,
0,
ATK_NORMAL
);
}
void finish_slam(void victim, void attacker)
{
void bind = get_entity_property(
victim,
ENTITY_PROPERTY_BIND
);
set_bind_property(
bind,
BIND_PROPERTY_TARGET,
NULL()
);
damageentity(
victim,
attacker,
40,
1,
ATK_NORMAL
);
}
The exact follow animation, offsets, intermediate damage, and final launch behavior are project decisions. Binding supplies the synchronization and override tools without imposing a particular grapple system.
Binding and Other Relationships
| Relationship | Primary purpose | Established by binding? |
|---|---|---|
| Bind target | One-way position, animation, direction, and sorting synchronization. | Yes |
| Owner | Attribution for attacks, projectiles, effects, and related systems. | No |
| Parent and child | Spawn lineage, summon behavior, and model-defined subentity relationships. | No |
| Grab and link | Native grapple, carry, and paired-action behavior. | No |
| Platform support | Standing on and moving with platform geometry. | No |
Projects often combine these relationships deliberately. For example, a weapon trail may bind to its owner for placement while also retaining an owner pointer for damage attribution. Each relationship must be configured through its own interface.
Common Mistakes
- Reversing the relationship and trying to make the target bind another entity to itself.
- Setting configuration without assigning a valid target.
- Setting
BIND_CONFIG_NONEand expecting it to clear the target. - Expecting level-axis flags to work without a target pointer.
- Assuming unconfigured axes will follow the target automatically.
- Forgetting that target X offset mirrors with the target's facing.
- Treating Y as screen position instead of world altitude.
- Assuming relative sort ID overrides differences in world Z.
- Matching target animation IDs when the binding model does not provide corresponding animation slots.
- Using position-removal flags without enabling a defined or target position match.
- Expecting binding to suppress native movement, collision, landing, or special behavior unless the applicable override is enabled.
- Assuming binding establishes owner, parent, child, grab, link, or platform relationships.
- Expecting a property change to reposition the entity immediately without
update_bind(). - Calling
update_bind()from a bind callback without preventing recursion. - Depending on active entity-list order for exact same-cycle behavior across a bind chain.
- Creating self-targets or cycles and expecting stable hierarchical placement.