Please note: Projectile system is incomplete and set for depreciation in favor of a generalized sub entity system. Use the following at your own risk.
Contents
- 1 Overview
- 2 Getting Started
- 3 Commands
- 3.1 custbomb <model name>
- 3.2 custknife <model name>
- 3.3 projectile_color_set_adjust <adjust type>
- 3.4 projectile_direction_adjust <direction>
- 3.5 projectile_offense <source>
- 3.6 projectile_position_x <position>
- 3.7 projectile_position_y <position>
- 3.8 projectile_position_z <position>
- 3.9 projectile_velocity_x <velocity>
- 3.10 projectile_velocity_y <velocity>
- 3.11 projectile_velocity_z <velocity>
- 3.12 throwframe <frame> <Offset Y>
- 3.13 tossframe <frame> <Offset Y>
- 4 Legacy
- 5 Script
Overview
Projectiles are generally entities spawned and thrown by another entity to cause damage from a distance. Ryu’s classic Hadouken is perhaps the most iconic, but projectiles can take virtually any form depending on your game design. OpenBOR supports two main projectile types: Knives – standard projectiles thrown straight forward, and Bombs – grenade like projectiles tossed in an arc with an optional explosion effect. Each include a wide array of settings. If the native projectile functions still aren’t enough, projectiles are tightly integrated with OpenBOR’s scripting engine allowing an infinite range of functionalities.
Assuming defaults, projectiles exhibit the following behaviors. It’s a good idea to familiarize yourself with them before you attempt to create more customized projectiles.
Knives
Knives are OpenBOR’s standard projectile method, useful for most forms of ranged attack.
- Fly straight and are not affected by gravity.
- Apply the projectile velocity setting (see below, default X = 2, X = 0, Z = 0). When moving the projectile model’s speed setting controls velocity.
- Take on faction data (who they can hit and who they are hostile to) form parent/owner.
- Can’t hit other projectiles.
- Are subject to walls and platforms.
- Automatically destroyed if they pass more than half a screen out of view. Ex: If horizontal resolution is 320, any knife passing more than 160 pixels out of screen terminates.
Bombs
Bombs simulate a lobbed or timed delay ranged attack. They operate identically to knives with the following exceptions:
- Thrown in an arc determined by projectile model’s jump height. Affected by gravity.
- Apply the projectile velocity setting (see below, default X = 2, Y = projectile model jump height, Z = 0). When moving the projectile model’s X, and Z speed setting controls velocity. Y is used for initial vertical toss velocity.
- If a bomb touches ground without hitting a target, it will play its ATTACK1 animation if available.
- If a bomb hits any eligible target or gets hit by any attack, it will play its ATTACK2 animation if available.
- After a bomb hits or lands and current animation is complete (which animation doesn’t matter), the bomb disappears.
Getting Started
Before going any further, note there are a lot of legacy options and behaviors associated with projectiles. These are in place for backward compatibility, but are otherwise depreciated. It is highly recommended you ignore them and stick to the options in this guide to avoid confusion and unexpected results.
Step 1 – The Projectile Model
You need a projectile to throw first. Projectiles are entities just like players and enemies, so you need to create a model text file for them the same way. The difference is projectiles are usually much simpler. For a basic projectile all you really need is an idle animation with an attack box. Make the model’s type Projectile
. Here is an example:
name ryu_hadouken
type projectile
health 1
alpha 1
palette data/chars/ryu/hadouken/idle_0.png
anim idle
loop 1
delay 5
offset 75 56
attack.damage.force 12
attack.position.x 59
attack.position.y 41
attack.size.x 21
attack.size.y 29
attack.reaction.reposition.direction -1
frame data/chars/ryu/hadouken/idle_0.png
frame data/chars/ryu/hadouken/idle_1.png
frame data/chars/ryu/hadouken/idle_2.png
frame data/chars/ryu/hadouken/idle_3.png
frame data/chars/ryu/hadouken/idle_4.png
frame data/chars/ryu/hadouken/idle_5.png
frame data/chars/ryu/hadouken/idle_6.png
frame data/chars/ryu/hadouken/idle_7.png
frame data/chars/ryu/hadouken/idle_8.png
frame data/chars/ryu/hadouken/idle_9.png
Step 2 – Knowing Is Half The Battle
We have a model ready to go, but it must be loaded into memory before we can use it. There are a several ways to do this, but the most recommended is know
in models.txt and then load
in any model that uses the projectile. This tells OpenBOR to only load the projectile when the model that uses it loads. Here is what the know and load commands might look like:
... know ryu_hadouken data/chars/ryu/hadouken/ryu_hadouken.txt # Haoudken projectile model. know Ryu_e data/chars/ryu/ryu_e.txt # Ryu (enemy). load Ryu data/chars/ryu/ryu.txt # Ryu (player). ... Then in both the enemy and player Ryu (or any other model who might use the Hadouken) model files, we add this line somewhere in the header:
... load ryu_haoudken ...
Behind The Curtain: In almost all cases player controlled models are loaded at all times, and that’s the case in our example too. Consequently, the ryu_haoudken model is always loaded too. But if we only had the enemy Ryu, the ryu_haoudken projectile wouldn’t load unless the player was in a level that spawned the enemy Ryu, thus saving memory. Either way it’s usually best practice using know for projectiles and sub entities.
Step 3 – Launch!
All that remains is to throw the projectile. Since we are building a straight forward Hadouken, we will use the knife
command. This has two mandatory parts, both in the animation you want to throw your projectile with. The first is model declaration, custknife <model name>
(short for “custom knife”). This tells OpenBOR which model projectile model you want to throw. Any model currently loaded is fair game. The second part is the frame declaration, throwframe <frame number>
. This tells OpenBOR which frame of the animation to spawn the projectile. Here’s what the animation looks like with knife commands.
anim Freespecial10 # Hadouken
custknife ryu_hadouken
throwframe 4
delay 5
offset 82 147
bbox.position.x 66
bbox.position.y 49
bbox.size.x 38
bbox.size.y 98
frame data/chars/ryu/hadouken_0.png
frame data/chars/ryu/hadouken_1.png
frame data/chars/ryu/hadouken_2.png
bbox.position.x 78
bbox.position.y 51
bbox.size.x 43
bbox.size.y 95
frame data/chars/ryu/hadouken_3.png
delay 6
bbox.position.x 87
bbox.position.y 60
bbox.size.x 53
bbox.size.y 85
frame data/chars/ryu/hadouken_4.png
frame data/chars/ryu/hadouken_5.png
frame data/chars/ryu/hadouken_6.png
frame data/chars/ryu/hadouken_7.png
frame data/chars/ryu/hadouken_8.png
bbox.position.x 81
bbox.position.y 58
bbox.size.x 44
bbox.size.y 89
frame data/chars/ryu/hadouken_9.png
bbox.position.x 78
bbox.position.y 50
bbox.size.x 37
bbox.size.y 98
frame data/chars/ryu/hadouken_10.png
bbox.position.x 71
bbox.position.y 48
bbox.size.x 38
bbox.size.y 103
frame data/chars/ryu/hadouken_11.png
When this animation reaches frame 4 (remember frames are 0 indexed), the model ryu_haoduken
spawns and flies forward.
Step 4 – Extra Credit
To keep the example simple we didn’t bother with any extra setup or adjustments. That means our example “Haoduken” will mostly follow default knife behaviors. Chances are you will want to modify these behaviors. See below for all the various options available. For even more versatility, try out some script. For instance, you are normally limited to throwing one projectile of each type per animation, but you can use script functions to throw dozens or more on a single frame.
Commands
custbomb <model name>
Model to spawn and launch with tossframe. This is the most recent and recommended native method to set a model for bomb style projectile spawns.
custknife <model name>
Model to spawn and launch with throwframe. This is the most recent and recommended native method to set a model for knife style projectile spawns.
projectile_color_set_adjust <adjust type>
Adjustment (if any) to projectile’s color set (palette).
none
(default) – No adjustment. Projectile uses its default palette.parent_index
– Use same palette index as parent. Ex: If parent is using palette index 2, projectile uses its palette index 2 (if available).parent_table
– Projectile assumes parent’s current color table. This is useful when projectile and parent sprites share the same color table. The projectile will match parent’s colors without the need for its own set of alternate palettes.
projectile_direction_adjust <direction>
Adjustment (if any) to projectile’s direction.
left
– Projectile faces left.none
– No adjustment. Projectile assumes default spawn direction.opposite
– Projectile faces opposite direction as parent.right
– Projectile faces right.same
(default) – Projectile faces same direction as its parent.
projectile_offense <source>
Where projectile derives its offense factors.
parent
– Copy parent’s offense on spawn.self
(default) – Use projectile’s own offense.
projectile_position_x <position>
X axis offset (default 0
) from parent entity position to spawn projectile. Positive values adjust toward direction parent is facing, negative values adjust away.
projectile_position_y <position>
Y axis offset (default 70
) from parent entity position to spawn projectile. Note throwframe
and tossframe
have legacy Y offset parameters. When either is used in conjunction with this command, whichever comes later in order will take precedence.
projectile_position_z <position>
Z axis offset (default 0
) from parent entity position to spawn projectile.
projectile_velocity_x <velocity>
X axis speed (default 1.0
). When projectile is thrown, its speed X
value is overwritten with this setting.
projectile_velocity_y <velocity>
Y axis speed. Behavior varies if spawned as bomb or knife.
- Bomb (
tossframe
) – Applied as a toss velocity, same principal as jumping or knockdowns. For legacy compatibility, this command must appear aftertossframe
. Otherwise legacy default behavior applies, and toss velocity is the projectile model’sjumpheight
. - Knife (
throwframe
) – Same asprojectile_velocity_x
, for Y axis. Default:0
.
projectile_velocity_z <velocity>
Same as projectile_velocity_x
, for Z axis. Default 0
.
throwframe <frame> <Offset Y>
When animation reaches frame
, selected projectile model spawns and fires as knife at Y offset
. For backward compatibility the selected model may come from one of several sources.
From highest to lowest priority:
- Custknife (recommended)
- Custpshotno
- Project
- Knife
- Playshotno
- Any loaded model named “Knife”.
- Any loaded model named “Shot”.
tossframe <frame> <Offset Y>
When animation reaches frame
, selected projectile model spawns and fires as bomb at Y offset
. For backward compatibility the selected model may come from one of several sources.
From highest to lowest priority:
- Custbomb (recommended)
- Project
- Bomb
Legacy
Legacy commands are depreciated and included for backward compatibility only. Use at your own risk. See description for replacement method.
Name | Level | Description |
---|---|---|
custpbomb <model name> | Animation | Same as custbomb. Replacement: Ignore and use Custbomb. |
custpshotno <model name> | Animation | Short for “custom player shot nomove”. Model to spawn and launch with throwframe. The intended behavior is model launches and stays in place. Replacement: Use Custknife and projectile_velocity settings of 0. |
Knife <model name> | Model | Model to spawn and launch with throwframe. Applies to all animations in model, method used before ability to select projectile models on a per-animation basis added. Replacement: Use Custknife in the model’s animation. |
Project <model name> | Model | Model to spawn and launch with throwframe. Only applies if used as part of a weapon model. Intended as a quick means of supplanting a model level projectile. Replacement: Use Custknife in the weapon model’s animation. |
Script
Projectile properties are accessible through the get_projectile_property()
and set_projectile_property()
functions. You will need the projectile pointer first. Typically you will get this from an animation.
Use Cases
Get a property value. Properties and their behavior can vary wildly – see the property list for details.
mixed x = get_projectile_property(void <projectile handle>, char <identifier>);
Modify a property value. Some properties are read only – see the property list for details.
mixed x = <value>;
set_projectile_property(void <projectile handle>, char <identifier>, x);
List
- Name: The identifier used to access property through script.
- Type: The property value’s variable type.
- Description: A short description of what the property is and does.
Name | Type | Description |
---|---|---|
color_set_adjust | Integer | Source for projectile’s color settings on spawn. * openborconstant("COLOR_SET_ADJUST_NONE") – No color change. The projectile spawns with its default palette. * openborconstant("COLOR_SET_ADJUST_PARENT_INDEX") – Projectile spawns with same palette index as parent.* openborconstant("COLOR_SET_ADJUST_PARENT_TABLE") – Projectile spawns with same palette as parent. |
direction_adjust | Integer | Direction applied to projectile on spawn. * openborconstant("DIRECTION_ADJUST_NONE") – No direction adjustment. * openborconstant("DIRECTION_ADJUST_SAME") – Parent’s current direction. * openborconstant("DIRECTION_ADJUST_OPPOSITE") – Opposite parent’s current direction.* openborconstant("DIRECTION_ADJUST_RIGHT") – Face right. * openborconstant("DIRECTION_ADJUST_LEFT") – Face Left. |
frame_shoot | Integer | Upon reaching this frame, OpenBOR attempts to locate a model index from the sources listed here (highest to lowest priority). If a valid model index is found, it is spawned and launched as a projectile entity. * Project property from a weapon model. * Knife model property. * model_index_flash. * model_index_knife. * Pshot model property. * Global Shot (attempts to find a model in the database named “Shot”). * Global Knife (attempts to find a model in the database named “Knife”). |
frame_throw | Integer | Legacy star projectile throw. Upon reaching this frame, OpenBOR attempts to locate a model index from the sources listed here. Repeat attempts of the same source are not typos – this is part of the legacy logic to maintain backward compatibility. * model_index_flash. * model_index_knife. * projectile star. Entity is jumping… * Project property from a weapon model. * Animation model_index_star. * Star model property. * Global Star (attempts to find a model in the database named “Star”). * Project property from a weapon model. * Knife model property. * model_index_flash. * model_index_knife. * Pshot model property. * Global Shot (attempts to find a model in the database named “Shot”). * Global Knife (attempts to find a model in the database named “Knife”). Entity not jumping… * Project property from a weapon model. * Knife model property. * model_index_flash. * model_index_knife. * Pshot model property. * Global Shot (attempts to find a model in the database named “Shot”). * Global Knife (attempts to find a model in the database named “Knife”). * Project property from a weapon model. * projectile star. * Star model property. * Global Star (attempts to find a model in the database named “Star”). |
frame_toss | Integer | Upon reaching this frame, OpenBOR attempts to locate a model index from the sources listed here (highest to lowest priority). If a valid model index is found, it is spawned and launched as a bomb entity. * Project property from a weapon model. * model_index_bomb. * Bomb model property. |
model_index_bomb | Integer | Model index for bomb spawns by frame_toss. |
model_index_flash | Integer | Model index for projectile spawns by frame_shoot. If this model index is used, the projectile does not move after spawning. |
model_index_knife | Integer | Model index for projectile spawns by frame_shoot. |
model_index_star | Integer | Model index for projectile spawns by frame_throw. When spawned as a star during jumps, three projectiles are launched at diagonal angles downward. |
offense | Integer | Source for projectile’s offense settings. Note these are only applied at point of spawn. * openborconstant("PROJECTILE_OFFENSE_PARENT") – Use parent’s current offense. * openborconstant("PROJECTILE_OFFENSE_SELF") – Use projectile model’s offense. |
placement | Integer | Anchor position for spawn offset. Currently projectile spawns always use the parent location – the logic for this property is not implemented yet and does nothing. * openborconstant("SUB_ENTITY_PLACEMENT_PARENT") – Parent. * openborconstant("SUB_ENTITY_PLACEMENT_SCREEN") – Visible screen. * openborconstant("SUB_ENTITY_PLACEMENT_ABSOLUTE") – Current level. |
position_x | Integer | X axis offset from parent (entity that throws projectile) position to spawn projectile. Offset is relative to parent’s facing. Positive values adjust position ahead of entity, negative values adjust behind. |
position_y | Integer | Y axis offset from parent position to spawn projectile. Positive values adjust position above entity, negative values adjust below. |
position_z | Integer | Z axis offset from parent position to spawn projectile. Positive values adjust position toward player view, negative values adjust into screen. |