Subversion Repositories eduke32

Rev

Rev 8697 | Blame | Compare with Previous | Last modification | View Log | RSS feed

//-------------------------------------------------------------------------
/*
Copyright (C) 1997, 2005 - 3D Realms Entertainment

This file is part of Shadow Warrior version 1.2

Shadow Warrior is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

Original Source: 1997 - Frank Maddin and Jim Norwood
Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
*/

//-------------------------------------------------------------------------
#include "build.h"
#include "common.h"

#include "keys.h"
#include "names2.h"
#include "panel.h"
#include "game.h"
#include "tags.h"
#include "common_game.h"
#include "break.h"
#include "quake.h"
#include "network.h"
#include "pal.h"
#include "vis.h"

#include "ai.h"
#include "weapon.h"
#include "anim.h"
#include "sector.h"
#include "sprite.h"
#include "actor.h"
#include "track.h"
#include "player.h"

//
// Damage Amounts defined in damage.h
//
#define DAMAGE_TABLE
DAMAGE_DATA DamageData[] =
{
#include "damage.h"
};
#undef  DAMAGE_TABLE

short ADJUST=120;
int ADJUSTV=1<<16;

FOOT_TYPE FootMode=WATER_FOOT;
SWBOOL left_foot = FALSE;
int FinishTimer = 0;

// This is how many bullet shells have been spawned since the beginning of the game.
int ShellCount = 0;

//short Zombies = 0;
short StarQueueHead=0;
short StarQueue[MAX_STAR_QUEUE];
short HoleQueueHead=0;
short HoleQueue[MAX_HOLE_QUEUE];
short WallBloodQueueHead=0;
short WallBloodQueue[MAX_WALLBLOOD_QUEUE];
short FloorBloodQueueHead=0;
short FloorBloodQueue[MAX_FLOORBLOOD_QUEUE];
short GenericQueueHead=0;
short GenericQueue[MAX_GENERIC_QUEUE];
short LoWangsQueueHead=0;
short LoWangsQueue[MAX_LOWANGS_QUEUE];
int SpawnBreakStaticFlames(short);

SWBOOL GlobalSkipZrange = FALSE;

int WeaponIsAmmo = BIT(WPN_STAR) | BIT(WPN_SWORD) | BIT(WPN_MINE) | BIT(WPN_FIST);

short target_ang;

ANIMATOR NullAnimator;
ANIMATOR DoStar;
ANIMATOR DoCrossBolt;
ANIMATOR DoSuicide, DoUziSmoke;
ANIMATOR DoShrapJumpFall;
ANIMATOR DoFastShrapJumpFall;

int SpawnSmokePuff(short SpriteNum);
SWBOOL WarpToUnderwater(short *sectnum, int *x, int *y, int *z);
SWBOOL WarpToSurface(short *sectnum, int *x, int *y, int *z);
short ElectroFindClosestEnemy(short SpriteNum);
int InitElectroJump(SPRITEp wp, SPRITEp sp);
SWBOOL TestDontStickSector(short hit_sect);
int SpawnShrapX(short SpriteNum);
SWBOOL WeaponMoveHit(short SpriteNum);
int HelpMissileLateral(int16_t Weapon, int dist);
void SpawnMidSplash(short SpriteNum);

int SopDamage(SECTOR_OBJECTp sop,short amt);
int SopCheckKill(SECTOR_OBJECTp sop);
int QueueStar(short SpriteNum);
int DoBlurExtend(int16_t Weapon,int16_t interval,int16_t blur_num);
int SpawnDemonFist(short Weapon);
int SpawnTankShellExp(int16_t Weapon);
int SpawnMicroExp(int16_t Weapon);
void SpawnExpZadjust(short Weapon, SPRITEp exp, int upper_zsize, int lower_zsize);
int BulletHitSprite(SPRITEp sp,short hit_sprite,int hit_x,int hit_y,int hit_z,short ID);
int SpawnSplashXY(int hit_x,int hit_y,int hit_z,short);
int SpawnBoatSparks(PLAYERp pp,short hit_sect,short hit_wall,int hit_x,int hit_y,int hit_z,short hit_ang);

short StatDamageList[STAT_DAMAGE_LIST_SIZE] =
{
    STAT_SO_SP_CHILD,
    STAT_ENEMY,
    STAT_ENEMY_SKIP4,
    STAT_PLAYER0,
    STAT_PLAYER1,
    STAT_PLAYER2,
    STAT_PLAYER3,
    STAT_PLAYER4,
    STAT_PLAYER5,
    STAT_PLAYER6,
    STAT_PLAYER7,
    STAT_PLAYER_UNDER0,
    STAT_PLAYER_UNDER1,
    STAT_PLAYER_UNDER2,
    STAT_PLAYER_UNDER3,
    STAT_PLAYER_UNDER4,
    STAT_PLAYER_UNDER5,
    STAT_PLAYER_UNDER6,
    STAT_PLAYER_UNDER7,
    // MINE MUST BE LAST
    STAT_MINE_STUCK
};

//////////////////////
//
// SPECIAL STATES
//
//////////////////////

// state for sprites that are not restored
STATE s_NotRestored[] =
{
    {2323, 100, NullAnimator, &s_NotRestored[0]}
};

STATE s_Suicide[] =
{
    {1, 100, DoSuicide, &s_Suicide[0]}
};

STATE s_DeadLoWang[] =
{
    {1160, 100, NullAnimator, &s_DeadLoWang[0]},
};

//////////////////////
//
// BREAKABLE STATES
//
//////////////////////

ANIMATOR DoDefaultStat;

#define BREAK_LIGHT_RATE 18
STATE s_BreakLight[] =
{
    {BREAK_LIGHT_ANIM + 0, BREAK_LIGHT_RATE, NullAnimator, &s_BreakLight[1]},
    {BREAK_LIGHT_ANIM + 1, BREAK_LIGHT_RATE, NullAnimator, &s_BreakLight[2]},
    {BREAK_LIGHT_ANIM + 2, BREAK_LIGHT_RATE, NullAnimator, &s_BreakLight[3]},
    {BREAK_LIGHT_ANIM + 3, BREAK_LIGHT_RATE, NullAnimator, &s_BreakLight[4]},
    {BREAK_LIGHT_ANIM + 4, BREAK_LIGHT_RATE, NullAnimator, &s_BreakLight[5]},
    {BREAK_LIGHT_ANIM + 5, BREAK_LIGHT_RATE, NullAnimator, &s_BreakLight[5]}
};

#define BREAK_BARREL_RATE 18
STATE s_BreakBarrel[] =
{
    {BREAK_BARREL + 4, BREAK_BARREL_RATE, NullAnimator, &s_BreakBarrel[1]},
    {BREAK_BARREL + 5, BREAK_BARREL_RATE, NullAnimator, &s_BreakBarrel[2]},
    {BREAK_BARREL + 6, BREAK_BARREL_RATE, NullAnimator, &s_BreakBarrel[3]},
    {BREAK_BARREL + 7, BREAK_BARREL_RATE, NullAnimator, &s_BreakBarrel[4]},
    {BREAK_BARREL + 8, BREAK_BARREL_RATE, NullAnimator, &s_BreakBarrel[5]},
    {BREAK_BARREL + 9, BREAK_BARREL_RATE, DoDefaultStat, &s_BreakBarrel[5]},
};

#define BREAK_PEDISTAL_RATE 28
STATE s_BreakPedistal[] =
{
    {BREAK_PEDISTAL + 1, BREAK_PEDISTAL_RATE, NullAnimator, &s_BreakPedistal[1]},
    {BREAK_PEDISTAL + 2, BREAK_PEDISTAL_RATE, NullAnimator, &s_BreakPedistal[2]},
    {BREAK_PEDISTAL + 3, BREAK_PEDISTAL_RATE, NullAnimator, &s_BreakPedistal[3]},
    {BREAK_PEDISTAL + 4, BREAK_PEDISTAL_RATE, NullAnimator, &s_BreakPedistal[3]},
};

#define BREAK_BOTTLE1_RATE 18
STATE s_BreakBottle1[] =
{
    {BREAK_BOTTLE1 + 1, BREAK_BOTTLE1_RATE, NullAnimator, &s_BreakBottle1[1]},
    {BREAK_BOTTLE1 + 2, BREAK_BOTTLE1_RATE, NullAnimator, &s_BreakBottle1[2]},
    {BREAK_BOTTLE1 + 3, BREAK_BOTTLE1_RATE, NullAnimator, &s_BreakBottle1[3]},
    {BREAK_BOTTLE1 + 4, BREAK_BOTTLE1_RATE, NullAnimator, &s_BreakBottle1[4]},
    {BREAK_BOTTLE1 + 5, BREAK_BOTTLE1_RATE, NullAnimator, &s_BreakBottle1[5]},
    {BREAK_BOTTLE1 + 6, BREAK_BOTTLE1_RATE, NullAnimator, &s_BreakBottle1[5]},
};

#define BREAK_BOTTLE2_RATE 18
STATE s_BreakBottle2[] =
{
    {BREAK_BOTTLE2 + 1, BREAK_BOTTLE2_RATE, NullAnimator, &s_BreakBottle2[1]},
    {BREAK_BOTTLE2 + 2, BREAK_BOTTLE2_RATE, NullAnimator, &s_BreakBottle2[2]},
    {BREAK_BOTTLE2 + 3, BREAK_BOTTLE2_RATE, NullAnimator, &s_BreakBottle2[3]},
    {BREAK_BOTTLE2 + 4, BREAK_BOTTLE2_RATE, NullAnimator, &s_BreakBottle2[4]},
    {BREAK_BOTTLE2 + 5, BREAK_BOTTLE2_RATE, NullAnimator, &s_BreakBottle2[5]},
    {BREAK_BOTTLE2 + 6, BREAK_BOTTLE2_RATE, NullAnimator, &s_BreakBottle2[5]},
};

#define PUFF_RATE 8
ANIMATOR DoPuff;
STATE s_Puff[] =
{
    {PUFF + 0, PUFF_RATE, DoPuff, &s_Puff[1]},
    {PUFF + 1, PUFF_RATE, DoPuff, &s_Puff[2]},
    {PUFF + 2, PUFF_RATE, DoPuff, &s_Puff[3]},
    {PUFF + 3, PUFF_RATE, DoPuff, &s_Puff[4]},
    {PUFF + 4, PUFF_RATE, DoPuff, &s_Puff[5]},
    {PUFF + 5, PUFF_RATE, DoPuff, &s_Puff[6]},
    {PUFF + 5, 100, DoSuicide, &s_Puff[0]}
};

#define RAIL_PUFF_R0 3969
#define RAIL_PUFF_R1 3985
#define RAIL_PUFF_R2 4001
#define RAIL_PUFF_RATE 6

ANIMATOR DoRailPuff;

STATE s_RailPuff[3][17] =
{
    {
        {RAIL_PUFF_R0 + 0, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[0][1]},
        {RAIL_PUFF_R0 + 1, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[0][2]},
        {RAIL_PUFF_R0 + 2, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[0][3]},
        {RAIL_PUFF_R0 + 3, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[0][4]},
        {RAIL_PUFF_R0 + 4, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[0][5]},
        {RAIL_PUFF_R0 + 5, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[0][6]},
        {RAIL_PUFF_R0 + 6, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[0][7]},
        {RAIL_PUFF_R0 + 7, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[0][8]},
        {RAIL_PUFF_R0 + 8, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[0][9]},
        {RAIL_PUFF_R0 + 9, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[0][10]},
        {RAIL_PUFF_R0 + 10, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[0][11]},
        {RAIL_PUFF_R0 + 11, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[0][12]},
        {RAIL_PUFF_R0 + 12, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[0][13]},
        {RAIL_PUFF_R0 + 13, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[0][14]},
        {RAIL_PUFF_R0 + 14, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[0][15]},
        {RAIL_PUFF_R0 + 15, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[0][16]},
        {RAIL_PUFF_R0 + 15, 100, DoSuicide, &s_RailPuff[0][0]},
    },
    {
        {RAIL_PUFF_R1 + 0, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[1][1]},
        {RAIL_PUFF_R1 + 1, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[1][2]},
        {RAIL_PUFF_R1 + 2, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[1][3]},
        {RAIL_PUFF_R1 + 3, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[1][4]},
        {RAIL_PUFF_R1 + 4, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[1][5]},
        {RAIL_PUFF_R1 + 5, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[1][6]},
        {RAIL_PUFF_R1 + 6, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[1][7]},
        {RAIL_PUFF_R1 + 7, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[1][8]},
        {RAIL_PUFF_R1 + 8, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[1][9]},
        {RAIL_PUFF_R1 + 9, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[1][10]},
        {RAIL_PUFF_R1 + 10, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[1][11]},
        {RAIL_PUFF_R1 + 11, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[1][12]},
        {RAIL_PUFF_R1 + 12, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[1][13]},
        {RAIL_PUFF_R1 + 13, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[1][14]},
        {RAIL_PUFF_R1 + 14, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[1][15]},
        {RAIL_PUFF_R1 + 15, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[1][16]},
        {RAIL_PUFF_R1 + 15, 100, DoSuicide, &s_RailPuff[1][0]},
    },
    {
        {RAIL_PUFF_R2 + 0, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[2][1]},
        {RAIL_PUFF_R2 + 1, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[2][2]},
        {RAIL_PUFF_R2 + 2, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[2][3]},
        {RAIL_PUFF_R2 + 3, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[2][4]},
        {RAIL_PUFF_R2 + 4, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[2][5]},
        {RAIL_PUFF_R2 + 5, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[2][6]},
        {RAIL_PUFF_R2 + 6, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[2][7]},
        {RAIL_PUFF_R2 + 7, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[2][8]},
        {RAIL_PUFF_R2 + 8, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[2][9]},
        {RAIL_PUFF_R2 + 9, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[2][10]},
        {RAIL_PUFF_R2 + 10, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[2][11]},
        {RAIL_PUFF_R2 + 11, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[2][12]},
        {RAIL_PUFF_R2 + 12, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[2][13]},
        {RAIL_PUFF_R2 + 13, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[2][14]},
        {RAIL_PUFF_R2 + 14, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[2][15]},
        {RAIL_PUFF_R2 + 15, RAIL_PUFF_RATE, DoRailPuff, &s_RailPuff[2][16]},
        {RAIL_PUFF_R2 + 15, 100, DoSuicide, &s_RailPuff[2][0]},
    }
};


STATEp sg_RailPuff[] =
{
    &s_RailPuff[0][0],
    &s_RailPuff[1][0],
    &s_RailPuff[2][0],
    &s_RailPuff[1][0],
    &s_RailPuff[0][0]
};

#define LASER_PUFF 3201
#define LASER_PUFF_RATE 8
STATE s_LaserPuff[] =
{
    {LASER_PUFF + 0, LASER_PUFF_RATE, NULL, &s_LaserPuff[1]},
    //{LASER_PUFF + 1, LASER_PUFF_RATE, NULL, &s_LaserPuff[2]},
    //{LASER_PUFF + 2, LASER_PUFF_RATE, NULL, &s_LaserPuff[3]},
    {LASER_PUFF + 0, 100, DoSuicide, &s_LaserPuff[0]}
};

#define TRACER 3201
#define TRACER_RATE 6
ANIMATOR DoTracer;
STATE s_Tracer[] =
{
    {TRACER + 0, TRACER_RATE, DoTracer, &s_Tracer[1]},
    {TRACER + 1, TRACER_RATE, DoTracer, &s_Tracer[2]},
    {TRACER + 2, TRACER_RATE, DoTracer, &s_Tracer[3]},
    {TRACER + 3, TRACER_RATE, DoTracer, &s_Tracer[4]},
    {TRACER + 4, TRACER_RATE, DoTracer, &s_Tracer[5]},
    {TRACER + 5, TRACER_RATE, DoTracer, &s_Tracer[0]}
};

#define EMP 2058
#define EMP_RATE 6
ANIMATOR DoEMP;
STATE s_EMP[] =
{
    {EMP + 0, EMP_RATE, DoEMP, &s_EMP[1]},
    {EMP + 1, EMP_RATE, DoEMP, &s_EMP[2]},
    {EMP + 2, EMP_RATE, DoEMP, &s_EMP[0]}
};

ANIMATOR DoEMPBurst;
STATE s_EMPBurst[] =
{
    {EMP + 0, EMP_RATE, DoEMPBurst, &s_EMPBurst[1]},
    {EMP + 1, EMP_RATE, DoEMPBurst, &s_EMPBurst[2]},
    {EMP + 2, EMP_RATE, DoEMPBurst, &s_EMPBurst[0]}
};

STATE s_EMPShrap[] =
{
    {EMP + 0, EMP_RATE, DoFastShrapJumpFall, &s_EMPShrap[1]},
    {EMP + 1, EMP_RATE, DoFastShrapJumpFall, &s_EMPShrap[2]},
    {EMP + 2, EMP_RATE, DoFastShrapJumpFall, &s_EMPShrap[0]},
};


#define TANK_SHELL 3201
#define TANK_SHELL_RATE 6
ANIMATOR DoTankShell;
STATE s_TankShell[] =
{
    {TRACER + 0, 200, DoTankShell, &s_TankShell[0]}
};

ANIMATOR DoVehicleSmoke, SpawnVehicleSmoke;
#define VEHICLE_SMOKE_RATE 18
STATE s_VehicleSmoke[] =
{
    {PUFF + 0, VEHICLE_SMOKE_RATE, DoVehicleSmoke, &s_VehicleSmoke[1]},
    {PUFF + 1, VEHICLE_SMOKE_RATE, DoVehicleSmoke, &s_VehicleSmoke[2]},
    {PUFF + 2, VEHICLE_SMOKE_RATE, DoVehicleSmoke, &s_VehicleSmoke[3]},
    {PUFF + 3, VEHICLE_SMOKE_RATE, DoVehicleSmoke, &s_VehicleSmoke[4]},
    {PUFF + 4, VEHICLE_SMOKE_RATE, DoVehicleSmoke, &s_VehicleSmoke[5]},
    {PUFF + 5, VEHICLE_SMOKE_RATE, DoVehicleSmoke, &s_VehicleSmoke[6]},
    {PUFF + 5, 100, DoSuicide, &s_VehicleSmoke[6]}
};

ANIMATOR DoWaterSmoke, SpawnWaterSmoke;
#define WATER_SMOKE_RATE 18
STATE s_WaterSmoke[] =
{
    {PUFF + 0, WATER_SMOKE_RATE, DoWaterSmoke, &s_WaterSmoke[1]},
    {PUFF + 1, WATER_SMOKE_RATE, DoWaterSmoke, &s_WaterSmoke[2]},
    {PUFF + 2, WATER_SMOKE_RATE, DoWaterSmoke, &s_WaterSmoke[3]},
    {PUFF + 3, WATER_SMOKE_RATE, DoWaterSmoke, &s_WaterSmoke[4]},
    {PUFF + 4, WATER_SMOKE_RATE, DoWaterSmoke, &s_WaterSmoke[5]},
    {PUFF + 5, WATER_SMOKE_RATE, DoWaterSmoke, &s_WaterSmoke[6]},
    {PUFF + 5, 100, DoSuicide, &s_WaterSmoke[6]}
};

#define UZI_SPARK_REPEAT 24
#define UZI_SMOKE_REPEAT 24 // Was 32
#define UZI_SMOKE_RATE 16 // Was 9
STATE s_UziSmoke[] =
{
    {UZI_SMOKE + 0, UZI_SMOKE_RATE, DoUziSmoke, &s_UziSmoke[1]},
    {UZI_SMOKE + 1, UZI_SMOKE_RATE, DoUziSmoke, &s_UziSmoke[2]},
    {UZI_SMOKE + 2, UZI_SMOKE_RATE, DoUziSmoke, &s_UziSmoke[3]},
    {UZI_SMOKE + 3, UZI_SMOKE_RATE, DoUziSmoke, &s_UziSmoke[4]},
    {UZI_SMOKE + 3, 100, DoSuicide, &s_UziSmoke[0]},
};

#define SHOTGUN_SMOKE_RATE 16
#define SHOTGUN_SMOKE_REPEAT 18 // Was 32
#define SHOTGUN_SMOKE UZI_SMOKE+1
ANIMATOR DoShotgunSmoke;
STATE s_ShotgunSmoke[] =
{
    {UZI_SMOKE + 0, SHOTGUN_SMOKE_RATE, DoShotgunSmoke, &s_ShotgunSmoke[1]},
    {UZI_SMOKE + 1, SHOTGUN_SMOKE_RATE, DoShotgunSmoke, &s_ShotgunSmoke[2]},
    {UZI_SMOKE + 2, SHOTGUN_SMOKE_RATE, DoShotgunSmoke, &s_ShotgunSmoke[3]},
    {UZI_SMOKE + 3, SHOTGUN_SMOKE_RATE, DoShotgunSmoke, &s_ShotgunSmoke[4]},
    {UZI_SMOKE + 3, 100, DoSuicide, &s_ShotgunSmoke[0]},
};

#define UZI_BULLET_RATE 100
#define UZI_BULLET 717 // actually a bubble
ANIMATOR DoUziBullet;

STATE s_UziBullet[] =
{
    {UZI_BULLET + 0, UZI_BULLET_RATE, DoUziBullet, &s_UziBullet[0]},
};

#define UZI_SPARK_RATE 8

STATE s_UziSpark[] =
{
    {UZI_SPARK + 0, UZI_SPARK_RATE, NullAnimator, &s_UziSpark[1]},
    {UZI_SPARK + 1, UZI_SPARK_RATE, NullAnimator, &s_UziSpark[2]},
    {UZI_SPARK + 2, UZI_SPARK_RATE, NullAnimator, &s_UziSpark[3]},
    {UZI_SPARK + 3, UZI_SPARK_RATE, NullAnimator, &s_UziSpark[4]},
    {UZI_SPARK + 4, UZI_SPARK_RATE, NullAnimator, &s_UziSpark[5]},
    {UZI_SPARK + 4, 100, DoSuicide, &s_UziSpark[0]},
};

STATE s_UziPowerSpark[] =
{
    {UZI_SPARK + 0, UZI_SPARK_RATE, DoUziSmoke, &s_UziSpark[1]},
    {UZI_SPARK + 1, UZI_SPARK_RATE, DoUziSmoke, &s_UziSpark[2]},
    {UZI_SPARK + 2, UZI_SPARK_RATE, DoUziSmoke, &s_UziSpark[3]},
    {UZI_SPARK + 3, UZI_SPARK_RATE, DoUziSmoke, &s_UziSpark[4]},
    {UZI_SPARK + 4, UZI_SPARK_RATE, DoUziSmoke, &s_UziSpark[5]},
    {UZI_SPARK + 4, 100, DoSuicide, &s_UziSpark[0]},
};

#define BUBBLE 716
#define BUBBLE_RATE 100
ANIMATOR DoBubble;

STATE s_Bubble[] =
{
    {BUBBLE + 0, BUBBLE_RATE, DoBubble, &s_Bubble[0]}
};


//#define SPLASH 2190
#define SPLASH 772
#define SPLASH_RATE 10

STATE s_Splash[] =
{
    {SPLASH + 0, SPLASH_RATE, NullAnimator, &s_Splash[1]},
    {SPLASH + 1, SPLASH_RATE, NullAnimator, &s_Splash[2]},
    {SPLASH + 2, SPLASH_RATE, NullAnimator, &s_Splash[3]},
    {SPLASH + 3, SPLASH_RATE, NullAnimator, &s_Splash[4]},
    {SPLASH + 4, SPLASH_RATE, NullAnimator, &s_Splash[5]},
    {SPLASH + 4, 100, DoSuicide, &s_Splash[0]}
};

#define CROSSBOLT 2230
#define CROSSBOLT_RATE 100
STATE s_CrossBolt[5][1] =
{
    {
        {CROSSBOLT + 0, CROSSBOLT_RATE, DoCrossBolt, &s_CrossBolt[0][0]},
    },
    {
        {CROSSBOLT + 2, CROSSBOLT_RATE, DoCrossBolt, &s_CrossBolt[1][0]},
    },
    {
        {CROSSBOLT + 3, CROSSBOLT_RATE, DoCrossBolt, &s_CrossBolt[2][0]},
    },
    {
        {CROSSBOLT + 4, CROSSBOLT_RATE, DoCrossBolt, &s_CrossBolt[3][0]},
    },
    {
        {CROSSBOLT + 1, CROSSBOLT_RATE, DoCrossBolt, &s_CrossBolt[4][0]},
    }
};

STATEp sg_CrossBolt[] =
{
    &s_CrossBolt[0][0],
    &s_CrossBolt[1][0],
    &s_CrossBolt[2][0],
    &s_CrossBolt[3][0],
    &s_CrossBolt[4][0]
};

#undef STAR
#define STAR 2102
#define STAR_RATE 6
STATE s_Star[] =
{
    {STAR + 0, STAR_RATE, DoStar, &s_Star[1]},
    {STAR + 1, STAR_RATE, DoStar, &s_Star[2]},
    {STAR + 2, STAR_RATE, DoStar, &s_Star[3]},
    {STAR + 3, STAR_RATE, DoStar, &s_Star[0]}
};

STATE s_StarStuck[] =
{
    {STAR + 0, STAR_RATE, NullAnimator, &s_StarStuck[0]},
};

#define STAR_DOWN 2066
STATE s_StarDown[] =
{
    {STAR_DOWN + 0, STAR_RATE, DoStar, &s_StarDown[1]},
    {STAR_DOWN + 1, STAR_RATE, DoStar, &s_StarDown[2]},
    {STAR_DOWN + 2, STAR_RATE, DoStar, &s_StarDown[3]},
    {STAR_DOWN + 3, STAR_RATE, DoStar, &s_StarDown[0]}
};

STATE s_StarDownStuck[] =
{
    {STAR + 0, STAR_RATE, NullAnimator, &s_StarDownStuck[0]},
};

//////////////////////
//
// LAVA BOSS
//
//////////////////////

#define LAVA_BOULDER_RATE 6
ANIMATOR DoLavaBoulder,DoShrapDamage,DoVulcanBoulder;

STATE s_LavaBoulder[] =
{
    {LAVA_BOULDER + 1, LAVA_BOULDER_RATE, DoLavaBoulder, &s_LavaBoulder[1]},
    {LAVA_BOULDER + 2, LAVA_BOULDER_RATE, DoLavaBoulder, &s_LavaBoulder[2]},
    {LAVA_BOULDER + 3, LAVA_BOULDER_RATE, DoLavaBoulder, &s_LavaBoulder[3]},
    {LAVA_BOULDER + 4, LAVA_BOULDER_RATE, DoLavaBoulder, &s_LavaBoulder[4]},
    {LAVA_BOULDER + 5, LAVA_BOULDER_RATE, DoLavaBoulder, &s_LavaBoulder[5]},
    {LAVA_BOULDER + 6, LAVA_BOULDER_RATE, DoLavaBoulder, &s_LavaBoulder[6]},
    {LAVA_BOULDER + 7, LAVA_BOULDER_RATE, DoLavaBoulder, &s_LavaBoulder[7]},
    {LAVA_BOULDER + 8, LAVA_BOULDER_RATE, DoLavaBoulder, &s_LavaBoulder[0]},
};

#define LAVA_SHARD (LAVA_BOULDER+1)

STATE s_LavaShard[] =
{
    {LAVA_BOULDER + 1, LAVA_BOULDER_RATE, DoShrapDamage, &s_LavaShard[1]},
    {LAVA_BOULDER + 2, LAVA_BOULDER_RATE, DoShrapDamage, &s_LavaShard[2]},
    {LAVA_BOULDER + 3, LAVA_BOULDER_RATE, DoShrapDamage, &s_LavaShard[3]},
    {LAVA_BOULDER + 4, LAVA_BOULDER_RATE, DoShrapDamage, &s_LavaShard[4]},
    {LAVA_BOULDER + 5, LAVA_BOULDER_RATE, DoShrapDamage, &s_LavaShard[5]},
    {LAVA_BOULDER + 6, LAVA_BOULDER_RATE, DoShrapDamage, &s_LavaShard[6]},
    {LAVA_BOULDER + 7, LAVA_BOULDER_RATE, DoShrapDamage, &s_LavaShard[7]},
    {LAVA_BOULDER + 8, LAVA_BOULDER_RATE, DoShrapDamage, &s_LavaShard[0]},
};

