Downloads containing MLLE-Weapons.asc

Downloads
Name Author Game Mode Rating
TSF with JJ2+ Only: Frosted PeaksFeatured Download PurpleJazz Capture the flag 9.3 Download file
TSF with JJ2+ Only: Hollow of the HauntedFeatured Download cooba Capture the flag 9.2 Download file
TSF with JJ2+ Only: street fight!!!!!!! cooba Battle N/A Download file
TSF with JJ2+ Only: Anniversary Bash 22 levels Jazz2Online Multiple N/A Download file
TSF with JJ2+ Only: The AbyssFeatured Download PurpleJazz Battle 9.8 Download file
Multi-Layer Level Editor...Featured Download Violet CLM Utility 9.5 Download file
TSF with JJ2+ Only: Facilis descensus Averno Loon Battle N/A Download file
TSF with JJ2+ Only: Umbral ThicketFeatured Download PurpleJazz Battle 9.5 Download file
JJ2+ Only: Tech Tree Violet CLM Capture the flag 7.8 Download file

File preview

  1. #pragma require "MLLE-Weapons.asc"
  2. #pragma require "SEweapon.asc"
  3. #include "SEweapon.asc"
  4.  
  5. shared interface MLLEWeaponApply { bool Apply(uint, se::WeaponHook@ = null, jjSTREAM@ = null, uint8 = 0); }
  6. namespace MLLEWeapons {
  7.         class ObjectTemplate {
  8.                 int Age;
  9.                 int AnimSpeed;
  10.                 HANDLING::Bullet BulletHandling;
  11.                 bool CausesRicochet;
  12.                 int Counter;
  13.                 uint8 CounterEnd;
  14.                 int16 CurAnim;
  15.                 uint CurFrame;
  16.                 bool Deactivates;
  17.                 uint8 DoesHurt;
  18.                 int8 Energy;
  19.                 int8 FrameID;
  20.                 uint8 Freeze;
  21.                 bool IsBlastable;
  22.                 bool IsFreezable;
  23.                 bool IsTarget;
  24.                 uint8 JustHit;
  25.                 int16 KillAnim;
  26.                 int8 Light;
  27.                 LIGHT::Type LightType;
  28.                 STATE::State OldState;
  29.                 HANDLING::Player PlayerHandling;
  30.                 uint16 Points;
  31.                 bool ScriptedCollisions;
  32.                 int Special;
  33.                 STATE::State State;
  34.                 bool TriggersTNT;
  35.                 array<int> Var;
  36.                 float XAcc;
  37.                 float XSpeed;
  38.                 float YAcc;
  39.                 float YSpeed;
  40.                 ObjectTemplate(
  41.                         int age = 0,
  42.                         int animSpeed = 1,
  43.                         HANDLING::Bullet bulletHandling = HANDLING::HURTBYBULLET,
  44.                         bool causesRicochet = false,
  45.                         int counter = 0,
  46.                         uint8 counterEnd = 0,
  47.                         int16 curAnim = 0,
  48.                         bool deactivates = true,
  49.                         uint8 doesHurt = 0,
  50.                         int8 energy = 0,
  51.                         int8 frameID = 0,
  52.                         uint8 freeze = 0,
  53.                         bool isBlastable = true,
  54.                         bool isFreezable = false,
  55.                         bool isTarget = false,
  56.                         uint8 justHit = 0,
  57.                         int16 killAnim = 0,
  58.                         int8 light = 0,
  59.                         LIGHT::Type lightType = LIGHT::NONE,
  60.                         STATE::State oldState = STATE::START,
  61.                         HANDLING::Player playerHandling = HANDLING::PLAYERBULLET,
  62.                         uint16 points = 0,
  63.                         bool scriptedCollisions = false,
  64.                         int special = 0,
  65.                         STATE::State state = STATE::START,
  66.                         bool triggersTNT = false,
  67.                         array<int> var = array<int>(0),
  68.                         float xAcc = 0,
  69.                         float yAcc = 0,
  70.                         float xSpeed = 0,
  71.                         float ySpeed = 0
  72.                 ) {
  73.                         Age = age;
  74.                         AnimSpeed = animSpeed;
  75.                         BulletHandling = bulletHandling;
  76.                         CausesRicochet = causesRicochet;
  77.                         Counter = counter;
  78.                         CounterEnd = counterEnd;
  79.                         CurAnim = curAnim;
  80.                         Deactivates = deactivates;
  81.                         DoesHurt = doesHurt;
  82.                         Energy = energy;
  83.                         FrameID = frameID;
  84.                         Freeze = freeze;
  85.                         IsBlastable = isBlastable;
  86.                         IsFreezable = isFreezable;
  87.                         IsTarget = isTarget;
  88.                         JustHit = justHit;
  89.                         KillAnim = killAnim;
  90.                         Light = light;
  91.                         LightType = lightType;
  92.                         OldState = oldState;
  93.                         PlayerHandling = playerHandling;
  94.                         Points = points;
  95.                         ScriptedCollisions = scriptedCollisions;
  96.                         Special = special;
  97.                         State = state;
  98.                         TriggersTNT = triggersTNT;
  99.                         for (uint i = 0; i < 11; ++i)
  100.                                 Var.insertLast(i < var.length ? var[i] : 0);
  101.                         XAcc = xAcc;
  102.                         XSpeed = xSpeed;
  103.                         YAcc = yAcc;
  104.                         YSpeed = ySpeed;
  105.                 }
  106.                 void Apply(jjOBJ@ obj, uint firstAnim, bool objIsPreset) const {
  107.                         obj.age = Age;
  108.                         obj.animSpeed = AnimSpeed;
  109.                         obj.bulletHandling = BulletHandling;
  110.                         obj.causesRicochet = CausesRicochet;
  111.                         obj.counter = Counter;
  112.                         obj.counterEnd = CounterEnd;
  113.                         obj.curAnim = (CurAnim < 200) ? firstAnim + CurAnim : CurAnim;
  114.                         obj.deactivates = Deactivates;
  115.                         obj.doesHurt = DoesHurt;
  116.                         obj.energy = Energy;
  117.                         obj.frameID = FrameID;
  118.                         obj.determineCurFrame();
  119.                         obj.freeze = Freeze;
  120.                         obj.isBlastable = IsBlastable;
  121.                         obj.isFreezable = IsFreezable;
  122.                         obj.isTarget = IsTarget;
  123.                         obj.justHit = JustHit;
  124.                         obj.killAnim = (KillAnim < 200) ? firstAnim + KillAnim : KillAnim;
  125.                         obj.light = Light;
  126.                         obj.lightType = LightType;
  127.                         obj.oldState = OldState;
  128.                         obj.playerHandling = PlayerHandling;
  129.                         obj.points = Points;
  130.                         obj.scriptedCollisions = ScriptedCollisions;
  131.                         obj.special =
  132.                                 (Special >= 0) ?
  133.                                         (Special != 0 && Special < 200) ?
  134.                                                 firstAnim + Special - 1 :
  135.                                                 Special :
  136.                                         obj.curAnim
  137.                                 ;
  138.                         obj.state = State;
  139.                         obj.triggersTNT = TriggersTNT;
  140.                         for (uint i = 0; i < 11; ++i)
  141.                                 if (/*objIsPreset || */(i != 7 && i != 3)) //pxSpeed, bullet type
  142.                                         obj.var[i] = Var[i];
  143.                         if (objIsPreset) {
  144.                                 obj.xAcc =              XAcc;
  145.                                 obj.xSpeed =    XSpeed;
  146.                                 obj.yAcc =              YAcc;
  147.                                 obj.ySpeed =    YSpeed;
  148.                         } else
  149.                                 ApplyTNTSpeeds(obj);
  150.                 }
  151.                 void ApplyTNTSpeeds(jjOBJ@ obj) const {
  152.                         const auto x = obj.xSpeed, y = obj.ySpeed; //radius of 1
  153.                         obj.xAcc =              x * XAcc;
  154.                         obj.xSpeed =    x * XSpeed;
  155.                         obj.yAcc =              abs(x) * YAcc + y * XAcc; //was abs(x * Ything)
  156.                         obj.ySpeed =    abs(x) * YSpeed + y * XSpeed;
  157.                 }
  158.         }
  159.        
  160.         enum AnimationIndices { PickupIndex, PoweredUpPickupIndex, PowerupIndex, AmmoCrateIndex, _COUNT };
  161.         funcdef void behaviorFunction(jjOBJ@, bool);
  162.         funcdef bool applyFunction(uint, se::WeaponHook@, jjSTREAM@);
  163.         funcdef void presetFunction(jjOBJ@, int);
  164.         abstract class WeaponInterface : se::WeaponInterface, MLLEWeaponApply, jjBEHAVIORINTERFACE {
  165.                 protected ObjectTemplate@ RegularObjectTemplate, PowerupObjectTemplate;
  166.                
  167.                 private behaviorFunction@ AssignBehavior;
  168.                 private applyFunction@ ExtraApply;
  169.                 private presetFunction@ CustomAmmo3, CustomAmmo15, CustomPowerup;
  170.                
  171.                 private se::MainCallback@ OnMain;
  172.                 private se::PlayerCallback@ OnPlayer;
  173.                 private se::PlayerCallback@ OnPlayerInput;
  174.                 private se::DrawingCallback@ OnDrawAmmo;
  175.                 private se::PacketCallback@ OnReceive;
  176.                
  177.                 private array<string> SampleFilenames(0);
  178.                 private string AnimSetFilename;
  179.                 private uint AnimSetID;
  180.                 private bool GenerateSupplementalAnimations;
  181.                 protected int PickupFrameIDToUseForAmmoCrate;
  182.                
  183.                 private array<int> Animations(AnimationIndices::_COUNT);
  184.                 protected int get_PickupAnimation() const { return Animations[AnimationIndices::PickupIndex]; }
  185.                 protected int get_PoweredUpPickupAnimation() const { return Animations[AnimationIndices::PoweredUpPickupIndex]; }
  186.                 protected int get_PowerupAnimation() const { return Animations[AnimationIndices::PowerupIndex]; }
  187.                 protected int get_AmmoCrateAnimation() const { return Animations[AnimationIndices::AmmoCrateIndex]; }
  188.                
  189.                 protected bool IsRFMissile;
  190.                 private uint Traits;
  191.                 private uint PoweredUpTraits;
  192.                 bool WeaponHookRequired;
  193.                
  194.                 protected uint RoundsPerPickup;
  195.                 protected SOUND::Sample PickupSample;
  196.                
  197.                 protected int Multiplier;
  198.                 protected bool GradualAim;
  199.                 protected bool ReplacedByBubbles;
  200.                 protected SPREAD::Spread Spread;
  201.                 protected WEAPON::Style Style;
  202.                
  203.                 protected jjANIMSET@ AnimSet;
  204.                 protected uint SetID;
  205.                 protected array<SOUND::Sample> Samples(0);
  206.                 protected array<bool> SamplesLoaded(0);
  207.                 protected se::PacketConstructor@ ConstructPacket;
  208.                
  209.                 WeaponInterface(
  210.                         ObjectTemplate regularObjectTemplate,
  211.                         behaviorFunction@ behavior,
  212.                         ObjectTemplate@ powerupObjectTemplate = null,
  213.                         array<string> sampleFilenames = array<string> = {},
  214.                         array<ANIM::Set> otherAnimSetsToLoad = array<ANIM::Set> = {},
  215.                         const string &in animSetFilename = "",
  216.                         uint animSetID = 0,
  217.                         int pickupAnimation = -1,
  218.                         int poweredUpPickupAnimation = -1,
  219.                         int powerupAnimation = -1,
  220.                         int ammoCrateAnimation = -1,
  221.                         bool generateSupplementalAnimations = true,
  222.                         int pickupFrameIDToUseForAmmoCrate = 0,
  223.                         bool isRFMissile = false,
  224.                         uint traits = se::WeaponTrait::weapon_default_traits,
  225.                         int poweredUpTraits = -1,
  226.                         bool weaponHookRequired = false,
  227.                         uint roundsPerPickup = 3,
  228.                         SOUND::Sample pickupSample = SOUND::COMMON_PICKUPW1,
  229.                         int multiplier = 1,
  230.                         bool gradualAim = false,
  231.                         bool replacedByBubbles = false,
  232.                         SPREAD::Spread spread = SPREAD::NORMAL,
  233.                         WEAPON::Style style = WEAPON::NORMAL,
  234.                         applyFunction@ apply = null,
  235.                         presetFunction@ customAmmo3 = null,
  236.                         presetFunction@ customAmmo15 = null,
  237.                         presetFunction@ customPowerup = null,
  238.                         se::MainCallback@ onMain = null,
  239.                         se::PlayerCallback@ onPlayer = null,
  240.                         se::PlayerCallback@ onPlayerInput = null,
  241.                         se::DrawingCallback@ onDrawAmmo = null,
  242.                         se::PacketCallback@ onReceive = null
  243.                 ) {
  244.                         @RegularObjectTemplate = @regularObjectTemplate;
  245.                         @AssignBehavior = @behavior;
  246.                         @PowerupObjectTemplate = @((powerupObjectTemplate !is null) ? powerupObjectTemplate : regularObjectTemplate);
  247.                         PowerupObjectTemplate.Var[6] = PowerupObjectTemplate.Var[6] | 8;
  248.                         RegularObjectTemplate.Var[6] = RegularObjectTemplate.Var[6] & ~8;
  249.                         SampleFilenames = sampleFilenames;
  250.                         for (uint i = 0; i < otherAnimSetsToLoad.length; ++i)
  251.                                 if (jjAnimSets[otherAnimSetsToLoad[i]] == 0)
  252.                                         jjAnimSets[otherAnimSetsToLoad[i]].load();
  253.                         AnimSetFilename = animSetFilename;
  254.                         AnimSetID = animSetID;
  255.                         Animations[AnimationIndices::PickupIndex] = pickupAnimation;
  256.                         Animations[AnimationIndices::PoweredUpPickupIndex] = poweredUpPickupAnimation;
  257.                         Animations[AnimationIndices::PowerupIndex] = powerupAnimation;
  258.                         Animations[AnimationIndices::AmmoCrateIndex] = ammoCrateAnimation;
  259.                         GenerateSupplementalAnimations = generateSupplementalAnimations;
  260.                         PickupFrameIDToUseForAmmoCrate = pickupFrameIDToUseForAmmoCrate;
  261.                         IsRFMissile = isRFMissile;
  262.                         Traits = traits;
  263.                         PoweredUpTraits = (poweredUpTraits == -1) ? traits : uint(poweredUpTraits);
  264.                         WeaponHookRequired = weaponHookRequired;
  265.                         RoundsPerPickup = roundsPerPickup;
  266.                         PickupSample = pickupSample;
  267.                         Multiplier = multiplier;
  268.                         GradualAim = gradualAim;
  269.                         ReplacedByBubbles = replacedByBubbles;
  270.                         Spread = spread;
  271.                         Style = style;
  272.                         @ExtraApply = @apply;
  273.                         @CustomAmmo3 = @customAmmo3;
  274.                         @CustomAmmo15 = @customAmmo15;
  275.                         @CustomPowerup = @customPowerup;
  276.                         @OnMain = @onMain;
  277.                         @OnPlayer = @onPlayer;
  278.                         @OnPlayerInput = @onPlayerInput;
  279.                         @OnDrawAmmo = @onDrawAmmo;
  280.                         @OnReceive = @onReceive;
  281.                 }
  282.                
  283.                 array<bool>@ loadSamples(const array<SOUND::Sample>& samples) {
  284.                         if (SamplesLoaded.length < getSampleCount()){
  285.                                 Samples = samples;
  286.                                 SamplesLoaded.resize(samples.length);
  287.                                 if (samples.length == SampleFilenames.length) {
  288.                                         for (uint i = 0; i < samples.length; ++i)
  289.                                                 SamplesLoaded[i] = samples[i] != 0 && jjSampleLoad(samples[i], SampleFilenames[i]);
  290.                                 }
  291.                         }
  292.                         return SamplesLoaded;
  293.                 }
  294.                 uint getSampleCount() const { return SampleFilenames.length; }
  295.                
  296.                 jjANIMSET@ loadAnims(jjANIMSET@ animSet) {
  297.                         if (AnimSet is null) {
  298.                                 if (AnimSetFilename.length > 0) {
  299.                                         if (AnimSetFilename.findFirst('.') < 0)
  300.                                                 AnimSetFilename += ".j2a";
  301.                                         animSet.load(AnimSetID, AnimSetFilename);
  302.                                 }
  303.                                 @AnimSet = @animSet;
  304.                         }
  305.                         return @animSet;
  306.                 }
  307.                
  308.                 uint getTraits(bool powerup) const { return powerup ? PoweredUpTraits : Traits; }
  309.                 bool onIsRFBullet(jjOBJ@) { return IsRFMissile; }
  310.                
  311.                 bool setAsWeapon(uint number, se::WeaponHook@ weaponHook) {
  312.                         if (se::isValidWeapon(number)) {
  313.                                 jjWEAPON@ weapon = jjWeapons[number];
  314.                                 weapon.defaultSample = false;
  315.                                 weapon.multiplier = Multiplier;
  316.                                 weapon.gradualAim = GradualAim;
  317.                                 weapon.replacedByBubbles = ReplacedByBubbles;
  318.                                 weapon.spread = Spread;
  319.                                 weapon.style = Style;
  320.                                
  321.                                 for (int i = 0; i < AnimationIndices::_COUNT; ++i)
  322.                                         if (Animations[i] >= 0 && Animations[i] < 200) //in case Apply wasn't called for whatever reason
  323.                                                 Animations[i] += AnimSet.firstAnim;
  324.                                
  325.                                 const auto combinedTraits = Traits | PoweredUpTraits;
  326.                                 jjOBJ@ ammo3;
  327.                                 {
  328.                                         const int pa = Animations[AnimationIndices::PickupIndex], ppa = Animations[AnimationIndices::PoweredUpPickupIndex];
  329.                                        
  330.                                         if (weaponHook !is null) {
  331.                                                 weaponHook.resetCallbacks(number);
  332.                                                
  333.                                                 if (pa >= 0 || ppa >= 0) {
  334.                                                         weaponHook.setWeaponSprite(number, false, jjAnimations[pa >= 0 ? pa : ppa]);
  335.                                                         weaponHook.setWeaponSprite(number, true, jjAnimations[ppa >= 0 ? ppa : pa]);
  336.                                                 }
  337.                                                        
  338.                                                 if (OnMain !is null)
  339.                                                         weaponHook.setMainCallback(number, OnMain);
  340.                                                 if (OnPlayer !is null)
  341.                                                         weaponHook.setPlayerCallback(number, OnPlayer);
  342.                                                 if (OnPlayerInput !is null)
  343.                                                         weaponHook.setPlayerInputCallback(number, OnPlayerInput);
  344.                                                 if (OnDrawAmmo !is null)
  345.                                                         weaponHook.setDrawingCallback(number, OnDrawAmmo);
  346.                                                 if (OnReceive !is null)
  347.                                                         @ConstructPacket = weaponHook.addPacketCallback(OnReceive);
  348.                                         } else if (WeaponHookRequired)
  349.                                                 return false;
  350.                                        
  351.                                         if ((combinedTraits & se::weapon_has_ammo_pickups) != 0 && (pa >= 0 || ppa >= 0)) {
  352.                                                 const uint ammo3EventID = se::getAmmoPickupOfWeapon(number);
  353.                                                 if (ammo3EventID != 0) {
  354.                                                         @ammo3 = jjObjectPresets[ammo3EventID];
  355.                                                         if (CustomAmmo3 !is null)
  356.                                                                 CustomAmmo3(ammo3, number);
  357.                                                         else {
  358.                                                                 if (PickupSample < 0)
  359.                                                                         PickupSample = SOUND::Sample(Samples[1-PickupSample]);
  360.                                                                 ammo3.behavior = AmmoPickupWithCrateAndCorpseSupport(
  361.                                                                         jjAnimations[pa >= 0 ? pa : ppa],
  362.                                                                         jjAnimations[ppa >= 0 ? ppa : pa],
  363.                                                                         RoundsPerPickup,
  364.                                                                         PickupSample
  365.                                                                 );
  366.                                                                 ammo3.state = STATE::START;
  367.                                                                 ammo3.curAnim = pa >= 0 ? pa : ppa;
  368.                                                                 ammo3.frameID = 0;
  369.                                                                 ammo3.determineCurFrame();
  370.                                                                 ammo3.killAnim = jjAnimSets[ANIM::PICKUPS] + 86;
  371.                                                                 ammo3.objType = HANDLING::PICKUP;
  372.                                                                 ammo3.isBlastable = true;
  373.                                                                 ammo3.var[3] = number - 1;
  374.                                                                 ammo3.points = 100;
  375.                                                         }
  376.                                                         if (jjGameConnection != GAME::LOCAL && jjObjectPresets[OBJECT::FLICKERGEM].behavior == BEHAVIOR::FLICKERGEM)
  377.                                                                 jjObjectPresets[OBJECT::FLICKERGEM].behavior = FlickerGemAmmoPickupAssigner;
  378.                                                 }
  379.                                         }
  380.                                 } {
  381.                                         const uint ammo15EventID = Ammo15s !is null ? Ammo15s[number-1] : se::getAmmoCrateOfWeapon(number);
  382.                                         if (ammo15EventID != 0) {
  383.                                                 jjOBJ@ ammo15 = @jjObjectPresets[ammo15EventID];
  384.                                                 if ((combinedTraits & se::weapon_has_ammo_crates) != 0 && Animations[AnimationIndices::AmmoCrateIndex] >= 0) {
  385.                                                         if (CustomAmmo15 !is null)
  386.                                                                 CustomAmmo15(ammo15, number);
  387.                                                         else {
  388.                                                                 ammo15.curAnim = Animations[AnimationIndices::AmmoCrateIndex];
  389.                                                                 ammo15.frameID = 0;
  390.                                                                 ammo15.determineCurFrame();
  391.                                                                 ammo15.killAnim = jjAnimSets[ANIM::AMMO] + 71;
  392.                                                                 ammo15.state = STATE::START;
  393.                                                                 ammo15.objType = HANDLING::SPECIAL;
  394.                                                                 ammo15.noHit = HANDLING::HURTBYBULLET;
  395.                                                                 ammo15.direction = 1;
  396.                                                                 ammo15.energy = 1;
  397.                                                                 ammo15.var[3] = number - 1;
  398.                                                                 ammo15.var[2] = se::getAmmoPickupOfWeapon(number);
  399.                                                                 ammo15.points = 300;
  400.                                                                 if (se::getAmmoCrateOfWeapon(number) != 0 && number != 2) { //3,4,5,6
  401.                                                                         ammo15.behavior = BEHAVIOR::AMMO15;
  402.                                                                         ammo15.eventID = ammo15EventID;
  403.                                                                 } else { //no normal ammo15 object available (or in the case of bouncers, can't be trusted to use the right curAnim)
  404.                                                                         ammo15.behavior = function(obj) { if (obj.state == STATE::DEACTIVATE) obj.eventID = obj.counterEnd; obj.behave(BEHAVIOR::AMMO15); };
  405.                                                                         ammo15.eventID = OBJECT::ICEAMMO15;
  406.                                                                         ammo15.counterEnd = ammo15EventID;
  407.                                                                 }
  408.                                                         }
  409.                                                 } else if (ammo3 !is null)
  410.                                                         CopyObject(ammo15, ammo3);
  411.                                         }
  412.                                         const uint powerupEventID = se::getPowerupMonitorOfWeapon(number);
  413.                                         jjOBJ@ powerup = @jjObjectPresets[powerupEventID];
  414.                                         if ((combinedTraits & se::weapon_has_powerup_monitors) != 0 && (combinedTraits & se::weapon_has_distinct_powerup) != 0 && Animations[AnimationIndices::PowerupIndex] >= 0) {
  415.                                                 if (CustomPowerup !is null)
  416.                                                         CustomPowerup(powerup, number);
  417.                                                 else {
  418.                                                         powerup.curAnim = Animations[AnimationIndices::PowerupIndex];
  419.                                                         powerup.frameID = 0;
  420.                                                         powerup.determineCurFrame();
  421.                                                         powerup.killAnim = jjAnimSets[ANIM::AMMO] + 71;
  422.                                                         powerup.state = STATE::START;
  423.                                                         powerup.objType = HANDLING::SPECIAL;
  424.                                                         powerup.noHit = HANDLING::HURTBYBULLET;
  425.                                                         powerup.energy = 1;
  426.                                                         powerup.var[3] = number - 1;
  427.                                                         powerup.points = 1000;
  428.                                                         if (number != WEAPON::BLASTER) {
  429.                                                                 powerup.behavior = BEHAVIOR::MONITOR;
  430.                                                                 powerup.eventID = powerupEventID;
  431.                                                         } else { //gun1 powerup shouldn't use player-dependent animations if it's been replaced by some other weapon
  432.                                                                 powerup.behavior = function(obj) { if (obj.state == STATE::DEACTIVATE) obj.eventID = obj.counterEnd; obj.behave(BEHAVIOR::MONITOR); };
  433.                                                                 powerup.counterEnd = powerupEventID;
  434.                                                                 powerup.eventID = OBJECT::BOUNCERPOWERUP;
  435.                                                         }
  436.                                                 }
  437.                                         } else if (ammo3 !is null)
  438.                                                 CopyObject(powerup, ammo3);
  439.                                 }
  440.                                
  441.                                 jjOBJ@ Preset1 = jjObjectPresets[se::getBasicBulletOfWeapon(number)];
  442.                                 jjOBJ@ Preset2 = jjObjectPresets[se::getPoweredBulletOfWeapon(number)];
  443.                                 RegularObjectTemplate.Apply(Preset1, AnimSet.firstAnim, true);
  444.                                 if (number != WEAPON::TNT)
  445.                                         PowerupObjectTemplate.Apply(Preset2, AnimSet.firstAnim, true);
  446.                                 else if (Preset1.xSpeed != 0) {
  447.                                         Preset1.xSpeed = 1; //for determining the angle
  448.                                         Preset1.ySpeed = 0;
  449.                                 }
  450.                                 Preset1.var[3] = Preset2.var[3] = number;
  451.                                 Preset1.behavior = Preset2.behavior = this; //onBehave, below
  452.                                 return true;
  453.                         }
  454.                         return false;
  455.                 }
  456.                 bool Apply(uint number, se::WeaponHook@ weaponHook = null, jjSTREAM@ parameters = null, uint8 ammo15EventID = 0) {
  457.                         if (se::isValidWeapon(number)) {
  458.                                 LoadResources();
  459.                                        
  460.                                 if (ExtraApply !is null && !ExtraApply(
  461.                                         number,
  462.                                         weaponHook,
  463.                                         parameters
  464.                                 ))
  465.                                         return false;
  466.                                
  467.                                 if (Ammo15s is null)
  468.                                         @Ammo15s = array<uint8>(9, 0);
  469.                                 if (Ammo15s[number-1] == 0) {
  470.                                         if (ammo15EventID != 0)
  471.                                                 Ammo15s[number-1] = ammo15EventID;
  472.                                         else if (number < WEAPON::TNT && number != WEAPON::BLASTER)
  473.                                                 Ammo15s[number-1] = se::getAmmoCrateOfWeapon(number);
  474.                                 }
  475.                                
  476.                                 for (int i = 0; i < AnimationIndices::_COUNT; ++i)
  477.                                         if (Animations[i] >= 0 && Animations[i] < 200)
  478.                                                 Animations[i] += AnimSet.firstAnim;
  479.                                
  480.                                 if (GenerateSupplementalAnimations)
  481.                                         GenerateSupplementaryWeaponSprites(Animations, Ammo15s[number-1], PickupFrameIDToUseForAmmoCrate);
  482.                                
  483.                                 return setAsWeapon(number, weaponHook);
  484.                         }
  485.                         return false;
  486.                 }
  487.                
  488.                 void onBehave(jjOBJ@ obj) {
  489.                         bool powerup;
  490.                         if (obj.eventID == OBJECT::TNT) {
  491.                                 float RFYSpeed = 0;
  492.                                 if (IsRFMissile && abs(obj.xSpeed) == jjObjectPresets[OBJECT::TNT].xSpeed) {
  493.                                         RFYSpeed = obj.ySpeed;
  494.                                         obj.ySpeed = 0;
  495.                                 }
  496.                                 if (powerup = (obj.creatorType == CREATOR::PLAYER && jjPlayers[obj.creator].powerup[WEAPON::TNT])) {
  497.                                         const bool firingUp = obj.counterEnd < jjObjectPresets[OBJECT::TNT].counterEnd;
  498.                                         PowerupObjectTemplate.Apply(obj, AnimSet.firstAnim, false);
  499.                                         if (firingUp) obj.counterEnd = obj.counterEnd * 2 / 3;
  500.                                 } else
  501.                                         RegularObjectTemplate.ApplyTNTSpeeds(obj);
  502.                                 if (RFYSpeed != 0) obj.ySpeed = RFYSpeed;
  503.                                 obj.eventID = OBJECT::BULLET; //don't use /tntdamage unless AssignBehavior requests it specifically
  504.                         } else
  505.                                 powerup = obj.eventID >= OBJECT::BLASTERBULLETPU;
  506.                         if (PowerupObjectTemplate is RegularObjectTemplate) {
  507.                                 if (powerup)
  508.                                         obj.var[6] = obj.var[6] | 8;
  509.                                 else
  510.                                         obj.var[6] = obj.var[6] & ~8;
  511.                         }
  512.                         AssignBehavior(obj, powerup);
  513.                         obj.behave();
  514.                 }
  515.                
  516.                 array<bool>@ LoadFirstAvailableSamples() {
  517.                         if (SamplesLoaded.length == getSampleCount())
  518.                                 return SamplesLoaded;
  519.                         array<SOUND::Sample> samples;
  520.                         const uint sampleCount = getSampleCount();
  521.                         array<SOUND::Sample>@ prospectiveSamples = SOUND::GetAllSampleConstantsInRoughOrderOfLikelihoodToBeUsed();
  522.                         while (samples.length < sampleCount) {
  523.                                 if (prospectiveSamples.length != 0) {
  524.                                         SOUND::Sample prospectiveSample = prospectiveSamples[0];
  525.                                         prospectiveSamples.removeAt(0);
  526.                                         if (!jjSampleIsLoaded(prospectiveSample))
  527.                                                 samples.insertLast(prospectiveSample);
  528.                                 } else
  529.                                         samples.insertLast(SOUND::Sample(0));
  530.                         }
  531.                         return loadSamples(samples);
  532.                 }
  533.                
  534.                 void LoadResources() {
  535.                         if (SetID == 0)
  536.                                 loadAnims(jjAnimSets[SetID = GetFirstAvailableCustomAnimsetID()]);
  537.                         LoadFirstAvailableSamples();
  538.                 }
  539.                
  540.                 uint getMaxDamage(bool powerup) const { return powerup ? 2 : 1; }
  541.                
  542.                 array<int> FireBullet(float xPos, float yPos, int angle, bool powerup, uint16 creatorID, CREATOR::Type creatorType = CREATOR::PLAYER, uint number = WEAPON::BLASTER, SPREAD::Spread spread = SPREAD::Spread(-1), float additionalXSpeed = 0) const {
  543.                         //LoadResources();
  544.                         int monsterDirection; float monsterXSpeed;
  545.                         if (creatorType != CREATOR::PLAYER) { //avoid issues with some startup code in some native bullet behaviors
  546.                                 jjOBJ@ monster = jjObjects[creatorID];
  547.                                 monsterDirection = monster.direction;   monster.direction = 1;
  548.                                 monsterXSpeed = monster.xSpeed;                 monster.xSpeed = 0;
  549.                         }
  550.                        
  551.                         const uint8 eventID = se::isValidWeapon(number) ? (!powerup ? se::getBasicBulletOfWeapon(number) : se::getPoweredBulletOfWeapon(number)) : OBJECT::BULLET;
  552.                         angle &= 1023;
  553.                         array<int> angles(1, angle);
  554.                         array<int> bulletObjectIDs;
  555.                        
  556.                         if (spread == -1) spread = Spread;
  557.                         if (spread == SPREAD::RF)
  558.                                 spread = powerup ? SPREAD::RFPU : SPREAD::RFNORMAL;
  559.                         else if (spread == SPREAD::ICE)
  560.                                 spread = powerup ? SPREAD::ICEPU : SPREAD::NORMAL;
  561.                         else if (spread == SPREAD::GUN8)
  562.                                 spread = !jjAllowsFireball ? SPREAD::PEPPERSPRAY : SPREAD::NORMAL;
  563.                         switch (spread) {
  564.                                 case SPREAD::ICEPU:
  565.                                         angles.insertLast((creatorType == CREATOR::PLAYER ? jjPlayers[creatorID].direction : jjObjects[creatorID].direction) >= 0 ? 0x000 : 0x200);
  566.                                         break;
  567.                                 case SPREAD::RFPU:
  568.                                         angles.insertLast(angle);
  569.                                         //fall through:
  570.                                 case SPREAD::RFNORMAL:
  571.                                         angles[0] -= 33;
  572.                                         angles.insertLast(angle + 33);
  573.                                         break;
  574.                                 case SPREAD::PEPPERSPRAY: {
  575.                                         angles.resize(0);
  576.                                         for (int pepperSprayBulletCount = 0; pepperSprayBulletCount < 2; ++pepperSprayBulletCount)
  577.                                                 angles.insertLast(angle + int(jjRandom() & 31) - 16);
  578.                                         if (creatorType == CREATOR::PLAYER)
  579.                                                 jjSample(xPos, yPos, SOUND::Sample(SOUND::AMMO_LASER2 + (jjRandom() & 1)));
  580.                                         break; }
  581.                                 case SPREAD::NORMAL:
  582.                                 case SPREAD::TOASTER:
  583.                                 default:
  584.                                         //already fine
  585.                                         break;
  586.                         }
  587.                        
  588.                         auto@ template = spread != SPREAD::PEPPERSPRAY ? (powerup ? PowerupObjectTemplate : RegularObjectTemplate) : MLLEWeapons::ObjectTemplate(
  589.                                 xSpeed: 3 + (jjRandom() & 31) / 16.f + additionalXSpeed,
  590.                                 animSpeed: powerup ? 2 : 1,
  591.                                 curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 10,
  592.                                 lightType: (powerup && jjStrongPowerups) ? LIGHT::POINT2 : LIGHT::NONE,
  593.                                 state: (powerup && jjStrongPowerups) ? STATE::FLY : STATE::START,
  594.                                 var: array<int> = {0,0,0,0,0,0, (powerup && jjStrongPowerups) ? 8 : 0}
  595.                         );
  596.                        
  597.                         for (uint i = 0; i < angles.length; ++i) {
  598.                                 int bulletObjectID = jjAddObject(eventID, xPos, yPos, creatorID, creatorType, BEHAVIOR::INACTIVE);
  599.                                 jjOBJ@ obj = jjObjects[bulletObjectID];
  600.                                 obj.xSpeed = jjCos(angles[i]);
  601.                                 obj.ySpeed = jjSin(angles[i]);
  602.                                 template.Apply(obj, AnimSet.firstAnim, false);
  603.                                 obj.direction = (obj.xAcc < 0) ? -1 : 0;
  604.                                 if (obj.special != 0 && abs(obj.ySpeed) > abs(obj.xSpeed)) { obj.curAnim = obj.special; obj.determineCurFrame(); }
  605.                                 else if (obj.direction == 0) obj.direction = 1;
  606.                                 obj.var[3] = number;
  607.                                 if (IsRFMissile && (angle == 0 || angle == 0x200)) {
  608.                                         const int dir = angle == 0 ? 1 : -1;
  609.                                         obj.xSpeed = template.XSpeed * dir + additionalXSpeed;
  610.                                         obj.xAcc = template.XAcc * dir;
  611.                                         obj.ySpeed = (angles[i] - angle) / 33;
  612.                                         obj.yAcc = 0;
  613.                                         obj.var[7] = 0;
  614.                                 } else {
  615.                                         if (additionalXSpeed > 8) additionalXSpeed = 8;
  616.                                         else if (additionalXSpeed < -8) additionalXSpeed = -8;
  617.                                         obj.var[7] = int(additionalXSpeed * 65536);
  618.                                         if (angle == 0x300 && !IsRFMissile) { //straight up
  619.                                                 obj.counterEnd = obj.counterEnd * 2 / 3;
  620.                                         }
  621.                                 }
  622.                                 if (spread == SPREAD::TOASTER) {
  623.                                         if (angle == 0x300) //straight up
  624.                                                 obj.yPos = (obj.yOrg -= 8);
  625.                                         if (creatorType == CREATOR::PLAYER) {
  626.                                                 const float mult = (99 - jjPlayers[creatorID].fastfire) / 32.f;
  627.                                                 obj.xSpeed *= mult;
  628.                                                 obj.ySpeed *= mult;
  629.                                         }
  630.                                 }
  631.                                 if (spread != SPREAD::PEPPERSPRAY) {
  632.                                         if (obj.eventID == OBJECT::TNT) obj.eventID = OBJECT::BULLET;
  633.                                         AssignBehavior(obj, powerup);
  634.                                 } else {
  635.                                         obj.behavior = BEHAVIOR::PEPPERBULLET;
  636.                                         template.XSpeed = 3 + (jjRandom() & 31) / 16.f + additionalXSpeed;
  637.                                 }
  638.                                 if (obj.creatorType != CREATOR::PLAYER && obj.playerHandling == HANDLING::PLAYERBULLET) {
  639.                                         if (obj.freeze == 0)
  640.                                                 obj.playerHandling = HANDLING::ENEMYBULLET;
  641.                                         else {
  642.                                                 obj.playerHandling = HANDLING::SPECIAL;
  643.                                                 obj.scriptedCollisions = true;
  644.                                                 obj.behavior = FreezingEnemyBullet(obj.behavior);
  645.                                         }
  646.                                 }
  647.                                 bulletObjectIDs.insertLast(bulletObjectID);
  648.                         }
  649.                        
  650.                         for (uint i = 0; i < bulletObjectIDs.length; ++i)
  651.                                 jjObjects[bulletObjectIDs[i]].behave();
  652.                                
  653.                         if (creatorType != CREATOR::PLAYER) {
  654.                                 jjOBJ@ monster = jjObjects[creatorID];
  655.                                 monster.direction = monsterDirection;
  656.                                 monster.xSpeed = monsterXSpeed;
  657.                         }
  658.                        
  659.                         return bulletObjectIDs;
  660.                 }
  661.         }
  662.        
  663.         class FreezingEnemyBullet : jjBEHAVIORINTERFACE {
  664.                 private jjBEHAVIOR nativeBehavior;
  665.                 FreezingEnemyBullet(const jjBEHAVIOR &in nb) { nativeBehavior = nb; }
  666.                 void onBehave(jjOBJ@ obj) { obj.behave(nativeBehavior); }
  667.                 bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int) {
  668.                         if (bullet is null) {
  669.                                 player.frozen = obj.freeze;
  670.                                 obj.state = STATE::EXPLODE;
  671.                         }
  672.                         return true;
  673.                 }
  674.         }
  675.        
  676.         class AmmoPickupWithCrateAndCorpseSupport : se::AmmoPickup {
  677.                 AmmoPickupWithCrateAndCorpseSupport(const ::jjANIMATION@ a, const ::jjANIMATION@ b, uint c = 3, SOUND::Sample d = SOUND::COMMON_PICKUPW1) { super(a,b,c,d); }
  678.                 void onBehave(::jjOBJ@ obj) override {
  679.                         if (obj.playerHandling == HANDLING::DELAYEDPICKUP) {
  680.                                 if (obj.var[2] == 1) { //about to be available to collect
  681.                                         obj.playerHandling = HANDLING::PICKUP; //native code also sets .scriptedCollisions to false, and that's not good
  682.                                         obj.scriptedCollisions = true;
  683.                                         obj.var[2] = 0; //probably not needed
  684.                                 } else
  685.                                         obj.scriptedCollisions = false; //so the native code knows to decrement var[2]
  686.                         }
  687.                         if ((obj.state == STATE::FLOAT || (obj.state == STATE::FLOATFALL && obj.ySpeed == 0)) && obj.counter > 0) { //temporary pickup (in MP)
  688.                                 if (--obj.counter < 210) {
  689.                                         if (obj.counter == 0) {
  690.                                                 obj.delete();
  691.                                                 return;
  692.                                         }
  693.                                         if (jjGameTicks & 1 == 0) //flickering
  694.                                                 return;
  695.                                 }
  696.                         }
  697.                         se::AmmoPickup::onBehave(obj);
  698.                 }
  699.         }
  700.         void FlickerGemAmmoPickupAssigner(jjOBJ@ obj) {
  701.                 jjBEHAVIORINTERFACE@ intermediateCast;
  702.                 if (
  703.                         obj.eventID >= OBJECT::ICEAMMO3 &&
  704.                         obj.eventID <= OBJECT::GUN9AMMO3 &&
  705.                         (@intermediateCast = cast<jjBEHAVIORINTERFACE@>(jjObjectPresets[obj.eventID].behavior)) !is null &&
  706.                         cast<AmmoPickupWithCrateAndCorpseSupport@>(@intermediateCast) !is null
  707.                 )
  708.                         obj.behavior = jjObjectPresets[obj.eventID].behavior;
  709.                 else
  710.                         obj.behavior = BEHAVIOR::FLICKERGEM;
  711.                 obj.behave();
  712.         }
  713.        
  714.         void _fitInto(jjPIXELMAP &inout dest, const jjPIXELMAP &in source) {
  715.                 const float xRatio = float(source.width) / float(dest.width);
  716.                 const float yRatio = float(source.height) / float(dest.height);
  717.                 for (uint xD = 0; xD < dest.width; ++xD)
  718.                         for (uint yD = 0; yD < dest.height; ++yD) {
  719.                                 const uint8 color = source[uint(xD * xRatio), uint(yD * yRatio)];
  720.                                 if (color != 0)
  721.                                         dest[xD,yD] = color;
  722.                         }
  723.         }
  724.  
  725.         uint GetFirstAvailableCustomAnimsetID() {
  726.                 uint setID;
  727.                 for (uint customAnimSetID = 0; customAnimSetID < 256; ++customAnimSetID)
  728.                         if (jjAnimSets[setID = ANIM::CUSTOM[customAnimSetID]] == 0)
  729.                                 return setID;
  730.                 return ANIM::JAZZ;
  731.         }
  732.        
  733.         void _recolorAnimation(const jjANIMATION@ dest, const jjANIMATION@ src, const array<uint8>@ lut) {
  734.                 for (uint i = 0; i < src.frameCount; ++i) {
  735.                         jjANIMFRAME@ destFrame = jjAnimFrames[dest + i], srcFrame = jjAnimFrames[src + i];
  736.                         jjPIXELMAP image(srcFrame);
  737.                         for (uint x = 0; x < image.width; ++x)
  738.                                 for (uint y = 0; y < image.height; ++y)
  739.                                         image[x,y] = lut[image[x,y]];
  740.                         image.save(destFrame);
  741.                         destFrame.hotSpotX = srcFrame.hotSpotX;
  742.                         destFrame.hotSpotY = srcFrame.hotSpotY;
  743.                 }
  744.         }
  745.        
  746.                
  747.         array<uint8>@ Ammo15s;
  748.        
  749.         void GenerateSupplementaryWeaponSprites(array<int>@ animations, uint8 ammoCrateEventID = 0, int pickupFrameIDToUseForAmmoCrate = 0) {
  750.                 if (animations[AnimationIndices::PickupIndex] >= 0 || animations[AnimationIndices::PoweredUpPickupIndex] >= 0) {
  751.                         array<bool> animationsToGenerate(4);
  752.                         array<uint> numberOfFramesToGenerate(0);
  753.                        
  754.                         if (animationsToGenerate[AnimationIndices::PickupIndex] = (animations[AnimationIndices::PickupIndex] < 0 && animations[AnimationIndices::PoweredUpPickupIndex] >= 0))
  755.                                 numberOfFramesToGenerate.insertLast(jjAnimations[animations[AnimationIndices::PoweredUpPickupIndex]].frameCount);
  756.                         else if (animationsToGenerate[AnimationIndices::PoweredUpPickupIndex] = (animations[AnimationIndices::PoweredUpPickupIndex] < 0 && animations[AnimationIndices::PickupIndex] >= 0))
  757.                                 numberOfFramesToGenerate.insertLast(jjAnimations[animations[AnimationIndices::PickupIndex]].frameCount);
  758.                         if (animationsToGenerate[AnimationIndices::AmmoCrateIndex] = (animations[AnimationIndices::AmmoCrateIndex] < 0 && ammoCrateEventID != 0))
  759.                                 numberOfFramesToGenerate.insertLast(1);
  760.                         if (animationsToGenerate[AnimationIndices::PowerupIndex] = (animations[AnimationIndices::PowerupIndex] < 0))
  761.                                 numberOfFramesToGenerate.insertLast(10);
  762.                         if (numberOfFramesToGenerate.length == 0) //nothing needs generating
  763.                                 return;
  764.                        
  765.                         jjANIMSET@ animSet = jjAnimSets[GetFirstAvailableCustomAnimsetID()];
  766.                         animSet.allocate(numberOfFramesToGenerate);
  767.                         uint animsetAnimationIndex = 0;
  768.                        
  769.                         if ((animationsToGenerate[AnimationIndices::PickupIndex] || animationsToGenerate[AnimationIndices::PoweredUpPickupIndex]) && _static::PowerupColorConversionRandomizer is null)
  770.                                 @_static::PowerupColorConversionRandomizer = jjRNG(jjLevelFileName[0] * jjLevelFileName[1] * jjLevelFileName[2] * jjLevelFileName[3] * jjLevelFileName[4]);
  771.                         if (animationsToGenerate[AnimationIndices::PickupIndex]) { //generate pickup anim from powerup pickup anim
  772.                                 if (_static::PowerupToNormal is null) { //setup
  773.                                         const array<uint8> OrangeTargets = { 32, 72, 88 };
  774.                                         @_static::PowerupToNormal = array<uint8> = {
  775.                                                 48,
  776.                                                 (_static::PowerupColorConversionRandomizer() & 1 == 1) ? 16 : 88,
  777.                                                 (_static::PowerupColorConversionRandomizer() & 1 == 1) ? 24 : 40,
  778.                                                 OrangeTargets[_static::PowerupColorConversionRandomizer() % 3],
  779.                                                 80,
  780.                                                 0,
  781.                                                 72,
  782.                                                 64,
  783.                                                 32,
  784.                                                 (_static::PowerupColorConversionRandomizer() & 1 == 1) ? 24 : 32
  785.                                         };
  786.                                         _static::PowerupToNormal[5] = _static::PowerupToNormal[3];
  787.                                         @_static::PowerupToNormalLUT = array<uint8>(256);
  788.                                         for (uint i = 1; i < 256; ++i)
  789.                                                 _static::PowerupToNormalLUT[i] = (i < 16 || i >= 96) ? i : (_static::PowerupToNormal[(i >> 3) - 2] | (i & 7));
  790.                                 }
  791.                                 _recolorAnimation(jjAnimations[animations[AnimationIndices::PickupIndex] = (animSet + animsetAnimationIndex++)], jjAnimations[animations[AnimationIndices::PoweredUpPickupIndex]],_static::PowerupToNormalLUT);
  792.                         } else if (animationsToGenerate[AnimationIndices::PoweredUpPickupIndex]) { //generate powerup pickup anim from pickup anim
  793.                                 if (_static::NormalToPowerup is null) { //setup
  794.                                         @_static::NormalToPowerup = array<uint8> = {
  795.                                                 24,
  796.                                                 (_static::PowerupColorConversionRandomizer() & 1 == 1) ? 32 : 88,
  797.                                                 (_static::PowerupColorConversionRandomizer() & 1 == 1) ? 40 : 88,
  798.                                                 32,
  799.                                                 16,
  800.                                                 32,
  801.                                                 72,
  802.                                                 40,
  803.                                                 48,
  804.                                                 40
  805.                                         };
  806.                                         @_static::NormalToPowerupLUT = array<uint8>(256);
  807.                                         for (uint i = 1; i < 256; ++i)
  808.                                                 _static::NormalToPowerupLUT[i] = (i < 16 || i >= 96) ? i : (_static::NormalToPowerup[(i >> 3) - 2] | (i & 7));
  809.                                 }
  810.                                 _recolorAnimation(jjAnimations[animations[AnimationIndices::PoweredUpPickupIndex] = (animSet + animsetAnimationIndex++)], jjAnimations[animations[AnimationIndices::PickupIndex]], _static::NormalToPowerupLUT);
  811.                         }
  812.                        
  813.                        
  814.                         if (animationsToGenerate[AnimationIndices::AmmoCrateIndex]) { //generate crate anim from pickup anim
  815.                                 if (_static::CrateImage is null) { //setup
  816.                                         @_static::CrateImage = jjPIXELMAP(jjAnimFrames[jjAnimations[jjAnimSets[ANIM::PICKUPS] + 59]]); //TNT crate--unlikely to have been replaced
  817.                                         for (uint x = 4; x < 20; ++x)
  818.                                                 for (uint y = 8; y < 18; ++y)
  819.                                                         if (_static::CrateImage[x,y] >= 88) //get rid of existing purple
  820.                                                                 _static::CrateImage[x,y] = 41;
  821.                                 }
  822.                                
  823.                                 jjPIXELMAP destImage(_static::CrateImage.width, _static::CrateImage.height);
  824.                                 for (uint x = 0; x < destImage.width; ++x)
  825.                                         for (uint y = 0; y < destImage.height; ++y)
  826.                                                 destImage[x,y] = _static::CrateImage[x,y];
  827.                                                
  828.                                 jjPIXELMAP resizedSourceImage(13, 13);
  829.                                 jjPIXELMAP pickupImage(jjAnimFrames[jjAnimations[animations[AnimationIndices::PickupIndex]].firstFrame + pickupFrameIDToUseForAmmoCrate]);
  830.                                 _fitInto(resizedSourceImage, pickupImage);
  831.                                
  832.                                 for (uint x = 0; x < resizedSourceImage.width; ++x)
  833.                                         for (uint y = 0; y < resizedSourceImage.height; ++y) {
  834.                                                 uint8 color = resizedSourceImage[x, y];
  835.                                                 if (color != 0) {
  836.                                                         if (color == 15) //white
  837.                                                                 color = 0; //bright
  838.                                                         else
  839.                                                                 color &= 7;
  840.                                                         destImage[5+x,7+y] = 95 - (color >> 1);
  841.                                                 }
  842.                                 }
  843.                                
  844.                                 jjANIMFRAME@ destFrame = jjAnimFrames[jjAnimations[animations[AnimationIndices::AmmoCrateIndex] = (animSet + animsetAnimationIndex++)]];
  845.                                 destImage.save(destFrame);
  846.                                 destFrame.hotSpotX = -13;
  847.                                 destFrame.hotSpotY = -14;
  848.                         }
  849.                        
  850.                         if (animationsToGenerate[AnimationIndices::PowerupIndex]) { //generate powerup monitor anim from powerup pickup anim
  851.                                 if (_static::PowerupImages is null) { //setup
  852.                                         @_static::PowerupImages = array<jjPIXELMAP@>();
  853.                                         const jjANIMATION@ powerupTemplate = jjAnimations[jjAnimSets[ANIM::PICKUPS] + 61]; //bouncer powerup has easy colors to work with
  854.                                         jjPIXELMAP powerupFrameBlankCorner(jjAnimFrames[powerupTemplate + 2]);
  855.                                         for (uint x = 3; x <= 13; ++x)
  856.                                                 for (uint y = 8; y <= 18; ++y) {
  857.                                                         const uint8 oldColor = powerupFrameBlankCorner[x,y];
  858.                                                         if (oldColor >= 88 || (oldColor >= 59 && oldColor <= 63)) //purple or yellow
  859.                                                                 powerupFrameBlankCorner[x,y] = 71; //monitor black
  860.                                                 }
  861.                                         for (uint i = 0; i < 10; ++i) { //powerupTemplate.length
  862.                                                 jjANIMFRAME@ srcFrame = jjAnimFrames[powerupTemplate + i];
  863.                                                 _static::PowerupImages.insertLast(jjPIXELMAP(srcFrame));
  864.                                                 jjPIXELMAP@ destImage = @_static::PowerupImages[_static::PowerupImages.length-1];
  865.                                                 for (uint x = 0; x < 17; ++x)
  866.                                                         for (uint y = 0; y < 21; ++y)
  867.                                                                 destImage[x,y] = powerupFrameBlankCorner[x,y];
  868.                                         }
  869.                                 }
  870.                                
  871.                                 const jjANIMATION@ poweredUpPickupAnimation = jjAnimations[animations[AnimationIndices::PoweredUpPickupIndex]];
  872.                                 const jjANIMATION@ newAnim = jjAnimations[animations[AnimationIndices::PowerupIndex] = (animSet + animsetAnimationIndex++)];
  873.                                 int minX = 0, minY = 0;
  874.                                 int maxRight = 0, maxBottom = 0;
  875.                                 array<jjPIXELMAP@> expandedPickupImages(poweredUpPickupAnimation.frameCount, null);
  876.                                 for (uint i = 0; i < poweredUpPickupAnimation.frameCount; ++i) {
  877.                                         const jjANIMFRAME@ frame = jjAnimFrames[poweredUpPickupAnimation + i];
  878.                                         if (frame.hotSpotX < minX) minX = frame.hotSpotX;
  879.                                         if (frame.hotSpotY < minY) minY = frame.hotSpotY;
  880.                                         const int right = frame.width + frame.hotSpotX, bottom = frame.height + frame.hotSpotY;
  881.                                         if (right > maxRight) maxRight = right;
  882.                                         if (bottom > maxBottom) maxBottom = bottom;
  883.                                 }
  884.                                 for (uint i = 0; i < poweredUpPickupAnimation.frameCount; ++i) {
  885.                                         @expandedPickupImages[i] = jjPIXELMAP(maxRight - minX, maxBottom - minY);
  886.                                         const jjANIMFRAME@ sourceFrame = jjAnimFrames[poweredUpPickupAnimation + i];
  887.                                         const jjPIXELMAP sourceImage(sourceFrame);
  888.                                         for (uint xS = 0; xS < sourceFrame.width; ++xS)
  889.                                                 for (uint yS = 0; yS < sourceFrame.height; ++yS)
  890.                                                         expandedPickupImages[i][xS - minX + sourceFrame.hotSpotX, yS - minY + sourceFrame.hotSpotY] = sourceImage[xS, yS];
  891.                                 }
  892.                                 for (uint i = 0; i < 10; ++i) {
  893.                                         const jjPIXELMAP@ templateImage = _static::PowerupImages[i];
  894.                                         jjPIXELMAP destImage(templateImage.width, templateImage.height);
  895.                                         for (uint x = 0; x < destImage.width; ++x)
  896.                                                 for (uint y = 0; y < destImage.height; ++y)
  897.                                                         destImage[x,y] = templateImage[x,y];
  898.                                                        
  899.                                         jjPIXELMAP resizedPickupImage(12, 14); //something like that
  900.                                         _fitInto(resizedPickupImage, expandedPickupImages[i % expandedPickupImages.length]);
  901.                                        
  902.                                         for (uint x = 0; x < resizedPickupImage.width; ++x)
  903.                                                 for (uint y = 0; y < resizedPickupImage.height; ++y) {
  904.                                                         const uint8 color = resizedPickupImage[x,y];
  905.                                                         if (color != 0)
  906.                                                                 destImage[3+x, 4+y] = color;
  907.                                                 }
  908.                                        
  909.                                         jjANIMFRAME@ destFrame = jjAnimFrames[newAnim + i];
  910.                                         destImage.save(destFrame);
  911.                                         destFrame.hotSpotX = destFrame.hotSpotY = -14;
  912.                                 }
  913.                         }
  914.                 }
  915.         }
  916.        
  917.         void CopyObject(jjOBJ@ dest, const jjOBJ@ src) {
  918.                 dest.frameID =  src.frameID;
  919.                 dest.curFrame = src.curFrame;
  920.                 dest.curAnim =  src.curAnim;
  921.                 dest.killAnim = src.killAnim;
  922.                 dest.behavior = src.behavior;
  923.                 dest.noHit =    src.noHit;
  924.                 dest.objType =  src.objType;
  925.                 dest.energy =   src.energy;
  926.                 dest.points =   src.points;
  927.                 dest.counterEnd=src.counterEnd;
  928.                 dest.state =    src.state;
  929.                 for (int i = 0; i < 11; ++i)
  930.                 dest.var[i] =   src.var[i];
  931.         }
  932.         void UpdateActiveObjectAnimations(uint number) {
  933.                 if (se::isValidWeapon(number)) {
  934.                         array<uint8> eventIDs = {se::getAmmoPickupOfWeapon(number), (Ammo15s !is null && Ammo15s[number-1] != 0) ? Ammo15s[number-1] : se::getAmmoCrateOfWeapon(number), se::getPowerupMonitorOfWeapon(number)};
  935.                         for (uint objectID = jjObjectCount; --objectID != 0;) {
  936.                                 jjOBJ@ obj = jjObjects[objectID];
  937.                                 if (obj.isActive && eventIDs.find(obj.eventID) >= 0)
  938.                                         CopyObject(obj, jjObjectPresets[obj.eventID]);
  939.                         }
  940.                 }
  941.         }
  942.        
  943.         bool WeaponHasBeenReplaced(uint number) {
  944.                 if (!se::isValidWeapon(number))
  945.                         return false;
  946.                 const array<BEHAVIOR::Behavior> behaviors = {
  947.                         BEHAVIOR::BULLET, BEHAVIOR::BULLET,
  948.                         BEHAVIOR::BOUNCERBULLET, BEHAVIOR::BOUNCERBULLETPU,
  949.                         BEHAVIOR::BULLET, BEHAVIOR::ICEBULLETPU,
  950.                         BEHAVIOR::SEEKERBULLET, BEHAVIOR::SEEKERBULLET,
  951.                         BEHAVIOR::RFBULLET, BEHAVIOR::RFBULLET,
  952.                         BEHAVIOR::TOASTERBULLET, BEHAVIOR::TOASTERBULLET,
  953.                         BEHAVIOR::TNT, BEHAVIOR::TNT,
  954.                         BEHAVIOR::BULLET, BEHAVIOR::BULLET,
  955.                         BEHAVIOR::ELECTROBULLET, BEHAVIOR::ELECTROBULLET,
  956.                 };
  957.                 const int idx = (number - 1) * 2;
  958.                 return !(
  959.                         jjObjectPresets[se::getBasicBulletOfWeapon(number)].behavior == behaviors[idx] &&
  960.                         jjObjectPresets[se::getPoweredBulletOfWeapon(number)].behavior == behaviors[idx + 1]);
  961.         }
  962.        
  963.         namespace HelpfulBulletFunctions {
  964.                 int GetAngle(const jjOBJ@ obj) {
  965.                         return int(atan2(
  966.                                         (obj.xSpeed >= 0) ? obj.ySpeed : -obj.ySpeed,
  967.                                         abs(obj.xSpeed)
  968.                         ) * -512.0 * 0.318309886142228);
  969.                 }
  970.                 int GetDirection(const jjOBJ@ obj) {
  971.                         if (obj.xSpeed >= 0)
  972.                                 return 1;
  973.                         return -1;
  974.                 }
  975.                 void DrawAngled(const jjOBJ@ obj, float xScale = 1, float yScale = 1, SPRITE::Mode mode = SPRITE::NORMAL, uint8 param = 0, int layerZ = 4, int layerXY = 4, int8 playerID = -1) {
  976.                         jjDrawRotatedSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, GetAngle(obj), GetDirection(obj) * xScale, yScale, mode, param, layerZ, layerXY, playerID);
  977.                 }
  978.                 bool MaskedPixel(const jjOBJ@ obj) {
  979.                         return jjMaskedPixel(int(obj.xPos), int(obj.yPos));
  980.                 }
  981.                 bool IsPowerup(const jjOBJ@ obj) {
  982.                         return (obj.var[6] & 8) == 8;
  983.                 }
  984.                 void Blast(jjOBJ@ obj, uint animID) {
  985.                         obj.killAnim = animID;
  986.                         obj.state = STATE::EXPLODE;
  987.                         obj.behavior = BEHAVIOR::RFBULLET;
  988.                         obj.behave(BEHAVIOR::DEFAULT, false);
  989.                 }
  990.                 bool PlayerIsEnemy(const jjOBJ@ obj, const jjPLAYER@ other) {
  991.                         if (obj.creatorType != CREATOR::PLAYER)
  992.                                 return true;
  993.                         else
  994.                                 return jjPlayers[obj.creatorID].isEnemy(other);
  995.                 }
  996.                 int GetNearestEnemyPlayer(const jjOBJ@ obj, uint maxDistance, bool canBeFlickering = false) {
  997.                         if (jjGameMode <= GAME::COOP && obj.creatorType == CREATOR::PLAYER)
  998.                                 return -1;
  999.                         if (!canBeFlickering && jjGameState != GAME::STARTED && jjGameState != GAME::OVERTIME)
  1000.                                 return -1;
  1001.                                
  1002.                         int nearestPlayerID = -1;
  1003.                         uint minDistance = maxDistance * maxDistance;
  1004.                         for (uint i = 0; i < 32; ++i) {
  1005.                                 const jjPLAYER@ potentialEnemy = jjPlayers[i];
  1006.                                 if (!potentialEnemy.isInGame)
  1007.                                         continue;
  1008.                                 if (!canBeFlickering && potentialEnemy.blink != 0)
  1009.                                         continue;
  1010.                                 const float dx = potentialEnemy.xPos - obj.xPos, dy = potentialEnemy.yPos - obj.yPos;
  1011.                                 const uint distance = uint(dx * dx + dy * dy);
  1012.                                 if (distance < minDistance && PlayerIsEnemy(obj, potentialEnemy)) {
  1013.                                         minDistance = distance;
  1014.                                         nearestPlayerID = i;
  1015.                                 }
  1016.                         }
  1017.                         return nearestPlayerID;
  1018.                 }
  1019.                 int GetNearestEnemyObject(const jjOBJ@ obj, uint maxDistance) {
  1020.                         if (obj.creatorType != CREATOR::PLAYER)
  1021.                                 return -1;
  1022.                         int nearestObjectID = -1;
  1023.                         uint minDistance = maxDistance * maxDistance;
  1024.                         for (int i = 1; i < jjObjectCount; ++i) {
  1025.                                 const jjOBJ@ potentialEnemy = jjObjects[i];
  1026.                                 if (!potentialEnemy.isActive || !potentialEnemy.isTarget)
  1027.                                         continue;
  1028.                                 const float dx = potentialEnemy.xPos - obj.xPos, dy = potentialEnemy.yPos - obj.yPos;
  1029.                                 const uint distance = uint(dx * dx + dy * dy);
  1030.                                 if (distance < minDistance) {
  1031.                                         minDistance = distance;
  1032.                                         nearestObjectID = i;
  1033.                                 }
  1034.                         }
  1035.                         return nearestObjectID;
  1036.                 }
  1037.                 array<float>@ GetNearestEnemyPosition(const jjOBJ@ obj, uint maxDistance, bool canBeFlickering = false) {
  1038.                         int nearestEnemyID = GetNearestEnemyPlayer(obj, maxDistance, canBeFlickering);
  1039.                         if (nearestEnemyID >= 0) {
  1040.                                 const jjPLAYER@ target = jjPlayers[nearestEnemyID];
  1041.                                 return array<float> = {target.xPos, target.yPos};
  1042.                         }
  1043.                         nearestEnemyID = GetNearestEnemyObject(obj, maxDistance);
  1044.                         if (nearestEnemyID >= 0) {
  1045.                                 const jjOBJ@ target = jjObjects[nearestEnemyID];
  1046.                                 return array<float> = {target.xPos, target.yPos};
  1047.                         }
  1048.                         return null;
  1049.                 }
  1050.         }
  1051.  
  1052.         const float LevelRight = float(jjLayerWidth[4] * 32);
  1053.         const float LevelBottom = float(jjLayerHeight[4] * 32);
  1054. }
  1055.  
  1056. namespace _static {
  1057.         jjRNG@ PowerupColorConversionRandomizer;
  1058.         array<uint8>@ NormalToPowerupLUT, NormalToPowerup, PowerupToNormalLUT, PowerupToNormal;
  1059.         jjPIXELMAP@ CrateImage;
  1060.         array<jjPIXELMAP@>@ PowerupImages;
  1061. }
  1062.  
  1063. namespace DefaultWeapons {
  1064.         void DefaultSample(const jjOBJ@ obj, WEAPON::Weapon number, bool definitelyPlaySample = false) {
  1065.                 const bool powerup = MLLEWeapons::HelpfulBulletFunctions::IsPowerup(obj);
  1066.                 if (obj.creatorType == CREATOR::PLAYER || definitelyPlaySample)
  1067.                         switch (number) {
  1068.                                 case WEAPON::BLASTER: {
  1069.                                         const bool jazz = obj.creatorType != CREATOR::PLAYER || jjPlayers[obj.creator].charCurr == CHAR::JAZZ;
  1070.                                         int sample;
  1071.                                         int frequency = 22050;
  1072.                                         if (!powerup) {
  1073.                                                 if (jazz)
  1074.                                                         sample = SOUND::AMMO_GUNJAZZ;
  1075.                                                 else
  1076.                                                         sample = SOUND::AMMO_GUN1;
  1077.                                         } else {
  1078.                                                 if (jazz)
  1079.                                                         sample = SOUND::AMMO_FUMP;
  1080.                                                 else {
  1081.                                                         sample = SOUND::AMMO_FUMP + ((jjRandom() & 1) * 3);
  1082.                                                         frequency = 0;
  1083.                                                 }
  1084.                                         }
  1085.                                         jjSample(obj.xPos,obj.yPos, SOUND::Sample(sample), 0, frequency);
  1086.                                         break;
  1087.                                 }
  1088.                                 case WEAPON::BOUNCER:
  1089.                                         jjSample(obj.xPos, obj.yPos, SOUND::Sample((powerup ? SOUND::AMMO_BMP1 : SOUND::AMMO_GUNFLP) + (jjRandom() % 6)), 0, (obj.creatorType != CREATOR::PLAYER || jjPlayers[obj.creator].charCurr == CHAR::JAZZ) ? 11025 : 22050);
  1090.                                         break;
  1091.                                 case WEAPON::ICE:
  1092.                                         if (powerup)
  1093.                                                 jjSample(obj.xPos, obj.yPos, SOUND::Sample(SOUND::AMMO_ICEPU1 + (jjRandom() & 3)));
  1094.                                         else
  1095.                                                 jjSample(obj.xPos, obj.yPos, SOUND::Sample(SOUND::AMMO_ICEGUN + (jjRandom() % 3)));
  1096.                                         break;
  1097.                                 case WEAPON::SEEKER:
  1098.                                         jjSample(obj.xPos, obj.yPos, SOUND::AMMO_MISSILE);
  1099.                                         break;
  1100.                                 case WEAPON::RF:
  1101.                                         jjSample(obj.xPos, obj.yPos, SOUND::AMMO_LAZRAYS);
  1102.                                         break;
  1103.                                 //TNT makes no noise
  1104.                                 case WEAPON::GUN8:
  1105.                                         jjSample(obj.xPos, obj.yPos, SOUND::COMMON_RINGGUN); //fireball
  1106.                                         break;
  1107.                                 case WEAPON::GUN9:
  1108.                                         jjSample(obj.xPos, obj.yPos, SOUND::Sample(SOUND::AMMO_LASER2 + (jjRandom() & 1)));
  1109.                                         break;
  1110.                         }
  1111.         }
  1112. }
  1113.  
  1114. namespace SOUND {
  1115.         array<Sample>@ _allSampleConstantsInRoughOrderOfLikelihoodToBeUsed;
  1116.         array<Sample>@ GetAllSampleConstantsInRoughOrderOfLikelihoodToBeUsed() {
  1117.                 if (_allSampleConstantsInRoughOrderOfLikelihoodToBeUsed is null)
  1118.                         @_allSampleConstantsInRoughOrderOfLikelihoodToBeUsed = array<Sample> = {
  1119.                                 BONUS_BONUSBLUB, ENDING_OHTHANK, EPICLOGO_EPIC1, EPICLOGO_EPIC2, FAN_FAN, GLOVE_HIT, STONED_STONED,
  1120.                                 INTRO_BOEM1, INTRO_BOEM2, INTRO_BRAKE, INTRO_END, INTRO_GRAB, INTRO_GREN1, INTRO_GREN2, INTRO_GREN3, INTRO_GUNM0, INTRO_GUNM1, INTRO_GUNM2, INTRO_HELI, INTRO_HITSPAZ, INTRO_HITTURT, INTRO_IFEEL, INTRO_INHALE, INTRO_INSECT, INTRO_KATROL, INTRO_LAND, INTRO_MONSTER, INTRO_MONSTER2, INTRO_ROCK, INTRO_ROPE1, INTRO_ROPE2, INTRO_RUN, INTRO_SHOT1, INTRO_SHOTGRN, INTRO_SKI, INTRO_STRING, INTRO_SWISH1, INTRO_SWISH2, INTRO_SWISH3, INTRO_SWISH4, INTRO_UHTURT, INTRO_UP1, INTRO_UP2, INTRO_WIND_01,
  1121.                                 ORANGE_BOEML, ORANGE_BOEMR, ORANGE_BUBBELSL, ORANGE_BUBBELSR, ORANGE_GLAS1L, ORANGE_GLAS1R, ORANGE_GLAS2L, ORANGE_GLAS2R, ORANGE_MERGE, ORANGE_SWEEP0L, ORANGE_SWEEP0R, ORANGE_SWEEP1L, ORANGE_SWEEP1R, ORANGE_SWEEP2L, ORANGE_SWEEP2R,
  1122.                                 P2_CRUNCH, P2_FART, P2_FOEW1, P2_FOEW4, P2_FOEW5, P2_FROG1, P2_FROG2, P2_FROG3, P2_FROG4, P2_FROG5, P2_KISS4, P2_OPEN, P2_PINCH1, P2_PINCH2, P2_PLOPSEQ1, P2_PLOPSEQ2, P2_PLOPSEQ3, P2_PLOPSEQ4, P2_POEP, P2_PTOEI, P2_SPLUT, P2_THROW, P2_TONG,
  1123.                                 BILSBOSS_BILLAPPEAR, BILSBOSS_FINGERSNAP, BILSBOSS_FIRE, BILSBOSS_FIRESTART, BILSBOSS_SCARY3, BILSBOSS_THUNDER, BILSBOSS_ZIP, BUBBA_BUBBABOUNCE1, BUBBA_BUBBABOUNCE2, BUBBA_BUBBAEXPLO, BUBBA_FROG2, BUBBA_FROG3, BUBBA_FROG4, BUBBA_FROG5, BUBBA_SNEEZE2, BUBBA_TORNADOATTACK2, DEVILDEVAN_DRAGONFIRE, DEVILDEVAN_FLAP, DEVILDEVAN_FROG4, DEVILDEVAN_JUMPUP, DEVILDEVAN_LAUGH, DEVILDEVAN_PHASER2, DEVILDEVAN_STRECH2, DEVILDEVAN_STRECHTAIL, DEVILDEVAN_STRETCH1, DEVILDEVAN_STRETCH3, DEVILDEVAN_VANISH1, DEVILDEVAN_WHISTLEDESCENDING2, DEVILDEVAN_WINGSOUT, QUEEN_LADYUP, QUEEN_SCREAM, ROBOT_BIG1, ROBOT_BIG2, ROBOT_CAN1, ROBOT_CAN2, ROBOT_HYDRO, ROBOT_HYDRO2, ROBOT_HYDROFIL, ROBOT_HYDROPUF, ROBOT_IDLE1, ROBOT_IDLE2, ROBOT_JMPCAN1, ROBOT_JMPCAN10, ROBOT_JMPCAN2, ROBOT_JMPCAN3, ROBOT_JMPCAN4, ROBOT_JMPCAN5, ROBOT_JMPCAN6, ROBOT_JMPCAN7, ROBOT_JMPCAN8, ROBOT_JMPCAN9, ROBOT_METAL1, ROBOT_METAL2, ROBOT_METAL3, ROBOT_METAL4, ROBOT_METAL5, ROBOT_OPEN, ROBOT_OUT, ROBOT_POEP, ROBOT_POLE, ROBOT_SHOOT, ROBOT_STEP1, ROBOT_STEP2, ROBOT_STEP3, SONCSHIP_METAL1, SONCSHIP_MISSILE2, SONCSHIP_SCRAPE, SONCSHIP_SHIPLOOP, SONCSHIP_TARGETLOCK, TUFBOSS_CATCH, TUFBOSS_RELEASE, TUFBOSS_SWING, UTERUS_CRABCLOSE, UTERUS_CRABOPEN2, UTERUS_SCISSORS1, UTERUS_SCISSORS2, UTERUS_SCISSORS3, UTERUS_SCISSORS4, UTERUS_SCISSORS5, UTERUS_SCISSORS6, UTERUS_SCISSORS7, UTERUS_SCISSORS8, UTERUS_SCREAM1, UTERUS_STEP1, UTERUS_STEP2,
  1124.                                 WITCH_LAUGH, WITCH_MAGIC, BAT_BATFLY1, BUMBEE_BEELOOP, CATERPIL_RIDOE, DEMON_RUN, DOG_AGRESSIV, DOG_SNIF1, DOG_WAF1, DOG_WAF2, DOG_WAF3, DRAGFLY_BEELOOP, EVA_KISS1, EVA_KISS2, EVA_KISS3, EVA_KISS4, FATCHK_HIT1, FATCHK_HIT2, FATCHK_HIT3, FENCER_FENCE1, HATTER_CUP, HATTER_HAT, HATTER_PTOEI, HATTER_SPLIN, HATTER_SPLOUT, LABRAT_BITE, LABRAT_EYE2, LABRAT_EYE3, LABRAT_MOUSE1, LABRAT_MOUSE2, LABRAT_MOUSE3, LIZARD_LIZ1, LIZARD_LIZ2, LIZARD_LIZ4, LIZARD_LIZ6, MONKEY_SPLUT, MONKEY_THROW, MOTH_FLAPMOTH, PINBALL_BELL, PINBALL_FLIP1, PINBALL_FLIP2, PINBALL_FLIP3, PINBALL_FLIP4, RAPIER_GOSTDIE, RAPIER_GOSTLOOP, RAPIER_GOSTOOOH, RAPIER_GOSTRIP, RAPIER_HITCHAR, ROCK_ROCK1, SCIENCE_PLOPKAOS, SKELETON_BONE1, SKELETON_BONE2, SKELETON_BONE3, SKELETON_BONE5, SKELETON_BONE6, SKELETON_BONE7, SMALTREE_FALL, SMALTREE_GROUND, SMALTREE_HEAD, STEAM_STEAM, SUCKER_FART, SUCKER_PINCH1, SUCKER_PINCH2, SUCKER_PINCH3, SUCKER_PLOPSEQ1, SUCKER_PLOPSEQ2, SUCKER_PLOPSEQ3, SUCKER_PLOPSEQ4, SUCKER_UP, TURTLE_BITE3, TURTLE_HIDE, TURTLE_HITSHELL, TURTLE_IDLE1, TURTLE_IDLE2, TURTLE_NECK, TURTLE_SPK1TURT, TURTLE_SPK2TURT, TURTLE_SPK3TURT, TURTLE_SPK4TURT, TURTLE_TURN, WIND_WIND2A, BONUS_BONUS1, P2_SPLOUT, INTRO_BLOW
  1125.                         };
  1126.                 return @_allSampleConstantsInRoughOrderOfLikelihoodToBeUsed;
  1127.         }
  1128. }