Inholescript: Difference between revisions
Created page with "<code>inholescript</code> defines a model-level event hook for entities detected inside level hole geometry. It executes during terrain-base adjustment and provides the entity together with the qualifying hole's height, depth, type, and collection index. Despite its name, Inholescript is not limited to standard bottomless pits. Hole type is creator-defined, allowing the same geometry and callback to represent lava, water, quicksand, trapdoors, teleport zones, collapsing..." |
No edit summary |
||
| Line 218: | Line 218: | ||
* [[Binding]] | * [[Binding]] | ||
* [[Movement configuration]] | * [[Movement configuration]] | ||
[[Category:Level]] | |||
[[Category:OpenBOR Index]] | |||
[[Category:Script Events]] | |||
[[Category:Model]] | |||
Latest revision as of 19:59, 18 August 2026
inholescript defines a model-level event hook for entities detected inside level hole geometry. It executes during terrain-base adjustment and provides the entity together with the qualifying hole's height, depth, type, and collection index.
Despite its name, Inholescript is not limited to standard bottomless pits. Hole type is creator-defined, allowing the same geometry and callback to represent lava, water, quicksand, trapdoors, teleport zones, collapsing floors, rescue volumes, environmental transitions, or any other region that should use hole detection.
Inholescript is a continuing contact event, not a one-time entry notification. OpenBOR can execute it once during every advancing logical cycle while the entity continues to satisfy the hole test.
Syntax
inholescript {path}
# Default
# No corresponding Inholescript
{path}- Path to an OpenBOR Script source file.- The command belongs in a model definition.
- OpenBOR loads and compiles the supplied source with the model.
- The source defines a normal
main()entry point. - The script's return value is ignored.
Example model header:
name example_entity
type enemy
inholescript data/scripts/example_inhole.c
Event code may also be embedded directly in the model:
inholescript @script
void main()
{
void self = getlocalvar("self");
int type = getlocalvar("type");
update_hole_contact(self, type);
}
@end_script
update_hole_contact() in this example represents a project-defined function.
Local Variables
| Local | Type | Value |
|---|---|---|
self
|
Entity pointer | Entity currently detected inside the hole. |
height
|
Decimal | Configured altitude of the selected hole. This is the eighth value in the level's hole declaration.
|
depth
|
Decimal | Configured Z depth of the selected hole geometry. This is the seventh value in the level's hole declaration.
|
type
|
Integer | Creator-defined hole type. This is the ninth value in the level's hole declaration.
|
index
|
Integer | Zero-based position of the selected hole in the current level's hole collection. |
height is the hole's configured world altitude, not the entity's current Y position or distance fallen. depth describes the hole's extent along the Z axis, not its vertical depth below the level.
Native hole handling does not interpret type. Projects may assign any useful numeric convention. Prefer type for semantic categories and index when behavior belongs to one specific hole in one specific level.
Trigger Conditions
OpenBOR executes Inholescript when all of the following are true during terrain-base adjustment:
- The model supplies an initialized Inholescript.
- The entity's movement configuration includes
MOVE_CONFIG_SUBJECT_TO_HOLE. - Base adjustment is enabled.
MOVE_CONFIG_NO_ADJUST_BASEcauses terrain processing to return before hole detection. - The entity's X and Z position point lies inside a hole's configured geometry.
- The entity is no more than the native walk-off tolerance above the hole's configured height.
- No qualifying wall or platform supports the entity at that position.
- When the entity is subject to basemaps, no basemap supplies terrain at that position.
Typical model configuration uses:
subject_to_hole 1
no_adjust_base 0
Defaults vary by model type.
Hole detection tests the entity's position point rather than its sprite dimensions, body box, or attack boxes. Large images may visibly overlap a hole without triggering the event until their actual X and Z positions enter the geometry.
Altitude Selection
Hole qualification requires:
entity Y <= hole height + walk-off tolerance
Current native walk-off tolerance is 2 world units. Entities passing high above a hole therefore do not trigger Inholescript merely because their X and Z coordinates overlap the hole.
When several holes overlap, OpenBOR selects the highest qualifying hole and passes its properties to the script. This permits stacked or partially overlapping terrain regions at different altitudes.
Runtime Timing
Inholescript belongs to the post-update terrain pass. The relevant order for each logical cycle is:
- OpenBOR performs the entity's ordinary update when eligible.
- Animation, attack collision, health display, and velocity accumulation may update.
- OpenBOR begins post-update movement processing for every existing entity.
- Terrain base, platform, wall, and hole conditions are evaluated.
- Inholescript executes when the entity satisfies the hole test.
- Native hole-base and link handling continues.
- Vertical velocity and gravity are applied.
- Pending X and Z movement is resolved.
- Binding resolves later, after movement is complete.
The callback consequently runs before gravity advances the entity for the current logical cycle and before ordinary pending X or Z movement is applied. Movement already performed directly by an earlier action or script is visible to the hole test.
Inholescript also runs before OpenBOR applies its normal pit base for the detected contact. Unless the current indexed animation position supplies a positive manual base, native handling then assigns the pit base and clears the entity's native grab/link relationship.
Frozen entities still undergo terrain-base adjustment and may execute Inholescript. Freshly spawned entities can also participate in the post-update terrain pass during their spawn cycle. Pausing the logical engine prevents the normal pass from advancing.
Repeated Execution
Inholescript can execute once per logical cycle for as long as the entity remains in the qualifying hole. It does not distinguish entry, continued presence, or exit.
Continuous effects may use the repeated behavior directly. One-shot effects must record whether the contact was already handled, while periodic effects should manage their own logical-time interval. Exit detection requires another hook, such as Updateentityscript, to notice when an altitude-aware checkhole(x, z, y) or checkholeindex(x, z, y) call no longer reports the region.
One display refresh may process several logical cycles during catch-up. Script behavior should therefore follow logical time rather than assuming one execution per displayed image.
Return and Native Behavior
The script's return value is ignored. Returning 0, 1, or another value does not cancel the hole contact or suppress native processing.
Hole eligibility and several follow-up decisions are calculated before the callback. Moving the entity, changing its animation, or disabling subject_to_hole from inside Inholescript does not reliably cancel native handling already in progress for that pass. Such changes can govern later cycles.
Projects requiring complete replacement hole physics should perform their own detection from an earlier general-purpose hook and configure the model so native hole handling does not begin. Inholescript is best used to observe, extend, classify, or react to a native hole contact.
Quick Example
The following example routes different creator-defined hole types to project systems. Each called function must account for Inholescript's repeated execution.
void main()
{
void self = getlocalvar("self");
float height = getlocalvar("height");
float depth = getlocalvar("depth");
int type = getlocalvar("type");
int index = getlocalvar("index");
switch(type)
{
case 1:
update_lava_contact(self, height);
break;
case 2:
update_quicksand_contact(self, depth);
break;
case 3:
begin_hole_transition(self, index);
break;
default:
update_standard_pit_contact(self, index);
break;
}
}
Hole type provides the reusable hazard category, while index identifies the exact level entry when one region needs unique behavior.
Common Uses
- Applying lava, acid, water, or electrical contact effects.
- Starting a custom fall, rescue, or recovery sequence.
- Selecting different pit behavior according to hole type.
- Triggering sounds, particles, camera effects, or scripted transitions.
- Recording which specific hole received an entity.
- Coordinating trapdoors, collapsing terrain, and hidden passages.
- Extending native pit handling with project-specific state or presentation.
Common Mistakes
- Treating Inholescript as a one-time entry event.
- Expecting the return value to cancel native hole handling.
- Enabling
subject_to_holewhile also enablingno_adjust_base. - Expecting a hole covered by a wall, platform, or applicable basemap to trigger.
- Assuming X and Z overlap is sufficient while the entity remains high above the hole.
- Interpreting
depthas vertical pit depth. - Interpreting
heightas the entity's current altitude. - Depending on
indexas a global identifier across different levels. - Applying damage or spawning effects every execution without accounting for logical-cycle frequency.
- Expecting proposed AI movement toward a hole to invoke the script before the entity actually enters.
- Trying to replace native hole physics after the current contact has already been accepted.