STATE s_VulcanBoulder[] =
{
    {LAVA_BOULDER + 1, LAVA_BOULDER_RATE, DoVulcanBoulder, &s_VulcanBoulder[1]},
    {LAVA_BOULDER + 2, LAVA_BOULDER_RATE, DoVulcanBoulder, &s_VulcanBoulder[2]},
    {LAVA_BOULDER + 3, LAVA_BOULDER_RATE, DoVulcanBoulder, &s_VulcanBoulder[3]},
    {LAVA_BOULDER + 4, LAVA_BOULDER_RATE, DoVulcanBoulder, &s_VulcanBoulder[4]},
    {LAVA_BOULDER + 5, LAVA_BOULDER_RATE, DoVulcanBoulder, &s_VulcanBoulder[5]},
    {LAVA_BOULDER + 6, LAVA_BOULDER_RATE, DoVulcanBoulder, &s_VulcanBoulder[6]},
    {LAVA_BOULDER + 7, LAVA_BOULDER_RATE, DoVulcanBoulder, &s_VulcanBoulder[7]},
    {LAVA_BOULDER + 8, LAVA_BOULDER_RATE, DoVulcanBoulder, &s_VulcanBoulder[0]},
};

//////////////////////
//
// GRENADE
//
//////////////////////

#if 0
ANIMATOR DoGrenade;
#undef GRENADE
#define GRENADE 5000
#define GRENADE_RATE 8

STATE s_Grenade[] =
{
    {FIREBALL + 0, GRENADE_RATE, DoGrenade, &s_Grenade[1]},
    {FIREBALL + 1, GRENADE_RATE, DoGrenade, &s_Grenade[2]},
    {FIREBALL + 2, GRENADE_RATE, DoGrenade, &s_Grenade[3]},
    {FIREBALL + 3, GRENADE_RATE, DoGrenade, &s_Grenade[0]}
};
#else
#define GRENADE_FRAMES 1
#define GRENADE_R0 2110
#define GRENADE_R1 GRENADE_R0 + (GRENADE_FRAMES * 1)
#define GRENADE_R2 GRENADE_R0 + (GRENADE_FRAMES * 2)
#define GRENADE_R3 GRENADE_R0 + (GRENADE_FRAMES * 3)
#define GRENADE_R4 GRENADE_R0 + (GRENADE_FRAMES * 4)

#undef GRENADE
#define GRENADE GRENADE_R0
#define GRENADE_RATE 8
ANIMATOR DoGrenade;

STATE s_Grenade[5][1] =
{
    {
        {GRENADE_R0 + 0, GRENADE_RATE, DoGrenade, &s_Grenade[0][0]},
    },
    {
        {GRENADE_R1 + 0, GRENADE_RATE, DoGrenade, &s_Grenade[1][0]},
    },
    {
        {GRENADE_R2 + 0, GRENADE_RATE, DoGrenade, &s_Grenade[2][0]},
    },
    {
        {GRENADE_R3 + 0, GRENADE_RATE, DoGrenade, &s_Grenade[3][0]},
    },
    {
        {GRENADE_R4 + 0, GRENADE_RATE, DoGrenade, &s_Grenade[4][0]},
    }
};


STATEp sg_Grenade[] =
{
    &s_Grenade[0][0],
    &s_Grenade[1][0],
    &s_Grenade[2][0],
    &s_Grenade[3][0],
    &s_Grenade[4][0]
};
#endif

//////////////////////
//
// MINE
//
//////////////////////

ANIMATOR DoMine,DoMineStuck;
#undef MINE
#define MINE 2223
#define MINE_SHRAP 5011
#define MINE_RATE 16

STATE s_MineStuck[] =
{
    {MINE + 0, MINE_RATE, DoMineStuck, &s_MineStuck[0]},
};

STATE s_Mine[] =
{
    {MINE + 0, MINE_RATE, DoMine, &s_Mine[1]},
    {MINE + 1, MINE_RATE, DoMine, &s_Mine[0]},
};

ANIMATOR DoMineSpark;
STATE s_MineSpark[] =
{
    {UZI_SPARK + 0, UZI_SPARK_RATE, DoMineSpark, &s_MineSpark[1]},
    {UZI_SPARK + 1, UZI_SPARK_RATE, DoMineSpark, &s_MineSpark[2]},
    {UZI_SPARK + 2, UZI_SPARK_RATE, DoMineSpark, &s_MineSpark[3]},
    {UZI_SPARK + 3, UZI_SPARK_RATE, DoMineSpark, &s_MineSpark[4]},
    {UZI_SPARK + 4, UZI_SPARK_RATE, DoMineSpark, &s_MineSpark[5]},
    {UZI_SPARK + 4, 100, DoSuicide, &s_MineSpark[0]},
};

//////////////////////
//
// METEOR
//
//////////////////////

#define METEOR_R0 2098
#define METEOR_R1 2090
#define METEOR_R2 2094
#define METEOR_R3 2090
#define METEOR_R4 2098


#define METEOR STAR
#define METEOR_RATE 8
ANIMATOR DoMeteor;

STATE s_Meteor[5][4] =
{
    {
        {METEOR_R0 + 0, METEOR_RATE, DoMeteor, &s_Meteor[0][1]},
        {METEOR_R0 + 1, METEOR_RATE, DoMeteor, &s_Meteor[0][2]},
        {METEOR_R0 + 2, METEOR_RATE, DoMeteor, &s_Meteor[0][3]},
        {METEOR_R0 + 3, METEOR_RATE, DoMeteor, &s_Meteor[0][0]},
    },
    {
        {METEOR_R1 + 0, METEOR_RATE, DoMeteor, &s_Meteor[1][1]},
        {METEOR_R1 + 1, METEOR_RATE, DoMeteor, &s_Meteor[1][2]},
        {METEOR_R1 + 2, METEOR_RATE, DoMeteor, &s_Meteor[1][3]},
        {METEOR_R1 + 3, METEOR_RATE, DoMeteor, &s_Meteor[1][0]},
    },
    {
        {METEOR_R2 + 0, METEOR_RATE, DoMeteor, &s_Meteor[2][1]},
        {METEOR_R2 + 1, METEOR_RATE, DoMeteor, &s_Meteor[2][2]},
        {METEOR_R2 + 2, METEOR_RATE, DoMeteor, &s_Meteor[2][3]},
        {METEOR_R2 + 3, METEOR_RATE, DoMeteor, &s_Meteor[2][0]},
    },
    {
        {METEOR_R3 + 0, METEOR_RATE, DoMeteor, &s_Meteor[3][1]},
        {METEOR_R3 + 1, METEOR_RATE, DoMeteor, &s_Meteor[3][2]},
        {METEOR_R3 + 2, METEOR_RATE, DoMeteor, &s_Meteor[3][3]},
        {METEOR_R3 + 3, METEOR_RATE, DoMeteor, &s_Meteor[3][0]},
    },
    {
        {METEOR_R4 + 0, METEOR_RATE, DoMeteor, &s_Meteor[4][1]},
        {METEOR_R4 + 1, METEOR_RATE, DoMeteor, &s_Meteor[4][2]},
        {METEOR_R4 + 2, METEOR_RATE, DoMeteor, &s_Meteor[4][3]},
        {METEOR_R4 + 3, METEOR_RATE, DoMeteor, &s_Meteor[4][0]},
    }
};


STATEp sg_Meteor[] =
{
    &s_Meteor[0][0],
    &s_Meteor[1][0],
    &s_Meteor[2][0],
    &s_Meteor[3][0],
    &s_Meteor[4][0]
};

#define METEOR_EXP 2115
#define METEOR_EXP_RATE 7

STATE s_MeteorExp[] =
{
    {METEOR_EXP + 0, METEOR_EXP_RATE, NullAnimator, &s_MeteorExp[1]},
    {METEOR_EXP + 1, METEOR_EXP_RATE, NullAnimator, &s_MeteorExp[2]},
    {METEOR_EXP + 2, METEOR_EXP_RATE, NullAnimator, &s_MeteorExp[3]},
    {METEOR_EXP + 3, METEOR_EXP_RATE, NullAnimator, &s_MeteorExp[4]},
    {METEOR_EXP + 4, METEOR_EXP_RATE, NullAnimator, &s_MeteorExp[5]},
    {METEOR_EXP + 5, METEOR_EXP_RATE, NullAnimator, &s_MeteorExp[6]},
    {METEOR_EXP + 5, METEOR_EXP_RATE, DoSuicide, &s_MeteorExp[6]}
};

#define MIRV_METEOR METEOR_R0
ANIMATOR DoMirvMissile;
STATE s_MirvMeteor[5][4] =
{
    {
        {METEOR_R0 + 0, METEOR_RATE, DoMirvMissile, &s_MirvMeteor[0][1]},
        {METEOR_R0 + 1, METEOR_RATE, DoMirvMissile, &s_MirvMeteor[0][2]},
        {METEOR_R0 + 2, METEOR_RATE, DoMirvMissile, &s_MirvMeteor[0][3]},
        {METEOR_R0 + 3, METEOR_RATE, DoMirvMissile, &s_MirvMeteor[0][0]},
    },
    {
        {METEOR_R1 + 0, METEOR_RATE, DoMirvMissile, &s_MirvMeteor[1][1]},
        {METEOR_R1 + 1, METEOR_RATE, DoMirvMissile, &s_MirvMeteor[1][2]},
        {METEOR_R1 + 2, METEOR_RATE, DoMirvMissile, &s_MirvMeteor[1][3]},
        {METEOR_R1 + 3, METEOR_RATE, DoMirvMissile, &s_MirvMeteor[1][0]},
    },
    {
        {METEOR_R2 + 0, METEOR_RATE, DoMirvMissile, &s_MirvMeteor[2][1]},
        {METEOR_R2 + 1, METEOR_RATE, DoMirvMissile, &s_MirvMeteor[2][2]},
        {METEOR_R2 + 2, METEOR_RATE, DoMirvMissile, &s_MirvMeteor[2][3]},
        {METEOR_R2 + 3, METEOR_RATE, DoMirvMissile, &s_MirvMeteor[2][0]},
    },
    {
        {METEOR_R3 + 0, METEOR_RATE, DoMirvMissile, &s_MirvMeteor[3][1]},
        {METEOR_R3 + 1, METEOR_RATE, DoMirvMissile, &s_MirvMeteor[3][2]},
        {METEOR_R3 + 2, METEOR_RATE, DoMirvMissile, &s_MirvMeteor[3][3]},
        {METEOR_R3 + 3, METEOR_RATE, DoMirvMissile, &s_MirvMeteor[3][0]},
    },
    {
        {METEOR_R4 + 0, METEOR_RATE, DoMirvMissile, &s_MirvMeteor[4][1]},
        {METEOR_R4 + 1, METEOR_RATE, DoMirvMissile, &s_MirvMeteor[4][2]},
        {METEOR_R4 + 2, METEOR_RATE, DoMirvMissile, &s_MirvMeteor[4][3]},
        {METEOR_R4 + 3, METEOR_RATE, DoMirvMissile, &s_MirvMeteor[4][0]},
    }
};


STATEp sg_MirvMeteor[] =
{
    &s_MirvMeteor[0][0],
    &s_MirvMeteor[1][0],
    &s_MirvMeteor[2][0],
    &s_MirvMeteor[3][0],
    &s_MirvMeteor[4][0]
};

STATE s_MirvMeteorExp[] =
{
    {METEOR_EXP + 0, METEOR_EXP_RATE, NullAnimator, &s_MirvMeteorExp[1]},
    {METEOR_EXP + 1, METEOR_EXP_RATE, NullAnimator, &s_MirvMeteorExp[2]},
    {METEOR_EXP + 2, METEOR_EXP_RATE, NullAnimator, &s_MirvMeteorExp[3]},
    {METEOR_EXP + 3, METEOR_EXP_RATE, NullAnimator, &s_MirvMeteorExp[4]},
    {METEOR_EXP + 4, METEOR_EXP_RATE, NullAnimator, &s_MirvMeteorExp[5]},
    {METEOR_EXP + 5, METEOR_EXP_RATE, NullAnimator, &s_MirvMeteorExp[6]},
    {METEOR_EXP + 5, METEOR_EXP_RATE, DoSuicide, &s_MirvMeteorExp[6]}
};

#define SERP_METEOR METEOR_R0+1
ANIMATOR DoSerpMeteor;
STATE s_SerpMeteor[5][4] =
{
    {
        {2031 + 0, METEOR_RATE, DoSerpMeteor, &s_SerpMeteor[0][1]},
        {2031 + 1, METEOR_RATE, DoSerpMeteor, &s_SerpMeteor[0][2]},
        {2031 + 2, METEOR_RATE, DoSerpMeteor, &s_SerpMeteor[0][3]},
        {2031 + 3, METEOR_RATE, DoSerpMeteor, &s_SerpMeteor[0][0]},
    },
    {
        {2031 + 0, METEOR_RATE, DoSerpMeteor, &s_SerpMeteor[1][1]},
        {2031 + 1, METEOR_RATE, DoSerpMeteor, &s_SerpMeteor[1][2]},
        {2031 + 2, METEOR_RATE, DoSerpMeteor, &s_SerpMeteor[1][3]},
        {2031 + 3, METEOR_RATE, DoSerpMeteor, &s_SerpMeteor[1][0]},
    },
    {
        {2031 + 0, METEOR_RATE, DoSerpMeteor, &s_SerpMeteor[2][1]},
        {2031 + 1, METEOR_RATE, DoSerpMeteor, &s_SerpMeteor[2][2]},
        {2031 + 2, METEOR_RATE, DoSerpMeteor, &s_SerpMeteor[2][3]},
        {2031 + 3, METEOR_RATE, DoSerpMeteor, &s_SerpMeteor[2][0]},
    },
    {
        {2031 + 0, METEOR_RATE, DoSerpMeteor, &s_SerpMeteor[3][1]},
        {2031 + 1, METEOR_RATE, DoSerpMeteor, &s_SerpMeteor[3][2]},
        {2031 + 2, METEOR_RATE, DoSerpMeteor, &s_SerpMeteor[3][3]},
        {2031 + 3, METEOR_RATE, DoSerpMeteor, &s_SerpMeteor[3][0]},
    },
    {
        {2031 + 0, METEOR_RATE, DoSerpMeteor, &s_SerpMeteor[4][1]},
        {2031 + 1, METEOR_RATE, DoSerpMeteor, &s_SerpMeteor[4][2]},
        {2031 + 2, METEOR_RATE, DoSerpMeteor, &s_SerpMeteor[4][3]},
        {2031 + 3, METEOR_RATE, DoSerpMeteor, &s_SerpMeteor[4][0]},
    }
};


STATEp sg_SerpMeteor[] =
{
    &s_SerpMeteor[0][0],
    &s_SerpMeteor[1][0],
    &s_SerpMeteor[2][0],
    &s_SerpMeteor[3][0],
    &s_SerpMeteor[4][0]
};


STATE s_SerpMeteorExp[] =
{
    {METEOR_EXP + 0, METEOR_EXP_RATE, NullAnimator, &s_SerpMeteorExp[1]},
    {METEOR_EXP + 1, METEOR_EXP_RATE, NullAnimator, &s_SerpMeteorExp[2]},
    {METEOR_EXP + 2, METEOR_EXP_RATE, NullAnimator, &s_SerpMeteorExp[3]},
    {METEOR_EXP + 3, METEOR_EXP_RATE, NullAnimator, &s_SerpMeteorExp[4]},
    {METEOR_EXP + 4, METEOR_EXP_RATE, NullAnimator, &s_SerpMeteorExp[5]},
    {METEOR_EXP + 5, METEOR_EXP_RATE, NullAnimator, &s_SerpMeteorExp[6]},
    {METEOR_EXP + 5, METEOR_EXP_RATE, DoSuicide, &s_SerpMeteorExp[6]}
};

//////////////////////
//
// SPEAR
//
//////////////////////

#define SPEAR_RATE 8
ANIMATOR DoSpear;

STATE s_Spear[5][1] =
{
    {
        {SPEAR_R0 + 0, SPEAR_RATE, DoSpear, s_Spear[0]},
    },
    {
        {SPEAR_R1 + 0, SPEAR_RATE, DoSpear, s_Spear[1]},
    },
    {
        {SPEAR_R2 + 0, SPEAR_RATE, DoSpear, s_Spear[2]},
    },
    {
        {SPEAR_R3 + 0, SPEAR_RATE, DoSpear, s_Spear[3]},
    },
    {
        {SPEAR_R4 + 0, SPEAR_RATE, DoSpear, s_Spear[4]},
    }
};

STATEp sg_Spear[] =
{
    s_Spear[0],
    s_Spear[1],
    s_Spear[2],
    s_Spear[3],
    s_Spear[4]
};

//////////////////////
//
// ROCKET
//
//////////////////////

#define ROCKET_FRAMES 1
#define ROCKET_R0 2206
#define ROCKET_R1 ROCKET_R0 + (ROCKET_FRAMES * 2)
#define ROCKET_R2 ROCKET_R0 + (ROCKET_FRAMES * 3)
#define ROCKET_R3 ROCKET_R0 + (ROCKET_FRAMES * 4)
#define ROCKET_R4 ROCKET_R0 + (ROCKET_FRAMES * 1)

ANIMATOR DoRocket;
#define ROCKET_RATE 8

STATE s_Rocket[5][1] =
{
    {
        {ROCKET_R0 + 0, ROCKET_RATE, DoRocket, &s_Rocket[0][0]},
    },
    {
        {ROCKET_R1 + 0, ROCKET_RATE, DoRocket, &s_Rocket[1][0]},
    },
    {
        {ROCKET_R2 + 0, ROCKET_RATE, DoRocket, &s_Rocket[2][0]},
    },
    {
        {ROCKET_R3 + 0, ROCKET_RATE, DoRocket, &s_Rocket[3][0]},
    },
    {
        {ROCKET_R4 + 0, ROCKET_RATE, DoRocket, &s_Rocket[4][0]},
    }
};

STATEp sg_Rocket[] =
{
    &s_Rocket[0][0],
    &s_Rocket[1][0],
    &s_Rocket[2][0],
    &s_Rocket[3][0],
    &s_Rocket[4][0]
};

//////////////////////
//
// BUNNY ROCKET
//
//////////////////////

#define BUNNYROCKET_FRAMES 5
#define BUNNYROCKET_R0 4550
#define BUNNYROCKET_R1 BUNNYROCKET_R0 + (BUNNYROCKET_FRAMES * 1)
#define BUNNYROCKET_R2 BUNNYROCKET_R0 + (BUNNYROCKET_FRAMES * 2)
#define BUNNYROCKET_R3 BUNNYROCKET_R0 + (BUNNYROCKET_FRAMES * 3)
#define BUNNYROCKET_R4 BUNNYROCKET_R0 + (BUNNYROCKET_FRAMES * 4)

ANIMATOR DoRocket;
#define BUNNYROCKET_RATE 8

STATE s_BunnyRocket[5][1] =
{
    {
        {BUNNYROCKET_R0 + 2, BUNNYROCKET_RATE, DoRocket, &s_BunnyRocket[0][0]},
    },
    {
        {BUNNYROCKET_R1 + 2, BUNNYROCKET_RATE, DoRocket, &s_BunnyRocket[1][0]},
    },
    {
        {BUNNYROCKET_R2 + 2, BUNNYROCKET_RATE, DoRocket, &s_BunnyRocket[2][0]},
    },
    {
        {BUNNYROCKET_R3 + 2, BUNNYROCKET_RATE, DoRocket, &s_BunnyRocket[3][0]},
    },
    {
        {BUNNYROCKET_R4 + 2, BUNNYROCKET_RATE, DoRocket, &s_BunnyRocket[4][0]},
    }
};

STATEp sg_BunnyRocket[] =
{
    &s_BunnyRocket[0][0],
    &s_BunnyRocket[1][0],
    &s_BunnyRocket[2][0],
    &s_BunnyRocket[3][0],
    &s_BunnyRocket[4][0]
};

ANIMATOR DoRail;
#define RAIL_RATE 8

STATE s_Rail[5][1] =
{
    {
        {ROCKET_R0 + 0, RAIL_RATE, DoRail, &s_Rail[0][0]},
    },
    {
        {ROCKET_R1 + 0, RAIL_RATE, DoRail, &s_Rail[1][0]},
    },
    {
        {ROCKET_R2 + 0, RAIL_RATE, DoRail, &s_Rail[2][0]},
    },
    {
        {ROCKET_R3 + 0, RAIL_RATE, DoRail, &s_Rail[3][0]},
    },
    {
        {ROCKET_R4 + 0, RAIL_RATE, DoRail, &s_Rail[4][0]},
    }
};

STATEp sg_Rail[] =
{
    &s_Rail[0][0],
    &s_Rail[1][0],
    &s_Rail[2][0],
    &s_Rail[3][0],
    &s_Rail[4][0]
};

ANIMATOR DoLaser;
#define LASER_RATE 8

STATE s_Laser[] =
{
    {ROCKET_R0 + 0, LASER_RATE, DoLaser, &s_Laser[0]}
};

//////////////////////
//
// MICRO
//
//////////////////////

#define MICRO_FRAMES 1
#define MICRO_R0 2206
#define MICRO_R1 MICRO_R0 + (MICRO_FRAMES * 2)
#define MICRO_R2 MICRO_R0 + (MICRO_FRAMES * 3)
#define MICRO_R3 MICRO_R0 + (MICRO_FRAMES * 4)
#define MICRO_R4 MICRO_R0 + (MICRO_FRAMES * 1)

ANIMATOR DoMicro;
#define MICRO_RATE 8

#if 0
#define PUFF 1748
#define PUFF_RATE 8
ANIMATOR DoMicroPuffSuicide;
STATE s_MicroPuff[] =
{
    {PUFF + 0, PUFF_RATE, DoPuff, &s_MicroPuff[1]},
    {PUFF + 1, PUFF_RATE, DoPuff, &s_MicroPuff[2]},
    {PUFF + 2, PUFF_RATE, DoPuff, &s_MicroPuff[3]},
    {PUFF + 3, PUFF_RATE, DoPuff, &s_MicroPuff[4]},
    {PUFF + 4, PUFF_RATE, DoPuff, &s_MicroPuff[5]},
    {PUFF + 5, PUFF_RATE, DoPuff, &s_MicroPuff[6]},
    {PUFF + 5, 100, DoMicroPuffSuicide, &s_MicroPuff[6]}
};
#endif

STATE s_Micro[5][1] =
{
    {
        {MICRO_R0 + 0, MICRO_RATE, DoMicro, &s_Micro[0][0]},
    },
    {
        {MICRO_R1 + 0, MICRO_RATE, DoMicro, &s_Micro[1][0]},
    },
    {
        {MICRO_R2 + 0, MICRO_RATE, DoMicro, &s_Micro[2][0]},
    },
    {
        {MICRO_R3 + 0, MICRO_RATE, DoMicro, &s_Micro[3][0]},
    },
    {
        {MICRO_R4 + 0, MICRO_RATE, DoMicro, &s_Micro[4][0]},
    }
};

STATEp sg_Micro[] =
{
    &s_Micro[0][0],
    &s_Micro[1][0],
    &s_Micro[2][0],
    &s_Micro[3][0],
    &s_Micro[4][0]
};

ANIMATOR DoMicroMini;
STATE s_MicroMini[5][1] =
{
    {
        {MICRO_R0 + 0, MICRO_RATE, DoMicroMini, &s_MicroMini[0][0]},
    },
    {
        {MICRO_R1 + 0, MICRO_RATE, DoMicroMini, &s_MicroMini[1][0]},
    },
    {
        {MICRO_R2 + 0, MICRO_RATE, DoMicroMini, &s_MicroMini[2][0]},
    },
    {
        {MICRO_R3 + 0, MICRO_RATE, DoMicroMini, &s_MicroMini[3][0]},
    },
    {
        {MICRO_R4 + 0, MICRO_RATE, DoMicroMini, &s_MicroMini[4][0]},
    }
};

STATEp sg_MicroMini[] =
{
    &s_MicroMini[0][0],
    &s_MicroMini[1][0],
    &s_MicroMini[2][0],
    &s_MicroMini[3][0],
    &s_MicroMini[4][0]
};

//////////////////////
//
// BOLT THINMAN
//
//////////////////////

#define BOLT_THINMAN_RATE 8
ANIMATOR DoBoltThinMan;

STATE s_BoltThinMan[5][1] =
{
    {
        {BOLT_THINMAN_R0 + 0, BOLT_THINMAN_RATE, DoBoltThinMan, &s_BoltThinMan[0][0]},
    },
    {
        {BOLT_THINMAN_R1 + 0, BOLT_THINMAN_RATE, DoBoltThinMan, &s_BoltThinMan[1][0]},
    },
    {
        {BOLT_THINMAN_R2 + 0, BOLT_THINMAN_RATE, DoBoltThinMan, &s_BoltThinMan[2][0]},
    },
    {
        {BOLT_THINMAN_R3 + 0, BOLT_THINMAN_RATE, DoBoltThinMan, &s_BoltThinMan[3][0]},
    },
    {
        {BOLT_THINMAN_R4 + 0, BOLT_THINMAN_RATE, DoBoltThinMan, &s_BoltThinMan[4][0]},
    }
};

STATEp sg_BoltThinMan[] =
{
    &s_BoltThinMan[0][0],
    &s_BoltThinMan[1][0],
    &s_BoltThinMan[2][0],
    &s_BoltThinMan[3][0],
    &s_BoltThinMan[4][0]
};

#define BOLT_SEEKER_RATE 8
ANIMATOR DoBoltSeeker;

STATE s_BoltSeeker[5][1] =
{
    {
        {BOLT_THINMAN_R0 + 0, BOLT_SEEKER_RATE, DoBoltSeeker, &s_BoltSeeker[0][0]},
    },
    {
        {BOLT_THINMAN_R1 + 0, BOLT_SEEKER_RATE, DoBoltSeeker, &s_BoltSeeker[1][0]},
    },
    {
        {BOLT_THINMAN_R2 + 0, BOLT_SEEKER_RATE, DoBoltSeeker, &s_BoltSeeker[2][0]},
    },
    {
        {BOLT_THINMAN_R3 + 0, BOLT_SEEKER_RATE, DoBoltSeeker, &s_BoltSeeker[3][0]},
    },
    {
        {BOLT_THINMAN_R4 + 0, BOLT_SEEKER_RATE, DoBoltSeeker, &s_BoltSeeker[4][0]},
    }
};

STATEp sg_BoltSeeker[] =
{
    &s_BoltSeeker[0][0],
    &s_BoltSeeker[1][0],
    &s_BoltSeeker[2][0],
    &s_BoltSeeker[3][0],
    &s_BoltSeeker[4][0]
};


#define BOLT_FATMAN STAR
#define BOLT_FATMAN_RATE 8
ANIMATOR DoBoltFatMan;

STATE s_BoltFatMan[] =
{
    {BOLT_FATMAN + 0, BOLT_FATMAN_RATE, DoBoltFatMan, &s_BoltFatMan[1]},
    {BOLT_FATMAN + 1, BOLT_FATMAN_RATE, DoBoltFatMan, &s_BoltFatMan[2]},
    {BOLT_FATMAN + 2, BOLT_FATMAN_RATE, DoBoltFatMan, &s_BoltFatMan[3]},
    {BOLT_FATMAN + 3, BOLT_FATMAN_RATE, DoBoltFatMan, &s_BoltFatMan[0]}
};


#define BOLT_SHRAPNEL STAR
#define BOLT_SHRAPNEL_RATE 8
ANIMATOR DoBoltShrapnel;

STATE s_BoltShrapnel[] =
{
    {BOLT_SHRAPNEL + 0, BOLT_SHRAPNEL_RATE, DoBoltShrapnel, &s_BoltShrapnel[1]},
    {BOLT_SHRAPNEL + 1, BOLT_SHRAPNEL_RATE, DoBoltShrapnel, &s_BoltShrapnel[2]},
    {BOLT_SHRAPNEL + 2, BOLT_SHRAPNEL_RATE, DoBoltShrapnel, &s_BoltShrapnel[3]},
    {BOLT_SHRAPNEL + 3, BOLT_SHRAPNEL_RATE, DoBoltShrapnel, &s_BoltShrapnel[0]}
};

