Name | Author | Game Mode | Rating | |||||
---|---|---|---|---|---|---|---|---|
Standard Weapon Interface | Seren | Other | 10 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Standard Weapon Interface API</title>
<style>
body {
background-color: #FFE082;
color: black;
font-family: "Trebuchet MS", Helvetica, sans-serif;
padding: 5em;
padding-top: 0;
}
h1 {
text-align: center;
}
h2::before, dt::before {
content: "\25C7\20";
}
p {
text-indent: 0.5em;
}
pre, code, dt, .values, .ini {
font-family: "Courier New", Courier, monospace;
}
.ini {
list-style-type: none;
}
pre, dl, .contents {
background-color: #FFFFB3;
border: none;
border-radius: 0.5em;
box-shadow: 0 7px 10px -1px rgba(133, 113, 41, 0.75);
margin-bottom: calc(1em + 7px);
padding: 0.5em;
}
.contents {
display: inline-block;
margin: 0;
padding-bottom: 1em;
padding-left: 2em;
padding-right: 2em;
}
dl pre, dl dl {
background-color: white;
}
dd {
margin: 2em;
margin-bottom: 1.25em;
margin-top: 0.1em;
}
dt, .arg, .concept, .keyword {
font-weight: bold;
}
.keyword, .type {
color: #1A237E;
}
.comment {
opacity: 0.6;
}
sup {
font-size: 0.7em;
}
</style>
</head>
<body>
<article>
<h1>Standard Weapon Interface</h1>
<section id="tableofcontents">
<h2>Table of Contents</h2>
<ul class="contents">
<li><a href="#concepts">Prelude: Concepts</a></li>
<li><a href="#weapon">Concept: Weapon</a></li>
<li><a href="#weaponhook">Concept: Weapon Hook</a></li>
<li><a href="#misc">Miscellaneous entities</a></li>
</ul>
</section>
<section id="concepts">
<h2>Prelude: Concepts</h2>
<p>In AngelScript, an <em>interface</em> is a named set of methods. A class is said to <em>implement an interface</em> when it provides implementations of all of its methods and the interface is listed on its inheritance list. For example:</p>
<pre>
<span class="keyword">interface</span> <span class="type">Base</span> {
<span class="keyword">void</span> foo();
<span class="type">string</span> bar(<span class="keyword">int</span>);
}
<span class="comment">// This class implements Base</span>
<span class="keyword">class</span> <span class="type">Derived</span> : <span class="type">Base</span> {
<span class="keyword">void</span> foo() {}
<span class="type">string</span> bar(<span class="keyword">int</span> a) {
<span class="keyword">return</span> formatInt(a);
}
}
<span class="comment">// This class doesn't implement Base
// because Base is not on the inheritance list</span>
<span class="keyword">class</span> <span class="type">NotDerived</span> {
<span class="keyword">void</span> foo() {}
<span class="type">string</span> bar(<span class="keyword">int</span> a) {
<span class="keyword">return</span> formatInt(a);
}
}
<span class="comment">// This class doesn't implement Base
// because it does not implement method foo
// The code wouldn't compile
// class Invalid : Base {
// string bar(int a) {
// return formatInt(a);
// }
// }</span>
</pre>
<p>An interface may define what methods a class exposes but it has no way to specify how they should be implemented. For this reason, this document defines an additional term: a <em>concept</em> is a named set of requirements for a type. A type is said to <em>satisfy a concept</em> if it meets all its requirements. For sufficiently complex concepts, it's impossible to test programmatically whether a given type satisfies them, therefore it is up to a human to settle. Concepts are useful because they allow programmers to have certain expectations of a type.</p>
<p>This document focuses on discussing two concepts: <span class="concept">Weapon</span> and <span class="concept">Weapon Hook</span>, side to side with their corresponding interfaces. The final section of this document discusses helper functions and classes that the library exposes.</p>
</section>
<section id="weapon">
<h2>Concept: Weapon</h2>
<p>
A <span class="concept">Weapon</span> is a class that fulfills the following requirements:
<ul>
<li>it is instantiable, i.e. it is not abstract, mixin, or otherwise impossible to create instances of;</li>
<li>it implements <code>WeaponInterface</code>;</li>
<li>its implementations of all methods inherited from <code>WeaponInterface</code> follow all rules described in the remainder of this section.</li>
</ul>
</p>
<p><code>WeaponInterface</code> is defined as follows:</p>
<pre>
<span class="keyword">shared</span> <span class="keyword">interface</span> <span class="type">WeaponInterface</span> {
<span class="type">jjANIMSET</span>@ loadAnims(<span class="type">jjANIMSET</span>@ animSet);
<span class="type">array</span><<span class="keyword">bool</span>>@ loadSamples(<span class="keyword">const</span> <span class="type">array</span><SOUND::<span class="type">Sample</span>>& samples);
<span class="keyword">uint</span> getSampleCount() <span class="keyword">const</span>;
<span class="keyword">uint</span> getTraits(<span class="keyword">bool</span> powerup) <span class="keyword">const</span>;
<span class="keyword">uint</span> getMaxDamage(<span class="keyword">bool</span> powerup) <span class="keyword">const</span>;
<span class="keyword">bool</span> setAsWeapon(<span class="keyword">uint</span> number, <span class="type">WeaponHook</span>@ weaponHook);
}
</pre>
<dl>
<dt>jjANIMSET@ loadAnims(jjANIMSET@ animSet)</dt>
<dd>
Loads or generates all external sprites used by the weapon and may load some or all internal sprites used by it. This method must not modify any game assets except that:
<ul>
<li>it may freely modify the animation set whose handle is passed as <span class="arg">animSet</span>, but must not make any assumptions about which set it is and what is its initial content;</li>
<li>it may load other animation sets, with the restriction that they must be loaded from their corresponding sources in Anims.j2a or plus.j2a and cannot be further modified by this method.</li>
</ul>
The method needs not actually load or generate any sprites, assuming the weapon doesn't require them. Null handle is an allowed value of the <span class="arg">animSet</span> argument and the method is not allowed to report an error if it receives it (but may fail to load animations). The method is allowed to assume existence and content of any file resources. The method must return <span class="arg">animSet</span>.
</dd>
<dt>array<bool>@ loadSamples(const array<SOUND::Sample>& samples)</dt>
<dd>
Loads all external samples used by the weapon. This method must not modify any game assets except that it may call <code>jjSampleLoad</code> with elements of <span class="arg">samples</span> as the first argument. The method should treat the <span class="arg">samples</span> argument as follows:
<ul>
<li>if the length of array <span class="arg">samples</span> is exactly equal to the number of samples to load, i.e. the same as the value returned by <code>getSampleCount()</code>, then the method shall attempt to load the samples. In this case, for each element of the array, the method shall call <code>jjSampleLoad</code> with the element as the first argument. The array returned by the method shall then contain results returned by the corresponding calls to <code>jjSampleLoad</code>;</li>
<li>otherwise, the method must not take any actions and has to return an array of length equal to the value returned by <code>getSampleCount()</code> with all elements set to false.</li>
</ul>
The method must not make any assumptions about the content of the argument <span class="arg">samples</span>, except that all elements are valid <code>SOUND::Sample</code> values and that all elements are pairwise distinct.
</dd>
<dt>uint getSampleCount() const</dt>
<dd>Returns the number of external samples used by the weapon (which may be 0). This value must remain constant for the entire lifetime of each class instance (but it is allowed to differ between individual instances of the class).</dd>
<dt>uint getTraits(bool powerup) const</dt>
<dd>
Returns a bitmask that is some combination of WeaponTrait enum constants, that can be used to obtain some basic information about the weapon. The constants are combined using the <code>|</code> (bitwise OR) operator. If the argument <span class="arg">powerup</span> is <code>true</code>, the result should indicate traits of the powered-up version of the weapon, otherwise the basic version. This value must remain constant for the entire lifetime of each class instance (but it is allowed to differ between individual instances of the class). For any flags that may depend on server settings, the game mode should be treated as Battle (unless the weapon does not work in Battle, then it should be treated as any multiplayer game mode it works in) and the following setup should be assumed, with remaining settings set to their defaults:
<ul class="ini">
<li>StartHealth=5</li>
<li>MaxHealth=7</li>
<li>DamageAmplifier=False</li>
<li>FriendlyFire=False</li>
<li>WeakPowerups=False</li>
<li>StrongPowerups=True</li>
<li>ExtendedTNT=False</li>
<li>TNTDamage=1</li>
<li>EvilIce=False</li>
<li>Gun8Fireball=True</li>
</ul>
Available constants are discussed in detail below. Note that for most of them there exists some gray area where it could be discussed whether a flag should be enabled or not so it's reasonable to treat them as an approximation of the weapon's properties rather than a precise description.
<dl>
<dt>weapon_deals_damage</dt>
<dd>The weapon may under some circumstances reduce the health of its target, or instantly kill it. This flag should not account for pits or other environmental hazards, only directly caused damage, i.e. it would be false for the built-in JJ2 ice and true for all remaining weapons.</dd>
<dt>weapon_causes_splash_damage</dt>
<dd>Each bullet may hit multiple targets within its area at the same time due to explosive-like or laser-like properties. In particular, this should generally be used if targets may be hit by bullets without direct contact with their sprite. The weapon need not actually cause damage to the targets, rather only have some significant effect on them. This flag would be enabled for built-in JJ2 TNT, RF missiles and the laser shield weapon.</dd>
<dt>weapon_may_harm_user</dt>
<dd>The weapon may have direct negative impact on the player using it, such as by freezing them or causing them damage, e.g. if it's an explosive missile fired at a nearby wall. No built-in JJ2 weapons do this, but most of weapons featured in <a href="https://www.jazz2online.com/downloads/7395/decimation/">Decimation</a> do.</dd>
<dt>weapon_may_heal_players</dt>
<dd>The weapon may increase health of some players, possibly the user, their team mates, or opponents.</dd>
<dt>weapon_increases_mobility</dt>
<dd>The weapon is useful as a means of moving around levels faster, or may make more locations accessible. This is a common use for RF missiles, and much more prominent in the energy blast weapon included with this library.</dd>
<dt>weapon_inflicts_status_condition</dt>
<dd>Players or enemies hit by the weapon experience temporary or permanent negative effects other than immediate loss of health, such as becoming dizzy, frozen, poisoned, or turned into a frog.</dd>
<dt>weapon_melts_ice</dt>
<dd>The weapon melts ice, in particular on frozen springs. This is typically associated with bullets having bit 2 enabled on <code>jjOBJ::var[6]</code>.</dd>
<dt>weapon_freezes_objects</dt>
<dd>The weapon may freeze objects such as crates or SP enemies.</dd>
<dt>weapon_fails_underwater</dt>
<dd>The weapon either becomes useless when fired underwater, or cannot be fired underwater at all, e.g. fire-based weapons.</dd>
<dt>weapon_fails_in_interiors</dt>
<dd>The weapon either becomes useless when fired inside of buildings and caves, or cannot be fired there at all, e.g. weapons involving any sort of an air strike.</dd>
<dt>weapon_goes_through_thin_walls</dt>
<dd>The weapon may go through sufficiently thin walls, roughly between half a tile and 2 tiles, e.g. bouncer or electroblaster.</dd>
<dt>weapon_goes_through_thick_walls</dt>
<dd>The weapon goes through even very thick walls, such as 6 tiles or more, e.g. electroblaster. Note that this does not imply <code>weapon_goes_through_thin_walls</code>, even though cases of weapons that go through thick but not thin walls are probably very obscure.</dd>
<dt>weapon_is_super_weapon</dt>
<dd>The weapon is particularly powerful. This is best used as an indication that ammo pickups for the weapon should be extremely rare and placed individually rather than in clusters.</dd>
<dt>weapon_is_effective_against_players</dt>
<dd>The weapon has some effect on other players, whether it damages them, inflicts a status, heals them, or other.</dd>
<dt>weapon_is_effective_against_sp_enemies</dt>
<dd>The weapon has some effect on SP enemies, whether it damages them, inflicts a status, heals them, or other.</dd>
<dt>weapon_destroys_crates</dt>
<dd>The weapon can be used to destroy ammo crates, power-ups, shields, etc.</dd>
<dt>weapon_supports_mouse_aim</dt>
<dd>The weapon works correctly when mouse aim is enabled.</dd>
<dt>weapon_requires_mouse_use</dt>
<dd>The weapon requires mouse use. This does not imply that mouse aim has to be enabled for the weapon to work.</dd>
<dt>weapon_works_in_mp</dt>
<dd>The weapon works correctly in at least Battle and CTF game modes. This does not imply that it works correctly over the network, as it may only support local splitscreen.</dd>
<dt>weapon_works_in_sp</dt>
<dd>The weapon works correctly in local Single Player mode.</dd>
<dt>weapon_works_in_coop</dt>
<dd>The weapon works correctly in Cooperation mode, either in local splitscreen or over the network.</dd>
<dt>weapon_works_in_splitscreen</dt>
<dd>The weapon works correctly in local splitscreen. If <code>weapon_works_online</code> is enabled, this also implies the weapon works correctly online and over LAN when splitscreen clients are present.</dd>
<dt>weapon_works_online</dt>
<dd>The weapon works correctly online and over LAN.</dd>
<dt>weapon_has_ammo_pickups</dt>
<dd>There exist pickups that, when collected, increase the player's ammo count for the weapon. If this is disabled, it may mean that weapon ammo is infinite, as is the case with blaster, or that ammo is only obtainable by some other means.</dd>
<dt>weapon_has_ammo_crates</dt>
<dd>There exist crates that drop the weapon's ammo pickups, or otherwise provide ammo for the weapon.</dd>
<dt>weapon_has_powerup_monitors</dt>
<dd>There exist power-up monitors for the weapon.</dd>
<dt>weapon_has_distinct_powerup</dt>
<dd>The weapon may be powered up, and its powered-up version differs from its basic version.</dd>
<dt>weapon_requires_no_ammo_pickups</dt>
<dd>Ammo pickups, crates, and power-ups of the weapon do not have to be placed in the level for the weapon to be possible to use. The weapon probably has its own means to provide players with ammo.</dd>
<dt>weapon_cannot_be_fired_by_key_press</dt>
<dd>Fire key, or any other key or mouse button, is not the trigger tied directly to firing the weapon. E.g. the weapon might fire periodically regardless of user input, automatically when enemies are nearby, or never fire at all.</dd>
<dt>weapon_requires_certain_events_in_level</dt>
<dd>The level must contain certain events for the weapon to be functional. This should not refer to ammo pickups, crates, power-ups, start positions, or events that are inseparable from the only game modes the weapon works in (e.g. if the weapon only works in CTF and it only requires CTF bases to be in the level, this flag should not be enabled). Instead it may e.g. refer to events such as vines, if for some reason they're the only place the weapon may be used, destruct scenery, if that's the only target the weapon is effective against, or path events, if the projectiles follow a preset path.</dd>
</dl>
The following convenience constants are also defined:
<dl class="values">
<dt>weapon_no_trait</dt>
<dd>0</dd>
<dt>weapon_goes_through_walls</dt>
<dd>weapon_goes_through_thin_walls | weapon_goes_through_thick_walls</dd>
<dt>weapon_is_effective_against_all_targets</dt>
<dd>weapon_is_effective_against_players | weapon_is_effective_against_sp_enemies | weapon_destroys_crates</dd>
<dt>weapon_works_in_all_modes</dt>
<dd>weapon_works_in_mp | weapon_works_in_sp | weapon_works_in_coop | weapon_works_in_splitscreen | weapon_works_online</dd>
<dt>weapon_has_all_pickups</dt>
<dd>weapon_has_ammo_pickups | weapon_has_ammo_crates | weapon_has_powerup_monitors | weapon_has_distinct_powerup</dd>
<dt>weapon_default_traits</dt>
<dd>weapon_deals_damage | weapon_is_effective_against_all_targets | weapon_supports_mouse_aim | weapon_works_in_all_modes | weapon_has_all_pickups</dd>
</dl>
</dd>
<dt>uint getMaxDamage(bool powerup) const</dt>
<dd>
Returns the maximum number that a player's life may be reduced by when they're hit by the weapon. If the argument <span class="arg">powerup</span> is <code>true</code>, the result should indicate damage done by the powered-up version of the weapon, otherwise the basic version. This value must remain constant for the entire lifetime of each class instance (but it is allowed to differ between individual instances of the class). For determining the outcome, the game mode should be treated as Battle (unless the weapon does not work in Battle, then it should be treated as any multiplayer game mode it works in) and the following setup should be assumed, with remaining settings set to their defaults:
<ul class="ini">
<li>StartHealth=5</li>
<li>MaxHealth=7</li>
<li>DamageAmplifier=False</li>
<li>FriendlyFire=False</li>
<li>WeakPowerups=False</li>
<li>StrongPowerups=True</li>
<li>ExtendedTNT=False</li>
<li>TNTDamage=1</li>
<li>EvilIce=False</li>
<li>Gun8Fireball=True</li>
</ul>
For determining the outcome, it should be assumed that there are no outside conditions (i.e. not directly caused by the weapon) that may increase the return value, such as the user being a zombie in Pestilence mode, or damage amplifier being in effect as a result of overtime. In instances when a weapon causes health loss by means other than subtracting from the original value, the way to determine damage is by subtracting the new health from the original health, i.e. if a weapon always sets a player's health to 1 on hit, then this method should return 6 because the maximum damage will be done if the player's original health was 7. The state of death is considered as 0 health even when health is not set directly and damage is not done, such as by a call to <code>jjPLAYER::kill</code>. A weapon that always kills instantly should thus return 7. Returned values greater than 7 are allowed and considered equivalent to 7. Healing, or negative damage as one may put it, must not be taken into account in any way for the purpose of this method, so if a weapon may only heal and not do damage, the returned value must be 0.
</dd>
<dt>bool setAsWeapon(uint number, WeaponHook@ weaponHook)</dt>
<dd>
Binds the class instance to game weapon with the specified <span class="arg">number</span>. This generally means performing some or all of the following actions:
<ul>
<li>modifying object presets of bullets to have custom behavior, handling, or other properties;</li>
<li>modifying the <code>jjWEAPON</code> instance corresponding to the weapon;</li>
<li>modifying object presets of ammo pickups, crates, and power-up monitors for the weapon;</li>
<li>setting weapon ammo sprite to be used in HUD by <span class="arg">weaponHook</span>;</li>
<li>registering callback functions with <span class="arg">weaponHook</span>.</li>
</ul>
The method returns whether it was successful. The method is allowed to fail for any reason (which it must then signal by returning <code>false</code>), for example:
<ul>
<li><code>loadAnims</code> or <code>loadSamples</code> were never called on the class instance, or file resources are missing;</li>
<li>the provided argument <span class="arg">number</span> is not a valid weapon number in the range 1-9;</li>
<li><span class="arg">weaponHook</span> is a null handle;</li>
<li>the call is made in an online game whereas the weapon only supports local games or vice versa.</li>
</ul>
In all of those circumstances the method is also allowed to succeed and return <code>true</code>, possibly sacrificing some functionality. For example, if samples are not loaded, the weapon may provide fallback built-in samples, or play no sounds at all. Similarly, if <span class="arg">weaponHook</span> is <code>null</code>, the weapon will not be able to display custom HUD sprites, but may be completely functional otherwise.
</dd>
<dd>
This method may access and modify any game resources with the following exceptions:
<ul>
<li><code>jjPLAYER</code> instances must not be modified;</li>
<li>the only <code>jjWEAPON</code> instance that may be modified is <code>jjWeapons[number]</code>, where <span class="arg">number</span> is the provided argument;</li>
<li>it is not allowed to make any calls to <code>jjANIMSET::load</code>, <code>jjANIMSET::allocate</code>, <code>jjPIXELMAP::save</code>, <code>jjMASKMAP::save</code>, <code>jjTilesFromTileset</code>, or <code>jjSampleLoad</code>;</li>
<li>it is not allowed to modify <code>jjANIMSET</code>, <code>jjANIMATION</code>, or <code>jjANIMFRAME</code> instances, except for those corresponding to the argument <code>loadAnims</code> was previously called with.</li>
</ul>
The weapon may freely modify the <code>WeaponHook</code> instance whose handle is passed as an argument, except that when calling non-const methods that expect a weapon number as an argument, it must pass the value of its own argument <span class="arg">number</span>.
</dd>
</dl>
</section>
<section id="weaponhook">
<h2>Concept: Weapon Hook</h2>
<p>
A <span class="concept">Weapon Hook</span> is a class that fulfills the following requirements:
<ul>
<li>it is instantiable, i.e. it is not abstract, mixin, or otherwise impossible to create instances of;</li>
<li>it implements <code>WeaponHook</code>;</li>
<li>its implementations of all methods inherited from <code>WeaponHook</code> follow all rules described in the remainder of this section.</li>
</ul>
</p>
<p>The objective of <span class="concept">Weapon Hook</span> is to provide a way for weapons to gain access to hooks such as <code>onPlayer</code>, <code>onDrawAmmo</code>, and <code>onReceive</code>, without directly registering those functions (which would make it impossible for users to register their own). It achieves this by allowing weapons to register several callbacks that are called from those respective hooks.</p>
<p>There exists a built-in class that satisfies <span class="concept">Weapon Hook</span> named <code>DefaultWeaponHook</code>. This class should be a sufficient implementation of the concept for most use cases. When it is not sufficient, it may be a good idea to inherit from it in order to keep most method implementations the same.</p>
<p><code>WeaponHook</code> is defined as follows:</p>
<pre>
<span class="keyword">shared</span> <span class="keyword">interface</span> <span class="type">WeaponHook</span> {
<span class="keyword">void</span> setUserData(<span class="keyword">uint</span> number, <span class="type">UserData</span>@ data);
<span class="type">UserData</span>@ getUserData(<span class="keyword">uint</span> number) <span class="keyword">const</span>;
<span class="keyword">void</span> setWeaponSprite(<span class="keyword">uint</span> number, <span class="keyword">bool</span> powerup, <span class="keyword">const</span> <span class="type">jjANIMATION</span>@ anim);
<span class="keyword">void</span> resetCallbacks(<span class="keyword">uint</span> number);
<span class="keyword">void</span> setMainCallback(<span class="keyword">uint</span> number, <span class="type">MainCallback</span>@ callback);
<span class="keyword">void</span> setPlayerCallback(<span class="keyword">uint</span> number, <span class="type">PlayerCallback</span>@ callback);
<span class="keyword">void</span> setPlayerInputCallback(<span class="keyword">uint</span> number, <span class="type">PlayerCallback</span>@ callback);
<span class="keyword">void</span> setDrawingCallback(<span class="keyword">uint</span> number, <span class="type">DrawingCallback</span>@ callback);
<span class="type">PacketConstructor</span>@ addPacketCallback(<span class="type">PacketCallback</span>@ callback);
<span class="keyword">bool</span> drawAmmo(<span class="type">jjPLAYER</span>@ player, <span class="type">jjCANVAS</span>@ canvas);
<span class="keyword">void</span> processMain();
<span class="keyword">void</span> processPlayer(<span class="type">jjPLAYER</span>@ player);
<span class="keyword">void</span> processPlayerInput(<span class="type">jjPLAYER</span>@ player);
<span class="keyword">bool</span> processPacket(<span class="type">jjSTREAM</span> &<span class="keyword">in</span> packet, <span class="keyword">int</span> clientID);
}
</pre>
<dl>
<dt>void setUserData(uint number, UserData@ data)</dt>
<dd>Sets user data for weapon <span class="arg">number</span>. User data may be used in any way by the <span class="concept">Weapon Hook</span> or remain completely unused (which is what <code>DefaultWeaponHook</code> does). <code>UserData</code> is defined as an empty interface, i.e. any class may be declared as implementing <code>UserData</code>. The <span class="concept">Weapon Hook</span> concept does not impose any requirements on <code>UserData</code> classes or how this method should be used.</dd>
<dt>UserData@ getUserData(uint number) const</dt>
<dd>Returns user data for weapon <span class="arg">number</span>, as last set by <code>setUserData</code> for the same <span class="arg">number</span>. The returned value is unspecified if <code>setUserData</code> with the same <span class="arg">number</span> was never called (<code>null</code> in the default implementation).</dd>
<dt>void setWeaponSprite(uint number, bool powerup, const jjANIMATION@ anim)</dt>
<dd>Sets animation to be used by HUD to represent weapon <span class="arg">number</span>. The argument <span class="arg">powerup</span> determines whether to set the sprite for the basic (<code>false</code>) or powered-up (<code>true</code>) version of the weapon. How exactly the animation is used, or whether it's used at all, is unspecified (by default the original JJ2 appearance is replicated).</dd>
<dt>void resetCallbacks(uint number)</dt>
<dd>Resets main, player, player input, and drawing callbacks for weapon <span class="arg">number</span>, setting them to their default values. User data, weapon sprites, and packet callbacks remain unchanged.</dd>
<dt>void setMainCallback(uint number, MainCallback@ callback)</dt>
<dd>Sets main callback for weapon <span class="arg">number</span> to the argument <span class="arg">callback</span>. The main callback of every weapon may be assumed to be called exactly once every time <code>onMain</code> is called.</dd>
<dd>
<code>MainCallback</code> is defined as follows:
<pre>
<span class="keyword">funcdef</span> <span class="keyword">void</span> <span class="type">MainCallback</span>(<span class="keyword">int</span> number);
</pre>
where <span class="arg">number</span> is the same value that the hook was registered with.
</dd>
<dt>void setPlayerCallback(uint number, PlayerCallback@ callback)</dt>
<dd>Sets player callback for weapon <span class="arg">number</span> to the argument <span class="arg">callback</span>. The player callback of every weapon may be assumed to be called exactly once every time <code>onPlayer</code> is called, regardless of whether the player has the weapon equipped or has ammo for the weapon.</dd>
<dd>
<code>PlayerCallback</code> is defined as follows:
<pre>
<span class="keyword">funcdef</span> <span class="keyword">void</span> <span class="type">PlayerCallback</span>(<span class="type">jjPLAYER</span>@ player, <span class="keyword">int</span> number);
</pre>
where <span class="arg">player</span> is the player <code>onPlayer</code> was called for, and <span class="arg">number</span> is the same value that the hook was registered with.
</dd>
<dt>void setPlayerInputCallback(uint number, PlayerCallback@ callback)</dt>
<dd>Sets player input callback for weapon <span class="arg">number</span> to the argument <span class="arg">callback</span>. The player input callback of every weapon may be assumed to be called exactly once every time <code>onPlayerInput</code> is called, regardless of whether the player has the weapon equipped or has ammo for the weapon.</dd>
<dd>
<code>PlayerCallback</code> is defined as follows:
<pre>
<span class="keyword">funcdef</span> <span class="keyword">void</span> <span class="type">PlayerCallback</span>(<span class="type">jjPLAYER</span>@ player, <span class="keyword">int</span> number);
</pre>
where <span class="arg">player</span> is the player <code>onPlayerInput</code> was called for, and <span class="arg">number</span> is the same value that the hook was registered with.
</dd>
<dt>void setDrawingCallback(uint number, DrawingCallback@ callback)</dt>
<dd>Sets drawing callback for weapon <span class="arg">number</span> to the argument <span class="arg">callback</span>. Drawing callbacks may be assumed to be called at most once per call to <code>onDrawAmmo</code> and only for the weapon currently equipped by the player.</dd>
<dd>
<code>DrawingCallback</code> is defined as follows:
<pre>
<span class="keyword">funcdef</span> <span class="keyword">bool</span> <span class="type">DrawingCallback</span>(<span class="type">jjPLAYER</span>@ player, <span class="type">jjCANVAS</span>@ canvas, <span class="keyword">const</span> <span class="type">jjANIMATION</span>@ anim);
</pre>
where <span class="arg">player</span> and <span class="arg">canvas</span> are the parameters passed to <code>onDrawAmmo</code>, and <span class="arg">anim</span> is the animation to be drawn as set by <code>setWeaponSprite</code> or <code>null</code> if none was provided. If the function returns <code>true</code>, it completely overrides the default drawing behavior, otherwise the default behavior is still applied afterwards. Note that weapon number is not explicitly provided as a parameter, but because drawing hooks are only called for currently selected weapons, it may be determined from <code>player.currWeapon</code>.
</dd>
<dt>PacketConstructor@ addPacketCallback(PacketCallback@ callback)</dt>
<dd>Adds a new packet callback. Unlike all remaining callbacks, packet callbacks are not associated with a specific weapon number. Instead, the <span class="arg">callback</span> becomes associated with packets created using the returned <code>PacketConstructor</code> function. In order for all clients in the server to interpret weapon packets correctly, packet callbacks must be registered in the same order for every game instance (i.e. all clients and the host). In order to guarantee that packets always trigger the correct response, callbacks registered by this method are stored indefinitely, i.e. there exists no way to remove registered packet callbacks. In every valid implementation of the <span class="concept">Weapon Hook</span> concept, it's guaranteed that it's possible to register at least 255 packet callbacks, but any further calls to this method may have undefined behavior in some implementations. The default implementation supports virtually unlimited callbacks (2<sup>31</sup>, but it's likely that the game will run out of RAM before that value is reached).</dd>
<dd>
<code>PacketCallback</code> is defined as follows:
<pre>
<span class="keyword">funcdef</span> <span class="keyword">void</span> <span class="type">PacketCallback</span>(<span class="type">jjSTREAM</span>& packet, <span class="keyword">int</span> clientID);
</pre>
where <span class="arg">packet</span> is the relevant portion of the obtained packet (i.e. everything past the prefix created by <code>PacketConstructor</code>) and <span class="arg">clientID</span> is the same client ID value as passed to <code>onReceive</code>. <span class="arg">packet</span> is passed by an <code>inout</code> reference and may be freely modified without consequences.
</dd>
<dd>
<code>PacketConstructor</code> is defined as follows:
<pre>
<span class="keyword">funcdef</span> <span class="type">jjSTREAM</span> <span class="type">PacketConstructor</span>();
</pre>
This function returns a non-empty <code>jjSTREAM</code> instance with unspecified content. This content is considered an obligatory prefix to every packet that is meant to be handled by the corresponding callback.
</dd>
<dd><strong>Note:</strong> <code>DefaultWeaponHook</code> constructor may be provided with a single <code>uint8</code> argument, in case of which its value will precede every packet prefix returned by its corresponding <code>PacketConstructor</code> functions, allowing a script module to differentiate between <code>DefaultWeaponHook</code> packets and custom packets of the module.</dd>
<dt>bool drawAmmo(jjPLAYER@ player, jjCANVAS@ canvas)</dt>
<dd>Calls drawing callback corresponding to <code>player.currWeapon</code> if one is specified. Otherwise, or if the callback returns <code>false</code>, proceeds to draw player ammo in a way specific to the weapon hook, which in the default implementation is the same as when no scripting is used. This method is meant to be invoked at most once (i.e. possibly zero times) in <code>onDrawAmmo</code> with the same arguments and nowhere else in a script module. The returned value indicates whether drawing was handled by the method, meaning that it may be used as the return value of <code>onDrawAmmo</code>. In particular, in the default implementation the method returns <code>false</code> if neither a drawing callback nor an animation for the weapon are set.</dd>
<dt>void processMain()</dt>
<dd>Calls main callbacks of all weapons and optionally performs additional actions (none by default). This method is meant to be invoked exactly once in <code>onMain</code> and nowhere else in a script module. Using it in any other ways may be undefined behavior depending on implementation of all registered weapons and the weapon hook.</dd>
<dt>void processPlayer(jjPLAYER@ player)</dt>
<dd>Calls player callbacks of all weapons and optionally performs additional actions (none by default). This method is meant to be invoked exactly once in <code>onPlayer</code> with the same argument and nowhere else in a script module. Using it in any other ways may be undefined behavior depending on implementation of all registered weapons and the weapon hook.</dd>
<dt>void processPlayerInput(jjPLAYER@ player)</dt>
<dd>Calls player input callbacks of all weapons and optionally performs additional actions (none by default). This method is meant to be invoked exactly once in <code>onPlayerInput</code> with the same argument and nowhere else in a script module. Using it in any other ways may be undefined behavior depending on implementation of all registered weapons and the weapon hook.</dd>
<dt>bool processPacket(jjSTREAM &in packet, int clientID)</dt>
<dd>Attempts to call packet callback corresponding to the prefix of <span class="arg">packet</span>. Returns <code>true</code> if the prefix indeed corresponds to a registered callback. This method is meant to be invoked exactly once in <code>onReceive</code> with the same arguments (in particular, <span class="arg">packet</span> must not be modified before being passed to the method) and nowhere else in a script module. A permitted exception is that if the packet is known not to have a prefix corresponding to this weapon hook, the method doesn't have to be called.</dd>
</dl>
</section>
<section id="misc">
<h2>Miscellaneous entities</h2>
<dl>
<dt>bool isValidWeapon(uint number)</dt>
<dd>Returns whether the <span class="arg">number</span> corresponds to a game weapon, i.e. whether (1 ≤ <span class="arg">number</span> ≤ 9).</dd>
<dt>uint getBasicBulletOfWeapon(uint number)</dt>
<dd>Returns event ID of projectile objects typically corresponding to the weapon <span class="arg">number</span> when fired by players who don't have the powerup of that weapon. For gun 8 this means fireball bullets, not pepper spray. For invalid arguments returns <code>0</code>.</dd>
<dt>uint getPoweredBulletOfWeapon(uint number)</dt>
<dd>Returns event ID of powered-up projectile objects typically corresponding to the weapon <span class="arg">number</span>. For gun 8 this means powered-up fireball bullets, not pepper spray. For TNT this value is the same as that returned by <code>getBasicBulletOfWeapon</code> and equal to <code>OBJECT::TNT</code>. For invalid arguments returns <code>0</code>.</dd>
<dt>uint getAmmoPickupOfWeapon(uint number)</dt>
<dd>Returns event ID of "ammo +3" pickup objects typically corresponding to the weapon <span class="arg">number</span>. For blaster and invalid arguments returns <code>0</code>.</dd>
<dt>uint getAmmoCrateOfWeapon(uint number)</dt>
<dd>Returns event ID of "ammo +15" crate objects typically corresponding to the weapon <span class="arg">number</span>. For blaster, TNT, gun 8, gun 9, and invalid arguments returns <code>0</code>.</dd>
<dt>uint getPowerupMonitorOfWeapon(uint number)</dt>
<dd>Returns event ID of power-up monitor objects typically corresponding to the weapon <span class="arg">number</span>. For TNT this means <code>OBJECT::TNTPOWERUP</code>. For invalid arguments returns <code>0</code>.</dd>
<dt>class AmmoPickup : jjBEHAVIORINTERFACE</dt>
<dd>
Implements behavior and collision handling imitating those of default "ammo +3" pickups, except that it supports customization of sprites, amount of ammo obtained by collecting the pickup, and sample played when it happens. The class exposes the following methods:
<dl>
<dt>AmmoPickup(const jjANIMATION@ basic, const jjANIMATION@ powered, uint count = 3, SOUND::Sample sample = SOUND::COMMON_PICKUPW1)</dt>
<dd>Constructs the instance. The arguments are used to initialize corresponding class properties, i.e. <span class="arg">basic</span> is used as the basic sprite, <span class="arg">powered</span> as the powered-up sprite, <span class="arg">count</span> as the amount of ammo gained by collecting the pickup, and <span class="arg">sample</span> as the triggered sound.</dd>
<dt>protected void draw(float x, float y, uint sprite, int direction, bool translucent, int playerID) const</dt>
<dd>Draws the sprite by calling <code>jjDrawSpriteFromCurFrame</code>. This method is called by <code>onBehave</code>. Its implementation is straightforward, but it exists because it may be useful to override it if you inherit from this class, for example because you want the sprite to be drawn with a specific sprite mode or at a different scale.</dd>
<dt>protected float getY(const jjOBJ@ obj) const</dt>
<dd>Returns y coordinate value that the sprite should currently be drawn at to exactly mimic the oscillatory vertical movement of JJ2 pickups. This method is called by <code>onBehave</code>.</dd>
<dt>void setAnimationBasic(const jjANIMATION@ basic)</dt>
<dd>Sets basic animation sprite used by pickups.</dd>
<dt>const jjANIMATION@ getAnimationBasic() const</dt>
<dd>Returns basic animation sprite used by pickups.</dd>
<dt>void setAnimationPowered(const jjANIMATION@ powered)</dt>
<dd>Sets powered-up animation sprite used by pickups.</dd>
<dt>const jjANIMATION@ getAnimationPowered() const</dt>
<dd>Returns powered-up animation sprite used by pickups.</dd>
<dt>void setCount(uint count)</dt>
<dd>Sets amount of ammo obtained by collecting pickups.</dd>
<dt>uint getCount() const</dt>
<dd>Returns amount of ammo obtained by collecting pickups.</dd>
<dt>void setSample(SOUND::Sample sample)</dt>
<dd>Sets sample played on collecting pickups.</dd>
<dt>SOUND::Sample getSample() const</dt>
<dd>Returns sample played on collecting pickups.</dd>
<dt>void onBehave(jjOBJ@ obj) override</dt>
<dd>Processes the object. The object behaves like any other pickup except that it sets its own <code>scriptedCollisions</code> to <code>true</code> when its <code>state</code> equals <code>STATE::START</code>, and that it selects the animation to draw depending on players' individual powerup statuses.</dd>
<dt>bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int)</dt>
<dd>Processes object collisions with players. Imitates the same behavior as when colliding with regular JJ2 ammo pickups, except that the amount of ammo gained is a custom value and the played sample may be customized.</dd>
</dl>
</dd>
</dl>
</section>
</article>
</body>
</html>
Jazz2Online © 1999-INFINITY (Site Credits). We have a Privacy Policy. Jazz Jackrabbit, Jazz Jackrabbit 2, Jazz Jackrabbit Advance and all related trademarks and media are ™ and © Epic Games. Lori Jackrabbit is © Dean Dodrill. J2O development powered by Loops of Fury and Chemical Beats.
Eat your lima beans, Johnny.