#define COOLG_FIRE 2430
//#define COOLG_FIRE 1465
#define COOLG_FIRE_RATE 8
ANIMATOR DoCoolgFire;

STATE s_CoolgFire[] =
{
    {2031 + 0, COOLG_FIRE_RATE, DoCoolgFire, &s_CoolgFire[1]},
    {2031 + 1, COOLG_FIRE_RATE, DoCoolgFire, &s_CoolgFire[2]},
    {2031 + 2, COOLG_FIRE_RATE, DoCoolgFire, &s_CoolgFire[3]},
    {2031 + 3, COOLG_FIRE_RATE, DoCoolgFire, &s_CoolgFire[0]}
};

#define COOLG_FIRE_DONE 2410
//#define COOLG_FIRE_DONE 1466
//#define COOLG_FIRE_DONE_RATE 8
#define COOLG_FIRE_DONE_RATE 3

STATE s_CoolgFireDone[] =
{
    {COOLG_FIRE_DONE + 0, COOLG_FIRE_DONE_RATE, NullAnimator, &s_CoolgFireDone[1]},
    {COOLG_FIRE_DONE + 1, COOLG_FIRE_DONE_RATE, NullAnimator, &s_CoolgFireDone[2]},
    {COOLG_FIRE_DONE + 2, COOLG_FIRE_DONE_RATE, NullAnimator, &s_CoolgFireDone[3]},
    {COOLG_FIRE_DONE + 3, COOLG_FIRE_DONE_RATE, NullAnimator, &s_CoolgFireDone[4]},
    {COOLG_FIRE_DONE + 4, COOLG_FIRE_DONE_RATE, NullAnimator, &s_CoolgFireDone[5]},
    {COOLG_FIRE_DONE + 4, COOLG_FIRE_DONE_RATE, DoSuicide, &s_CoolgFireDone[5]}
};

ANIMATOR DoCoolgDrip;
#define COOLG_DRIP 1720
STATE s_CoolgDrip[] =
{
    {COOLG_DRIP + 0, 100, DoCoolgDrip, &s_CoolgDrip[0]}
};

#define GORE_FLOOR_SPLASH_RATE 8
#define GORE_FLOOR_SPLASH 1710
STATE s_GoreFloorSplash[] =
{
    {GORE_FLOOR_SPLASH + 0, GORE_FLOOR_SPLASH_RATE, NullAnimator, &s_GoreFloorSplash[1]},
    {GORE_FLOOR_SPLASH + 1, GORE_FLOOR_SPLASH_RATE, NullAnimator, &s_GoreFloorSplash[2]},
    {GORE_FLOOR_SPLASH + 2, GORE_FLOOR_SPLASH_RATE, NullAnimator, &s_GoreFloorSplash[3]},
    {GORE_FLOOR_SPLASH + 3, GORE_FLOOR_SPLASH_RATE, NullAnimator, &s_GoreFloorSplash[4]},
    {GORE_FLOOR_SPLASH + 4, GORE_FLOOR_SPLASH_RATE, NullAnimator, &s_GoreFloorSplash[5]},
    {GORE_FLOOR_SPLASH + 5, GORE_FLOOR_SPLASH_RATE, NullAnimator, &s_GoreFloorSplash[6]},
    {GORE_FLOOR_SPLASH + 5, GORE_FLOOR_SPLASH_RATE, DoSuicide, &s_GoreFloorSplash[6]}
};

#define GORE_SPLASH_RATE 8
#define GORE_SPLASH 2410
STATE s_GoreSplash[] =
{
    {GORE_SPLASH + 0, GORE_SPLASH_RATE, NullAnimator, &s_GoreSplash[1]},
    {GORE_SPLASH + 1, GORE_SPLASH_RATE, NullAnimator, &s_GoreSplash[2]},
    {GORE_SPLASH + 2, GORE_SPLASH_RATE, NullAnimator, &s_GoreSplash[3]},
    {GORE_SPLASH + 3, GORE_SPLASH_RATE, NullAnimator, &s_GoreSplash[4]},
    {GORE_SPLASH + 4, GORE_SPLASH_RATE, NullAnimator, &s_GoreSplash[5]},
    {GORE_SPLASH + 5, GORE_SPLASH_RATE, NullAnimator, &s_GoreSplash[6]},
    {GORE_SPLASH + 5, GORE_SPLASH_RATE, DoSuicide, &s_GoreSplash[6]}
};

//////////////////////////////////////////////
//
//  HEART ATTACK & PLASMA
//
//////////////////////////////////////////////

#define PLASMA 1562 //2058
#define PLASMA_FOUNTAIN 2058+1
#define PLASMA_RATE 8
#define PLASMA_FOUNTAIN_TIME (3*120);

ANIMATOR DoPlasma;

// regular bolt from heart
STATE s_Plasma[] =
{
    {PLASMA + 0, PLASMA_RATE, DoPlasma, &s_Plasma[1]},
    {PLASMA + 1, PLASMA_RATE, DoPlasma, &s_Plasma[2]},
    {PLASMA + 2, PLASMA_RATE, DoPlasma, &s_Plasma[0]}
};

ANIMATOR DoPlasmaFountain;

// follows actor spewing blood
#define PLASMA_Drip 1562 //2420
STATE s_PlasmaFountain[] =
{
    {PLASMA_Drip + 0, PLASMA_RATE, DoPlasmaFountain, &s_PlasmaFountain[1]},
    {PLASMA_Drip + 1, PLASMA_RATE, DoPlasmaFountain, &s_PlasmaFountain[2]},
    {PLASMA_Drip + 2, PLASMA_RATE, DoPlasmaFountain, &s_PlasmaFountain[3]},
    {PLASMA_Drip + 3, PLASMA_RATE, DoPlasmaFountain, &s_PlasmaFountain[0]},
};

#define PLASMA_Drip_RATE 12
STATE s_PlasmaDrip[] =
{
    {PLASMA_Drip + 0, PLASMA_Drip_RATE, DoShrapJumpFall, &s_PlasmaDrip[1]},
    {PLASMA_Drip + 1, PLASMA_Drip_RATE, DoShrapJumpFall, &s_PlasmaDrip[2]},
    {PLASMA_Drip + 2, PLASMA_Drip_RATE, DoShrapJumpFall, &s_PlasmaDrip[3]},
    {PLASMA_Drip + 3, PLASMA_Drip_RATE, DoShrapJumpFall, &s_PlasmaDrip[4]},
    {PLASMA_Drip + 4, PLASMA_Drip_RATE, DoShrapJumpFall, &s_PlasmaDrip[5]},
    {PLASMA_Drip + 5, PLASMA_Drip_RATE, DoShrapJumpFall, &s_PlasmaDrip[6]},
    {PLASMA_Drip + 7, PLASMA_Drip_RATE, DoSuicide, &s_PlasmaDrip[6]}
};

#define PLASMA_DONE 2061
#define PLASMA_DONE_RATE 15

ANIMATOR DoPlasmaDone;

STATE s_PlasmaDone[] =
{
    {PLASMA + 0, PLASMA_DONE_RATE, DoPlasmaDone, &s_PlasmaDone[1]},
    {PLASMA + 2, PLASMA_DONE_RATE, DoPlasmaDone, &s_PlasmaDone[2]},
    {PLASMA + 1, PLASMA_DONE_RATE, DoPlasmaDone, &s_PlasmaDone[0]}
};

#define TELEPORT_EFFECT 3240
#define TELEPORT_EFFECT_RATE 6
ANIMATOR DoTeleportEffect;
STATE s_TeleportEffect[] =
{
    {TELEPORT_EFFECT + 0, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect[1]},
    {TELEPORT_EFFECT + 1, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect[2]},
    {TELEPORT_EFFECT + 2, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect[3]},
    {TELEPORT_EFFECT + 3, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect[4]},
    {TELEPORT_EFFECT + 4, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect[5]},
    {TELEPORT_EFFECT + 5, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect[6]},
    {TELEPORT_EFFECT + 6, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect[7]},
    {TELEPORT_EFFECT + 7, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect[8]},
    {TELEPORT_EFFECT + 8, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect[9]},
    {TELEPORT_EFFECT + 9, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect[10]},
    {TELEPORT_EFFECT + 10, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect[11]},
    {TELEPORT_EFFECT + 11, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect[12]},
    {TELEPORT_EFFECT + 12, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect[13]},
    {TELEPORT_EFFECT + 13, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect[14]},
    {TELEPORT_EFFECT + 14, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect[15]},
    {TELEPORT_EFFECT + 15, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect[16]},
    {TELEPORT_EFFECT + 16, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect[17]},
    {TELEPORT_EFFECT + 17, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect[18]},
    {TELEPORT_EFFECT + 17, TELEPORT_EFFECT_RATE, DoSuicide, &s_TeleportEffect[18]},
};

// Spawn a RIPPER teleport effect
ANIMATOR DoTeleRipper;
STATE s_TeleportEffect2[] =
{
    {TELEPORT_EFFECT + 0, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect2[1]},
    {TELEPORT_EFFECT + 1, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect2[2]},
    {TELEPORT_EFFECT + 2, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect2[3]},
    {TELEPORT_EFFECT + 3, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect2[4]},
    {TELEPORT_EFFECT + 4, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect2[5]},
    {TELEPORT_EFFECT + 5, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect2[6]},
    {TELEPORT_EFFECT + 6, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect2[7]},
    {TELEPORT_EFFECT + 7, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect2[8]},
    {TELEPORT_EFFECT + 8, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect2[9]},
    {TELEPORT_EFFECT + 9, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect2[10]},
    {TELEPORT_EFFECT + 10, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect2[11]},
    {TELEPORT_EFFECT + 11, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect2[12]},
    {TELEPORT_EFFECT + 12, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect2[13]},
    {TELEPORT_EFFECT + 13, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect2[14]},
    {TELEPORT_EFFECT + 14, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect2[15]},
    {TELEPORT_EFFECT + 15, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect2[16]},
    {TELEPORT_EFFECT + 16, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect2[17]},
    {TELEPORT_EFFECT + 17, TELEPORT_EFFECT_RATE, NullAnimator, &s_TeleportEffect2[18]},
    {TELEPORT_EFFECT + 17, SF_QUICK_CALL, DoTeleRipper, &s_TeleportEffect2[19]},
    {TELEPORT_EFFECT + 17, TELEPORT_EFFECT_RATE, DoSuicide, &s_TeleportEffect2[19]},
};


ANIMATOR DoElectro;
#define ELECTRO_SNAKE 2073
#define ELECTRO_PLAYER (ELECTRO)
#define ELECTRO_ENEMY (ELECTRO + 1)
#define ELECTRO_SHARD (ELECTRO + 2)

STATE s_Electro[] =
{
    {ELECTRO + 0, 12, DoElectro, &s_Electro[1]},
    {ELECTRO + 1, 12, DoElectro, &s_Electro[2]},
    {ELECTRO + 2, 12, DoElectro, &s_Electro[3]},
    {ELECTRO + 3, 12, DoElectro, &s_Electro[0]}
};

STATE s_ElectroShrap[] =
{
    {ELECTRO + 0, 12, DoShrapDamage, &s_ElectroShrap[1]},
    {ELECTRO + 1, 12, DoShrapDamage, &s_ElectroShrap[2]},
    {ELECTRO + 2, 12, DoShrapDamage, &s_ElectroShrap[3]},
    {ELECTRO + 3, 12, DoShrapDamage, &s_ElectroShrap[0]}
};

//////////////////////
//
// EXPS
//
//////////////////////
#define GRENADE_EXP 3121
#define MINE_EXP GRENADE_EXP+1
#define GRENADE_EXP_RATE 6

#if 0
STATE s_GrenadeExp[] =
{
    {GRENADE_EXP + 0, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[1]},
    {GRENADE_EXP + 1, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[2]},
    {GRENADE_EXP + 2, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[3]},
    {GRENADE_EXP + 3, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[4]},
    {GRENADE_EXP + 4, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[5]},
    {GRENADE_EXP + 5, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[6]},
    {GRENADE_EXP + 6, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[7]},
    {GRENADE_EXP + 7, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[8]},
    {GRENADE_EXP + 8, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[9]},
    {GRENADE_EXP + 9, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[10]},
    {GRENADE_EXP + 10, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[11]},
    {GRENADE_EXP + 11, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[12]},
    {GRENADE_EXP + 12, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[13]},
    {GRENADE_EXP + 13, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[14]},
    {GRENADE_EXP + 14, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[15]},
    {GRENADE_EXP + 15, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[16]},
    {GRENADE_EXP + 16, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[17]},
    {GRENADE_EXP + 17, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[18]},
    {GRENADE_EXP + 18, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[19]},
    {GRENADE_EXP + 19, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[20]},
    {GRENADE_EXP + 20, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[21]},
    {GRENADE_EXP + 21, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[22]},
    {GRENADE_EXP + 21, 100, DoSuicide, &s_GrenadeExp[22]}
};
#else
STATE s_GrenadeSmallExp[] =
{
    {GRENADE_EXP + 0, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeSmallExp[1]},
    {GRENADE_EXP + 1, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeSmallExp[2]},
    {GRENADE_EXP + 2, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeSmallExp[3]},
    {GRENADE_EXP + 3, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeSmallExp[4]},
    {GRENADE_EXP + 4, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeSmallExp[5]},
    {GRENADE_EXP + 5, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeSmallExp[6]},
    {GRENADE_EXP + 6, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeSmallExp[7]},
    {GRENADE_EXP + 7, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeSmallExp[8]},
    {GRENADE_EXP + 8, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeSmallExp[9]},
    {GRENADE_EXP + 9, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeSmallExp[10]},
    {GRENADE_EXP + 10, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeSmallExp[11]},
    {GRENADE_EXP + 11, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeSmallExp[12]},
    {GRENADE_EXP + 12, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeSmallExp[13]},
    {GRENADE_EXP + 13, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeSmallExp[14]},
    {GRENADE_EXP + 14, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeSmallExp[15]},
    {GRENADE_EXP + 15, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeSmallExp[16]},
    {GRENADE_EXP + 16, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeSmallExp[17]},
    {GRENADE_EXP + 17, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeSmallExp[18]},
    {GRENADE_EXP + 18, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeSmallExp[19]},
    {GRENADE_EXP + 19, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeSmallExp[20]},
    {GRENADE_EXP + 20, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeSmallExp[21]},
    {GRENADE_EXP + 21, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeSmallExp[22]},
    {GRENADE_EXP + 21, 100, DoSuicide, &s_GrenadeSmallExp[22]}
};

ANIMATOR SpawnGrenadeSmallExp;
STATE s_GrenadeExp[] =
{
    {GRENADE_EXP + 0, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[1]},
    {GRENADE_EXP + 1, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[2]},
    {GRENADE_EXP + 2, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[3]},
    {GRENADE_EXP + 3, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[4]},
    {GRENADE_EXP + 4, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[5]},
    {GRENADE_EXP + 5, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[6]},
    {GRENADE_EXP + 6, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[7]},
    {GRENADE_EXP + 6, SF_QUICK_CALL,     SpawnGrenadeSmallExp, &s_GrenadeExp[8]},
    {GRENADE_EXP + 7, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[9]},
    {GRENADE_EXP + 8, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[10]},
    {GRENADE_EXP + 9, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[11]},
    {GRENADE_EXP + 10, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[12]},
    {GRENADE_EXP + 11, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[13]},
    {GRENADE_EXP + 12, SF_QUICK_CALL,     SpawnGrenadeSmallExp, &s_GrenadeExp[14]},
    {GRENADE_EXP + 12, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[15]},
    {GRENADE_EXP + 13, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[16]},
    {GRENADE_EXP + 14, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[17]},
    {GRENADE_EXP + 15, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[18]},
    {GRENADE_EXP + 16, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[19]},
    {GRENADE_EXP + 17, SF_QUICK_CALL,     SpawnGrenadeSmallExp, &s_GrenadeExp[20]},
    {GRENADE_EXP + 17, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[21]},
    {GRENADE_EXP + 18, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[22]},
    {GRENADE_EXP + 19, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[23]},
    {GRENADE_EXP + 20, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[24]},
    {GRENADE_EXP + 21, GRENADE_EXP_RATE, NullAnimator, &s_GrenadeExp[25]},
    {GRENADE_EXP + 21, 100, DoSuicide, &s_GrenadeExp[25]}
};
#endif

#define MINE_EXP GRENADE_EXP+1
ANIMATOR DoMineExp, DoMineExpMine;
STATE s_MineExp[] =
{
    {GRENADE_EXP + 0, GRENADE_EXP_RATE, NullAnimator, &s_MineExp[1]},
    {GRENADE_EXP + 1, GRENADE_EXP_RATE, NullAnimator, &s_MineExp[2]},
    {GRENADE_EXP + 2, GRENADE_EXP_RATE, NullAnimator, &s_MineExp[3]},
    {GRENADE_EXP + 3, 0|SF_QUICK_CALL, DoMineExp, &s_MineExp[4]},
    {GRENADE_EXP + 3, GRENADE_EXP_RATE, NullAnimator, &s_MineExp[5]},
    {GRENADE_EXP + 4, GRENADE_EXP_RATE, NullAnimator, &s_MineExp[6]},
    {GRENADE_EXP + 5, GRENADE_EXP_RATE, NullAnimator, &s_MineExp[7]},
    {GRENADE_EXP + 6, GRENADE_EXP_RATE, NullAnimator, &s_MineExp[8]},
    {GRENADE_EXP + 7, GRENADE_EXP_RATE, NullAnimator, &s_MineExp[9]},
    {GRENADE_EXP + 8, GRENADE_EXP_RATE, NullAnimator, &s_MineExp[10]},
    {GRENADE_EXP + 9, GRENADE_EXP_RATE, NullAnimator, &s_MineExp[11]},
    {GRENADE_EXP + 10, GRENADE_EXP_RATE, NullAnimator, &s_MineExp[12]},
    {GRENADE_EXP + 11, GRENADE_EXP_RATE, NullAnimator, &s_MineExp[13]},
    {GRENADE_EXP + 12, GRENADE_EXP_RATE, NullAnimator, &s_MineExp[14]},
    {GRENADE_EXP + 13, GRENADE_EXP_RATE, NullAnimator, &s_MineExp[15]},
    {GRENADE_EXP + 14, GRENADE_EXP_RATE, NullAnimator, &s_MineExp[16]},
    {GRENADE_EXP + 15, GRENADE_EXP_RATE, NullAnimator, &s_MineExp[17]},
    {GRENADE_EXP + 16, GRENADE_EXP_RATE, NullAnimator, &s_MineExp[18]},
    {GRENADE_EXP + 17, GRENADE_EXP_RATE, NullAnimator, &s_MineExp[19]},
    {GRENADE_EXP + 17, 0|SF_QUICK_CALL, DoMineExpMine, &s_MineExp[20]},
    {GRENADE_EXP + 18, GRENADE_EXP_RATE, NullAnimator, &s_MineExp[21]},
    {GRENADE_EXP + 19, GRENADE_EXP_RATE, NullAnimator, &s_MineExp[22]},
    {GRENADE_EXP + 20, GRENADE_EXP_RATE, NullAnimator, &s_MineExp[23]},
    {GRENADE_EXP + 21, GRENADE_EXP_RATE, NullAnimator, &s_MineExp[24]},
    {GRENADE_EXP + 21, 100, DoSuicide, &s_MineExp[24]}
};

#define EXP_RATE 7
#define BOLT_EXP EXP
#define FIREBALL_EXP EXP+1
#define BASIC_EXP EXP+2
#define SECTOR_EXP EXP+3
#define MICRO_EXP EXP+5
#define TRACER_EXP EXP+6
#define TANK_SHELL_EXP EXP+7

STATE s_BasicExp[] =
{
    {EXP + 0, EXP_RATE, NullAnimator, &s_BasicExp[1]},
    {EXP + 1, EXP_RATE, NullAnimator, &s_BasicExp[2]},
    {EXP + 2, EXP_RATE, NullAnimator, &s_BasicExp[3]},
    {EXP + 3, EXP_RATE, NullAnimator, &s_BasicExp[4]},
    {EXP + 4, EXP_RATE, NullAnimator, &s_BasicExp[5]},
    {EXP + 5, EXP_RATE, NullAnimator, &s_BasicExp[6]},
    {EXP + 6, EXP_RATE, NullAnimator, &s_BasicExp[7]},
    {EXP + 7, EXP_RATE, NullAnimator, &s_BasicExp[8]},
    {EXP + 8, EXP_RATE, NullAnimator, &s_BasicExp[9]},
    {EXP + 9, EXP_RATE, NullAnimator, &s_BasicExp[10]},
    {EXP + 10, EXP_RATE, NullAnimator, &s_BasicExp[11]},
    {EXP + 11, EXP_RATE, NullAnimator, &s_BasicExp[12]},
    {EXP + 12, EXP_RATE, NullAnimator, &s_BasicExp[13]},
    {EXP + 13, EXP_RATE, NullAnimator, &s_BasicExp[14]},
    {EXP + 14, EXP_RATE, NullAnimator, &s_BasicExp[15]},
    {EXP + 15, EXP_RATE, NullAnimator, &s_BasicExp[16]},
    {EXP + 16, EXP_RATE, NullAnimator, &s_BasicExp[17]},
    {EXP + 17, EXP_RATE, NullAnimator, &s_BasicExp[18]},
    {EXP + 18, EXP_RATE, NullAnimator, &s_BasicExp[19]},
    {EXP + 19, EXP_RATE, NullAnimator, &s_BasicExp[20]},
    {EXP + 20, 100, DoSuicide, &s_BasicExp[0]}
};

#define MICRO_EXP_RATE 3
ANIMATOR DoExpDamageTest;

STATE s_MicroExp[] =
{
    {EXP + 0, MICRO_EXP_RATE, NullAnimator, &s_MicroExp[1]},
    {EXP + 0, SF_QUICK_CALL,  DoExpDamageTest,   &s_MicroExp[2]},
    {EXP + 1, MICRO_EXP_RATE, NullAnimator, &s_MicroExp[3]},
    {EXP + 2, MICRO_EXP_RATE, NullAnimator, &s_MicroExp[4]},
    {EXP + 3, MICRO_EXP_RATE, NullAnimator, &s_MicroExp[5]},
    {EXP + 4, MICRO_EXP_RATE, NullAnimator, &s_MicroExp[6]},
    {EXP + 5, MICRO_EXP_RATE, NullAnimator, &s_MicroExp[7]},
    {EXP + 6, MICRO_EXP_RATE, NullAnimator, &s_MicroExp[8]},
    {EXP + 7, MICRO_EXP_RATE, NullAnimator, &s_MicroExp[9]},
    {EXP + 8, MICRO_EXP_RATE, NullAnimator, &s_MicroExp[10]},
    {EXP + 9, MICRO_EXP_RATE, NullAnimator, &s_MicroExp[11]},
    {EXP + 10, MICRO_EXP_RATE, NullAnimator, &s_MicroExp[12]},
    {EXP + 11, MICRO_EXP_RATE, NullAnimator, &s_MicroExp[13]},
    {EXP + 12, MICRO_EXP_RATE, NullAnimator, &s_MicroExp[14]},
    {EXP + 13, MICRO_EXP_RATE, NullAnimator, &s_MicroExp[15]},
    {EXP + 14, MICRO_EXP_RATE, NullAnimator, &s_MicroExp[16]},
    {EXP + 15, MICRO_EXP_RATE, NullAnimator, &s_MicroExp[17]},
    {EXP + 16, MICRO_EXP_RATE, NullAnimator, &s_MicroExp[18]},
    {EXP + 17, MICRO_EXP_RATE, NullAnimator, &s_MicroExp[19]},
    {EXP + 18, MICRO_EXP_RATE, NullAnimator, &s_MicroExp[20]},
    {EXP + 19, MICRO_EXP_RATE, NullAnimator, &s_MicroExp[21]},
    {EXP + 20, MICRO_EXP_RATE, NullAnimator, &s_MicroExp[22]},
    {EXP + 20, 100, DoSuicide, &s_MicroExp[22]}
};


#define BIG_GUN_FLAME_RATE 15
STATE s_BigGunFlame[] =
{
    // first 3 frames
    {EXP + 0, BIG_GUN_FLAME_RATE, NullAnimator, &s_BigGunFlame[1]},
    {EXP + 1, BIG_GUN_FLAME_RATE, NullAnimator, &s_BigGunFlame[2]},
    {EXP + 2, BIG_GUN_FLAME_RATE, NullAnimator, &s_BigGunFlame[3]},
    // last 4 frames frames
    {EXP + 17, BIG_GUN_FLAME_RATE, NullAnimator, &s_BigGunFlame[4]},
    {EXP + 18, BIG_GUN_FLAME_RATE, NullAnimator, &s_BigGunFlame[5]},
    {EXP + 19, BIG_GUN_FLAME_RATE, NullAnimator, &s_BigGunFlame[6]},
    {EXP + 20, BIG_GUN_FLAME_RATE, NullAnimator, &s_BigGunFlame[7]},
    {EXP + 20, 100, DoSuicide, &s_BigGunFlame[0]}
};

STATE s_BoltExp[] =
{
    {EXP + 0, EXP_RATE, NullAnimator, &s_BoltExp[1]},
    {EXP + 0, SF_QUICK_CALL,  NullAnimator,  &s_BoltExp[2]},
    {EXP + 0, SF_QUICK_CALL,  SpawnShrapX,   &s_BoltExp[3]},
    {EXP + 1, EXP_RATE, NullAnimator, &s_BoltExp[4]},
    {EXP + 2, EXP_RATE, NullAnimator, &s_BoltExp[5]},
    {EXP + 3, EXP_RATE, NullAnimator, &s_BoltExp[6]},
    {EXP + 4, EXP_RATE, NullAnimator, &s_BoltExp[7]},
    {EXP + 5, EXP_RATE, NullAnimator, &s_BoltExp[8]},
    {EXP + 6, EXP_RATE, NullAnimator, &s_BoltExp[9]},
    {EXP + 7, EXP_RATE, NullAnimator, &s_BoltExp[10]},
    {EXP + 7, SF_QUICK_CALL,  SpawnShrapX,   &s_BoltExp[11]},
    {EXP + 8, EXP_RATE, NullAnimator, &s_BoltExp[12]},
    {EXP + 9, EXP_RATE, NullAnimator, &s_BoltExp[13]},
    {EXP + 10, EXP_RATE, NullAnimator, &s_BoltExp[14]},
    {EXP + 11, EXP_RATE, NullAnimator, &s_BoltExp[15]},
    {EXP + 12, EXP_RATE, NullAnimator, &s_BoltExp[16]},
    {EXP + 13, EXP_RATE, NullAnimator, &s_BoltExp[17]},
    {EXP + 14, EXP_RATE, NullAnimator, &s_BoltExp[18]},
    {EXP + 15, EXP_RATE, NullAnimator, &s_BoltExp[19]},
    {EXP + 16, EXP_RATE, NullAnimator, &s_BoltExp[20]},
    {EXP + 17, EXP_RATE, NullAnimator, &s_BoltExp[21]},
    {EXP + 18, EXP_RATE, NullAnimator, &s_BoltExp[22]},
    {EXP + 19, EXP_RATE, NullAnimator, &s_BoltExp[23]},
    {EXP + 20, EXP_RATE, NullAnimator, &s_BoltExp[24]},
    {EXP + 20, 100, DoSuicide, &s_BoltExp[0]}
};

STATE s_TankShellExp[] =
{
    {EXP + 0, EXP_RATE, NullAnimator, &s_TankShellExp[1]},
    {EXP + 0, SF_QUICK_CALL,  NullAnimator,  &s_TankShellExp[2]},
    {EXP + 0, SF_QUICK_CALL,  SpawnShrapX,   &s_TankShellExp[3]},
    {EXP + 1, EXP_RATE, NullAnimator, &s_TankShellExp[4]},
    {EXP + 2, EXP_RATE, NullAnimator, &s_TankShellExp[5]},
    {EXP + 3, EXP_RATE, NullAnimator, &s_TankShellExp[6]},
    {EXP + 4, EXP_RATE, NullAnimator, &s_TankShellExp[7]},
    {EXP + 5, EXP_RATE, NullAnimator, &s_TankShellExp[8]},
    {EXP + 6, EXP_RATE, NullAnimator, &s_TankShellExp[9]},
    {EXP + 7, EXP_RATE, NullAnimator, &s_TankShellExp[10]},
    {EXP + 7, SF_QUICK_CALL,  SpawnShrapX,   &s_TankShellExp[11]},
    {EXP + 8, EXP_RATE, NullAnimator, &s_TankShellExp[12]},
    {EXP + 9, EXP_RATE, NullAnimator, &s_TankShellExp[13]},
    {EXP + 10, EXP_RATE, NullAnimator, &s_TankShellExp[14]},
    {EXP + 11, EXP_RATE, NullAnimator, &s_TankShellExp[15]},
    {EXP + 12, EXP_RATE, NullAnimator, &s_TankShellExp[16]},
    {EXP + 13, EXP_RATE, NullAnimator, &s_TankShellExp[17]},
    {EXP + 14, EXP_RATE, NullAnimator, &s_TankShellExp[18]},
    {EXP + 15, EXP_RATE, NullAnimator, &s_TankShellExp[19]},
    {EXP + 16, EXP_RATE, NullAnimator, &s_TankShellExp[20]},
    {EXP + 17, EXP_RATE, NullAnimator, &s_TankShellExp[21]},
    {EXP + 18, EXP_RATE, NullAnimator, &s_TankShellExp[22]},
    {EXP + 19, EXP_RATE, NullAnimator, &s_TankShellExp[23]},
    {EXP + 20, EXP_RATE, NullAnimator, &s_TankShellExp[24]},
    {EXP + 20, 100, DoSuicide, &s_TankShellExp[0]}
};

#define TRACER_EXP_RATE 4
STATE s_TracerExp[] =
{
    {EXP + 0, TRACER_EXP_RATE, NullAnimator, &s_TracerExp[1]},
    {EXP + 0, SF_QUICK_CALL,  NullAnimator,  &s_TracerExp[2]},
    {EXP + 0, SF_QUICK_CALL,  NullAnimator,   &s_TracerExp[3]},
    {EXP + 1, TRACER_EXP_RATE, NullAnimator, &s_TracerExp[4]},
    {EXP + 2, TRACER_EXP_RATE, NullAnimator, &s_TracerExp[5]},
    {EXP + 3, TRACER_EXP_RATE, NullAnimator, &s_TracerExp[6]},
    {EXP + 4, TRACER_EXP_RATE, NullAnimator, &s_TracerExp[7]},
    {EXP + 5, TRACER_EXP_RATE, NullAnimator, &s_TracerExp[8]},
    {EXP + 6, TRACER_EXP_RATE, NullAnimator, &s_TracerExp[9]},
    {EXP + 7, TRACER_EXP_RATE, NullAnimator, &s_TracerExp[10]},
    {EXP + 7, SF_QUICK_CALL,  NullAnimator,   &s_TracerExp[11]},
    {EXP + 8, TRACER_EXP_RATE, NullAnimator, &s_TracerExp[12]},
    {EXP + 9, TRACER_EXP_RATE, NullAnimator, &s_TracerExp[13]},
    {EXP + 10, TRACER_EXP_RATE, NullAnimator, &s_TracerExp[14]},
    {EXP + 11, TRACER_EXP_RATE, NullAnimator, &s_TracerExp[15]},
    {EXP + 12, TRACER_EXP_RATE, NullAnimator, &s_TracerExp[16]},
    {EXP + 13, TRACER_EXP_RATE, NullAnimator, &s_TracerExp[17]},
    {EXP + 14, TRACER_EXP_RATE, NullAnimator, &s_TracerExp[18]},
    {EXP + 15, TRACER_EXP_RATE, NullAnimator, &s_TracerExp[19]},
    {EXP + 16, TRACER_EXP_RATE, NullAnimator, &s_TracerExp[20]},
    {EXP + 17, TRACER_EXP_RATE, NullAnimator, &s_TracerExp[21]},
    {EXP + 18, TRACER_EXP_RATE, NullAnimator, &s_TracerExp[22]},
    {EXP + 19, TRACER_EXP_RATE, NullAnimator, &s_TracerExp[23]},
    {EXP + 20, TRACER_EXP_RATE, NullAnimator, &s_TracerExp[24]},
    {EXP + 20, 100, DoSuicide, &s_TracerExp[0]}
};

#define EXP_RATE 7
ANIMATOR SpawnShrapX;
ANIMATOR DoSectorExp;

STATE s_SectorExp[] =
{
    {EXP + 0, EXP_RATE, DoSectorExp, &s_SectorExp[1]},
    {EXP + 0, SF_QUICK_CALL,  SpawnShrapX,  &s_SectorExp[2]},
    {EXP + 0, SF_QUICK_CALL,  DoSectorExp,   &s_SectorExp[3]},
    {EXP + 1, EXP_RATE, DoSectorExp, &s_SectorExp[4]},
    {EXP + 2, EXP_RATE, DoSectorExp, &s_SectorExp[5]},
    {EXP + 3, EXP_RATE, DoSectorExp, &s_SectorExp[6]},
    {EXP + 4, EXP_RATE, DoSectorExp, &s_SectorExp[7]},
    {EXP + 5, EXP_RATE, DoSectorExp, &s_SectorExp[8]},
    {EXP + 6, EXP_RATE, DoSectorExp, &s_SectorExp[9]},
    {EXP + 7, EXP_RATE, DoSectorExp, &s_SectorExp[10]},
    {EXP + 7, SF_QUICK_CALL,  DoSectorExp,  &s_SectorExp[11]},
    {EXP + 8, EXP_RATE, DoSectorExp, &s_SectorExp[12]},
    {EXP + 9, EXP_RATE, DoSectorExp, &s_SectorExp[13]},
    {EXP + 10, EXP_RATE, DoSectorExp, &s_SectorExp[14]},
    {EXP + 11, EXP_RATE, DoSectorExp, &s_SectorExp[15]},
    {EXP + 12, EXP_RATE, DoSectorExp, &s_SectorExp[16]},
    {EXP + 13, EXP_RATE, DoSectorExp, &s_SectorExp[17]},
    {EXP + 14, EXP_RATE, DoSectorExp, &s_SectorExp[18]},
    {EXP + 15, EXP_RATE, DoSectorExp, &s_SectorExp[19]},
    {EXP + 16, EXP_RATE, DoSectorExp, &s_SectorExp[20]},
    {EXP + 17, EXP_RATE, DoSectorExp, &s_SectorExp[21]},
    {EXP + 18, EXP_RATE, DoSectorExp, &s_SectorExp[22]},
    {EXP + 19, EXP_RATE, DoSectorExp, &s_SectorExp[23]},
    {EXP + 20, EXP_RATE, DoSectorExp, &s_SectorExp[24]},
    {EXP + 20, 100, DoSuicide, &s_SectorExp[0]}
};


#define FIREBALL_DISS 3196
#define FIREBALL_DISS_RATE 8
STATE s_FireballExp[] =
{
    {FIREBALL_DISS + 0, FIREBALL_DISS_RATE, NullAnimator, &s_FireballExp[1]},
    {FIREBALL_DISS + 1, FIREBALL_DISS_RATE, NullAnimator, &s_FireballExp[2]},
    {FIREBALL_DISS + 2, FIREBALL_DISS_RATE, NullAnimator, &s_FireballExp[3]},
    {FIREBALL_DISS + 3, FIREBALL_DISS_RATE, NullAnimator, &s_FireballExp[4]},
    {FIREBALL_DISS + 4, FIREBALL_DISS_RATE, NullAnimator, &s_FireballExp[5]},
    {FIREBALL_DISS + 4, 100, DoSuicide, &s_FireballExp[0]}
};

#define NAP_EXP (3072)
#define NAP_EXP_RATE 6

STATE s_NapExp[] =
{
    {NAP_EXP + 0,     NAP_EXP_RATE,      NullAnimator,  &s_NapExp[1]},
    {NAP_EXP + 0,     0 | SF_QUICK_CALL,       DoDamageTest,  &s_NapExp[2]},
    {NAP_EXP + 1,     NAP_EXP_RATE,      NullAnimator,  &s_NapExp[3]},
    {NAP_EXP + 2,     NAP_EXP_RATE,      NullAnimator,  &s_NapExp[4]},
    {NAP_EXP + 3,     NAP_EXP_RATE,      NullAnimator,  &s_NapExp[5]},
    {NAP_EXP + 4,     NAP_EXP_RATE,      NullAnimator,  &s_NapExp[6]},
    {NAP_EXP + 5,     NAP_EXP_RATE,      NullAnimator,  &s_NapExp[7]},
    {NAP_EXP + 6,     NAP_EXP_RATE,      NullAnimator,  &s_NapExp[8]},
    {NAP_EXP + 7,     NAP_EXP_RATE,      NullAnimator,  &s_NapExp[9]},
    {NAP_EXP + 8,     NAP_EXP_RATE,      NullAnimator,  &s_NapExp[10]},
    {NAP_EXP + 9,     NAP_EXP_RATE,      NullAnimator,  &s_NapExp[11]},
    {NAP_EXP + 10,    NAP_EXP_RATE,      NullAnimator,  &s_NapExp[12]},
    {NAP_EXP + 11,    NAP_EXP_RATE,      NullAnimator,  &s_NapExp[13]},
    {NAP_EXP + 12,    NAP_EXP_RATE,      NullAnimator,  &s_NapExp[14]},
    {NAP_EXP + 13,    NAP_EXP_RATE,      NullAnimator,  &s_NapExp[15]},
    {NAP_EXP + 14,    NAP_EXP_RATE,      NullAnimator,  &s_NapExp[16]},
    {NAP_EXP + 15,    NAP_EXP_RATE-2,    NullAnimator,  &s_NapExp[17]},
    {NAP_EXP + 16,    NAP_EXP_RATE-2,    NullAnimator,  &s_NapExp[18]},
    {NAP_EXP + 17,    NAP_EXP_RATE-2,    NullAnimator,  &s_NapExp[19]},
    {NAP_EXP + 18,    NAP_EXP_RATE-2,    NullAnimator,  &s_NapExp[20]},
    {NAP_EXP + 19,    NAP_EXP_RATE-2,    NullAnimator,  &s_NapExp[21]},
    {NAP_EXP + 20,    NAP_EXP_RATE-2,    NullAnimator,  &s_NapExp[22]},
    {NAP_EXP + 21,    NAP_EXP_RATE-2,    NullAnimator,  &s_NapExp[23]},
    {NAP_EXP + 21,    NAP_EXP_RATE-2,    DoSuicide,     &s_NapExp[23]}
};

ANIMATOR DoFireballFlames;
#define FLAME_RATE 6

STATE s_FireballFlames[] =
{
    {FIREBALL_FLAMES + 0, FLAME_RATE, DoFireballFlames, &s_FireballFlames[1]},
    {FIREBALL_FLAMES + 1, FLAME_RATE, DoFireballFlames, &s_FireballFlames[2]},
    {FIREBALL_FLAMES + 2, FLAME_RATE, DoFireballFlames, &s_FireballFlames[3]},
    {FIREBALL_FLAMES + 3, FLAME_RATE, DoFireballFlames, &s_FireballFlames[4]},
    {FIREBALL_FLAMES + 4, FLAME_RATE, DoFireballFlames, &s_FireballFlames[5]},
    {FIREBALL_FLAMES + 5, FLAME_RATE, DoFireballFlames, &s_FireballFlames[6]},
    {FIREBALL_FLAMES + 6, FLAME_RATE, DoFireballFlames, &s_FireballFlames[7]},
    {FIREBALL_FLAMES + 7, FLAME_RATE, DoFireballFlames, &s_FireballFlames[8]},
    {FIREBALL_FLAMES + 8, FLAME_RATE, DoFireballFlames, &s_FireballFlames[9]},
    {FIREBALL_FLAMES + 9, FLAME_RATE, DoFireballFlames, &s_FireballFlames[10]},
    {FIREBALL_FLAMES +10, FLAME_RATE, DoFireballFlames, &s_FireballFlames[11]},
    {FIREBALL_FLAMES +11, FLAME_RATE, DoFireballFlames, &s_FireballFlames[12]},
    {FIREBALL_FLAMES +12, FLAME_RATE, DoFireballFlames, &s_FireballFlames[13]},
    {FIREBALL_FLAMES +13, FLAME_RATE, DoFireballFlames, &s_FireballFlames[0]},
};

ANIMATOR DoBreakFlames;
#define FLAME_RATE 6

STATE s_BreakFlames[] =
{
    {FIREBALL_FLAMES + 0, FLAME_RATE, DoBreakFlames, &s_BreakFlames[1]},
    {FIREBALL_FLAMES + 1, FLAME_RATE, DoBreakFlames, &s_BreakFlames[2]},
    {FIREBALL_FLAMES + 2, FLAME_RATE, DoBreakFlames, &s_BreakFlames[3]},
    {FIREBALL_FLAMES + 3, FLAME_RATE, DoBreakFlames, &s_BreakFlames[4]},
    {FIREBALL_FLAMES + 4, FLAME_RATE, DoBreakFlames, &s_BreakFlames[5]},
    {FIREBALL_FLAMES + 5, FLAME_RATE, DoBreakFlames, &s_BreakFlames[6]},
    {FIREBALL_FLAMES + 6, FLAME_RATE, DoBreakFlames, &s_BreakFlames[7]},
    {FIREBALL_FLAMES + 7, FLAME_RATE, DoBreakFlames, &s_BreakFlames[8]},
    {FIREBALL_FLAMES + 8, FLAME_RATE, DoBreakFlames, &s_BreakFlames[9]},
    {FIREBALL_FLAMES + 9, FLAME_RATE, DoBreakFlames, &s_BreakFlames[10]},
    {FIREBALL_FLAMES +10, FLAME_RATE, DoBreakFlames, &s_BreakFlames[11]},
    {FIREBALL_FLAMES +11, FLAME_RATE, DoBreakFlames, &s_BreakFlames[12]},
    {FIREBALL_FLAMES +12, FLAME_RATE, DoBreakFlames, &s_BreakFlames[13]},
    {FIREBALL_FLAMES +13, FLAME_RATE, DoBreakFlames, &s_BreakFlames[0]},
};

//////////////////////
//
// FIREBALL
//
//////////////////////

#if 1
ANIMATOR DoFireball;
#define FIREBALL_RATE 8
#define GORO_FIREBALL FIREBALL+1

STATE s_Fireball[] =
{
    {FIREBALL + 0, 12, DoFireball, &s_Fireball[1]},
    {FIREBALL + 1, 12, DoFireball, &s_Fireball[2]},
    {FIREBALL + 2, 12, DoFireball, &s_Fireball[3]},
    {FIREBALL + 3, 12, DoFireball, &s_Fireball[0]}
};

#else
#define GORO_FIREBALL FIREBALL_R0
#define FIREBALL_RATE 6
ANIMATOR DoFireball;

STATE s_Fireball[5][4] =
{
    {
        {FIREBALL_R0 + 0, FIREBALL_RATE, DoFireball, &s_Fireball[0][1]},
        {FIREBALL_R0 + 1, FIREBALL_RATE, DoFireball, &s_Fireball[0][2]},
        {FIREBALL_R0 + 2, FIREBALL_RATE, DoFireball, &s_Fireball[0][3]},
        {FIREBALL_R0 + 3, FIREBALL_RATE, DoFireball, &s_Fireball[0][0]},
    },
    {
        {FIREBALL_R1 + 0, FIREBALL_RATE, DoFireball, &s_Fireball[1][1]},
        {FIREBALL_R1 + 1, FIREBALL_RATE, DoFireball, &s_Fireball[1][2]},
        {FIREBALL_R1 + 2, FIREBALL_RATE, DoFireball, &s_Fireball[1][3]},
        {FIREBALL_R1 + 3, FIREBALL_RATE, DoFireball, &s_Fireball[1][0]},
    },
    {
        {FIREBALL_R2 + 0, FIREBALL_RATE, DoFireball, &s_Fireball[2][1]},
        {FIREBALL_R2 + 1, FIREBALL_RATE, DoFireball, &s_Fireball[2][2]},
        {FIREBALL_R2 + 2, FIREBALL_RATE, DoFireball, &s_Fireball[2][3]},
        {FIREBALL_R2 + 3, FIREBALL_RATE, DoFireball, &s_Fireball[2][0]},
    },
    {
        {FIREBALL_R3 + 0, FIREBALL_RATE, DoFireball, &s_Fireball[3][1]},
        {FIREBALL_R3 + 1, FIREBALL_RATE, DoFireball, &s_Fireball[3][2]},
        {FIREBALL_R3 + 2, FIREBALL_RATE, DoFireball, &s_Fireball[3][3]},
        {FIREBALL_R3 + 3, FIREBALL_RATE, DoFireball, &s_Fireball[3][0]},
    },
    {
        {FIREBALL_R4 + 0, FIREBALL_RATE, DoFireball, &s_Fireball[4][1]},
        {FIREBALL_R4 + 1, FIREBALL_RATE, DoFireball, &s_Fireball[4][2]},
        {FIREBALL_R4 + 2, FIREBALL_RATE, DoFireball, &s_Fireball[4][3]},
        {FIREBALL_R4 + 3, FIREBALL_RATE, DoFireball, &s_Fireball[4][0]},
    }
};

STATEp sg_Fireball[] =
{
    s_Fireball[0],
    s_Fireball[1],
    s_Fireball[2],
    s_Fireball[3],
    s_Fireball[4]
};
#endif

#if 0
ANIMATOR DoRing;

STATE s_Ring[5][4] =
{
    {
        {FIREBALL_R0 + 0, FIREBALL_RATE, DoRing, &s_Ring[0][1]},
        {FIREBALL_R0 + 1, FIREBALL_RATE, DoRing, &s_Ring[0][2]},
        {FIREBALL_R0 + 2, FIREBALL_RATE, DoRing, &s_Ring[0][3]},
        {FIREBALL_R0 + 3, FIREBALL_RATE, DoRing, &s_Ring[0][0]},
    },
    {
        {FIREBALL_R1 + 0, FIREBALL_RATE, DoRing, &s_Ring[1][1]},
        {FIREBALL_R1 + 1, FIREBALL_RATE, DoRing, &s_Ring[1][2]},
        {FIREBALL_R1 + 2, FIREBALL_RATE, DoRing, &s_Ring[1][3]},
        {FIREBALL_R1 + 3, FIREBALL_RATE, DoRing, &s_Ring[1][0]},
    },
    {
        {FIREBALL_R2 + 0, FIREBALL_RATE, DoRing, &s_Ring[2][1]},
        {FIREBALL_R2 + 1, FIREBALL_RATE, DoRing, &s_Ring[2][2]},
        {FIREBALL_R2 + 2, FIREBALL_RATE, DoRing, &s_Ring[2][3]},
        {FIREBALL_R2 + 3, FIREBALL_RATE, DoRing, &s_Ring[2][0]},
    },
    {
        {FIREBALL_R3 + 0, FIREBALL_RATE, DoRing, &s_Ring[3][1]},
        {FIREBALL_R3 + 1, FIREBALL_RATE, DoRing, &s_Ring[3][2]},
        {FIREBALL_R3 + 2, FIREBALL_RATE, DoRing, &s_Ring[3][3]},
        {FIREBALL_R3 + 3, FIREBALL_RATE, DoRing, &s_Ring[3][0]},
    },
    {
        {FIREBALL_R4 + 0, FIREBALL_RATE, DoRing, &s_Ring[4][1]},
        {FIREBALL_R4 + 1, FIREBALL_RATE, DoRing, &s_Ring[4][2]},
        {FIREBALL_R4 + 2, FIREBALL_RATE, DoRing, &s_Ring[4][3]},
        {FIREBALL_R4 + 3, FIREBALL_RATE, DoRing, &s_Ring[4][0]},
    }
};

STATEp sg_Ring[] =
{
    s_Ring[0],
    s_Ring[1],
    s_Ring[2],
    s_Ring[3],
    s_Ring[4]
};
#else
ANIMATOR DoRing;

STATE s_Ring[] =
{
    {FIREBALL + 0, 12, DoRing, &s_Ring[1]},
    {FIREBALL + 1, 12, DoRing, &s_Ring[2]},
    {FIREBALL + 2, 12, DoRing, &s_Ring[3]},
    {FIREBALL + 3, 12, DoRing, &s_Ring[0]}
};
#endif

STATE s_Ring2[] =
{
    {2031 + 0, 12, DoRing, &s_Ring2[1]},
    {2031 + 1, 12, DoRing, &s_Ring2[2]},
    {2031 + 2, 12, DoRing, &s_Ring2[3]},
    {2031 + 3, 12, DoRing, &s_Ring2[0]}
};

ANIMATOR DoNapalm;

STATE s_Napalm[] =
{
    {FIREBALL + 0, 12, DoNapalm, &s_Napalm[1]},
    {FIREBALL + 1, 12, DoNapalm, &s_Napalm[2]},
    {FIREBALL + 2, 12, DoNapalm, &s_Napalm[3]},
    {FIREBALL + 3, 12, DoNapalm, &s_Napalm[0]}
};


ANIMATOR DoBloodWorm;

#if 1
#define BLOOD_WORM 2106
STATE s_BloodWorm[] =
{
    {BLOOD_WORM + 0, 12, DoBloodWorm, &s_BloodWorm[1]},
    {BLOOD_WORM + 1, 12, DoBloodWorm, &s_BloodWorm[2]},
    {BLOOD_WORM + 2, 12, DoBloodWorm, &s_BloodWorm[3]},
    {BLOOD_WORM + 3, 12, DoBloodWorm, &s_BloodWorm[4]},
    {BLOOD_WORM + 2, 12, DoBloodWorm, &s_BloodWorm[5]},
    {BLOOD_WORM + 1, 12, DoBloodWorm, &s_BloodWorm[0]}
};
#else
#define BLOOD_WORM FIREBALL+5
STATE s_BloodWorm[] =
{
    {FIREBALL + 0, 12, DoBloodWorm, &s_BloodWorm[1]},
    {FIREBALL + 1, 12, DoBloodWorm, &s_BloodWorm[2]},
    {FIREBALL + 2, 12, DoBloodWorm, &s_BloodWorm[3]},
    {FIREBALL + 3, 12, DoBloodWorm, &s_BloodWorm[0]}
};
#endif

#if 1
#define PLASMA_EXP BLOOD_WORM+1
#define PLASMA_EXP_RATE 8

STATE s_PlasmaExp[] =
{
    {BLOOD_WORM + 0, PLASMA_EXP_RATE, NullAnimator, &s_PlasmaExp[1]},
    {BLOOD_WORM + 1, PLASMA_EXP_RATE, NullAnimator, &s_PlasmaExp[2]},
    {BLOOD_WORM + 2, PLASMA_EXP_RATE, NullAnimator, &s_PlasmaExp[3]},
    {BLOOD_WORM + 3, PLASMA_EXP_RATE, NullAnimator, &s_PlasmaExp[4]},
    {BLOOD_WORM + 2, PLASMA_EXP_RATE, NullAnimator, &s_PlasmaExp[5]},
    {BLOOD_WORM + 1, PLASMA_EXP_RATE, NullAnimator, &s_PlasmaExp[6]},
    {BLOOD_WORM + 0, PLASMA_EXP_RATE, NullAnimator, &s_PlasmaExp[7]},
    {BLOOD_WORM + 1, PLASMA_EXP_RATE, NullAnimator, &s_PlasmaExp[8]},
    {BLOOD_WORM + 2, PLASMA_EXP_RATE, NullAnimator, &s_PlasmaExp[9]},
    {BLOOD_WORM + 3, PLASMA_EXP_RATE, NullAnimator, &s_PlasmaExp[10]},
    {BLOOD_WORM + 2, PLASMA_EXP_RATE, NullAnimator, &s_PlasmaExp[11]},
    {BLOOD_WORM + 1, PLASMA_EXP_RATE, NullAnimator, &s_PlasmaExp[12]},
    {BLOOD_WORM + 0, PLASMA_EXP_RATE, DoSuicide, &s_PlasmaExp[12]},
};

#else
#define PLASMA_EXP (NAP_EXP+1)
#define PLASMA_EXP_RATE 4

STATE s_PlasmaExp[] =
{
    {PLASMA_EXP + 0,     PLASMA_EXP_RATE,      NullAnimator,  &s_PlasmaExp[1]},
    {PLASMA_EXP + 0,     0 | SF_QUICK_CALL,    DoDamageTest,  &s_PlasmaExp[2]},
    {PLASMA_EXP + 1,     PLASMA_EXP_RATE,      NullAnimator,  &s_PlasmaExp[3]},
    {PLASMA_EXP + 2,     PLASMA_EXP_RATE,      NullAnimator,  &s_PlasmaExp[4]},
    {PLASMA_EXP + 3,     PLASMA_EXP_RATE,      NullAnimator,  &s_PlasmaExp[5]},
    {PLASMA_EXP + 4,     PLASMA_EXP_RATE,      NullAnimator,  &s_PlasmaExp[6]},
    {PLASMA_EXP + 5,     PLASMA_EXP_RATE,      NullAnimator,  &s_PlasmaExp[7]},
    {PLASMA_EXP + 6,     PLASMA_EXP_RATE,      NullAnimator,  &s_PlasmaExp[8]},
    {PLASMA_EXP + 7,     PLASMA_EXP_RATE,      NullAnimator,  &s_PlasmaExp[9]},
    {PLASMA_EXP + 8,     PLASMA_EXP_RATE,      NullAnimator,  &s_PlasmaExp[10]},
    {PLASMA_EXP + 9,     PLASMA_EXP_RATE,      NullAnimator,  &s_PlasmaExp[11]},
    {PLASMA_EXP + 10,    PLASMA_EXP_RATE,      NullAnimator,  &s_PlasmaExp[12]},
    {PLASMA_EXP + 11,    PLASMA_EXP_RATE,      NullAnimator,  &s_PlasmaExp[13]},
    {PLASMA_EXP + 9,     PLASMA_EXP_RATE,      NullAnimator,  &s_PlasmaExp[14]},
    {PLASMA_EXP + 8,     PLASMA_EXP_RATE,      NullAnimator,  &s_PlasmaExp[15]},
    {PLASMA_EXP + 7,     PLASMA_EXP_RATE,      NullAnimator,  &s_PlasmaExp[16]},
    {PLASMA_EXP + 6,     PLASMA_EXP_RATE-2,    NullAnimator,  &s_PlasmaExp[17]},
    {PLASMA_EXP + 5,     PLASMA_EXP_RATE-2,    NullAnimator,  &s_PlasmaExp[18]},
    {PLASMA_EXP + 4,     PLASMA_EXP_RATE-2,    NullAnimator,  &s_PlasmaExp[19]},
    {PLASMA_EXP + 3,     PLASMA_EXP_RATE-2,    NullAnimator,  &s_PlasmaExp[20]},
    {PLASMA_EXP + 2,     PLASMA_EXP_RATE-2,    NullAnimator,  &s_PlasmaExp[21]},
    {PLASMA_EXP + 1,     PLASMA_EXP_RATE-2,    NullAnimator,  &s_PlasmaExp[22]},
    {PLASMA_EXP + 1,     PLASMA_EXP_RATE-2,    NullAnimator,  &s_PlasmaExp[23]},
    {PLASMA_EXP + 1,     PLASMA_EXP_RATE-2,    DoSuicide,     &s_PlasmaExp[23]}
};
#endif


ANIMATOR DoMirv;

STATE s_Mirv[] =
{
    {FIREBALL + 0, 12, DoMirv, &s_Mirv[1]},
    {FIREBALL + 1, 12, DoMirv, &s_Mirv[2]},
    {FIREBALL + 2, 12, DoMirv, &s_Mirv[3]},
    {FIREBALL + 3, 12, DoMirv, &s_Mirv[0]}
};

ANIMATOR DoMirvMissile;

STATE s_MirvMissile[] =
{
    {FIREBALL + 0, 12, DoMirvMissile, &s_MirvMissile[1]},
    {FIREBALL + 1, 12, DoMirvMissile, &s_MirvMissile[2]},
    {FIREBALL + 2, 12, DoMirvMissile, &s_MirvMissile[3]},
    {FIREBALL + 3, 12, DoMirvMissile, &s_MirvMissile[0]}
};

//#define Vomit1 1740
//#define Vomit2 1741
#define Vomit1 1719
#define Vomit2 1721
//#define VomitSplash 1742
#define VomitSplash 1711
#define Vomit_RATE 16
ANIMATOR DoVomit,DoVomitSplash;

STATE s_Vomit1[] =
{
    {Vomit1 + 0, Vomit_RATE, DoVomit, &s_Vomit1[0]}
};

STATE s_Vomit2[] =
{
    {Vomit2 + 0, Vomit_RATE, DoVomit, &s_Vomit2[0]}
};

STATE s_VomitSplash[] =
{
    {VomitSplash + 0, Vomit_RATE, DoVomitSplash, &s_VomitSplash[0]}
};

#define GORE_Head 1670
#define GORE_Head_RATE 16

STATE s_GoreHead[] =
{
    {GORE_Head + 0, GORE_Head_RATE, DoShrapJumpFall, &s_GoreHead[1]},
    {GORE_Head + 1, GORE_Head_RATE, DoShrapJumpFall, &s_GoreHead[2]},
    {GORE_Head + 2, GORE_Head_RATE, DoShrapJumpFall, &s_GoreHead[3]},
    {GORE_Head + 3, GORE_Head_RATE, DoShrapJumpFall, &s_GoreHead[4]},
    {GORE_Head + 4, GORE_Head_RATE, DoShrapJumpFall, &s_GoreHead[5]},
    {GORE_Head + 5, GORE_Head_RATE, DoShrapJumpFall, &s_GoreHead[6]},
    {GORE_Head + 6, GORE_Head_RATE, DoShrapJumpFall, &s_GoreHead[7]},
    {GORE_Head + 7, GORE_Head_RATE, DoShrapJumpFall, &s_GoreHead[8]},
    {GORE_Head + 8, GORE_Head_RATE, DoShrapJumpFall, &s_GoreHead[9]},
    {GORE_Head + 9, GORE_Head_RATE, DoShrapJumpFall, &s_GoreHead[10]},
    {GORE_Head + 10, GORE_Head_RATE, DoShrapJumpFall, &s_GoreHead[11]},
    {GORE_Head + 11, GORE_Head_RATE, DoShrapJumpFall, &s_GoreHead[0]},
};

#define GORE_Leg 1689
#define GORE_Leg_RATE 16

STATE s_GoreLeg[] =
{
    {GORE_Leg + 0, GORE_Leg_RATE, DoShrapJumpFall, &s_GoreLeg[1]},
    {GORE_Leg + 1, GORE_Leg_RATE, DoShrapJumpFall, &s_GoreLeg[2]},
    {GORE_Leg + 2, GORE_Leg_RATE, DoShrapJumpFall, &s_GoreLeg[0]},
};

#define GORE_Eye 1692
#define GORE_Eye_RATE 16

STATE s_GoreEye[] =
{
    {GORE_Eye + 0, GORE_Eye_RATE, DoShrapJumpFall, &s_GoreEye[1]},
    {GORE_Eye + 1, GORE_Eye_RATE, DoShrapJumpFall, &s_GoreEye[2]},
    {GORE_Eye + 2, GORE_Eye_RATE, DoShrapJumpFall, &s_GoreEye[3]},
    {GORE_Eye + 3, GORE_Eye_RATE, DoShrapJumpFall, &s_GoreEye[0]},
};

#define GORE_Torso 1696
#define GORE_Torso_RATE 16

STATE s_GoreTorso[] =
{
    {GORE_Torso + 0, GORE_Torso_RATE, DoShrapJumpFall, &s_GoreTorso[1]},
    {GORE_Torso + 1, GORE_Torso_RATE, DoShrapJumpFall, &s_GoreTorso[2]},
    {GORE_Torso + 2, GORE_Torso_RATE, DoShrapJumpFall, &s_GoreTorso[3]},
    {GORE_Torso + 3, GORE_Torso_RATE, DoShrapJumpFall, &s_GoreTorso[4]},
    {GORE_Torso + 4, GORE_Torso_RATE, DoShrapJumpFall, &s_GoreTorso[5]},
    {GORE_Torso + 5, GORE_Torso_RATE, DoShrapJumpFall, &s_GoreTorso[6]},
    {GORE_Torso + 6, GORE_Torso_RATE, DoShrapJumpFall, &s_GoreTorso[7]},
    {GORE_Torso + 7, GORE_Torso_RATE, DoShrapJumpFall, &s_GoreTorso[0]},
};


#define GORE_Arm 1550
#define GORE_Arm_RATE 16

STATE s_GoreArm[] =
{
    {GORE_Arm + 0, GORE_Arm_RATE, DoShrapJumpFall, &s_GoreArm[1]},
    {GORE_Arm + 1, GORE_Arm_RATE, DoShrapJumpFall, &s_GoreArm[2]},
    {GORE_Arm + 2, GORE_Arm_RATE, DoShrapJumpFall, &s_GoreArm[3]},
    {GORE_Arm + 3, GORE_Arm_RATE, DoShrapJumpFall, &s_GoreArm[4]},
    {GORE_Arm + 4, GORE_Arm_RATE, DoShrapJumpFall, &s_GoreArm[5]},
    {GORE_Arm + 5, GORE_Arm_RATE, DoShrapJumpFall, &s_GoreArm[6]},
    {GORE_Arm + 6, GORE_Arm_RATE, DoShrapJumpFall, &s_GoreArm[7]},
    {GORE_Arm + 7, GORE_Arm_RATE, DoShrapJumpFall, &s_GoreArm[8]},
    {GORE_Arm + 8, GORE_Arm_RATE, DoShrapJumpFall, &s_GoreArm[9]},
    {GORE_Arm + 9, GORE_Arm_RATE, DoShrapJumpFall, &s_GoreArm[10]},
    {GORE_Arm + 10, GORE_Arm_RATE, DoShrapJumpFall, &s_GoreArm[11]},
    {GORE_Arm + 11, GORE_Arm_RATE, DoShrapJumpFall, &s_GoreArm[0]},
};

#define GORE_Lung 903
#define GORE_Lung_RATE 16

STATE s_GoreLung[] =
{
    {GORE_Lung + 0, GORE_Lung_RATE, DoShrapJumpFall, &s_GoreLung[1]},
    {GORE_Lung + 1, GORE_Lung_RATE, DoShrapJumpFall, &s_GoreLung[2]},
    {GORE_Lung + 2, GORE_Lung_RATE, DoShrapJumpFall, &s_GoreLung[3]},
    {GORE_Lung + 3, GORE_Lung_RATE, DoShrapJumpFall, &s_GoreLung[4]},
    {GORE_Lung + 4, GORE_Lung_RATE, DoShrapJumpFall, &s_GoreLung[5]},
    {GORE_Lung + 5, GORE_Lung_RATE, DoShrapJumpFall, &s_GoreLung[6]},
    {GORE_Lung + 6, GORE_Lung_RATE, DoShrapJumpFall, &s_GoreLung[7]},
    {GORE_Lung + 7, GORE_Lung_RATE, DoShrapJumpFall, &s_GoreLung[8]},
    {GORE_Lung + 8, GORE_Lung_RATE, DoShrapJumpFall, &s_GoreLung[9]},
    {GORE_Lung + 9, GORE_Lung_RATE, DoShrapJumpFall, &s_GoreLung[10]},
    {GORE_Lung + 10, GORE_Lung_RATE, DoShrapJumpFall, &s_GoreLung[11]},
    {GORE_Lung + 11, GORE_Lung_RATE, DoShrapJumpFall, &s_GoreLung[0]},
};

#define GORE_Liver 918
#define GORE_Liver_RATE 16

STATE s_GoreLiver[] =
{
    {GORE_Liver + 0, GORE_Liver_RATE, DoShrapJumpFall, &s_GoreLiver[1]},
    {GORE_Liver + 1, GORE_Liver_RATE, DoShrapJumpFall, &s_GoreLiver[2]},
    {GORE_Liver + 2, GORE_Liver_RATE, DoShrapJumpFall, &s_GoreLiver[3]},
    {GORE_Liver + 3, GORE_Liver_RATE, DoShrapJumpFall, &s_GoreLiver[4]},
    {GORE_Liver + 4, GORE_Liver_RATE, DoShrapJumpFall, &s_GoreLiver[5]},
    {GORE_Liver + 5, GORE_Liver_RATE, DoShrapJumpFall, &s_GoreLiver[6]},
    {GORE_Liver + 6, GORE_Liver_RATE, DoShrapJumpFall, &s_GoreLiver[7]},
    {GORE_Liver + 7, GORE_Liver_RATE, DoShrapJumpFall, &s_GoreLiver[8]},
    {GORE_Liver + 8, GORE_Liver_RATE, DoShrapJumpFall, &s_GoreLiver[9]},
    {GORE_Liver + 9, GORE_Liver_RATE, DoShrapJumpFall, &s_GoreLiver[10]},
    {GORE_Liver + 10, GORE_Liver_RATE, DoShrapJumpFall, &s_GoreLiver[11]},
    {GORE_Liver + 11, GORE_Liver_RATE, DoShrapJumpFall, &s_GoreLiver[0]},
};

#define GORE_SkullCap 933
#define GORE_SkullCap_RATE 16

STATE s_GoreSkullCap[] =
{
    {GORE_SkullCap + 0, GORE_SkullCap_RATE, DoShrapJumpFall, &s_GoreSkullCap[1]},
    {GORE_SkullCap + 1, GORE_SkullCap_RATE, DoShrapJumpFall, &s_GoreSkullCap[2]},
    {GORE_SkullCap + 2, GORE_SkullCap_RATE, DoShrapJumpFall, &s_GoreSkullCap[3]},
    {GORE_SkullCap + 3, GORE_SkullCap_RATE, DoShrapJumpFall, &s_GoreSkullCap[4]},
    {GORE_SkullCap + 4, GORE_SkullCap_RATE, DoShrapJumpFall, &s_GoreSkullCap[5]},
    {GORE_SkullCap + 5, GORE_SkullCap_RATE, DoShrapJumpFall, &s_GoreSkullCap[6]},
    {GORE_SkullCap + 6, GORE_SkullCap_RATE, DoShrapJumpFall, &s_GoreSkullCap[7]},
    {GORE_SkullCap + 7, GORE_SkullCap_RATE, DoShrapJumpFall, &s_GoreSkullCap[8]},
    {GORE_SkullCap + 8, GORE_SkullCap_RATE, DoShrapJumpFall, &s_GoreSkullCap[9]},
    {GORE_SkullCap + 9, GORE_SkullCap_RATE, DoShrapJumpFall, &s_GoreSkullCap[10]},
    {GORE_SkullCap + 10, GORE_SkullCap_RATE, DoShrapJumpFall, &s_GoreSkullCap[11]},
    {GORE_SkullCap + 11, GORE_SkullCap_RATE, DoShrapJumpFall, &s_GoreSkullCap[0]},
};


#define GORE_ChunkS 2430
#define GORE_ChunkS_RATE 16

STATE s_GoreChunkS[] =
{
    {GORE_ChunkS + 0, GORE_ChunkS_RATE, DoShrapJumpFall, &s_GoreChunkS[1]},
    {GORE_ChunkS + 1, GORE_ChunkS_RATE, DoShrapJumpFall, &s_GoreChunkS[2]},
    {GORE_ChunkS + 2, GORE_ChunkS_RATE, DoShrapJumpFall, &s_GoreChunkS[3]},
    {GORE_ChunkS + 3, GORE_ChunkS_RATE, DoShrapJumpFall, &s_GoreChunkS[0]},
};

#define GORE_Drip 1562 //2430
#define GORE_Drip_RATE 16

STATE s_GoreDrip[] =
{
    {GORE_Drip + 0, GORE_Drip_RATE, DoShrapJumpFall, &s_GoreDrip[1]},
    {GORE_Drip + 1, GORE_Drip_RATE, DoShrapJumpFall, &s_GoreDrip[2]},
    {GORE_Drip + 2, GORE_Drip_RATE, DoShrapJumpFall, &s_GoreDrip[3]},
    {GORE_Drip + 3, GORE_Drip_RATE, DoShrapJumpFall, &s_GoreDrip[0]},
};

STATE s_FastGoreDrip[] =
{
    {GORE_Drip + 0, GORE_Drip_RATE, DoFastShrapJumpFall, &s_FastGoreDrip[1]},
    {GORE_Drip + 1, GORE_Drip_RATE, DoFastShrapJumpFall, &s_FastGoreDrip[2]},
    {GORE_Drip + 2, GORE_Drip_RATE, DoFastShrapJumpFall, &s_FastGoreDrip[3]},
    {GORE_Drip + 3, GORE_Drip_RATE, DoFastShrapJumpFall, &s_FastGoreDrip[0]},
};

///////////////////////////////////////////////
//
// This GORE mostly for the Accursed Heads
//
///////////////////////////////////////////////

#define GORE_Flame 847
#define GORE_Flame_RATE 8

STATE s_GoreFlame[] =
{
    {GORE_Flame + 0, GORE_Flame_RATE, DoFastShrapJumpFall, &s_GoreFlame[1]},
    {GORE_Flame + 1, GORE_Flame_RATE, DoFastShrapJumpFall, &s_GoreFlame[2]},
    {GORE_Flame + 2, GORE_Flame_RATE, DoFastShrapJumpFall, &s_GoreFlame[3]},
    {GORE_Flame + 3, GORE_Flame_RATE, DoFastShrapJumpFall, &s_GoreFlame[4]},
    {GORE_Flame + 4, GORE_Flame_RATE, DoFastShrapJumpFall, &s_GoreFlame[5]},
    {GORE_Flame + 5, GORE_Flame_RATE, DoFastShrapJumpFall, &s_GoreFlame[6]},
    {GORE_Flame + 6, GORE_Flame_RATE, DoFastShrapJumpFall, &s_GoreFlame[7]},
    {GORE_Flame + 7, GORE_Flame_RATE, DoFastShrapJumpFall, &s_GoreFlame[0]},
};

ANIMATOR DoTracerShrap;
STATE s_TracerShrap[] =
{
    {GORE_Flame + 0, GORE_Flame_RATE, DoTracerShrap, &s_TracerShrap[1]},
    {GORE_Flame + 1, GORE_Flame_RATE, DoTracerShrap, &s_TracerShrap[2]},
    {GORE_Flame + 2, GORE_Flame_RATE, DoTracerShrap, &s_TracerShrap[3]},
    {GORE_Flame + 3, GORE_Flame_RATE, DoTracerShrap, &s_TracerShrap[4]},
    {GORE_Flame + 4, GORE_Flame_RATE, DoTracerShrap, &s_TracerShrap[5]},
    {GORE_Flame + 5, GORE_Flame_RATE, DoTracerShrap, &s_TracerShrap[6]},
    {GORE_Flame + 6, GORE_Flame_RATE, DoTracerShrap, &s_TracerShrap[7]},
    {GORE_Flame + 7, GORE_Flame_RATE, DoTracerShrap, &s_TracerShrap[0]},
};

#define UZI_SHELL 2152
#define UZISHELL_RATE 8
//ANIMATOR DoShellShrap;
STATE s_UziShellShrap[] =
{
    {UZI_SHELL + 0, UZISHELL_RATE, DoShrapJumpFall, &s_UziShellShrap[1]},
    {UZI_SHELL + 1, UZISHELL_RATE, DoShrapJumpFall, &s_UziShellShrap[2]},
    {UZI_SHELL + 2, UZISHELL_RATE, DoShrapJumpFall, &s_UziShellShrap[3]},
    {UZI_SHELL + 3, UZISHELL_RATE, DoShrapJumpFall, &s_UziShellShrap[4]},
    {UZI_SHELL + 4, UZISHELL_RATE, DoShrapJumpFall, &s_UziShellShrap[5]},
    {UZI_SHELL + 5, UZISHELL_RATE, DoShrapJumpFall, &s_UziShellShrap[0]},
};

STATE s_UziShellShrapStill1[] =
{
    {UZI_SHELL + 0, UZISHELL_RATE, NullAnimator, &s_UziShellShrapStill1[0]}
};
STATE s_UziShellShrapStill2[] =
{
    {UZI_SHELL + 1, UZISHELL_RATE, NullAnimator, &s_UziShellShrapStill2[0]}
};
STATE s_UziShellShrapStill3[] =
{
    {UZI_SHELL + 2, UZISHELL_RATE, NullAnimator, &s_UziShellShrapStill3[0]}
};
STATE s_UziShellShrapStill4[] =
{
    {UZI_SHELL + 3, UZISHELL_RATE, NullAnimator, &s_UziShellShrapStill4[0]}
};
STATE s_UziShellShrapStill5[] =
{
    {UZI_SHELL + 4, UZISHELL_RATE, NullAnimator, &s_UziShellShrapStill5[0]}
};
STATE s_UziShellShrapStill6[] =
{
    {UZI_SHELL + 5, UZISHELL_RATE, NullAnimator, &s_UziShellShrapStill6[0]}
};

#define SHOT_SHELL 2180
#define SHOTSHELL_RATE 8
STATE s_ShotgunShellShrap[] =
{
    {SHOT_SHELL + 0, SHOTSHELL_RATE, DoShrapJumpFall, &s_ShotgunShellShrap[1]},
    {SHOT_SHELL + 1, SHOTSHELL_RATE, DoShrapJumpFall, &s_ShotgunShellShrap[2]},
    {SHOT_SHELL + 2, SHOTSHELL_RATE, DoShrapJumpFall, &s_ShotgunShellShrap[3]},
    {SHOT_SHELL + 3, SHOTSHELL_RATE, DoShrapJumpFall, &s_ShotgunShellShrap[4]},
    {SHOT_SHELL + 4, SHOTSHELL_RATE, DoShrapJumpFall, &s_ShotgunShellShrap[5]},
    {SHOT_SHELL + 5, SHOTSHELL_RATE, DoShrapJumpFall, &s_ShotgunShellShrap[6]},
    {SHOT_SHELL + 6, SHOTSHELL_RATE, DoShrapJumpFall, &s_ShotgunShellShrap[7]},
    {SHOT_SHELL + 7, SHOTSHELL_RATE, DoShrapJumpFall, &s_ShotgunShellShrap[0]},
};

STATE s_ShotgunShellShrapStill1[] =
{
    {SHOT_SHELL + 1, SHOTSHELL_RATE, NullAnimator, &s_ShotgunShellShrapStill1[0]}
};
STATE s_ShotgunShellShrapStill2[] =
{
    {SHOT_SHELL + 3, SHOTSHELL_RATE, NullAnimator, &s_ShotgunShellShrapStill2[0]}
};
STATE s_ShotgunShellShrapStill3[] =
{
    {SHOT_SHELL + 7, SHOTSHELL_RATE, NullAnimator, &s_ShotgunShellShrapStill3[0]}
};

#define GORE_FlameChunkA 839
#define GORE_FlameChunkA_RATE 8

STATE s_GoreFlameChunkA[] =
{
    {GORE_FlameChunkA + 0, GORE_FlameChunkA_RATE, DoShrapJumpFall, &s_GoreFlameChunkA[1]},
    {GORE_FlameChunkA + 1, GORE_FlameChunkA_RATE, DoShrapJumpFall, &s_GoreFlameChunkA[2]},
    {GORE_FlameChunkA + 2, GORE_FlameChunkA_RATE, DoShrapJumpFall, &s_GoreFlameChunkA[3]},
    {GORE_FlameChunkA + 3, GORE_FlameChunkA_RATE, DoShrapJumpFall, &s_GoreFlameChunkA[0]},
};

#define GORE_FlameChunkB 843
#define GORE_FlameChunkB_RATE 8

STATE s_GoreFlameChunkB[] =
{
    {GORE_FlameChunkB + 0, GORE_FlameChunkB_RATE, DoShrapJumpFall, &s_GoreFlameChunkB[1]},
    {GORE_FlameChunkB + 1, GORE_FlameChunkB_RATE, DoShrapJumpFall, &s_GoreFlameChunkB[2]},
    {GORE_FlameChunkB + 2, GORE_FlameChunkB_RATE, DoShrapJumpFall, &s_GoreFlameChunkB[3]},
    {GORE_FlameChunkB + 3, GORE_FlameChunkB_RATE, DoShrapJumpFall, &s_GoreFlameChunkB[0]},
};

/////////////////////////////////////////////////////////////////////
//
// General Breaking Shrapnel
//
/////////////////////////////////////////////////////////////////////

#define COIN_SHRAP 2530
#define CoinShrap_RATE 12

STATE s_CoinShrap[] =
{
    {COIN_SHRAP + 0, CoinShrap_RATE, DoShrapJumpFall, &s_CoinShrap[1]},
    {COIN_SHRAP + 1, CoinShrap_RATE, DoShrapJumpFall, &s_CoinShrap[2]},
    {COIN_SHRAP + 2, CoinShrap_RATE, DoShrapJumpFall, &s_CoinShrap[3]},
    {COIN_SHRAP + 3, CoinShrap_RATE, DoShrapJumpFall, &s_CoinShrap[0]},
};

#define MARBEL 5096
#define Marbel_RATE 12

STATE s_Marbel[] =
{
    {MARBEL, Marbel_RATE, DoShrapJumpFall, &s_Marbel[0]},
};

//
// Glass
//

#define GLASS_SHRAP_A 3864
#define GlassShrapA_RATE 12

STATE s_GlassShrapA[] =
{
    {GLASS_SHRAP_A + 0, GlassShrapA_RATE, DoShrapJumpFall, &s_GlassShrapA[1]},
    {GLASS_SHRAP_A + 1, GlassShrapA_RATE, DoShrapJumpFall, &s_GlassShrapA[2]},
    {GLASS_SHRAP_A + 2, GlassShrapA_RATE, DoShrapJumpFall, &s_GlassShrapA[3]},
    {GLASS_SHRAP_A + 3, GlassShrapA_RATE, DoShrapJumpFall, &s_GlassShrapA[4]},
    {GLASS_SHRAP_A + 4, GlassShrapA_RATE, DoShrapJumpFall, &s_GlassShrapA[5]},
    {GLASS_SHRAP_A + 5, GlassShrapA_RATE, DoShrapJumpFall, &s_GlassShrapA[6]},
    {GLASS_SHRAP_A + 6, GlassShrapA_RATE, DoShrapJumpFall, &s_GlassShrapA[7]},
    {GLASS_SHRAP_A + 7, GlassShrapA_RATE, DoShrapJumpFall, &s_GlassShrapA[0]},
};

#define GLASS_SHRAP_B 3872
#define GlassShrapB_RATE 12

STATE s_GlassShrapB[] =
{
    {GLASS_SHRAP_B + 0, GlassShrapB_RATE, DoShrapJumpFall, &s_GlassShrapB[1]},
    {GLASS_SHRAP_B + 1, GlassShrapB_RATE, DoShrapJumpFall, &s_GlassShrapB[2]},
    {GLASS_SHRAP_B + 2, GlassShrapB_RATE, DoShrapJumpFall, &s_GlassShrapB[3]},
    {GLASS_SHRAP_B + 3, GlassShrapB_RATE, DoShrapJumpFall, &s_GlassShrapB[4]},
    {GLASS_SHRAP_B + 4, GlassShrapB_RATE, DoShrapJumpFall, &s_GlassShrapB[5]},
    {GLASS_SHRAP_B + 5, GlassShrapB_RATE, DoShrapJumpFall, &s_GlassShrapB[6]},
    {GLASS_SHRAP_B + 6, GlassShrapB_RATE, DoShrapJumpFall, &s_GlassShrapB[7]},
    {GLASS_SHRAP_B + 7, GlassShrapB_RATE, DoShrapJumpFall, &s_GlassShrapB[0]},
};

#define GLASS_SHRAP_C 3880
#define GlassShrapC_RATE 12

STATE s_GlassShrapC[] =
{
    {GLASS_SHRAP_C + 0, GlassShrapC_RATE, DoShrapJumpFall, &s_GlassShrapC[1]},
    {GLASS_SHRAP_C + 1, GlassShrapC_RATE, DoShrapJumpFall, &s_GlassShrapC[2]},
    {GLASS_SHRAP_C + 2, GlassShrapC_RATE, DoShrapJumpFall, &s_GlassShrapC[3]},
    {GLASS_SHRAP_C + 3, GlassShrapC_RATE, DoShrapJumpFall, &s_GlassShrapC[4]},
    {GLASS_SHRAP_C + 4, GlassShrapC_RATE, DoShrapJumpFall, &s_GlassShrapC[5]},
    {GLASS_SHRAP_C + 5, GlassShrapC_RATE, DoShrapJumpFall, &s_GlassShrapC[6]},
    {GLASS_SHRAP_C + 6, GlassShrapC_RATE, DoShrapJumpFall, &s_GlassShrapC[7]},
    {GLASS_SHRAP_C + 7, GlassShrapC_RATE, DoShrapJumpFall, &s_GlassShrapC[0]},
};

//
// Wood
//

#define WOOD_SHRAP_A 3924
#define WoodShrapA_RATE 12

STATE s_WoodShrapA[] =
{
    {WOOD_SHRAP_A + 0, WoodShrapA_RATE, DoShrapJumpFall, &s_WoodShrapA[1]},
    {WOOD_SHRAP_A + 1, WoodShrapA_RATE, DoShrapJumpFall, &s_WoodShrapA[2]},
    {WOOD_SHRAP_A + 2, WoodShrapA_RATE, DoShrapJumpFall, &s_WoodShrapA[3]},
    {WOOD_SHRAP_A + 3, WoodShrapA_RATE, DoShrapJumpFall, &s_WoodShrapA[4]},
    {WOOD_SHRAP_A + 4, WoodShrapA_RATE, DoShrapJumpFall, &s_WoodShrapA[5]},
    {WOOD_SHRAP_A + 5, WoodShrapA_RATE, DoShrapJumpFall, &s_WoodShrapA[6]},
    {WOOD_SHRAP_A + 6, WoodShrapA_RATE, DoShrapJumpFall, &s_WoodShrapA[7]},
    {WOOD_SHRAP_A + 7, WoodShrapA_RATE, DoShrapJumpFall, &s_WoodShrapA[0]},
};

#define WOOD_SHRAP_B 3932
#define WoodShrapB_RATE 12

STATE s_WoodShrapB[] =
{
    {WOOD_SHRAP_B + 0, WoodShrapB_RATE, DoShrapJumpFall, &s_WoodShrapB[1]},
    {WOOD_SHRAP_B + 1, WoodShrapB_RATE, DoShrapJumpFall, &s_WoodShrapB[2]},
    {WOOD_SHRAP_B + 2, WoodShrapB_RATE, DoShrapJumpFall, &s_WoodShrapB[3]},
    {WOOD_SHRAP_B + 3, WoodShrapB_RATE, DoShrapJumpFall, &s_WoodShrapB[4]},
    {WOOD_SHRAP_B + 4, WoodShrapB_RATE, DoShrapJumpFall, &s_WoodShrapB[5]},
    {WOOD_SHRAP_B + 5, WoodShrapB_RATE, DoShrapJumpFall, &s_WoodShrapB[6]},
    {WOOD_SHRAP_B + 6, WoodShrapB_RATE, DoShrapJumpFall, &s_WoodShrapB[7]},
    {WOOD_SHRAP_B + 7, WoodShrapB_RATE, DoShrapJumpFall, &s_WoodShrapB[0]},
};

#define WOOD_SHRAP_C 3941
#define WoodShrapC_RATE 12

STATE s_WoodShrapC[] =
{
    {WOOD_SHRAP_C + 0, WoodShrapC_RATE, DoShrapJumpFall, &s_WoodShrapC[1]},
    {WOOD_SHRAP_C + 1, WoodShrapC_RATE, DoShrapJumpFall, &s_WoodShrapC[2]},
    {WOOD_SHRAP_C + 2, WoodShrapC_RATE, DoShrapJumpFall, &s_WoodShrapC[3]},
    {WOOD_SHRAP_C + 3, WoodShrapC_RATE, DoShrapJumpFall, &s_WoodShrapC[4]},
    {WOOD_SHRAP_C + 4, WoodShrapC_RATE, DoShrapJumpFall, &s_WoodShrapC[5]},
    {WOOD_SHRAP_C + 5, WoodShrapC_RATE, DoShrapJumpFall, &s_WoodShrapC[6]},
    {WOOD_SHRAP_C + 6, WoodShrapC_RATE, DoShrapJumpFall, &s_WoodShrapC[7]},
    {WOOD_SHRAP_C + 7, WoodShrapC_RATE, DoShrapJumpFall, &s_WoodShrapC[0]},
};

//
// Stone
//

#define STONE_SHRAP_A 3840
#define StoneShrapA_RATE 12

STATE s_StoneShrapA[] =
{
    {STONE_SHRAP_A + 0, StoneShrapA_RATE, DoShrapJumpFall, &s_StoneShrapA[1]},
    {STONE_SHRAP_A + 1, StoneShrapA_RATE, DoShrapJumpFall, &s_StoneShrapA[2]},
    {STONE_SHRAP_A + 2, StoneShrapA_RATE, DoShrapJumpFall, &s_StoneShrapA[3]},
    {STONE_SHRAP_A + 3, StoneShrapA_RATE, DoShrapJumpFall, &s_StoneShrapA[4]},
    {STONE_SHRAP_A + 4, StoneShrapA_RATE, DoShrapJumpFall, &s_StoneShrapA[5]},
    {STONE_SHRAP_A + 5, StoneShrapA_RATE, DoShrapJumpFall, &s_StoneShrapA[6]},
    {STONE_SHRAP_A + 6, StoneShrapA_RATE, DoShrapJumpFall, &s_StoneShrapA[7]},
    {STONE_SHRAP_A + 7, StoneShrapA_RATE, DoShrapJumpFall, &s_StoneShrapA[0]},
};

#define STONE_SHRAP_B 3848
#define StoneShrapB_RATE 12

STATE s_StoneShrapB[] =
{
    {STONE_SHRAP_B + 0, StoneShrapB_RATE, DoShrapJumpFall, &s_StoneShrapB[1]},
    {STONE_SHRAP_B + 1, StoneShrapB_RATE, DoShrapJumpFall, &s_StoneShrapB[2]},
    {STONE_SHRAP_B + 2, StoneShrapB_RATE, DoShrapJumpFall, &s_StoneShrapB[3]},
    {STONE_SHRAP_B + 3, StoneShrapB_RATE, DoShrapJumpFall, &s_StoneShrapB[4]},
    {STONE_SHRAP_B + 4, StoneShrapB_RATE, DoShrapJumpFall, &s_StoneShrapB[5]},
    {STONE_SHRAP_B + 5, StoneShrapB_RATE, DoShrapJumpFall, &s_StoneShrapB[6]},
    {STONE_SHRAP_B + 6, StoneShrapB_RATE, DoShrapJumpFall, &s_StoneShrapB[7]},
    {STONE_SHRAP_B + 7, StoneShrapB_RATE, DoShrapJumpFall, &s_StoneShrapB[0]},
};

#define STONE_SHRAP_C 3856
#define StoneShrapC_RATE 12

STATE s_StoneShrapC[] =
{
    {STONE_SHRAP_C + 0, StoneShrapC_RATE, DoShrapJumpFall, &s_StoneShrapC[1]},
    {STONE_SHRAP_C + 1, StoneShrapC_RATE, DoShrapJumpFall, &s_StoneShrapC[2]},
    {STONE_SHRAP_C + 2, StoneShrapC_RATE, DoShrapJumpFall, &s_StoneShrapC[3]},
    {STONE_SHRAP_C + 3, StoneShrapC_RATE, DoShrapJumpFall, &s_StoneShrapC[4]},
    {STONE_SHRAP_C + 4, StoneShrapC_RATE, DoShrapJumpFall, &s_StoneShrapC[5]},
    {STONE_SHRAP_C + 5, StoneShrapC_RATE, DoShrapJumpFall, &s_StoneShrapC[6]},
    {STONE_SHRAP_C + 6, StoneShrapC_RATE, DoShrapJumpFall, &s_StoneShrapC[7]},
    {STONE_SHRAP_C + 7, StoneShrapC_RATE, DoShrapJumpFall, &s_StoneShrapC[0]},
};

//
// Metal
//

#define METAL_SHRAP_A 3888
#define MetalShrapA_RATE 12

STATE s_MetalShrapA[] =
{
    {METAL_SHRAP_A + 0, MetalShrapA_RATE, DoShrapJumpFall, &s_MetalShrapA[1]},
    {METAL_SHRAP_A + 1, MetalShrapA_RATE, DoShrapJumpFall, &s_MetalShrapA[2]},
    {METAL_SHRAP_A + 2, MetalShrapA_RATE, DoShrapJumpFall, &s_MetalShrapA[3]},
    {METAL_SHRAP_A + 3, MetalShrapA_RATE, DoShrapJumpFall, &s_MetalShrapA[4]},
    {METAL_SHRAP_A + 4, MetalShrapA_RATE, DoShrapJumpFall, &s_MetalShrapA[5]},
    {METAL_SHRAP_A + 5, MetalShrapA_RATE, DoShrapJumpFall, &s_MetalShrapA[6]},
    {METAL_SHRAP_A + 6, MetalShrapA_RATE, DoShrapJumpFall, &s_MetalShrapA[7]},
    {METAL_SHRAP_A + 7, MetalShrapA_RATE, DoShrapJumpFall, &s_MetalShrapA[0]},
};

#define METAL_SHRAP_B 3896
#define MetalShrapB_RATE 12

STATE s_MetalShrapB[] =
{
    {METAL_SHRAP_B + 0, MetalShrapB_RATE, DoShrapJumpFall, &s_MetalShrapB[1]},
    {METAL_SHRAP_B + 1, MetalShrapB_RATE, DoShrapJumpFall, &s_MetalShrapB[2]},
    {METAL_SHRAP_B + 2, MetalShrapB_RATE, DoShrapJumpFall, &s_MetalShrapB[3]},
    {METAL_SHRAP_B + 3, MetalShrapB_RATE, DoShrapJumpFall, &s_MetalShrapB[4]},
    {METAL_SHRAP_B + 4, MetalShrapB_RATE, DoShrapJumpFall, &s_MetalShrapB[5]},
    {METAL_SHRAP_B + 5, MetalShrapB_RATE, DoShrapJumpFall, &s_MetalShrapB[6]},
    {METAL_SHRAP_B + 6, MetalShrapB_RATE, DoShrapJumpFall, &s_MetalShrapB[7]},
    {METAL_SHRAP_B + 7, MetalShrapB_RATE, DoShrapJumpFall, &s_MetalShrapB[0]},
};

#define METAL_SHRAP_C 3904
#define MetalShrapC_RATE 12

STATE s_MetalShrapC[] =
{
    {METAL_SHRAP_C + 0, MetalShrapC_RATE, DoShrapJumpFall, &s_MetalShrapC[1]},
    {METAL_SHRAP_C + 1, MetalShrapC_RATE, DoShrapJumpFall, &s_MetalShrapC[2]},
    {METAL_SHRAP_C + 2, MetalShrapC_RATE, DoShrapJumpFall, &s_MetalShrapC[3]},
    {METAL_SHRAP_C + 3, MetalShrapC_RATE, DoShrapJumpFall, &s_MetalShrapC[4]},
    {METAL_SHRAP_C + 4, MetalShrapC_RATE, DoShrapJumpFall, &s_MetalShrapC[5]},
    {METAL_SHRAP_C + 5, MetalShrapC_RATE, DoShrapJumpFall, &s_MetalShrapC[6]},
    {METAL_SHRAP_C + 6, MetalShrapC_RATE, DoShrapJumpFall, &s_MetalShrapC[7]},
    {METAL_SHRAP_C + 7, MetalShrapC_RATE, DoShrapJumpFall, &s_MetalShrapC[0]},
};

//
// Paper
//

#define PAPER_SHRAP_A 3924
#define PaperShrapA_RATE 12

STATE s_PaperShrapA[] =
{
    {PAPER_SHRAP_A + 0, PaperShrapA_RATE, DoShrapJumpFall, &s_PaperShrapA[1]},
    {PAPER_SHRAP_A + 1, PaperShrapA_RATE, DoShrapJumpFall, &s_PaperShrapA[2]},
    {PAPER_SHRAP_A + 2, PaperShrapA_RATE, DoShrapJumpFall, &s_PaperShrapA[3]},
    {PAPER_SHRAP_A + 3, PaperShrapA_RATE, DoShrapJumpFall, &s_PaperShrapA[0]},
};

#define PAPER_SHRAP_B 3932
#define PaperShrapB_RATE 12

STATE s_PaperShrapB[] =
{
    {PAPER_SHRAP_B + 0, PaperShrapB_RATE, DoShrapJumpFall, &s_PaperShrapB[1]},
    {PAPER_SHRAP_B + 1, PaperShrapB_RATE, DoShrapJumpFall, &s_PaperShrapB[2]},
    {PAPER_SHRAP_B + 2, PaperShrapB_RATE, DoShrapJumpFall, &s_PaperShrapB[3]},
    {PAPER_SHRAP_B + 3, PaperShrapB_RATE, DoShrapJumpFall, &s_PaperShrapB[0]},
};

#define PAPER_SHRAP_C 3941
#define PaperShrapC_RATE 12

STATE s_PaperShrapC[] =
{
    {PAPER_SHRAP_C + 0, PaperShrapC_RATE, DoShrapJumpFall, &s_PaperShrapC[1]},
    {PAPER_SHRAP_C + 1, PaperShrapC_RATE, DoShrapJumpFall, &s_PaperShrapC[2]},
    {PAPER_SHRAP_C + 2, PaperShrapC_RATE, DoShrapJumpFall, &s_PaperShrapC[3]},
    {PAPER_SHRAP_C + 3, PaperShrapC_RATE, DoShrapJumpFall, &s_PaperShrapC[0]},
};

#if 1
SWBOOL MissileHitMatch(short Weapon, short WeaponNum, short hit_sprite)
{
    SPRITEp hsp = &sprite[hit_sprite];

    if (WeaponNum <= -1)
    {
        ASSERT(Weapon >= 0);
        USERp wu = User[Weapon];
        WeaponNum = wu->WeaponNum;

        // can be hit by SO only
        if (SP_TAG7(hsp) == 4)
        {
            if (TEST(wu->Flags2, SPR2_SO_MISSILE))
            {
                DoMatchEverything(NULL, hsp->hitag, -1);
                return TRUE;
            }
            else
            {
                return FALSE;
            }
        }
    }

    if (SP_TAG7(hsp) == 0)
    {
        switch (WeaponNum)
        {
        case WPN_RAIL:
        case WPN_MICRO:
        case WPN_NAPALM:
        case WPN_ROCKET:
            DoMatchEverything(NULL, hsp->hitag, -1);
            return TRUE;
        }
    }
    else if (SP_TAG7(hsp) == 1)
    {
        switch (WeaponNum)
        {
        case WPN_MICRO:
        case WPN_RAIL:
        case WPN_HOTHEAD:
        case WPN_NAPALM:
        case WPN_ROCKET:
            DoMatchEverything(NULL, hsp->hitag, -1);
            return TRUE;
        }
    }
    else if (SP_TAG7(hsp) == 2)
    {
        switch (WeaponNum)
        {
        case WPN_MICRO:
        case WPN_RAIL:
        case WPN_HOTHEAD:
        case WPN_NAPALM:
        case WPN_ROCKET:
        case WPN_UZI:
        case WPN_SHOTGUN:
            DoMatchEverything(NULL, hsp->hitag, -1);
            return TRUE;
        }
    }
    else if (SP_TAG7(hsp) == 3)
    {
        switch (WeaponNum)
        {
        case WPN_STAR:
        case WPN_SWORD:
        case WPN_FIST:
        case WPN_MICRO:
        case WPN_RAIL:
        case WPN_HOTHEAD:
        case WPN_NAPALM:
        case WPN_ROCKET:
        case WPN_UZI:
        case WPN_SHOTGUN:
            DoMatchEverything(NULL, hsp->hitag, -1);
            return TRUE;
        }
    }

    return FALSE;

#if 0
    WPN_STAR
    WPN_UZI
    WPN_SHOTGUN
    WPN_MICRO
    WPN_GRENADE
    WPN_MINE
    WPN_RAIL
    WPN_HEART
    WPN_HOTHEAD
    WPN_NAPALM
    WPN_RING
    WPN_ROCKET
    WPN_SWORD
        WPN_FIST
#endif
}
#endif

int SpawnShrapX(short SpriteNum)
{
    //For shrap that has no Weapon to send over
    SpawnShrap(SpriteNum, -1);
    return 0;
}

int DoLavaErupt(short SpriteNum)
{
    SPRITEp sp = &sprite[SpriteNum];
    USERp u = User[SpriteNum];
    short i,nexti,pnum;
    PLAYERp pp;
    SPRITEp tsp;
    SWBOOL found = FALSE;

    if (TEST_BOOL1(sp))
    {
        TRAVERSE_CONNECT(pnum)
        {
            pp = Player + pnum;
            if (pp->cursectnum >= 0 && TEST(sector[pp->cursectnum].extra, SECTFX_TRIGGER))
            {
                TRAVERSE_SPRITE_SECT(headspritesect[pp->cursectnum],i,nexti)
                {
                    tsp = &sprite[i];

                    if (tsp->statnum == STAT_TRIGGER && SP_TAG7(tsp) == 0 && SP_TAG5(tsp) == 1)
                    {
                        found = TRUE;
                        break;
                    }
                }
                if (found)
                    break;
            }
        }

        if (!found)
            return 0;
    }

    if (!TEST(u->Flags, SPR_ACTIVE))
    {
        // inactive
        if ((u->WaitTics -= synctics) <= 0)
        {
            SET(u->Flags, SPR_ACTIVE);
            u->Counter = 0;
            u->WaitTics = SP_TAG9(sp) * 120L;
        }
    }
    else
    {
        // active
        if ((u->WaitTics -= synctics) <= 0)
        {
            // Stop for this long
            RESET(u->Flags, SPR_ACTIVE);
            u->Counter = 0;
            u->WaitTics = SP_TAG10(sp) * 120L;
        }

        // Counter controls the volume of lava erupting
        // starts out slow and increases to a max
        u->Counter += synctics;
        if (u->Counter > SP_TAG2(sp))
            u->Counter = SP_TAG2(sp);

        if ((RANDOM_P2(1024<<6)>>6) < u->Counter)
        {
            switch (SP_TAG3(sp))
            {
            case 0:
                SpawnShrapX(SpriteNum);
                break;
            case 1:
                InitVulcanBoulder(SpriteNum);
                break;
            }
        }
    }

    return 0;
}


void UserShrapSetup(SHRAPp shrap, STATEp state, int num_shrap)
{
    shrap->state = state;
    shrap->num = num_shrap;
}

#if 0
STATEp UserStateSetup(short base_tile, short num_tiles)
{
    STATEp base_state, stp;
    short tile;

#define USER_PIC 0
#define USER_RATE 12

    base_state = CallocMem(sizeof(STATE) * num_tiles, 1);

    for (stp = base_state, tile = 0; stp->state || tile < num_tiles; stp++, tile++)
    {
        stp->Pic = base_tile + tile;
        stp->Tics = USER_RATE;
        stp->Animator = DoShrapJumpFall;

        // if last tile
        if (tile == num_tiles - 1)
            stp->NextState = base_state;
        else
            stp->NextState = stp + 1;
    }

    return base_state;
}
#endif

int
SpawnShrap(short ParentNum, short Secondary)
{
    SPRITEp parent = &sprite[ParentNum];
    SPRITEp sp;
    USERp u, pu = User[ParentNum];
    short SpriteNum;
    short i;

    /////////////////////////////////////////
    //
    // BREAK shrap types
    //
    /////////////////////////////////////////

    // Individual shraps can be copied to this and then values can be changed
    static SHRAP CustomShrap[20];

    static SHRAP CoinShrap[] =
    {
        {s_CoinShrap, COIN_SHRAP,      5, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {s_MetalShrapA, METAL_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {s_MetalShrapB, METAL_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {s_MetalShrapC, METAL_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

    static SHRAP GlassShrap[] =
    {
        {s_GlassShrapA, GLASS_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {s_GlassShrapB, GLASS_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {s_GlassShrapC, GLASS_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

    static SHRAP WoodShrap[] =
    {
        {s_WoodShrapA, WOOD_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {s_WoodShrapB, WOOD_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {s_WoodShrapC, WOOD_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

    static SHRAP StoneShrap[] =
    {
        {s_StoneShrapA, STONE_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {s_StoneShrapB, STONE_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {s_StoneShrapC, STONE_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

    static SHRAP PaperShrap[] =
    {
        {s_PaperShrapA, PAPER_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {s_PaperShrapB, PAPER_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {s_PaperShrapC, PAPER_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

    static SHRAP MetalShrap[] =
    {
        {s_MetalShrapA, METAL_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {s_MetalShrapB, METAL_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {s_MetalShrapC, METAL_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

    static SHRAP MetalMix[] =
    {
        {s_GlassShrapA, GLASS_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {s_GlassShrapB, GLASS_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {s_GlassShrapC, GLASS_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {s_MetalShrapA, METAL_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {s_MetalShrapB, METAL_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {s_MetalShrapC, METAL_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

    static SHRAP WoodMix[] =
    {
        {s_WoodShrapA, WOOD_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {s_WoodShrapB, WOOD_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {s_WoodShrapC, WOOD_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {s_MetalShrapA, METAL_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {s_MetalShrapB, METAL_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {s_MetalShrapC, METAL_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

    static SHRAP PaperMix[] =
    {
        {s_WoodShrapA, WOOD_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {s_WoodShrapB, WOOD_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {s_WoodShrapC, WOOD_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {s_PaperShrapA, PAPER_SHRAP_A, 2, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {s_PaperShrapB, PAPER_SHRAP_A, 2, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {s_PaperShrapC, PAPER_SHRAP_A, 2, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

    static SHRAP Marbels[] =
    {
        {s_Marbel,      MARBEL,        5, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {s_GlassShrapA, GLASS_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {s_GlassShrapB, GLASS_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {s_GlassShrapC, GLASS_SHRAP_A, 1, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

#if 0
    static SHRAP BloodShrap[] =
    {
        {s_BloodShrap, BLOOD_SHRAP, 8, Z_MID, 200, 600, 100, 500, TRUE, 2048},
        {NULL},
    };
#endif

    ////
    // END - BREAK shrap types
    ////

    static SHRAP EMPShrap[] =
    {
        {s_EMPShrap, EMP, 1, Z_MID, 500, 1100, 300, 600, FALSE, 128},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

    static SHRAP StdShrap[] =
    {
        {s_GoreHead, GORE_Head, 1, Z_TOP, 400, 700, 20, 40, TRUE, 2048},
        {s_GoreLung, GORE_Lung, 2, Z_TOP, 500, 800, 100, 300, TRUE, 2048},
        {s_GoreLiver, GORE_Liver, 1, Z_MID, 300, 500, 100, 150, TRUE, 2048},
        {s_GoreArm, GORE_Arm, 1, Z_MID, 300, 500, 250, 500, TRUE, 2048},
        {s_GoreSkullCap, GORE_SkullCap, 1, Z_TOP, 300, 500, 250, 500, TRUE, 2048},
        {s_FastGoreDrip, GORE_Drip, 8, Z_BOT, 600, 800, 50, 70, FALSE, 2048},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

    static SHRAP HeartAttackShrap[] = // fewer gibs because of the plasma fountain sprites
    {
        {s_GoreLung,     GORE_Lung,       2, Z_TOP, 500, 1100, 300, 600, TRUE, 2048},
        {s_GoreLiver,   GORE_Liver,     1, Z_MID, 500, 1100, 300, 500, TRUE, 2048},
        {s_GoreArm,     GORE_Arm,       2, Z_MID, 500, 1100, 350, 600, TRUE, 2048},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

    static SHRAP SkelGore[] =
    {
        {s_GoreHead, GORE_Head, 1, Z_TOP, 400, 700, 20, 40, TRUE, 2048},
        {s_GoreLung, GORE_Lung, 2, Z_TOP, 500, 800, 100, 300, TRUE, 2048},
        {s_GoreLiver, GORE_Liver, 1, Z_MID, 300, 500, 100, 150, TRUE, 2048},
        {s_GoreSkullCap, GORE_SkullCap, 1, Z_TOP, 300, 500, 100, 150, TRUE, 2048},
        {s_GoreArm, GORE_Arm, 1, Z_MID, 300, 500, 250, 500, TRUE, 2048},
        {s_GoreLeg, GORE_Leg, 2, Z_BOT, 200, 400, 250, 500, TRUE, 2048},
        {s_GoreChunkS, GORE_ChunkS, 4, Z_BOT, 200, 400, 250, 400, TRUE, 2048},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

    static SHRAP UpperGore[] =
    {
        {s_GoreHead, GORE_Head, 1, Z_TOP, 400, 700, 20, 40, TRUE, 2048},
        {s_GoreLung, GORE_Lung, 2, Z_TOP, 500, 800, 100, 300, TRUE, 2048},
        {s_GoreLiver, GORE_Liver, 1, Z_MID, 300, 500, 100, 150, TRUE, 2048},
        {s_GoreSkullCap, GORE_SkullCap, 1, Z_TOP, 300, 500, 100, 150, TRUE, 2048},
        {s_GoreArm, GORE_Arm, 1, Z_MID, 300, 500, 250, 500, TRUE, 2048},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

#if 0
    static SHRAP LowerGore[] =
    {
        {s_GoreLeg, GORE_Leg, 4, Z_BOT, 300, 500, 100, 200, TRUE, 2048},
        {NULL,0,0,0,0,0,0,0,0,0},
    };
#endif

    static SHRAP SmallGore[] =
    {
        {s_GoreDrip, GORE_Drip, 3, Z_TOP, 600, 800, 50, 70, FALSE, 2048},
        {s_FastGoreDrip, GORE_Drip, 3, Z_BOT, 600, 800, 70, 100, FALSE, 2048},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

    static SHRAP FlamingGore[] =
    {
        {s_GoreFlame, GORE_Drip, 2, Z_TOP, 600, 800, 100, 200, FALSE, 2048},
        {s_GoreFlameChunkB, GORE_Drip, 4, Z_MID, 300, 500, 100, 200, FALSE, 2048},
        {s_GoreFlame, GORE_Drip, 2, Z_BOT, 100, 200, 100, 200, FALSE, 2048},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

#if 0
    static SHRAP BoltExpShrap[] =
    {
        {s_GoreFlame, GORE_Drip, 4, Z_MID, 300, 700, 300, 600, TRUE, 2048},
        {s_GoreFlame, GORE_Drip, 4, Z_BOT, 300, 700, 300, 600, TRUE, 2048},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

    static SHRAP TracerExpShrap[] =
    {
        {s_TracerShrap, GORE_Drip, 3, Z_MID, 300, 700, 300, 600, TRUE, 2048},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

    static SHRAP FireballExpShrap1[] =
    {
        {s_GoreFlame, GORE_Drip, 1, Z_MID, 100, 300, 100, 200, TRUE, 2048},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

    static SHRAP FireballExpShrap2[] =
    {
        {s_GoreFlame, GORE_Drip, 2, Z_MID, 100, 300, 100, 200, TRUE, 2048},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

    static SHRAPp FireballExpShrap[] =
    {
        FireballExpShrap1,
        FireballExpShrap2
    };
#endif

    // state, id, num, zlevel, min_jspeed, max_jspeed, min_vel, max_vel,
    // random_disperse, ang_range;
    static SHRAP ElectroShrap[] =
    {
        {s_ElectroShrap, ELECTRO_SHARD, 12, Z_TOP, 200, 600, 100, 500, TRUE, 2048},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

    // state, id, num, zlevel, min_jspeed, max_jspeed, min_vel, max_vel,
    // random_disperse, ang_range;
    static SHRAP LavaShrap1[] =
    {
        {s_GoreFlame, GORE_Drip, 1, Z_TOP, 400, 1400, 100, 400, TRUE, 2048},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

    static SHRAP LavaShrap2[] =
    {
        {s_GoreFlameChunkB, GORE_Drip, 1, Z_TOP, 400, 1400, 100, 400, TRUE, 2048},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

    static SHRAP *LavaShrapTable[] =
    {
        LavaShrap1,
        LavaShrap2
    };

    static SHRAP LavaBoulderShrap[] =
    {
        {s_LavaShard, LAVA_SHARD, 16, Z_MID, 400, 900, 200, 600, TRUE, 2048},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

#if 0
    static SHRAP SectorSquishGore[] =
    {
        {s_FastGoreDrip,    GORE_Drip,   24, Z_MID, -400, -200, 600, 800, FALSE, 2048},
        {NULL,0,0,0,0,0,0,0,0,0},
    };
#endif



    //
    // PLAYER SHRAP
    //

    // state, id, num, zlevel, min_jspeed, max_jspeed, min_vel, max_vel,
    // random_disperse, ang_range;
    static SHRAP PlayerGoreFall[] =
    {
        {s_GoreSkullCap,GORE_SkullCap,  1, Z_TOP, 200, 300, 100, 200, TRUE, 2048},
        {s_GoreLiver,   GORE_Liver,     1, Z_MID, 200, 300, 100, 200, TRUE, 2048},
        {s_GoreLung,   GORE_Lung,       1, Z_MID, 200, 300, 100, 200, TRUE, 2048},
        {s_GoreDrip,    GORE_Drip,      10, Z_MID, 200, 300, 100, 200, FALSE, 2048},
        {s_GoreArm,     GORE_Arm,       1, Z_MID, 200, 300, 100, 200, TRUE, 2048},
        {s_FastGoreDrip,    GORE_Drip,      10, Z_BOT, 200, 300, 100, 200, FALSE, 2048},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

    static SHRAP PlayerGoreFly[] =
    {
        {s_GoreSkullCap,GORE_SkullCap,  1, Z_TOP, 500, 1100, 300, 600, TRUE, 2048},
        {s_GoreTorso,   GORE_Torso,     1, Z_MID, 500, 1100, 300, 500, TRUE, 2048},
        {s_GoreLiver,   GORE_Liver,     1, Z_MID, 200, 300, 100, 200, TRUE, 2048},
        {s_GoreArm,     GORE_Arm,       1, Z_MID, 500, 1100, 350, 600, TRUE, 2048},
        {s_FastGoreDrip,    GORE_Drip,      16, Z_MID, 500, 1100, 350, 600, FALSE, 2048},
        {s_FastGoreDrip,    GORE_Drip,      16, Z_BOT, 500, 1100, 350, 600, FALSE, 2048},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

    static SHRAP PlayerDeadHead[] =
    {
        {s_GoreDrip, GORE_Drip, 2, Z_TOP, 150, 400, 40, 80, TRUE, 2048},
        {s_GoreDrip, GORE_Drip, 2, Z_MID, 150, 400, 40, 80, TRUE, 2048},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

    // state, id, num, zlevel, min_jspeed, max_jspeed, min_vel, max_vel,
    // random_disperse, ang_range;
    static SHRAP PlayerHeadHurl1[] =
    {
        {s_Vomit1, Vomit1, 1, Z_BOT, 250, 400, 100, 200, TRUE, 256},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

#define WALL_FLOOR_SHRAP 4097
    ANIMATOR DoShrapWallFloor;
#if 0
    static SHRAP SectorExpShrap[] =
    {
        {NULL, WALL_FLOOR_SHRAP, 1, Z_BOT, 550, 800, 200, 400, TRUE, 512},
        {NULL,0,0,0,0,0,0,0,0,0},
    };
#endif

    int hz[3];
    short dang = 0;

    //SHRAPp p = StdShrap;
    SHRAPp p = SmallGore;
    short shrap_shade = -15;
    short shrap_xsize = 48, shrap_ysize = 48;
    short retval = TRUE;
    short shrap_pal = PALETTE_DEFAULT;
    int shrap_floor_dist = Z(2);
    int shrap_ceiling_dist = Z(2);
    int nx,ny;
    short jump_grav = ACTOR_GRAVITY;
    short start_ang = 0;
    short shrap_owner = -1;
    int shrap_bounce = FALSE;
    short WaitTics = 64; // for FastShrap
    short shrap_type;
    int shrap_rand_zamt = 0;
    short shrap_ang = parent->ang;
    short shrap_delta_size = 0;
    short shrap_amt = 0;
    extern BREAK_INFOp GlobBreakInfo;

    if (Prediction)
        return 0;

    // Don't spawn shrapnel in invalid sectors gosh dern it!
    if (parent->sectnum < 0 || parent->sectnum >= MAXSECTORS)
    {
        //DSPRINTF(ds,"SpawnShrap: Invalid sector %d, picnum=%d\n",parent->sectnum,parent->picnum);
        MONO_PRINT(ds);
        return 0;
    }

    if (GlobBreakInfo)
    {
        shrap_type = GlobBreakInfo->shrap_type;
        shrap_amt = GlobBreakInfo->shrap_amt;
        GlobBreakInfo = NULL;
        goto AutoShrap;
    }
    else if (TEST(parent->extra, SPRX_BREAKABLE))
    {
        // if no user
        if (!User[parent - sprite])
        {
            // Jump to shrap type
            shrap_type = SP_TAG8(parent);
            goto UserShrap;
        }
        else
        {
            // has a user - is programmed
            change_sprite_stat(parent - sprite, STAT_MISC);
            RESET(parent->extra, SPRX_BREAKABLE);
            RESET(parent->cstat, CSTAT_SPRITE_BLOCK|CSTAT_SPRITE_BLOCK_HITSCAN);
        }
    }

    ASSERT(pu);

    switch (pu->ID)
    {
    case ST1:
        switch (parent->hitag)
        {
        case SPAWN_SPOT:
        {
            if (pu->LastDamage)
                shrap_type = SP_TAG3(parent);
            else
                shrap_type = SP_TAG6(parent);

UserShrap:

            shrap_delta_size = (signed char)SP_TAG10(parent);
            shrap_rand_zamt = SP_TAG9(parent);
            // Hey, better limit this in case mappers go crazy, like I did. :)
            // Kills frame rate!
            shrap_amt = SP_TAG8(parent);
            if (shrap_amt > 5)
                shrap_amt = 5;

AutoShrap:

            switch (shrap_type)
            {
            case SHRAP_NONE:
                return FALSE;

            case SHRAP_GLASS:
                PlaySound(DIGI_BREAKGLASS,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler);
                p = GlassShrap;
                //BreakShrapSetup(GlassShrap, sizeof(GlassShrap), CustomShrap, shrap_amt);
                if (shrap_amt)
                {
                    memcpy(CustomShrap, GlassShrap, sizeof(GlassShrap));
                    CustomShrap->num = shrap_amt;
                    p = CustomShrap;
                }

                shrap_xsize = shrap_ysize = 16 + shrap_delta_size;
                shrap_bounce = TRUE;
                break;

            case SHRAP_GENERIC:
            case SHRAP_STONE:
                PlaySound(DIGI_BREAKSTONES,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler);
                p = StoneShrap;
                if (shrap_amt)
                {
                    memcpy(CustomShrap, StoneShrap, sizeof(StoneShrap));
                    CustomShrap->num = shrap_amt;
                    p = CustomShrap;
                }

                shrap_xsize = shrap_ysize = 8 + shrap_delta_size;
                shrap_bounce = TRUE;
                break;

            case SHRAP_WOOD:
                PlaySound(DIGI_BREAKINGWOOD,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler);
                p = WoodShrap;
                if (shrap_amt)
                {
                    memcpy(CustomShrap, WoodShrap, sizeof(WoodShrap));
                    CustomShrap->num = shrap_amt;
                    p = CustomShrap;
                }

                shrap_xsize = shrap_ysize = 16 + shrap_delta_size;
                shrap_bounce = TRUE;
                break;

            case SHRAP_BLOOD:
                shrap_xsize = shrap_ysize = 16 + shrap_delta_size;
                break;

            case SHRAP_GIBS:
                PlaySound(DIGI_GIBS1,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler);
                p = SmallGore;
                shrap_xsize = shrap_ysize = 34;
                shrap_bounce = FALSE;
                break;

            case SHRAP_TREE_BARK:
                PlaySound(DIGI_BREAKINGWOOD,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler);
                p = WoodShrap;
                if (shrap_amt)
                {
                    memcpy(CustomShrap, WoodShrap, sizeof(WoodShrap));
                    CustomShrap->num = shrap_amt;
                    p = CustomShrap;
                }

                shrap_xsize = shrap_ysize = 16 + shrap_delta_size;
                shrap_bounce = TRUE;
                break;

            case SHRAP_PAPER:
                p = PaperShrap;
                if (shrap_amt)
                {
                    memcpy(CustomShrap, PaperShrap, sizeof(PaperShrap));
                    CustomShrap->num = shrap_amt;
                    p = CustomShrap;
                }

                shrap_xsize = shrap_ysize = 16 + shrap_delta_size;
                break;

            case SHRAP_METAL:
                PlaySound(DIGI_BREAKMETAL,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler);
                p = MetalShrap;
                if (shrap_amt)
                {
                    memcpy(CustomShrap, MetalShrap, sizeof(MetalShrap));
                    CustomShrap->num = shrap_amt;
                    p = CustomShrap;
                }

                shrap_xsize = shrap_ysize = 16 + shrap_delta_size;
                shrap_bounce = TRUE;
                break;


            case SHRAP_COIN:
                PlaySound(DIGI_COINS,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler);
                p = CoinShrap;
                if (shrap_amt)
                {
                    memcpy(CustomShrap, CoinShrap, sizeof(CoinShrap));
                    CustomShrap->num = shrap_amt;
                    p = CustomShrap;
                }

                shrap_xsize = shrap_ysize = 16 + shrap_delta_size;
                shrap_bounce = TRUE;
                break;

            case SHRAP_METALMIX:
                PlaySound(DIGI_BREAKMETAL,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler);
                p = MetalMix;
                if (shrap_amt)
                {
                    memcpy(CustomShrap, MetalMix, sizeof(MetalMix));
                    CustomShrap->num = shrap_amt;
                    p = CustomShrap;
                }

                shrap_xsize = shrap_ysize = 16 + shrap_delta_size;
                shrap_bounce = TRUE;
                break;

            case SHRAP_MARBELS:
            {
#if 0
                short spnum;
                short size;
                SPRITEp ep;
                USERp eu;
                int SpawnLittleExp(int16_t Weapon);

                spnum = SpawnLittleExp(ParentNum);
                ASSERT(spnum >= 0);
                ep = &sprite[spnum];
                eu = User[spnum];

                //eu->xchange = MOVEx(92, ep->ang);
                //eu->ychange = MOVEy(92, ep->ang);

                size = ep->xrepeat/2;
                ep->xrepeat = ep->yrepeat = size + shrap_delta_size;
#endif

                //PlaySound(DIGI_BREAKMARBELS,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler);
                p = Marbels;
                if (shrap_amt)
                {
                    memcpy(CustomShrap, Marbels, sizeof(Marbels));
                    CustomShrap->num = shrap_amt;
                    p = CustomShrap;
                }

                shrap_xsize = shrap_ysize = 10 + shrap_delta_size;
                shrap_bounce = TRUE;
            }
            break;

            case SHRAP_WOODMIX:
                PlaySound(DIGI_BREAKINGWOOD,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler);
                p = WoodMix;
                if (shrap_amt)
                {
                    memcpy(CustomShrap, WoodMix, sizeof(WoodMix));
                    CustomShrap->num = shrap_amt;
                    p = CustomShrap;
                }

                shrap_xsize = shrap_ysize = 16 + shrap_delta_size;
                shrap_bounce = TRUE;
                break;

            case SHRAP_PAPERMIX:
                PlaySound(DIGI_BREAKINGWOOD,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler);
                p = PaperMix;
                if (shrap_amt)
                {
                    memcpy(CustomShrap, PaperMix, sizeof(PaperMix));
                    CustomShrap->num = shrap_amt;
                    p = CustomShrap;
                }

                shrap_xsize = shrap_ysize = 16 + shrap_delta_size;
                shrap_bounce = FALSE;
                break;

            case SHRAP_SO_SMOKE:
                return FALSE;

            case SHRAP_EXPLOSION:
            {
                short spnum;
                short size;
                SPRITEp ep;
//                USERp eu;

                spnum = SpawnLargeExp(ParentNum);
                ASSERT(spnum >= 0);
                //spnum = SpawnSectorExp(ParentNum);
                ep = &sprite[spnum];
//                eu = User[spnum];

                //eu->xchange = MOVEx(92, ep->ang);
                //eu->ychange = MOVEy(92, ep->ang);

                size = ep->xrepeat;
                ep->xrepeat = ep->yrepeat = size + shrap_delta_size;

                return FALSE;
            }

            case SHRAP_LARGE_EXPLOSION:
            {
                short spnum;
                short size;
                SPRITEp ep;
//                USERp eu;

                //spnum = SpawnSectorExp(ParentNum);
                spnum = SpawnLargeExp(ParentNum);
                ASSERT(spnum >= 0);
                ep = &sprite[spnum];
//                eu = User[spnum];

                //eu->xchange = MOVEx(92, ep->ang);
                //eu->ychange = MOVEy(92, ep->ang);

                size = ep->xrepeat;
                ep->xrepeat = ep->yrepeat = size + shrap_delta_size;

                InitPhosphorus(spnum);

                return FALSE;
            }

            default:
            {
                return FALSE;
            }
            }
            break;
        }

        default:
            p = LavaShrapTable[RANDOM_P2(2<<8)>>8];
        }
        break;

    case BREAK_BARREL:
        PlaySound(DIGI_BREAKDEBRIS,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler);
        p = WoodShrap;
        shrap_xsize = shrap_ysize = 24;
        shrap_bounce = TRUE;
        ChangeState(parent - sprite, s_BreakBarrel);
        break;
    case BREAK_LIGHT:
        PlaySound(DIGI_BREAKGLASS,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler);
        p = GlassShrap;
        shrap_xsize = shrap_ysize = 24;
        shrap_bounce = TRUE;
        ChangeState(parent - sprite, s_BreakLight);
        break;
    case BREAK_PEDISTAL:
        PlaySound(DIGI_BREAKSTONES,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler);
        p = StoneShrap;
        shrap_xsize = shrap_ysize = 24;
        shrap_bounce = TRUE;
        ChangeState(parent - sprite, s_BreakPedistal);
        break;
    case BREAK_BOTTLE1:
        PlaySound(DIGI_BREAKGLASS,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler);
        p = GlassShrap;
        shrap_xsize = shrap_ysize = 8;
        shrap_bounce = TRUE;
        ChangeState(parent - sprite, s_BreakBottle1);
        break;
    case BREAK_BOTTLE2:
        PlaySound(DIGI_BREAKGLASS,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler);
        p = GlassShrap;
        shrap_xsize = shrap_ysize = 8;
        shrap_bounce = TRUE;
        ChangeState(parent - sprite, s_BreakBottle2);
        break;
    case BREAK_MUSHROOM:
        PlaySound(DIGI_BREAKDEBRIS,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler);
        p = StoneShrap;
        shrap_xsize = shrap_ysize = 4;
        shrap_bounce = TRUE;
        SetSuicide(parent - sprite); // kill next iteration
        break;
    case BOLT_EXP:
        return FALSE;
//        p = BoltExpShrap;
//        break;
    case TANK_SHELL_EXP:
        return FALSE;
//        p = BoltExpShrap;
//        break;
    case TRACER_EXP:
        return FALSE;
//        p = TracerExpShrap;
//        shrap_xsize = shrap_ysize = 20;
//        WaitTics = 10;
//        break;
    case BOLT_THINMAN_R1:
        p = MetalShrap;
        if (shrap_amt)
        {
            memcpy(CustomShrap, MetalShrap, sizeof(MetalShrap));
            CustomShrap->num = 1;
            p = CustomShrap;
        }

        shrap_xsize = shrap_ysize = 10;
        break;
    case LAVA_BOULDER:
        PlaySound(DIGI_BREAKSTONES,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler);
        p = LavaBoulderShrap;
        shrap_owner = parent->owner;
        shrap_xsize = shrap_ysize = 24;
        shrap_bounce = TRUE;
        break;
    case SECTOR_EXP:
        //p = SectorExpShrap;
        //break;
        return FALSE;
    case GRENADE_EXP:
        //p = SectorExpShrap;
        //break;
        return FALSE;
    case FIREBALL_EXP:
        return FALSE;
//        p = FireballExpShrap[RANDOM_P2(2<<8)>>8];
//        shrap_pal = pu->spal;
        break;
    case ELECTRO_PLAYER:
    case ELECTRO_ENEMY:
        shrap_owner = parent->owner;
        p = ElectroShrap;
        shrap_xsize = shrap_ysize = 20;
        break;
    case COOLIE_RUN_R0:
        if (Secondary == WPN_NM_SECTOR_SQUISH)
            break;
//        return (FALSE);
        break;
    case NINJA_DEAD:
        return FALSE;
        break;
    case NINJA_Head_R0:
    {
        extern STATEp sg_PlayerHeadHurl[];

        if (pu->Rot == sg_PlayerHeadHurl)
        {
            p = PlayerHeadHurl1;
        }
        else
        {
            p = PlayerDeadHead;
            shrap_xsize = shrap_ysize = 16+8;
            shrap_bounce = TRUE;
        }
        break;
    }
    case GIRLNINJA_RUN_R0:
        p = StdShrap;
        break;
    case NINJA_RUN_R0:
    {
        p = StdShrap;
        if (pu->PlayerP)
        {
            PLAYERp pp = pu->PlayerP;

            if (pp->DeathType == PLAYER_DEATH_CRUMBLE)
                p = PlayerGoreFall;
            else
                p = PlayerGoreFly;
        }
        break;
    }
    case GORO_RUN_R0:
        p = StdShrap;
        shrap_xsize = shrap_ysize = 64;
        break;
    case COOLG_RUN_R0:
        p = UpperGore;
        break;
    case RIPPER_RUN_R0:
        p = StdShrap;
        if (pu->spal != 0)
            shrap_xsize = shrap_ysize = 64;
        else
            shrap_xsize = shrap_ysize = 32;
        break;
    case RIPPER2_RUN_R0:
        p = StdShrap;
        if (pu->spal != 0)
            shrap_xsize = shrap_ysize = 64;
        else
            shrap_xsize = shrap_ysize = 32;
        break;
    case SERP_RUN_R0:
        p = StdShrap;
        //return (FALSE);
        break;
    case SUMO_RUN_R0:
        p = StdShrap;
        break;
    case SKEL_RUN_R0:
        p = SkelGore;
        shrap_pal = PALETTE_SKEL_GORE;
        break;
    case HORNET_RUN_R0:
        p = SmallGore;
        shrap_pal = PALETTE_SKEL_GORE;
        break;
    case SKULL_R0:
    case SKULL_R0 + 1:
        p = FlamingGore;
        break;
    case SKULL_SERP:
        return FALSE;
    case BETTY_R0:
    case TRASHCAN:
    case PACHINKO1:
    case PACHINKO2:
    case PACHINKO3:
    case PACHINKO4:
    case 623:
        PlaySound(DIGI_BREAKGLASS,&parent->x,&parent->y,&parent->z,v3df_dontpan|v3df_doppler);
        p = MetalShrap;
        shrap_xsize = shrap_ysize = 10;
        break;
    case ZILLA_RUN_R0:
        p = MetalShrap;
        shrap_xsize = shrap_ysize = 10;
        break;
    case EMP:
        p = EMPShrap;
        shrap_xsize = shrap_ysize = 8;
        shrap_bounce = FALSE;
        break;
    }

    // second sprite involved
    // most of the time is is the weapon
    if (Secondary >= 0)
    {
        USERp wu = User[Secondary];

        if (wu->PlayerP && wu->PlayerP->sop_control)
        {
            p = StdShrap;
        }
        else
            switch (wu->ID)
            {
            case PLASMA_FOUNTAIN:
                p = HeartAttackShrap;
                break;
            }
    }

    hz[Z_TOP] = SPRITEp_TOS(parent);        // top
    hz[Z_BOT] = SPRITEp_BOS(parent);        // bottom
    hz[Z_MID] = DIV2(hz[0] + hz[2]);        // mid

    for (; p->id; p++)
    {
        if (!p->random_disperse)
        {
            //dang = (2048 / p->num);
            start_ang = NORM_ANGLE(shrap_ang - DIV2(p->ang_range));
            dang = (p->ang_range / p->num);
        }

        for (i = 0; i < p->num; i++)
        {
            SpriteNum = SpawnSprite(STAT_SKIP4, p->id, p->state, parent->sectnum,
                                    parent->x, parent->y, hz[p->zlevel], shrap_ang, 512);

            sp = &sprite[SpriteNum];
            u = User[SpriteNum];

            if (p->random_disperse)
            {
                sp->ang = shrap_ang + (RANDOM_P2(p->ang_range<<5)>>5) - DIV2(p->ang_range);
                sp->ang = NORM_ANGLE(sp->ang);
            }
            else
            {
                sp->ang = start_ang + (i * dang);
                sp->ang = NORM_ANGLE(sp->ang);
            }

            // for FastShrap
            u->zchange = labs(u->jump_speed*4) - RANDOM_RANGE(labs(u->jump_speed)*8)*2;
            u->WaitTics = WaitTics + RANDOM_RANGE(WaitTics/2);

            switch (u->ID)
            {
            case GORE_Drip:
                shrap_bounce = FALSE;
                break;
            case GORE_Lung:
                shrap_xsize = 20;
                shrap_ysize = 20;
                shrap_bounce = FALSE;
                break;
            case GORE_Liver:
                shrap_xsize = 20;
                shrap_ysize = 20;
                shrap_bounce = FALSE;
                break;
            case GORE_SkullCap:
                shrap_xsize = 24;
                shrap_ysize = 24;
                shrap_bounce = TRUE;
                break;
            case GORE_Arm:
                shrap_xsize = 21;
                shrap_ysize = 21;
                shrap_bounce = FALSE;
                break;
            case GORE_Head:
                shrap_xsize = 26;
                shrap_ysize = 30;
                shrap_bounce = TRUE;
                break;
            case Vomit1:
                shrap_bounce = FALSE;
                sp->z -= Z(4);
                shrap_xsize = u->sx = 12 + (RANDOM_P2(32<<8)>>8);
                shrap_ysize = u->sy = 12 + (RANDOM_P2(32<<8)>>8);
                u->Counter = (RANDOM_P2(2048<<5)>>5);

                nx = sintable[NORM_ANGLE(sp->ang+512)]>>6;
                ny = sintable[sp->ang]>>6;
                move_missile(SpriteNum, nx, ny, 0, Z(8), Z(8), CLIPMASK_MISSILE, MISSILEMOVETICS);

                if (RANDOM_P2(1024)<700)
                    u->ID = 0;

                break;
            case EMP:
                shrap_bounce = FALSE;
                sp->z -= Z(4);
                //sp->ang = NORM_ANGLE(sp->ang + 1024);
                shrap_xsize = u->sx = 5 + (RANDOM_P2(4<<8)>>8);
                shrap_ysize = u->sy = 5 + (RANDOM_P2(4<<8)>>8);
                break;
            }

            sp->shade = shrap_shade;
            sp->xrepeat = shrap_xsize;
            sp->yrepeat = shrap_ysize;
            sp->clipdist = 16L >> 2;

            if (shrap_owner >= 0)
            {
                SetOwner(shrap_owner, SpriteNum);
            }

            if (shrap_rand_zamt)
            {
                sp->z += Z(RANDOM_RANGE(shrap_rand_zamt) - (shrap_rand_zamt/2));
            }

            sp->pal = u->spal = shrap_pal;

            sp->xvel = p->min_vel*2;
            sp->xvel += RANDOM_RANGE(p->max_vel - p->min_vel);

            u->floor_dist = shrap_floor_dist;
            u->ceiling_dist = shrap_ceiling_dist;
            u->jump_speed = p->min_jspeed;
            u->jump_speed += RANDOM_RANGE(p->max_jspeed - p->min_jspeed);
            u->jump_speed = -u->jump_speed;

            DoBeginJump(SpriteNum);
            u->jump_grav = jump_grav;

            u->xchange = MOVEx(sp->xvel, sp->ang);
            u->ychange = MOVEy(sp->xvel, sp->ang);

            if (!shrap_bounce)
                SET(u->Flags, SPR_BOUNCE);
        }
    }

    return retval;
}

int
DoShrapMove(int16_t SpriteNum)
{
    USERp u = User[SpriteNum];

    u->ret = move_missile(SpriteNum, u->xchange, u->ychange, 0, u->ceiling_dist, u->floor_dist, CLIPMASK_MISSILE, MISSILEMOVETICS*2);

    return 0;
}

#if 1
int
DoVomit(short SpriteNum)
{
    SPRITEp sp = &sprite[SpriteNum];
    USERp u = User[SpriteNum];

    u->Counter = NORM_ANGLE(u->Counter + (30*MISSILEMOVETICS));
    sp->xrepeat = u->sx + ((12 * sintable[NORM_ANGLE(u->Counter+512)]) >> 14);
    sp->yrepeat = u->sy + ((12 * sintable[u->Counter]) >> 14);

    if (TEST(u->Flags, SPR_JUMPING))
    {
        DoJump(SpriteNum);
        DoJump(SpriteNum);
        DoShrapMove(SpriteNum);
    }
    else if (TEST(u->Flags, SPR_FALLING))
    {
        DoFall(SpriteNum);
        DoFall(SpriteNum);
        DoShrapMove(SpriteNum);
    }
    else
    {
        ChangeState(SpriteNum, s_VomitSplash);
        DoFindGroundPoint(SpriteNum);
        MissileWaterAdjust(SpriteNum);
        sp->z = u->loz;
        u->WaitTics = 60;
        u->sx = sp->xrepeat;
        u->sy = sp->yrepeat;
        return 0;
    }

    if (TEST(u->ret, HIT_MASK) == HIT_SPRITE)
    {
        short hit_sprite = NORM_SPRITE(u->ret);
        if (TEST(sprite[hit_sprite].extra, SPRX_PLAYER_OR_ENEMY))
        {
            DoDamage(hit_sprite, SpriteNum);
            //KillSprite(SpriteNum);
            return 0;
        }
    }

    //if (u->ID)
    //    DoDamageTest(SpriteNum);

    return 0;
}
#else
int
DoVomit(short SpriteNum)
{
    SPRITEp sp = &sprite[SpriteNum];
    USERp u = User[SpriteNum];

    u->Counter = NORM_ANGLE(u->Counter + (30*MISSILEMOVETICS));
    sp->xrepeat = u->sx + ((12 * sintable[NORM_ANGLE(u->Counter+512)]) >> 14);
    sp->yrepeat = u->sy + ((12 * sintable[u->Counter]) >> 14);

    if (TEST(u->Flags, SPR_JUMPING))
    {
        DoShrapVelocity(SpriteNum);
    }
    else if (TEST(u->Flags, SPR_FALLING))
    {
        DoShrapVelocity(SpriteNum);
    }
    else
    {
        ChangeState(SpriteNum, s_VomitSplash);
        DoFindGroundPoint(SpriteNum);
        MissileWaterAdjust(SpriteNum);
        sp->z = u->loz;
        u->WaitTics = 60;
        u->sx = sp->xrepeat;
        u->sy = sp->yrepeat;
        return 0;
    }

    if (TEST(u->ret, HIT_MASK) == HIT_SPRITE)
    {
        short hit_sprite = NORM_SPRITE(u->ret);
        if (TEST(sprite[hit_sprite].extra, SPRX_PLAYER_OR_ENEMY))
        {
            DoDamage(hit_sprite, SpriteNum);
            //KillSprite(SpriteNum);
            return 0;
        }
    }

    return 0;
}
#endif


int
DoVomitSplash(short SpriteNum)
{
    USERp u = User[SpriteNum];

    if ((u->WaitTics-=MISSILEMOVETICS) < 0)
    {
        KillSprite(SpriteNum);
        return 0;
    }

    return 0;
}

int
DoFastShrapJumpFall(short SpriteNum)
{
    SPRITEp sp = &sprite[SpriteNum];
    USERp u = User[SpriteNum];

    sp->x += u->xchange*2;
    sp->y += u->ychange*2;
    sp->z += u->zchange*2;

    u->WaitTics -= MISSILEMOVETICS;
    if (u->WaitTics <= 0)
        KillSprite(SpriteNum);

    return 0;
}

int
DoTracerShrap(short SpriteNum)
{
    SPRITEp sp = &sprite[SpriteNum];
    USERp u = User[SpriteNum];

    sp->x += u->xchange;
    sp->y += u->ychange;
    sp->z += u->zchange;

    u->WaitTics -= MISSILEMOVETICS;
    if (u->WaitTics <= 0)
        KillSprite(SpriteNum);

    return 0;
}

//#define ShrapKillSprite(num) _Shrap_Kill_Sprite(num, __FILE__, __LINE__) //#define DoShrapVelocity(num) _Do_Shrap_Velocity(num, __FILE__, __LINE__)

int
DoShrapJumpFall(short SpriteNum)
{
    USERp u = User[SpriteNum];

    if (TEST(u->Flags, SPR_JUMPING))
    {
        DoShrapVelocity(SpriteNum);
    }
    else if (TEST(u->Flags, SPR_FALLING))
    {
        DoShrapVelocity(SpriteNum);
    }
    else
    {
        if (!TEST(u->Flags, SPR_BOUNCE))
        {
            DoShrapVelocity(SpriteNum);
            return 0;
        }

        if (u->ID == GORE_Drip)
            ChangeState(SpriteNum, s_GoreFloorSplash);
        else
            ShrapKillSprite(SpriteNum);
    }


    return 0;
}

int
DoShrapDamage(short SpriteNum)
{
    SPRITEp sp = &sprite[SpriteNum];
    USERp u = User[SpriteNum];

    if (TEST(u->Flags, SPR_JUMPING))
    {
        DoJump(SpriteNum);
        DoShrapMove(SpriteNum);
    }
    else if (TEST(u->Flags, SPR_FALLING))
    {
        DoFall(SpriteNum);
        DoShrapMove(SpriteNum);
    }
    else
    {
        if (!TEST(u->Flags, SPR_BOUNCE))
        {
            SET(u->Flags, SPR_BOUNCE);
            u->jump_speed = -300;
            sp->xvel >>= 2;
            DoBeginJump(SpriteNum);
            return 0;
        }

        KillSprite(SpriteNum);
        return 0;
    }

    if (u->ret)
    {
        switch (TEST(u->ret, HIT_MASK))
        {
        case HIT_SPRITE:
        {
            WeaponMoveHit(SpriteNum);
            KillSprite(SpriteNum);
            return 0;
        }
        }
    }

    return 0;
}

int
SpawnBlood(short SpriteNum, short Weapon, short hit_ang, int hit_x, int hit_y, int hit_z)
{
    SPRITEp sp = &sprite[SpriteNum];
    SPRITEp np;
    USERp nu, u;
    short i,New;


    // state, id, num, zlevel, min_jspeed, max_jspeed, min_vel, max_vel,
    // random_disperse, ang_range;

    static SHRAP UziBlood[] =
    {
        {s_GoreDrip, GORE_Drip, 1, Z_MID, 100, 250, 10, 20, TRUE, 512},  // 70,200 vels
        //{s_GoreSplash, PLASMA_Drip, 1, Z_BOT, 0, 0, 0, 0, FALSE, 512},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

    static SHRAP SmallBlood[] =
    {
        {s_GoreDrip, GORE_Drip, 1, Z_TOP, 100, 250, 10, 20, TRUE, 512},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

    static SHRAP PlasmaFountainBlood[] =
    {
        {s_PlasmaDrip, PLASMA_Drip, 1, Z_TOP, 200, 500, 100, 300, TRUE, 16},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

    static SHRAP SomeBlood[] =
    {
        {s_GoreDrip, GORE_Drip, 1, Z_TOP, 100, 250, 10, 20, TRUE, 512},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

#if 0
    static SHRAP MoreBlood[] =
    {
        {s_GoreDrip, GORE_Drip, 2, Z_TOP, 100, 250, 10, 20, TRUE, 512},
        {NULL,0,0,0,0,0,0,0,0,0},
    };
#endif

    static SHRAP ExtraBlood[] =
    {
        {s_GoreDrip, GORE_Drip, 4, Z_TOP, 100, 250, 10, 20, TRUE, 512},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

    static SHRAP HariKariBlood[] =
    {
        {s_FastGoreDrip, GORE_Drip, 32, Z_TOP, 200, 650, 70, 100, TRUE, 1024},
        {NULL,0,0,0,0,0,0,0,0,0},
    };

#if 0
    static SHRAP SwordPowerup[] =
    {
        {s_ElectroShrap, ELECTRO_SHARD, 16, Z_TOP, 75, 200, 70, 150, TRUE, 512},
        {NULL,0,0,0,0,0,0,0,0,0},
    };
#endif

    short dang = 0;

    SHRAPp p = UziBlood;
    short shrap_shade = -15;
    short shrap_xsize = 20, shrap_ysize = 20;
    short retval = TRUE;
    short shrap_pal = PALETTE_DEFAULT;
    short start_ang = 0;

    u = User[SpriteNum];

    switch (u->ID)
    {
    case TRASHCAN:
    case PACHINKO1:
    case PACHINKO2:
    case PACHINKO3:
    case PACHINKO4:
    case 623:
    case ZILLA_RUN_R0:
        return 0;   // Don't put blood on trashcan
    }

    // second sprite involved
    // most of the time is the weapon
    if (Weapon >= 0)
    {
        SPRITEp wp = &sprite[Weapon];
        USERp wu = User[Weapon];

        switch (wu->ID)
        {
        case NINJA_RUN_R0: //sword
            // if sprite and weapon are the same it must be HARIII-KARIII
            if (sp == wp)
            {
                p = HariKariBlood;
                hit_ang = sp->ang;
                hit_x = sp->x;
                hit_y = sp->y;
                hit_z = SPRITEp_TOS(wp) + DIV16(SPRITEp_SIZE_Z(wp));
            }
            else
            {
                p = ExtraBlood;
                hit_ang = NORM_ANGLE(wp->ang + 1024);
                hit_x = sp->x;
                hit_y = sp->y;
                hit_z = SPRITEp_TOS(wp) + DIV4(SPRITEp_SIZE_Z(wp));

                //ASSERT(wu->PlayerP);
            }
            break;
        case SERP_RUN_R0:
            p = ExtraBlood;
            hit_ang = NORM_ANGLE(wp->ang + 1024);
            hit_x = sp->x;
            hit_y = sp->y;
            hit_z = SPRITEp_TOS(sp) + DIV4(SPRITEp_SIZE_Z(sp));
            break;
        case BLADE1:
        case BLADE2:
        case BLADE3:
        case 5011:
            p = SmallBlood;
            hit_ang = NORM_ANGLE(ANG2SPRITE(sp, wp) + 1024);
            hit_x = sp->x;
            hit_y = sp->y;
            hit_z = wp->z - DIV2(SPRITEp_SIZE_Z(wp));
            break;
        case STAR1:
        case CROSSBOLT:
            p = SomeBlood;
            hit_ang = NORM_ANGLE(wp->ang + 1024);
            hit_x = sp->x;
            hit_y = sp->y;
            hit_z = wp->z;
            break;
        case PLASMA_FOUNTAIN:
            p = PlasmaFountainBlood;
            hit_ang = wp->ang;
            hit_x = sp->x;
            hit_y = sp->y;
            hit_z = SPRITEp_TOS(sp) + DIV4(SPRITEp_SIZE_Z(sp));
            break;
        default:
            p = SomeBlood;
            hit_ang = NORM_ANGLE(wp->ang + 1024);
            hit_x = sp->x;
            hit_y = sp->y;
            hit_z = SPRITEp_TOS(wp) + DIV4(SPRITEp_SIZE_Z(wp));
            break;
        }
    }
    else
    {
        hit_ang = NORM_ANGLE(hit_ang + 1024);
    }

    for (; p->state; p++)
    {
        if (!p->random_disperse)
        {
            start_ang = NORM_ANGLE(hit_ang - DIV2(p->ang_range)+1024);
            dang = (p->ang_range / p->num);
        }

        for (i = 0; i < p->num; i++)
        {
            New = SpawnSprite(STAT_SKIP4, p->id, p->state, sp->sectnum,
                              hit_x, hit_y, hit_z, hit_ang, 0);
            np = &sprite[New];
            nu = User[New];

            switch (nu->ID)
            {
            case ELECTRO_SHARD:
                shrap_xsize = 7;
                shrap_ysize = 7;
                break;

            case PLASMA_Drip:
                // Don't do central blood splats for every hitscan
                if (RANDOM_P2(1024) < 950)
                {
                    np->xrepeat = np->yrepeat = 0;
                }
                if (RANDOM_P2(1024) < 512)
                    SET(np->cstat, CSTAT_SPRITE_XFLIP);
                //shrap_xsize = 96;
                //shrap_ysize = 75;
                //shrap_xsize = 10;
                //shrap_ysize = 10;
                break;
            }

            if (p->random_disperse)
            {
                np->ang = hit_ang + (RANDOM_P2(p->ang_range<<5)>>5) - DIV2(p->ang_range);
                np->ang = NORM_ANGLE(np->ang);
            }
            else
            {
                np->ang = start_ang + (i * dang);
                np->ang = NORM_ANGLE(np->ang);
            }

            SET(nu->Flags, SPR_BOUNCE);

            np->shade = shrap_shade;
            np->xrepeat = shrap_xsize;
            np->yrepeat = shrap_ysize;
            np->clipdist = 16L >> 2;

            np->pal = nu->spal = shrap_pal;

            np->xvel = p->min_vel;
            np->xvel += RANDOM_RANGE(p->max_vel - p->min_vel);

            // special case
            // blood coming off of actors should have the acceleration of the actor
            // so add it in
            np->xvel += sp->xvel;

            nu->ceiling_dist = nu->floor_dist = Z(2);
            nu->jump_speed = p->min_jspeed;
            nu->jump_speed += RANDOM_RANGE(p->max_jspeed - p->min_jspeed);
            nu->jump_speed = -nu->jump_speed;

            //setspritez(New, (vec3_t *)np);
            nu->xchange = MOVEx(np->xvel, np->ang);
            nu->ychange = MOVEy(np->xvel, np->ang);

            // for FastShrap
            nu->zchange = labs(nu->jump_speed*4) - RANDOM_RANGE(labs(nu->jump_speed)*8);
            nu->WaitTics = 64 + RANDOM_P2(32);

            SET(u->Flags, SPR_BOUNCE);

            DoBeginJump(New);
        }
    }

    return retval;
}


SWBOOL
VehicleMoveHit(short SpriteNum)
{
    USERp u = User[SpriteNum];
    SPRITEp cp;
    SECTOR_OBJECTp sop;
    SECTOR_OBJECTp hsop;
    SWBOOL TestKillSectorObject(SECTOR_OBJECTp);
    short controller;

    if (!u->ret)
        return FALSE;

    sop = u->sop_parent;

    // sprite controlling sop
    cp = sop->controller;
    controller = cp - sprite;

    switch (TEST(u->ret, HIT_MASK))
    {
    case HIT_SECTOR:
    {
        short hit_sect = NORM_SECTOR(u->ret);
        SECTORp sectp = &sector[hit_sect];

        if (TEST(sectp->extra, SECTFX_SECTOR_OBJECT))
        {
            // shouldn't ever really happen
        }

        return TRUE;
    }

    case HIT_SPRITE:
    {
        short hit_sprite = NORM_SPRITE(u->ret);
        SPRITEp hsp = &sprite[hit_sprite];

        if (TEST(hsp->extra, SPRX_BREAKABLE))
        {
            HitBreakSprite(hit_sprite, u->ID);
            return TRUE;
        }

        if (TEST(hsp->extra, SPRX_PLAYER_OR_ENEMY))
        {
            if (hit_sprite != cp->owner)
            {
                DoDamage(hit_sprite, controller);
                return TRUE;
            }
        }
        else
        {
            if (hsp->statnum == STAT_MINE_STUCK)
            {
                DoDamage(hit_sprite, SpriteNum);
                return TRUE;
            }
        }

        return TRUE;
    }

    case HIT_WALL:
    {
        short hit_wall = NORM_WALL(u->ret);
        WALLp wph = &wall[hit_wall];

        if (TEST(wph->extra, WALLFX_SECTOR_OBJECT))
        {
            // sector object collision
            if ((hsop = DetectSectorObjectByWall(wph)))
            {
#if 1
                SopDamage(hsop, sop->ram_damage);
                if (hsop->max_damage <= 0)
                    SopCheckKill(hsop);
                else
                    DoSpawnSpotsForDamage(hsop->match_event);
#else
                // drivable damage is DIE_HARD type
                if (hsop->max_damage != -9999 && sop->ram_damage)
                {
                    hsop->max_damage -= sop->ram_damage;
                    if (hsop->max_damage <= 0)
                    {
                        TestKillSectorObject(hsop);
                    }
                    else
                    {
                        DoSpawnSpotsForDamage(hsop->match_event);
                    }
                }
#endif
            }
        }

        return TRUE;
    }
    }

    return FALSE;
}


SWBOOL
WeaponMoveHit(short SpriteNum)
{
    USERp u = User[SpriteNum];
    SPRITEp sp = User[SpriteNum]->SpriteP;


    if (!u->ret)
        return FALSE;

    switch (TEST(u->ret, HIT_MASK))
    {
    case HIT_PLAX_WALL:
        SetSuicide(SpriteNum);
        return TRUE;

    case HIT_SECTOR:
    {
        short hit_sect;
        SECTORp sectp;
        SECTOR_OBJECTp sop;

        hit_sect = NORM_SECTOR(u->ret);
        sectp = &sector[hit_sect];

        ASSERT(sectp->extra != -1);

        // hit floor - closer to floor than ceiling
        if (sp->z > DIV2(u->hiz + u->loz))
        {
            // hit a floor sprite
            if (u->lo_sp)
            {

                if (u->lo_sp->lotag == TAG_SPRITE_HIT_MATCH)
                {
                    if (MissileHitMatch(SpriteNum, -1, u->lo_sp - sprite))
                        return TRUE;
                    //DoMatchEverything(NULL, u->lo_sp->hitag, -1);
                    //return(TRUE);
                }

                return TRUE;
            }

            if (SectUser[hit_sect] && SectUser[hit_sect]->depth > 0)
            {
                SpawnSplash(SpriteNum);
                //SetSuicide(SpriteNum);
                return TRUE;
            }

        }
        // hit ceiling
        else
        {
            // hit a floor sprite
            if (u->hi_sp)
            {
                if (u->hi_sp->lotag == TAG_SPRITE_HIT_MATCH)
                {
                    if (MissileHitMatch(SpriteNum, -1, u->hi_sp - sprite))
                        return TRUE;
                    //DoMatchEverything(NULL, u->hi_sp->hitag, -1);
                    //return(TRUE);
                }
            }
        }


        if (TEST(sectp->extra, SECTFX_SECTOR_OBJECT))
        {
            if ((sop = DetectSectorObject(sectp)))
            {
                //if (sop->max_damage != -9999)
                DoDamage(sop->sp_child - sprite, SpriteNum);
                return TRUE;
            }
        }

        if (TEST(sectp->ceilingstat, CEILING_STAT_PLAX) && sectp->ceilingpicnum != FAF_MIRROR_PIC)
        {
            if (labs(sp->z - sectp->ceilingz) < SPRITEp_SIZE_Z(sp))
            {
                SetSuicide(SpriteNum);
                return TRUE;
            }
        }

        return TRUE;
    }

    case HIT_SPRITE:
    {
        SPRITEp hsp;
        USERp hu;
        short hit_sprite;

        hit_sprite = NORM_SPRITE(u->ret);
        hsp = &sprite[hit_sprite];
        hu = User[hit_sprite];

        if (hsp->statnum == STAT_ENEMY)
        {
            ////DSPRINTF(ds, "Bullet Hit Monster %d, stat %d ", hsp-sprite, (short)hsp->statnum);
            //MONO_PRINT(ds);
        }

        ASSERT(hsp->extra != -1);

        if (TEST(hsp->extra, SPRX_BREAKABLE))
        {
            HitBreakSprite(hit_sprite, u->ID);
            return TRUE;
        }

        if (TEST(hsp->extra, SPRX_PLAYER_OR_ENEMY))
        {
            // make sure you didn't hit the owner of the missile
            //if (sp->owner != -1 && hit_sprite != sp->owner)
            if (hit_sprite != sp->owner)
            {
                if (u->ID == STAR1)
                {
                    extern STATE s_TrashCanPain[];
                    switch (hu->ID)
                    {
                    case TRASHCAN:
                        PlaySound(DIGI_TRASHLID, &sp->x, &sp->y, &sp->z, v3df_none);
                        PlaySound(DIGI_STARCLINK, &sp->x, &sp->y, &sp->z, v3df_none);
                        if (hu->WaitTics <= 0)
                        {
                            hu->WaitTics = SEC(2);
                            ChangeState(hit_sprite,s_TrashCanPain);
                        }
                        break;
                    case PACHINKO1:
                    case PACHINKO2:
                    case PACHINKO3:
                    case PACHINKO4:
                    case ZILLA_RUN_R0:
                    case 623:
                    {
                        PlaySound(DIGI_STARCLINK, &sp->x, &sp->y, &sp->z, v3df_none);
                    }
                    break;
                    }
                }
                DoDamage(hit_sprite, SpriteNum);
                return TRUE;
            }
        }
        else
        {
            if (hsp->statnum == STAT_MINE_STUCK)
            {
                DoDamage(hit_sprite, SpriteNum);
                return TRUE;
            }
        }

        if (hsp->lotag == TAG_SPRITE_HIT_MATCH)
        {
            if (MissileHitMatch(SpriteNum, -1, hit_sprite))
                return TRUE;
            //DoMatchEverything(NULL, hsp->hitag, -1);
            //return(TRUE);
        }

        if (TEST(hsp->cstat, CSTAT_SPRITE_ALIGNMENT_WALL))
        {
            if (hsp->lotag || hsp->hitag)
            {
                ShootableSwitch(hit_sprite);
                return TRUE;
            }
        }

        return TRUE;
    }

    case HIT_WALL:
    {
        hitdata_t hitinfo = { { 0, 0, 0 }, -2, (int16_t)NORM_WALL(u->ret), -2 };
        WALLp wph = &wall[hitinfo.wall];
        SECTOR_OBJECTp sop;

        ASSERT(wph->extra != -1);

        if (TEST(wph->extra, WALLFX_SECTOR_OBJECT))
        {
            if ((sop = DetectSectorObjectByWall(wph)))
            {
                if (sop->max_damage != -999)
                    DoDamage(sop->sp_child - sprite, SpriteNum);
                return TRUE;
            }
        }

        if (wph->lotag == TAG_WALL_BREAK)
        {
            HitBreakWall(&wall[hitinfo.wall], sp->x, sp->y, sp->z, sp->ang, u->ID);
            u->ret = 0;
            return TRUE;
        }

        // clipmove does not correctly return the sprite for WALL sprites
        // on walls, so look with hitscan

        hitscan((vec3_t *)sp, sp->sectnum,   // Start position
                sintable[NORM_ANGLE(sp->ang + 512)],    // X vector of 3D ang
                sintable[NORM_ANGLE(sp->ang)],  // Y vector of 3D ang
                sp->zvel,               // Z vector of 3D ang
                &hitinfo, CLIPMASK_MISSILE);

        if (hitinfo.sect < 0)
        {
            return FALSE;
        }

        if (hitinfo.sprite >= 0)
        {
            SPRITEp hsp = &sprite[hitinfo.sprite];

            if (hsp->lotag == TAG_SPRITE_HIT_MATCH)
            {
                if (MissileHitMatch(SpriteNum, -1, hitinfo.sprite))
                    return TRUE;
            }

            if (TEST(hsp->cstat, CSTAT_SPRITE_ALIGNMENT_WALL))
            {
                if (hsp->lotag || hsp->hitag)
                {
                    ShootableSwitch(hitinfo.sprite);
                    return TRUE;
                }
            }
        }

        return TRUE;
    }
    }

    return FALSE;
}

int
DoUziSmoke(short SpriteNum)
{
    SPRITEp sp = &sprite[SpriteNum];

    //if (sp->picnum != NULL)
    //    DoDamageTest(SpriteNum);
    sp->z -= 200; // !JIM! Make them float up

    return 0;
}

int
DoShotgunSmoke(short SpriteNum)
{
    SPRITEp sp = &sprite[SpriteNum];

    //if (sp->picnum != NULL)
    //    DoDamageTest(SpriteNum);
    sp->z -= 200; // !JIM! Make them float up

    return 0;
}

int
DoMineSpark(short SpriteNum)
{
    SPRITEp sp = &sprite[SpriteNum];

    if (sp->picnum != 0)
    {
        DoDamageTest(SpriteNum);
    }

    return 0;
}

int
DoFireballFlames(short SpriteNum)
{
    SPRITEp sp = &sprite[SpriteNum],ap;
    USERp u = User[SpriteNum];
    SWBOOL jumping = FALSE;

    // if no owner then stay where you are
    if (u->Attach >= 0)
    {
        ap = &sprite[u->Attach];

        sp->x = ap->x;
        sp->y = ap->y;

        sp->z = DIV2(SPRITEp_TOS(ap) + SPRITEp_BOS(ap));

        if (TEST(ap->extra, SPRX_BURNABLE))
        {
            if (MOD2(u->Counter2) == 0)
            {
                ap->shade++;
                if (ap->shade > 10)
                    ap->shade = 10;
            }
        }
    }
    else
    {
        if (TEST(u->Flags, SPR_JUMPING))
        {
            DoJump(SpriteNum);
            jumping = TRUE;
            //u->ret = move_missile(SpriteNum, dax, day, daz, Z(16), Z(16), CLIPMASK_MISSILE, MISSILEMOVETICS);
        }
        else if (TEST(u->Flags, SPR_FALLING))
        {
            DoFall(SpriteNum);
            jumping = TRUE;
            //u->ret = move_missile(SpriteNum, dax, day, daz, Z(16), Z(16), CLIPMASK_MISSILE, MISSILEMOVETICS);
        }
        else
        {
            if (SectUser[sp->sectnum] && SectUser[sp->sectnum]->depth > 0)
            {
                if (labs(sector[sp->sectnum].floorz - sp->z) <= Z(4))
                {
                    KillSprite(SpriteNum);
                    return 0;
                }
            }

            if (TestDontStickSector(sp->sectnum))
            {
                KillSprite(SpriteNum);
                return 0;
            }
        }
    }

    if (!jumping)
    {
        if ((u->WaitTics += MISSILEMOVETICS) > 4 * 120)
        {
            // shrink and go away
            sp->xrepeat--;
            sp->yrepeat--;

            if (((signed char)sp->xrepeat) == 0)
            {
                if (u->Attach >= 0)
                    User[u->Attach]->flame = -1;
                KillSprite(SpriteNum);
                return 0;
            }
        }
        else
        {
            // grow until the right size
            if (sp->xrepeat <= u->Counter)
            {
                sp->xrepeat += 3;
                sp->yrepeat += 3;
            }
        }
    }

    u->Counter2++;
    if (u->Counter2 > 9)
    {
        u->Counter2 = 0;
        DoFlamesDamageTest(SpriteNum);
    }

    return 0;
}

int
DoBreakFlames(short SpriteNum)
{
    SPRITEp sp = &sprite[SpriteNum];
    USERp u = User[SpriteNum];
    SWBOOL jumping = FALSE;

    if (TEST(u->Flags, SPR_JUMPING))
    {
        DoJump(SpriteNum);
        jumping = TRUE;
    }
    else if (TEST(u->Flags, SPR_FALLING))
    {
        DoFall(SpriteNum);
        jumping = TRUE;
    }
    else
    {
        if (SectUser[sp->sectnum] && SectUser[sp->sectnum]->depth > 0)
        {
            if (labs(sector[sp->sectnum].floorz - sp->z) <= Z(4))
            {
                KillSprite(SpriteNum);
                return 0;
            }
        }

        if (TestDontStickSector(sp->sectnum))
        {
            KillSprite(SpriteNum);
            return 0;
        }
    }

    if (!jumping)
    {
        if ((u->WaitTics += MISSILEMOVETICS) > 4 * 120)
        {
            // shrink and go away
            sp->xrepeat--;
            sp->yrepeat--;

            if (((signed char)sp->xrepeat) == 0)
            {
                if (u->Attach >= 0)
                    User[u->Attach]->flame = -1;
                KillSprite(SpriteNum);
                return 0;
            }
        }
        else
        {
            // grow until the right size
            if (sp->xrepeat <= u->Counter)
            {
                sp->xrepeat += 3;
                sp->yrepeat += 3;
            }

            if (u->WaitTics + MISSILEMOVETICS > 4 * 120)
            {
                SpawnBreakStaticFlames(SpriteNum);
            }
        }
    }

    u->Counter2++;
    if (u->Counter2 > 9)
    {
        u->Counter2 = 0;
        DoFlamesDamageTest(SpriteNum);
    }

    return 0;
}

int
SetSuicide(short SpriteNum)
{
#if 1
    USERp u = User[SpriteNum];

    if (u != nullptr)
    {
        SET(u->Flags, SPR_SUICIDE);
        u->RotNum = 0;
    }
    ChangeState(SpriteNum, s_Suicide);
#else
    // this will NOT work because
    // TRAVERSE_SPRITE_STAT(headspritestat[STAT_MISSILE], i, nexti)
    // nexti will still be valid but will be on a different list
    // and will have a different nextspritestat[nexti] result
    changespritestat(SpriteNum, STAT_SUICIDE);
#endif
    return 0;
}

int
DoActorScale(short SpriteNum)
{
    USERp u = User[SpriteNum];
    SPRITEp sp = &sprite[SpriteNum];

    u->scale_speed = 70;
    u->scale_value = sp->xrepeat << 8;
    u->scale_tgt = sp->xrepeat + 25;

    if (u->scale_tgt > 256)
    {
        u->scale_speed = 0;
        u->scale_tgt = 256;
    }

    return 0;
}

int
DoRipperGrow(short SpriteNum)
{
    USERp u = User[SpriteNum];
    SPRITEp sp = &sprite[SpriteNum];

    u->scale_speed = 70;
    u->scale_value = sp->xrepeat << 8;
    u->scale_tgt = sp->xrepeat + 20;

    if (u->scale_tgt > 128)
    {
        u->scale_speed = 0;
        u->scale_tgt = 128;
    }

    return 0;
}

void UpdateSinglePlayKills(short SpriteNum)
{
    // single play and coop kill count
    if (gNet.MultiGameType != MULTI_GAME_COMMBAT)
    {
#if DEBUG
        extern SWBOOL DebugSecret;
        if (DebugSecret)
        {
            SPRITEp sp = &sprite[SpriteNum];
            sprintf(ds,"KILLED: spnum %d, pic %d, x %d, y %d",SpriteNum,sp->picnum,sp->x,sp->y);
            DebugWriteString(ds);
        }
#endif

        ASSERT(User[SpriteNum]);

        if (TEST(User[SpriteNum]->Flags, SPR_SUICIDE))
        {
            return;
        }

        switch (User[SpriteNum]->ID)
        {
        case COOLIE_RUN_R0:
        case NINJA_RUN_R0:
        case NINJA_CRAWL_R0:
        case GORO_RUN_R0:
        case 1441:
        case COOLG_RUN_R0:
        case EEL_RUN_R0:
        case SUMO_RUN_R0:
        case ZILLA_RUN_R0:
        //case TOILETGIRL_R0:
        //case WASHGIRL_R0:
        //case BUNNY_RUN_R0:
        case RIPPER_RUN_R0:
        case RIPPER2_RUN_R0:
        case SERP_RUN_R0:
        case LAVA_RUN_R0:
        case SKEL_RUN_R0:
        case HORNET_RUN_R0:
        case GIRLNINJA_RUN_R0:
        case SKULL_R0:
        case BETTY_R0:
            // always give kills to the first player
            Player->Kills++;
            break;
        }
    }
}


int
ActorChooseDeath(short SpriteNum, short Weapon)
{
    SPRITEp sp = &sprite[SpriteNum];
    USERp u = User[SpriteNum];
    SPRITEp wp = &sprite[Weapon];
    USERp wu = User[Weapon];

    ASSERT(u);

    if (u->Health > 0)
        return FALSE;

    UpdateSinglePlayKills(SpriteNum);

    ASSERT(Weapon >= 0);

#if 0
    if (Weapon < 0)
    {
        switch (Weapon)
        {
        default:
            DoActorDie(SpriteNum, Weapon);
            UpdateSinglePlayKills(SpriteNum);
            break;
        }
        return FALSE;
    }
#endif

    if (u->Attrib)
        PlaySpriteSound(SpriteNum,attr_die,v3df_follow);

    switch (u->ID)
    {
    case PACHINKO1:
    case PACHINKO2:
    case PACHINKO3:
    case PACHINKO4:
    case 623:
    case TOILETGIRL_R0:
    case WASHGIRL_R0:
    case CARGIRL_R0:
    case MECHANICGIRL_R0:
    case SAILORGIRL_R0:
    case PRUNEGIRL_R0:
    case TRASHCAN:
    case GORO_RUN_R0:
    case RIPPER2_RUN_R0:
        break;
    case BUNNY_RUN_R0:
    {
        extern short Bunny_Count;
        Bunny_Count--;  // Bunny died, decrease the population
    }
    break;
    default:
        ActorCoughItem(SpriteNum);
        //UpdateSinglePlayKills(SpriteNum);
        break;
    }

    switch (u->ID)
    {
    case BETTY_R0:
    {
        ANIMATOR DoBettyBeginDeath;
        DoBettyBeginDeath(SpriteNum);
        break;
    }
    case SKULL_R0:
    {
        ANIMATOR DoSkullBeginDeath;
        DoSkullBeginDeath(SpriteNum);
        break;
    }
    case TOILETGIRL_R0:
    case WASHGIRL_R0:
    case CARGIRL_R0:
    case MECHANICGIRL_R0:
    case SAILORGIRL_R0:
    case PRUNEGIRL_R0:
    case TRASHCAN:
    case PACHINKO1:
    case PACHINKO2:
    case PACHINKO3:
    case PACHINKO4:
    case 623:
    {
        if ((u->ID == TOILETGIRL_R0 ||
             u->ID == CARGIRL_R0 || u->ID == MECHANICGIRL_R0 || u->ID == SAILORGIRL_R0 || u->ID == PRUNEGIRL_R0 ||
             u->ID == WASHGIRL_R0) && wu->ID == NINJA_RUN_R0 && wu->PlayerP)
        {
            PLAYERp pp = wu->PlayerP;
            if (pp && !TEST(pp->Flags, PF_DIVING))  // JBF: added null test
                pp->Bloody = TRUE;
            PlaySound(DIGI_TOILETGIRLSCREAM, &sp->x, &sp->y, &sp->z, v3df_none);
        }
        if (SpawnShrap(SpriteNum, Weapon))
            SetSuicide(SpriteNum);
        break;
    }

    // These are player zombies
    case ZOMBIE_RUN_R0:
        InitBloodSpray(SpriteNum,TRUE,105);
        InitBloodSpray(SpriteNum,TRUE,105);
        if (SpawnShrap(SpriteNum, Weapon))
            SetSuicide(SpriteNum);
        break;

    default:

        switch (wu->ID)
        {
        case NINJA_RUN_R0: //sword
            if (wu->PlayerP)
            {
                PLAYERp pp = wu->PlayerP;

                if (wu->WeaponNum == WPN_FIST && STD_RANDOM_RANGE(1000)>500 && pp == Player+myconnectindex)
                {
                    char choosesnd = 0;

                    choosesnd=STD_RANDOM_RANGE(6);

                    if (choosesnd == 0)
                        PlayerSound(DIGI_KUNGFU,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp);
                    else if (choosesnd == 1)
                        PlayerSound(DIGI_PAYINGATTENTION,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp);
                    else if (choosesnd == 2)
                        PlayerSound(DIGI_EATTHIS,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp);
                    else if (choosesnd == 3)
                        PlayerSound(DIGI_TAUNTAI4,&pp->posx,&pp->posy,&pp->posz,v3df_follow|v3df_dontpan,pp);
                    else if (choosesnd ==