code:
//-------------------------------------------------------------------------
/*
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
*/
//-------------------------------------------------------------------------

#ifndef WEAPON_H
#define WEAPON_H

#define NEW_ELECTRO 1
#define HORIZ_MULT 128L

#define ANG2PLAYER(pp,sp) (getangle((pp)->posx - (sp)->x, (pp)->posy - (sp)->y))
#define ANG2SPRITE(sp,op) (getangle((sp)->x - (op)->x, (sp)->y - (op)->y))

#define MAX_HOLE_QUEUE 64
#define MAX_STAR_QUEUE 32
#define MAX_WALLBLOOD_QUEUE  32
#define MAX_FLOORBLOOD_QUEUE 32
#define MAX_GENERIC_QUEUE 32
#define MAX_LOWANGS_QUEUE 16

//#define NUKE_RADIUS 16384
#define NUKE_RADIUS 30000
#define RAIL_RADIUS 3500

// This is how many bullet shells have been spawned since the beginning of the game.
extern FOOT_TYPE FootMode;
extern int ShellCount;
#define MAXSHELLS 32

extern short StarQueueHead;
extern short StarQueue[MAX_STAR_QUEUE];
extern short HoleQueueHead;
extern short HoleQueue[MAX_HOLE_QUEUE];
extern short WallBloodQueueHead;
extern short WallBloodQueue[MAX_WALLBLOOD_QUEUE];
extern short FloorBloodQueueHead;
extern short FloorBloodQueue[MAX_FLOORBLOOD_QUEUE];
extern short GenericQueueHead;
extern short GenericQueue[MAX_GENERIC_QUEUE];
extern short LoWangsQueueHead;
extern short LoWangsQueue[MAX_LOWANGS_QUEUE];

void ChangeState(short SpriteNum, STATEp statep);
void DoPlayerBeginRecoil(PLAYERp pp, short pix_amt);
SECTOR_OBJECTp DetectSectorObject(SECTORp);
SECTOR_OBJECTp DetectSectorObjectByWall(WALLp);
void ScaleSpriteVector(short SpriteNum, int scale);
int QueueHole(short hit_sect, short hit_wall, int hit_x, int hit_y, int hit_z);
int QueueWallBlood(short hit_sprite, short ang);
SWBOOL SlopeBounce(short SpriteNum, SWBOOL *hit_wall);
SWBOOL HitscanSpriteAdjust(short SpriteNum, short hit_wall);
int SpawnSwordSparks(PLAYERp pp, short hit_sect, short hit_wall, int hit_x, int hit_y, int hit_z, short hit_ang);
int SpawnBubble(short SpriteNum);
int SpawnFireballExp(int16_t Weapon);
int SpawnFireballFlames(int16_t SpriteNum,int16_t enemy);
int SpawnRadiationCloud(short SpriteNum);
int SpawnGrenadeExp(int16_t Weapon);
int SpawnSectorExp(int16_t Weapon);
int DoShrapVelocity(int16_t SpriteNum);
int ShrapKillSprite(short SpriteNum);
SWBOOL MissileSetPos(short Weapon,ANIMATORp DoWeapon,int dist);
int ActorPain(short SpriteNum);
int SpawnBreakFlames(int16_t SpriteNum);
const char *DeathString(short SpriteNum);

//
// Damage Amounts defined in damage.h
//
extern DAMAGE_DATA DamageData[];

// Damage Times - takes damage after this many tics
#define DAMAGE_BLADE_TIME       (10)

// Player Missile Speeds
#define STAR_VELOCITY           (1800)
#define BOLT_VELOCITY           (900)
#define ROCKET_VELOCITY         (1350)
#define BOLT_SEEKER_VELOCITY    (820)
#define FIREBALL_VELOCITY       (2000)
#define ELECTRO_VELOCITY        (800)
#define PLASMA_VELOCITY         (1000)
#define UZI_BULLET_VELOCITY     (2500)
#define TRACER_VELOCITY         (1200)
#define TANK_SHELL_VELOCITY     (1200)
#define GRENADE_VELOCITY        (900)
#define MINE_VELOCITY           (520)   // Was 420
#define CHEMBOMB_VELOCITY       (420)

// Player Spell Missile Speeds
#define BLOOD_WORM_VELOCITY   (800)
#define NAPALM_VELOCITY         (800)
#define MIRV_VELOCITY          (600)
#define SPIRAL_VELOCITY         (600)

// Trap Speeds
#define BOLT_TRAP_VELOCITY      (950)
#define SPEAR_TRAP_VELOCITY     (650)
#define FIREBALL_TRAP_VELOCITY  (750)

// NPC Missile Speeds
#define NINJA_STAR_VELOCITY     (1800)
#define NINJA_BOLT_VELOCITY     (500)
#define GORO_FIREBALL_VELOCITY  (800)
#define SKEL_ELECTRO_VELOCITY   (850)
#define COOLG_FIRE_VELOCITY     (400)

#define GRENADE_RECOIL_AMT      (12)
#define ROCKET_RECOIL_AMT       (7)
#define RAIL_RECOIL_AMT       (7)
#define SHOTGUN_RECOIL_AMT      (12)
//#define MICRO_RECOIL_AMT        (15)

// Damage amounts that determine the type of player death
// The standard flip over death is default
#define PLAYER_DEATH_CRUMBLE_DAMMAGE_AMT   (25)
#define PLAYER_DEATH_EXPLODE_DAMMAGE_AMT   (65)

// electro weapon
#define ELECTRO_MAX_JUMP_DIST 25000

extern int WeaponIsAmmo;

#define MISSILEMOVETICS 6

#define CLOSE_RANGE_DIST_FUDGE(sp1, sp2, fudge) \
    (((int)(sp1)->clipdist<<2) + ((int)(sp2)->clipdist<<2) + (fudge))

#define CLOSE_RANGE_DIST(sp1, sp2) CLOSE_RANGE_DIST_FUDGE(sp1, sp2, 400)

extern short target_ang;

SWBOOL SpriteOverlap(short, short);

int SpawnShotgunSparks(PLAYERp pp, short hit_sect, short hit_wall, int hit_x, int hit_y, int hit_z, short hit_ang);
int DoActorBeginSlide(short SpriteNum, short ang, short vel, short dec);
int GetOverlapSector(int x, int y, short *over, short *under);
SWBOOL MissileHitDiveArea(short SpriteNum);

int DoDamageTest(short);

extern short StatDamageList[STAT_DAMAGE_LIST_SIZE];

#define RADIATION_CLOUD 3258
#define MUSHROOM_CLOUD 3280
extern STATE s_NukeMushroom[];

void WallBounce(short SpriteNum, short ang);

#define PUFF 1748
#define CALTROPS 2218
#define PHOSPHORUS 1397

int PlayerInitChemBomb(PLAYERp pp);
int InitChemBomb(short SpriteNum);
int PlayerInitCaltrops(PLAYERp pp);
int InitBloodSpray(int16_t SpriteNum, SWBOOL dogib, short velocity);
int SpawnBunnyExp(int16_t Weapon);
int InitBunnyRocket(PLAYERp pp);

int GetDamage(short SpriteNum, short Weapon, short DamageNdx);
int DoFlamesDamageTest(short Weapon);

void DoActorSpawnIcon(int16_t SpriteNum);

typedef struct
{
    STATEp state;
    short id, num, zlevel, min_jspeed, max_jspeed, min_vel, max_vel, random_disperse, ang_range;
    // state, id, num, min_jspeed, max_jspeed, min_vel, max_vel, size,
    // random_disperse, ang_range
} SHRAP, *SHRAPp;

enum ShrapPos
{
    Z_TOP,
    Z_MID,
    Z_BOT
};

int SetSuicide(short SpriteNum);
void UpdateSinglePlayKills(short SpriteNum);
int InitPlasmaFountain(SPRITEp wp, SPRITEp sp);
int InitCoolgDrip(short SpriteNum);
int InitFireball(PLAYERp pp);
void InitSpellRing(PLAYERp pp);
void InitSpellNapalm(PLAYERp pp);
int InitUzi(PLAYERp pp);
int InitSobjGun(PLAYERp pp);
int InitBoltTrap(short SpriteNum);
int InitSpearTrap(short SpriteNum);
int InitTurretMgun(SECTOR_OBJECTp sop);
int InitVulcanBoulder(short SpriteNum);
int DoBladeDamage(short SpriteNum);
int DoFindGround(int16_t SpriteNum);
int DoFindGroundPoint(int16_t SpriteNum);
void SpriteQueueDelete(short SpriteNum);
int HelpMissileLateral(int16_t Weapon,int dist);
int AddSpriteToSectorObject(short SpriteNum,SECTOR_OBJECTp sop);
void QueueReset(void);
int PlayerCheckDeath(PLAYERp pp,short Weapon);
SWBOOL SpriteWarpToUnderwater(SPRITEp sp);
int PlayerDamageSlide(PLAYERp pp,short damage,short ang);
SWBOOL VehicleMoveHit(short SpriteNum);
int SpawnSplash(short SpriteNum);
int SpawnMineExp(int16_t Weapon);
int SpawnLittleExp(int16_t Weapon);
int SpawnLargeExp(int16_t Weapon);
int SpawnNuclearExp(int16_t Weapon);
int SpawnBoltExp(int16_t Weapon);
int SpawnTracerExp(int16_t Weapon);
int SpawnGoroFireballExp(int16_t Weapon);
SWBOOL MissileHitMatch(short Weapon,short WeaponNum,short hit_sprite);
int DoItemFly(int16_t SpriteNum);
int SpawnVehicleSmoke(short SpriteNum);
short PrevWall(short wall_num);
int DoDamage(short SpriteNum,short Weapon);

#endif

repo_name: orochi/nblood

license: mit


code:
//-------------------------------------------------------------------------
/*
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 "keys.h"
#include "names2.h"
#include "panel.h"
#include "game.h"
#include "tags.h"
#include "ai.h"
#include "quake.h"
#include "actor.h"
#include "track.h"
#include "fx_man.h"

extern uint8_t RedBookSong[40];
extern short BossSpriteNum[3];

ANIMATOR InitZillaCharge;

DECISION ZillaBattle[] =
{
    {100,   InitActorRunAway      },
    {690,   InitActorMoveCloser   },
    {692,   InitActorAlertNoise   },
    {1024,  InitActorAttack       }
};

DECISION ZillaOffense[] =
{
    {100,   InitActorRunAway      },
    {690,   InitActorMoveCloser   },
    {692,   InitActorAlertNoise   },
    {1024,  InitActorAttack       }
};

DECISION ZillaBroadcast[] =
{
    {2,     InitActorAlertNoise   },
    {4,     InitActorAmbientNoise  },
    {1024,  InitActorDecide       }
};

DECISION ZillaSurprised[] =
{
    {700,   InitActorMoveCloser   },
    {703,   InitActorAlertNoise   },
    {1024,  InitActorDecide       }
};

DECISION ZillaEvasive[] =
{
    {1024, InitActorWanderAround }
};

DECISION ZillaLostTarget[] =
{
    {900,   InitActorFindPlayer         },
    {1024,  InitActorWanderAround       }
};

DECISION ZillaCloseRange[] =
{
    {1024,  InitActorAttack         }
};

PERSONALITY ZillaPersonality =
{
    ZillaBattle,
    ZillaOffense,
    ZillaBroadcast,
    ZillaSurprised,
    ZillaEvasive,
    ZillaLostTarget,
    ZillaCloseRange,
    ZillaCloseRange
};

ATTRIBUTE ZillaAttrib =
{
    {100, 100, 100, 100},                 // Speeds
    {3, 0, 0, 0},                     // Tic Adjusts
    3,                               // MaxWeapons;
    {
        DIGI_Z17010, DIGI_Z17010, DIGI_Z17025,
        DIGI_Z17052, DIGI_Z17025, 0,0,0,0,0
    }
};

//////////////////////
//
// ZILLA RUN
//
//////////////////////

#define ZILLA_RATE 48

ANIMATOR DoZillaMove,NullZilla,DoStayOnFloor,
         DoActorDebris, SpawnZillaExp, DoZillaStomp,
         SpawnCoolg;

STATE s_ZillaRun[5][6] =
{
    {
        {ZILLA_RUN_R0 + 0, ZILLA_RATE, DoZillaMove, &s_ZillaRun[0][1]},
        {ZILLA_RUN_R0 + 1, SF_QUICK_CALL, DoZillaStomp, &s_ZillaRun[0][2]},
        {ZILLA_RUN_R0 + 1, ZILLA_RATE, DoZillaMove, &s_ZillaRun[0][3]},
        {ZILLA_RUN_R0 + 2, ZILLA_RATE, DoZillaMove, &s_ZillaRun[0][4]},
        {ZILLA_RUN_R0 + 3, SF_QUICK_CALL, DoZillaStomp, &s_ZillaRun[0][5]},
        {ZILLA_RUN_R0 + 3, ZILLA_RATE, DoZillaMove, &s_ZillaRun[0][0]}
    },
    {
        {ZILLA_RUN_R1 + 0, ZILLA_RATE, DoZillaMove, &s_ZillaRun[1][1]},
        {ZILLA_RUN_R1 + 1, SF_QUICK_CALL, DoZillaStomp, &s_ZillaRun[1][2]},
        {ZILLA_RUN_R1 + 1, ZILLA_RATE, DoZillaMove, &s_ZillaRun[1][3]},
        {ZILLA_RUN_R1 + 2, ZILLA_RATE, DoZillaMove, &s_ZillaRun[1][4]},
        {ZILLA_RUN_R1 + 3, SF_QUICK_CALL, DoZillaStomp, &s_ZillaRun[1][5]},
        {ZILLA_RUN_R1 + 3, ZILLA_RATE, DoZillaMove, &s_ZillaRun[1][0]}
    },
    {
        {ZILLA_RUN_R2 + 0, ZILLA_RATE, DoZillaMove, &s_ZillaRun[2][1]},
        {ZILLA_RUN_R2 + 1, SF_QUICK_CALL, DoZillaStomp, &s_ZillaRun[2][2]},
        {ZILLA_RUN_R2 + 1, ZILLA_RATE, DoZillaMove, &s_ZillaRun[2][3]},
        {ZILLA_RUN_R2 + 2, ZILLA_RATE, DoZillaMove, &s_ZillaRun[2][4]},
        {ZILLA_RUN_R2 + 3, SF_QUICK_CALL, DoZillaStomp, &s_ZillaRun[2][5]},
        {ZILLA_RUN_R2 + 3, ZILLA_RATE, DoZillaMove, &s_ZillaRun[2][0]}
    },
    {
        {ZILLA_RUN_R3 + 0, ZILLA_RATE, DoZillaMove, &s_ZillaRun[3][1]},
        {ZILLA_RUN_R3 + 1, SF_QUICK_CALL, DoZillaStomp, &s_ZillaRun[3][2]},
        {ZILLA_RUN_R3 + 1, ZILLA_RATE, DoZillaMove, &s_ZillaRun[3][3]},
        {ZILLA_RUN_R3 + 2, ZILLA_RATE, DoZillaMove, &s_ZillaRun[3][4]},
        {ZILLA_RUN_R3 + 3, SF_QUICK_CALL, DoZillaStomp, &s_ZillaRun[3][5]},
        {ZILLA_RUN_R3 + 3, ZILLA_RATE, DoZillaMove, &s_ZillaRun[3][0]}
    },
    {
        {ZILLA_RUN_R4 + 0, ZILLA_RATE, DoZillaMove, &s_ZillaRun[4][1]},
        {ZILLA_RUN_R4 + 1, SF_QUICK_CALL, DoZillaStomp, &s_ZillaRun[4][2]},
        {ZILLA_RUN_R4 + 1, ZILLA_RATE, DoZillaMove, &s_ZillaRun[4][3]},
        {ZILLA_RUN_R4 + 2, ZILLA_RATE, DoZillaMove, &s_ZillaRun[4][4]},
        {ZILLA_RUN_R4 + 3, SF_QUICK_CALL, DoZillaStomp, &s_ZillaRun[4][5]},
        {ZILLA_RUN_R4 + 3, ZILLA_RATE, DoZillaMove, &s_ZillaRun[4][0]}
    }
};

STATEp sg_ZillaRun[] =
{
    &s_ZillaRun[0][0],
    &s_ZillaRun[1][0],
    &s_ZillaRun[2][0],
    &s_ZillaRun[3][0],
    &s_ZillaRun[4][0]
};

//////////////////////
//
// ZILLA STAND
//
//////////////////////

STATE s_ZillaStand[5][1] =
{
    {
        {ZILLA_RUN_R0 + 0, ZILLA_RATE, DoZillaMove, &s_ZillaStand[0][0]}
    },
    {
        {ZILLA_RUN_R1 + 0, ZILLA_RATE, DoZillaMove, &s_ZillaStand[1][0]}
    },
    {
        {ZILLA_RUN_R2 + 0, ZILLA_RATE, DoZillaMove, &s_ZillaStand[2][0]}
    },
    {
        {ZILLA_RUN_R3 + 0, ZILLA_RATE, DoZillaMove, &s_ZillaStand[3][0]}
    },
    {
        {ZILLA_RUN_R4 + 0, ZILLA_RATE, DoZillaMove, &s_ZillaStand[4][0]}
    }
};

STATEp sg_ZillaStand[] =
{
    &s_ZillaStand[0][0],
    &s_ZillaStand[1][0],
    &s_ZillaStand[2][0],
    &s_ZillaStand[3][0],
    &s_ZillaStand[4][0]
};

//////////////////////
//
// ZILLA PAIN
//
//////////////////////

#define ZILLA_PAIN_RATE 30

STATE s_ZillaPain[5][2] =
{
    {
        {ZILLA_PAIN_R0 + 0, ZILLA_PAIN_RATE, NullZilla, &s_ZillaPain[0][1]},
        {ZILLA_PAIN_R0 + 0, 0|SF_QUICK_CALL, InitActorDecide, &s_ZillaPain[0][0]}
    },
    {
        {ZILLA_PAIN_R1 + 0, ZILLA_PAIN_RATE, NullZilla, &s_ZillaPain[1][1]},
        {ZILLA_PAIN_R1 + 0, 0|SF_QUICK_CALL, InitActorDecide, &s_ZillaPain[1][0]}
    },
    {
        {ZILLA_PAIN_R2 + 0, ZILLA_PAIN_RATE, NullZilla, &s_ZillaPain[2][1]},
        {ZILLA_PAIN_R2 + 0, 0|SF_QUICK_CALL, InitActorDecide, &s_ZillaPain[2][0]}
    },
    {
        {ZILLA_PAIN_R3 + 0, ZILLA_PAIN_RATE, NullZilla, &s_ZillaPain[3][1]},
        {ZILLA_PAIN_R3 + 0, 0|SF_QUICK_CALL, InitActorDecide, &s_ZillaPain[3][0]}
    },
    {
        {ZILLA_PAIN_R4 + 0, ZILLA_PAIN_RATE, NullZilla, &s_ZillaPain[4][1]},
        {ZILLA_PAIN_R4 + 0, 0|SF_QUICK_CALL, InitActorDecide, &s_ZillaPain[4][0]}
    }
};

STATEp sg_ZillaPain[] =
{
    &s_ZillaPain[0][0],
    &s_ZillaPain[1][0],
    &s_ZillaPain[2][0],
    &s_ZillaPain[3][0],
    &s_ZillaPain[4][0]
};

//////////////////////
//
// ZILLA RAIL
//
//////////////////////

#define ZILLA_RAIL_RATE 12
ANIMATOR InitZillaRail;

STATE s_ZillaRail[5][14] =
{
    {
        {ZILLA_RAIL_R0 + 0, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[0][1]},
        {ZILLA_RAIL_R0 + 1, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[0][2]},
        {ZILLA_RAIL_R0 + 2, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[0][3]},
        {ZILLA_RAIL_R0 + 3, SF_QUICK_CALL, InitZillaRail, &s_ZillaRail[0][4]},
        {ZILLA_RAIL_R0 + 0, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[0][5]},
        {ZILLA_RAIL_R0 + 1, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[0][6]},
        {ZILLA_RAIL_R0 + 2, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[0][7]},
        {ZILLA_RAIL_R0 + 3, SF_QUICK_CALL, InitZillaRail, &s_ZillaRail[0][8]},
        {ZILLA_RAIL_R0 + 0, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[0][9]},
        {ZILLA_RAIL_R0 + 1, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[0][10]},
        {ZILLA_RAIL_R0 + 2, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[0][11]},
        {ZILLA_RAIL_R0 + 3, SF_QUICK_CALL, InitZillaRail, &s_ZillaRail[0][12]},
        {ZILLA_RAIL_R0 + 3, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[0][13]},
        {ZILLA_RAIL_R0 + 3, SF_QUICK_CALL, InitActorDecide, &s_ZillaRail[0][0]}
    },
    {
        {ZILLA_RAIL_R1 + 0, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[1][1]},
        {ZILLA_RAIL_R1 + 1, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[1][2]},
        {ZILLA_RAIL_R1 + 2, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[1][3]},
        {ZILLA_RAIL_R1 + 3, SF_QUICK_CALL, InitZillaRail, &s_ZillaRail[1][4]},
        {ZILLA_RAIL_R1 + 0, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[1][5]},
        {ZILLA_RAIL_R1 + 1, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[1][6]},
        {ZILLA_RAIL_R1 + 2, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[1][7]},
        {ZILLA_RAIL_R1 + 3, SF_QUICK_CALL, InitZillaRail, &s_ZillaRail[1][8]},
        {ZILLA_RAIL_R1 + 0, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[1][9]},
        {ZILLA_RAIL_R1 + 1, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[1][10]},
        {ZILLA_RAIL_R1 + 2, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[1][11]},
        {ZILLA_RAIL_R1 + 3, SF_QUICK_CALL, InitZillaRail, &s_ZillaRail[1][12]},
        {ZILLA_RAIL_R1 + 3, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[1][13]},
        {ZILLA_RAIL_R1 + 3, SF_QUICK_CALL, InitActorDecide, &s_ZillaRail[1][0]}
    },
    {
        {ZILLA_RAIL_R2 + 0, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[2][1]},
        {ZILLA_RAIL_R2 + 1, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[2][2]},
        {ZILLA_RAIL_R2 + 2, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[2][3]},
        {ZILLA_RAIL_R2 + 3, SF_QUICK_CALL, InitZillaRail, &s_ZillaRail[2][4]},
        {ZILLA_RAIL_R2 + 0, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[2][5]},
        {ZILLA_RAIL_R2 + 1, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[2][6]},
        {ZILLA_RAIL_R2 + 2, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[2][7]},
        {ZILLA_RAIL_R2 + 3, SF_QUICK_CALL, InitZillaRail, &s_ZillaRail[2][8]},
        {ZILLA_RAIL_R2 + 0, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[2][9]},
        {ZILLA_RAIL_R2 + 1, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[2][10]},
        {ZILLA_RAIL_R2 + 2, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[2][11]},
        {ZILLA_RAIL_R2 + 3, SF_QUICK_CALL, InitZillaRail, &s_ZillaRail[2][12]},
        {ZILLA_RAIL_R2 + 3, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[2][13]},
        {ZILLA_RAIL_R2 + 3, SF_QUICK_CALL, InitActorDecide, &s_ZillaRail[2][0]}
    },
    {
        {ZILLA_RAIL_R3 + 0, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[3][1]},
        {ZILLA_RAIL_R3 + 1, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[3][2]},
        {ZILLA_RAIL_R3 + 2, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[3][3]},
        {ZILLA_RAIL_R3 + 3, SF_QUICK_CALL, InitZillaRail, &s_ZillaRail[3][4]},
        {ZILLA_RAIL_R3 + 0, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[3][5]},
        {ZILLA_RAIL_R3 + 1, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[3][6]},
        {ZILLA_RAIL_R3 + 2, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[3][7]},
        {ZILLA_RAIL_R3 + 3, SF_QUICK_CALL, InitZillaRail, &s_ZillaRail[3][8]},
        {ZILLA_RAIL_R3 + 0, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[3][9]},
        {ZILLA_RAIL_R3 + 1, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[3][10]},
        {ZILLA_RAIL_R3 + 2, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[3][11]},
        {ZILLA_RAIL_R3 + 3, SF_QUICK_CALL, InitZillaRail, &s_ZillaRail[3][12]},
        {ZILLA_RAIL_R3 + 3, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[3][13]},
        {ZILLA_RAIL_R3 + 3, SF_QUICK_CALL, InitActorDecide, &s_ZillaRail[3][0]}
    },
    {
        {ZILLA_RAIL_R4 + 0, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[4][1]},
        {ZILLA_RAIL_R4 + 1, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[4][2]},
        {ZILLA_RAIL_R4 + 2, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[4][3]},
        {ZILLA_RAIL_R4 + 3, SF_QUICK_CALL, InitZillaRail, &s_ZillaRail[4][4]},
        {ZILLA_RAIL_R4 + 0, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[4][5]},
        {ZILLA_RAIL_R4 + 1, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[4][6]},
        {ZILLA_RAIL_R4 + 2, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[4][7]},
        {ZILLA_RAIL_R4 + 3, SF_QUICK_CALL, InitZillaRail, &s_ZillaRail[4][8]},
        {ZILLA_RAIL_R4 + 0, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[4][9]},
        {ZILLA_RAIL_R4 + 1, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[4][10]},
        {ZILLA_RAIL_R4 + 2, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[4][11]},
        {ZILLA_RAIL_R4 + 3, SF_QUICK_CALL, InitZillaRail, &s_ZillaRail[4][12]},
        {ZILLA_RAIL_R4 + 3, ZILLA_RAIL_RATE, NullZilla, &s_ZillaRail[4][13]},
        {ZILLA_RAIL_R4 + 3, SF_QUICK_CALL, InitActorDecide, &s_ZillaRail[4][0]}
    }
};

STATEp sg_ZillaRail[] =
{
    &s_ZillaRail[0][0],
    &s_ZillaRail[1][0],
    &s_ZillaRail[2][0],
    &s_ZillaRail[3][0],
    &s_ZillaRail[4][0]
};

//////////////////////
//
// ZILLA ROCKET
//
//////////////////////

#define ZILLA_ROCKET_RATE 12
ANIMATOR InitZillaRocket;

STATE s_ZillaRocket[5][7] =
{
    {
        {ZILLA_ROCKET_R0 + 0, ZILLA_ROCKET_RATE, NullZilla, &s_ZillaRocket[0][1]},
        {ZILLA_ROCKET_R0 + 1, ZILLA_ROCKET_RATE, NullZilla, &s_ZillaRocket[0][2]},
        {ZILLA_ROCKET_R0 + 2, ZILLA_ROCKET_RATE*4, NullZilla, &s_ZillaRocket[0][3]},
        {ZILLA_ROCKET_R0 + 2, SF_QUICK_CALL, InitZillaRocket, &s_ZillaRocket[0][4]},
        {ZILLA_ROCKET_R0 + 2, ZILLA_ROCKET_RATE*4, NullZilla, &s_ZillaRocket[0][5]},
        {ZILLA_ROCKET_R0 + 3, SF_QUICK_CALL, InitActorDecide, &s_ZillaRocket[0][6]},
        {ZILLA_ROCKET_R0 + 3, ZILLA_ROCKET_RATE*10, NullZilla, &s_ZillaRocket[0][5]}
    },
    {
        {ZILLA_ROCKET_R1 + 0, ZILLA_ROCKET_RATE, NullZilla, &s_ZillaRocket[1][1]},
        {ZILLA_ROCKET_R1 + 1, ZILLA_ROCKET_RATE, NullZilla, &s_ZillaRocket[1][2]},
        {ZILLA_ROCKET_R1 + 2, ZILLA_ROCKET_RATE*4, NullZilla, &s_ZillaRocket[1][3]},
        {ZILLA_ROCKET_R1 + 2, SF_QUICK_CALL, InitZillaRocket, &s_ZillaRocket[1][4]},
        {ZILLA_ROCKET_R1 + 2, ZILLA_ROCKET_RATE*4, NullZilla, &s_ZillaRocket[1][5]},
        {ZILLA_ROCKET_R1 + 3, SF_QUICK_CALL, InitActorDecide, &s_ZillaRocket[1][6]},
        {ZILLA_ROCKET_R1 + 3, ZILLA_ROCKET_RATE*10, NullZilla, &s_ZillaRocket[1][5]}
    },
    {
        {ZILLA_ROCKET_R2 + 0, ZILLA_ROCKET_RATE, NullZilla, &s_ZillaRocket[2][1]},
        {ZILLA_ROCKET_R2 + 1, ZILLA_ROCKET_RATE, NullZilla, &s_ZillaRocket[2][2]},
        {ZILLA_ROCKET_R2 + 2, ZILLA_ROCKET_RATE*4, NullZilla, &s_ZillaRocket[2][3]},
        {ZILLA_ROCKET_R2 + 2, SF_QUICK_CALL, InitZillaRocket, &s_ZillaRocket[2][4]},
        {ZILLA_ROCKET_R2 + 2, ZILLA_ROCKET_RATE*4, NullZilla, &s_ZillaRocket[2][5]},
        {ZILLA_ROCKET_R2 + 3, SF_QUICK_CALL, InitActorDecide, &s_ZillaRocket[2][6]},
        {ZILLA_ROCKET_R2 + 3, ZILLA_ROCKET_RATE*10, NullZilla, &s_ZillaRocket[2][5]}
    },
    {
        {ZILLA_ROCKET_R3 + 0, ZILLA_ROCKET_RATE, NullZilla, &s_ZillaRocket[3][1]},
        {ZILLA_ROCKET_R3 + 1, ZILLA_ROCKET_RATE, NullZilla, &s_ZillaRocket[3][2]},
        {ZILLA_ROCKET_R3 + 2, ZILLA_ROCKET_RATE*4, NullZilla, &s_ZillaRocket[3][3]},
        {ZILLA_ROCKET_R3 + 2, SF_QUICK_CALL, InitZillaRocket, &s_ZillaRocket[3][4]},
        {ZILLA_ROCKET_R3 + 2, ZILLA_ROCKET_RATE*4, NullZilla, &s_ZillaRocket[3][5]},
        {ZILLA_ROCKET_R3 + 3, SF_QUICK_CALL, InitActorDecide, &s_ZillaRocket[3][6]},
        {ZILLA_ROCKET_R3 + 3, ZILLA_ROCKET_RATE*10, NullZilla, &s_ZillaRocket[3][5]}
    },
    {
        {ZILLA_ROCKET_R4 + 0, ZILLA_ROCKET_RATE, NullZilla, &s_ZillaRocket[4][1]},
        {ZILLA_ROCKET_R4 + 1, ZILLA_ROCKET_RATE, NullZilla, &s_ZillaRocket[4][2]},
        {ZILLA_ROCKET_R4 + 2, ZILLA_ROCKET_RATE*4, NullZilla, &s_ZillaRocket[4][3]},
        {ZILLA_ROCKET_R4 + 2, SF_QUICK_CALL, InitZillaRocket, &s_ZillaRocket[4][4]},
        {ZILLA_ROCKET_R4 + 2, ZILLA_ROCKET_RATE*4, NullZilla, &s_ZillaRocket[4][5]},
        {ZILLA_ROCKET_R4 + 3, SF_QUICK_CALL, InitActorDecide, &s_ZillaRocket[4][6]},
        {ZILLA_ROCKET_R4 + 3, ZILLA_ROCKET_RATE*10, NullZilla, &s_ZillaRocket[4][5]}
    }
};

STATEp sg_ZillaRocket[] =
{
    &s_ZillaRocket[0][0],
    &s_ZillaRocket[1][0],
    &s_ZillaRocket[2][0],
    &s_ZillaRocket[3][0],
    &s_ZillaRocket[4][0]
};

//////////////////////
//
// ZILLA UZI
//
//////////////////////

#define ZILLA_UZI_RATE 8
ANIMATOR InitEnemyUzi;

STATE s_ZillaUzi[5][17] =
{
    {
        {ZILLA_SHOOT_R0 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[0][1]},
        {ZILLA_SHOOT_R0 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[0][2]},
        {ZILLA_SHOOT_R0 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[0][3]},
        {ZILLA_SHOOT_R0 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[0][4]},
        {ZILLA_SHOOT_R0 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[0][5]},
        {ZILLA_SHOOT_R0 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[0][6]},
        {ZILLA_SHOOT_R0 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[0][7]},
        {ZILLA_SHOOT_R0 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[0][8]},
        {ZILLA_SHOOT_R0 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[0][9]},
        {ZILLA_SHOOT_R0 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[0][10]},
        {ZILLA_SHOOT_R0 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[0][11]},
        {ZILLA_SHOOT_R0 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[0][12]},
        {ZILLA_SHOOT_R0 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[0][13]},
        {ZILLA_SHOOT_R0 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[0][14]},
        {ZILLA_SHOOT_R0 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[0][15]},
        {ZILLA_SHOOT_R0 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[0][16]},
        {ZILLA_SHOOT_R0 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZillaUzi[0][16]},
    },
    {
        {ZILLA_SHOOT_R1 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[1][1]},
        {ZILLA_SHOOT_R1 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[1][2]},
        {ZILLA_SHOOT_R1 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[1][3]},
        {ZILLA_SHOOT_R1 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[1][4]},
        {ZILLA_SHOOT_R1 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[1][5]},
        {ZILLA_SHOOT_R1 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[1][6]},
        {ZILLA_SHOOT_R1 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[1][7]},
        {ZILLA_SHOOT_R1 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[1][8]},
        {ZILLA_SHOOT_R1 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[1][9]},
        {ZILLA_SHOOT_R1 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[1][10]},
        {ZILLA_SHOOT_R1 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[1][11]},
        {ZILLA_SHOOT_R1 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[1][12]},
        {ZILLA_SHOOT_R1 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[1][13]},
        {ZILLA_SHOOT_R1 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[1][14]},
        {ZILLA_SHOOT_R1 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[1][15]},
        {ZILLA_SHOOT_R1 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[1][16]},
        {ZILLA_SHOOT_R1 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZillaUzi[1][16]},
    },
    {
        {ZILLA_SHOOT_R2 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[2][1]},
        {ZILLA_SHOOT_R2 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[2][2]},
        {ZILLA_SHOOT_R2 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[2][3]},
        {ZILLA_SHOOT_R2 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[2][4]},
        {ZILLA_SHOOT_R2 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[2][5]},
        {ZILLA_SHOOT_R2 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[2][6]},
        {ZILLA_SHOOT_R2 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[2][7]},
        {ZILLA_SHOOT_R2 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[2][8]},
        {ZILLA_SHOOT_R2 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[2][9]},
        {ZILLA_SHOOT_R2 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[2][10]},
        {ZILLA_SHOOT_R2 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[2][11]},
        {ZILLA_SHOOT_R2 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[2][12]},
        {ZILLA_SHOOT_R2 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[2][13]},
        {ZILLA_SHOOT_R2 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[2][14]},
        {ZILLA_SHOOT_R2 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[2][15]},
        {ZILLA_SHOOT_R2 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[2][16]},
        {ZILLA_SHOOT_R2 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZillaUzi[2][16]},
    },
    {
        {ZILLA_SHOOT_R3 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[3][1]},
        {ZILLA_SHOOT_R3 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[3][2]},
        {ZILLA_SHOOT_R3 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[3][3]},
        {ZILLA_SHOOT_R3 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[3][4]},
        {ZILLA_SHOOT_R3 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[3][5]},
        {ZILLA_SHOOT_R3 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[3][6]},
        {ZILLA_SHOOT_R3 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[3][7]},
        {ZILLA_SHOOT_R3 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[3][8]},
        {ZILLA_SHOOT_R3 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[3][9]},
        {ZILLA_SHOOT_R3 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[3][10]},
        {ZILLA_SHOOT_R3 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[3][11]},
        {ZILLA_SHOOT_R3 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[3][12]},
        {ZILLA_SHOOT_R3 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[3][13]},
        {ZILLA_SHOOT_R3 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[3][14]},
        {ZILLA_SHOOT_R3 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[3][15]},
        {ZILLA_SHOOT_R3 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[3][16]},
        {ZILLA_SHOOT_R3 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZillaUzi[3][16]},
    },
    {
        {ZILLA_SHOOT_R4 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[4][1]},
        {ZILLA_SHOOT_R4 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[4][2]},
        {ZILLA_SHOOT_R4 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[4][3]},
        {ZILLA_SHOOT_R4 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[4][4]},
        {ZILLA_SHOOT_R4 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[4][5]},
        {ZILLA_SHOOT_R4 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[4][6]},
        {ZILLA_SHOOT_R4 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[4][7]},
        {ZILLA_SHOOT_R4 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[4][8]},
        {ZILLA_SHOOT_R4 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[4][9]},
        {ZILLA_SHOOT_R4 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[4][10]},
        {ZILLA_SHOOT_R4 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[4][11]},
        {ZILLA_SHOOT_R4 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[4][12]},
        {ZILLA_SHOOT_R4 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[4][13]},
        {ZILLA_SHOOT_R4 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[4][14]},
        {ZILLA_SHOOT_R4 + 0, ZILLA_UZI_RATE, NullZilla, &s_ZillaUzi[4][15]},
        {ZILLA_SHOOT_R4 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZillaUzi[4][16]},
        {ZILLA_SHOOT_R4 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZillaUzi[4][16]},
    },
};

STATEp sg_ZillaUzi[] =
{
    s_ZillaUzi[0],
    s_ZillaUzi[1],
    s_ZillaUzi[2],
    s_ZillaUzi[3],
    s_ZillaUzi[4]
};

//////////////////////
//
// ZILLA DIE
//
//////////////////////

#define ZILLA_DIE_RATE 30
ANIMATOR DoZillaDeathMelt;

STATE s_ZillaDie[] =
{
    {ZILLA_DIE + 0, ZILLA_DIE_RATE*15, DoZillaDeathMelt, &s_ZillaDie[1]},
    {ZILLA_DIE + 1, ZILLA_DIE_RATE, NullZilla, &s_ZillaDie[2]},
    {ZILLA_DIE + 2, ZILLA_DIE_RATE, NullZilla, &s_ZillaDie[3]},
    {ZILLA_DIE + 3, ZILLA_DIE_RATE, NullZilla, &s_ZillaDie[4]},
    {ZILLA_DIE + 4, ZILLA_DIE_RATE, NullZilla, &s_ZillaDie[5]},
    {ZILLA_DIE + 5, ZILLA_DIE_RATE, NullZilla, &s_ZillaDie[6]},
    {ZILLA_DIE + 6, ZILLA_DIE_RATE, NullZilla, &s_ZillaDie[7]},
    {ZILLA_DIE + 7, ZILLA_DIE_RATE*3, NullZilla, &s_ZillaDie[8]},
    {ZILLA_DEAD, ZILLA_DIE_RATE, DoActorDebris, &s_ZillaDie[8]}
};

STATEp sg_ZillaDie[] =
{
    s_ZillaDie
};

STATE s_ZillaDead[] =
{
    {ZILLA_DEAD, ZILLA_DIE_RATE, DoActorDebris, &s_ZillaDead[0]},
};

STATEp sg_ZillaDead[] =
{
    s_ZillaDead
};

/*
typedef struct
{
#define MAX_ACTOR_CLOSE_ATTACK 2
#define MAX_ACTOR_ATTACK 6
STATEp *Stand;
STATEp *Run;
STATEp *Jump;
STATEp *Fall;
STATEp *Crawl;
STATEp *Swim;
STATEp *Fly;
STATEp *Rise;
STATEp *Sit;
STATEp *Look;
STATEp *Climb;
STATEp *Pain;
STATEp *Death1;
STATEp *Death2;
STATEp *Dead;
STATEp *DeathJump;
STATEp *DeathFall;

STATEp *CloseAttack[MAX_ACTOR_CLOSE_ATTACK];
short  CloseAttackPercent[MAX_ACTOR_CLOSE_ATTACK];

STATEp *Attack[MAX_ACTOR_ATTACK];
short  AttackPercent[MAX_ACTOR_ATTACK];

STATEp *Special[2];
STATEp *Duck;
STATEp *Dive;
}ACTOR_ACTION_SET,*ACTOR_ACTION_SETp;
*/

ACTOR_ACTION_SET ZillaActionSet =
{
    sg_ZillaStand,
    sg_ZillaRun,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL, //climb
    sg_ZillaPain, //pain
    sg_ZillaDie,
    NULL,
    sg_ZillaDead,
    NULL,
    NULL,
    {sg_ZillaUzi,sg_ZillaRail},
    {950,1024},
    {sg_ZillaUzi,sg_ZillaRocket,sg_ZillaRail},
    {400,950,1024},
    {NULL},
    NULL,
    NULL
};

int
SetupZilla(short SpriteNum)
{
    SPRITEp sp = &sprite[SpriteNum];
    USERp u;
    ANIMATOR DoActorDecide;

    if (TEST(sp->cstat, CSTAT_SPRITE_RESTORE))
    {
        u = User[SpriteNum];
        ASSERT(u);
    }
    else
    {
        User[SpriteNum] = u = SpawnUser(SpriteNum,ZILLA_RUN_R0,s_ZillaRun[0]);
        u->Health = 6000;
    }

    if (Skill == 0) u->Health = 2000;
    if (Skill == 1) u->Health = 4000;

    ChangeState(SpriteNum,s_ZillaRun[0]);
    u->Attrib = &ZillaAttrib;
    DoActorSetSpeed(SpriteNum, NORM_SPEED);
    u->StateEnd = s_ZillaDie;
    u->Rot = sg_ZillaRun;

    EnemyDefaults(SpriteNum, &ZillaActionSet, &ZillaPersonality);

    sp->clipdist = (512) >> 2;
    sp->xrepeat = 97;
    sp->yrepeat = 79;

    //SET(u->Flags, SPR_XFLIP_TOGGLE);

    return 0;
}

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

    //if (TEST(u->Flags,SPR_SLIDING))
    //DoActorSlide(SpriteNum);

#if 0
    if (u->State == s_ZillaDie)
    {
        getzsofslope(sp->sectnum, sp->x, sp->y, &u->hiz, &u->loz);
        u->lo_sectp = &sector[sp->sectnum];
        u->hi_sectp = &sector[sp->sectnum];
        sp->z = u->loz;
    }
#endif

    //if (!TEST(u->Flags,SPR_CLIMBING))
    //    KeepActorOnFloor(SpriteNum);
    getzsofslope(sp->sectnum, sp->x, sp->y, &u->hiz, &u->loz);
    u->lo_sectp = &sector[sp->sectnum];
    u->hi_sectp = &sector[sp->sectnum];
    u->lo_sp = NULL;
    u->hi_sp = NULL;
    sp->z = u->loz;

    DoActorSectorDamage(SpriteNum);

    return 0;
}

int DoZillaMove(short SpriteNum)
{
    SPRITEp sp = &sprite[SpriteNum];
    USERp u = User[SpriteNum];
    short choose;
    static int handle;

    //if (TEST(u->Flags,SPR_SLIDING))
    //DoActorSlide(SpriteNum);

    // Random Zilla taunts
    if (!FX_SoundValidAndActive(handle))
    {
        choose = STD_RANDOM_RANGE(1000);
        if (choose > 990)
            handle = PlaySound(DIGI_Z16004,&sp->x,&sp->y,&sp->z,v3df_none);
        else if (choose > 985)
            handle = PlaySound(DIGI_Z16004,&sp->x,&sp->y,&sp->z,v3df_none);
        else if (choose > 980)
            handle = PlaySound(DIGI_Z16004,&sp->x,&sp->y,&sp->z,v3df_none);
        else if (choose > 975)
            handle = PlaySound(DIGI_Z16004,&sp->x,&sp->y,&sp->z,v3df_none);
    }

    if (u->track >= 0)
        ActorFollowTrack(SpriteNum, ACTORMOVETICS);
    else
        (*u->ActorActionFunc)(SpriteNum);

    KeepActorOnFloor(SpriteNum);

    if (DoActorSectorDamage(SpriteNum))
    {
        return 0;
    }

    return 0;
}

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

    PlaySound(DIGI_ZILLASTOMP,&sp->x,&sp->y,&sp->z,v3df_follow);

    return 0;
}

extern int SpawnGrenadeExp(int16_t Weapon);

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

    if (RANDOM_RANGE(1000) > 800)
        SpawnGrenadeExp(SpriteNum);

    u->ID = ZILLA_RUN_R0;
    RESET(u->Flags, SPR_JUMPING|SPR_FALLING|SPR_MOVED);

    //DoMatchEverything(NULL, sp->lotag, ON);
    if (!SW_SHAREWARE && gs.MusicOn)
        PlaySong(0, RedBookSong[Level], TRUE, FALSE);

    //KeepActorOnFloor(SpriteNum);
    getzsofslope(sp->sectnum, sp->x, sp->y, &u->hiz, &u->loz);
    u->lo_sectp = &sector[sp->sectnum];
    u->hi_sectp = &sector[sp->sectnum];
    u->lo_sp = NULL;
    u->hi_sp = NULL;
    sp->z = u->loz;

    BossSpriteNum[2] = -2;
    return 0;
}

#include "saveable.h"

static saveable_code saveable_zilla_code[] =
{
    SAVE_CODE(SetupZilla),
    SAVE_CODE(NullZilla),
    SAVE_CODE(DoZillaMove),
    SAVE_CODE(DoZillaStomp),
    SAVE_CODE(DoZillaDeathMelt),
};

static saveable_data saveable_zilla_data[] =
{
    SAVE_DATA(ZillaBattle),
    SAVE_DATA(ZillaOffense),
    SAVE_DATA(ZillaBroadcast),
    SAVE_DATA(ZillaSurprised),
    SAVE_DATA(ZillaEvasive),
    SAVE_DATA(ZillaLostTarget),
    SAVE_DATA(ZillaCloseRange),

    SAVE_DATA(ZillaPersonality),

    SAVE_DATA(ZillaAttrib),

    SAVE_DATA(s_ZillaRun),
    SAVE_DATA(sg_ZillaRun),
    SAVE_DATA(s_ZillaStand),
    SAVE_DATA(sg_ZillaStand),
    SAVE_DATA(s_ZillaPain),
    SAVE_DATA(sg_ZillaPain),
    SAVE_DATA(s_ZillaRail),
    SAVE_DATA(sg_ZillaRail),
    SAVE_DATA(s_ZillaRocket),
    SAVE_DATA(sg_ZillaRocket),
    SAVE_DATA(s_ZillaUzi),
    SAVE_DATA(sg_ZillaUzi),
    SAVE_DATA(s_ZillaDie),
    SAVE_DATA(sg_ZillaDie),
    SAVE_DATA(s_ZillaDead),
    SAVE_DATA(sg_ZillaDead),

    SAVE_DATA(ZillaActionSet),
};

saveable_module saveable_zilla =
{
    // code
    saveable_zilla_code,
    SIZ(saveable_zilla_code),

    // data
    saveable_zilla_data,
    SIZ(saveable_zilla_data)
};


code:
//-------------------------------------------------------------------------
/*
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 "keys.h"
#include "names2.h"
#include "panel.h"
#include "game.h"
#include "tags.h"
#include "ai.h"
#include "pal.h"
#include "player.h"
#include "network.h"
#include "sprite.h"
#include "weapon.h"
#include "actor.h"
#include "track.h"

//extern short Zombies;
#define ZOMBIE_TIME_LIMIT ((120*20)/ACTORMOVETICS)

DECISION ZombieBattle[] =
{
    {399, InitActorMoveCloser},
    {1024, InitActorAttack}
};

DECISION ZombieOffense[] =
{
    {399, InitActorMoveCloser},
    {1024, InitActorAttack}
};

DECISION ZombieBroadcast[] =
{
    {6, InitActorAmbientNoise},
    {1024, InitActorDecide}
};

DECISION ZombieSurprised[] =
{
    {701, InitActorMoveCloser},
    {1024, InitActorDecide}
};

DECISION ZombieEvasive[] =
{
    {400,   InitActorDuck},
    {1024,  NULL}
};

DECISION ZombieLostTarget[] =
{
    {900, InitActorFindPlayer},
    {1024, InitActorWanderAround}
};

DECISION ZombieCloseRange[] =
{
    {800,   InitActorAttack             },
    {1024,  InitActorReposition         }
};

PERSONALITY ZombiePersonality =
{
    ZombieBattle,
    ZombieOffense,
    ZombieBroadcast,
    ZombieSurprised,
    ZombieEvasive,
    ZombieLostTarget,
    ZombieCloseRange,
    ZombieCloseRange
};

ATTRIBUTE ZombieAttrib =
{
    //{50, 60, 70, 80},                   // Speeds
    {120, 140, 170, 200},                 // Speeds
    {4, 0, 0, -2},                      // Tic Adjusts
    3,                                 // MaxWeapons;
    {
        DIGI_NINJAAMBIENT, DIGI_NINJAALERT, DIGI_STAR,
        DIGI_NINJAPAIN, DIGI_NINJASCREAM,0,0,0,0,0
    }
};

//////////////////////
//
// ZOMBIE RUN
//
//////////////////////

#define ZOMBIE_RATE 32
ANIMATOR DoZombieMove, NullZombie;

STATE s_ZombieRun[5][4] =
{
    {
        {PLAYER_NINJA_RUN_R0 + 0, ZOMBIE_RATE | SF_TIC_ADJUST, DoZombieMove, &s_ZombieRun[0][1]},
        {PLAYER_NINJA_RUN_R0 + 1, ZOMBIE_RATE | SF_TIC_ADJUST, DoZombieMove, &s_ZombieRun[0][2]},
        {PLAYER_NINJA_RUN_R0 + 2, ZOMBIE_RATE | SF_TIC_ADJUST, DoZombieMove, &s_ZombieRun[0][3]},
        {PLAYER_NINJA_RUN_R0 + 3, ZOMBIE_RATE | SF_TIC_ADJUST, DoZombieMove, &s_ZombieRun[0][0]},
    },
    {
        {PLAYER_NINJA_RUN_R1 + 0, ZOMBIE_RATE | SF_TIC_ADJUST, DoZombieMove, &s_ZombieRun[1][1]},
        {PLAYER_NINJA_RUN_R1 + 1, ZOMBIE_RATE | SF_TIC_ADJUST, DoZombieMove, &s_ZombieRun[1][2]},
        {PLAYER_NINJA_RUN_R1 + 2, ZOMBIE_RATE | SF_TIC_ADJUST, DoZombieMove, &s_ZombieRun[1][3]},
        {PLAYER_NINJA_RUN_R1 + 3, ZOMBIE_RATE | SF_TIC_ADJUST, DoZombieMove, &s_ZombieRun[1][0]},
    },
    {
        {PLAYER_NINJA_RUN_R2 + 0, ZOMBIE_RATE | SF_TIC_ADJUST, DoZombieMove, &s_ZombieRun[2][1]},
        {PLAYER_NINJA_RUN_R2 + 1, ZOMBIE_RATE | SF_TIC_ADJUST, DoZombieMove, &s_ZombieRun[2][2]},
        {PLAYER_NINJA_RUN_R2 + 2, ZOMBIE_RATE | SF_TIC_ADJUST, DoZombieMove, &s_ZombieRun[2][3]},
        {PLAYER_NINJA_RUN_R2 + 3, ZOMBIE_RATE | SF_TIC_ADJUST, DoZombieMove, &s_ZombieRun[2][0]},
    },
    {
        {PLAYER_NINJA_RUN_R3 + 0, ZOMBIE_RATE | SF_TIC_ADJUST, DoZombieMove, &s_ZombieRun[3][1]},
        {PLAYER_NINJA_RUN_R3 + 1, ZOMBIE_RATE | SF_TIC_ADJUST, DoZombieMove, &s_ZombieRun[3][2]},
        {PLAYER_NINJA_RUN_R3 + 2, ZOMBIE_RATE | SF_TIC_ADJUST, DoZombieMove, &s_ZombieRun[3][3]},
        {PLAYER_NINJA_RUN_R3 + 3, ZOMBIE_RATE | SF_TIC_ADJUST, DoZombieMove, &s_ZombieRun[3][0]},
    },
    {
        {PLAYER_NINJA_RUN_R4 + 0, ZOMBIE_RATE | SF_TIC_ADJUST, DoZombieMove, &s_ZombieRun[4][1]},
        {PLAYER_NINJA_RUN_R4 + 1, ZOMBIE_RATE | SF_TIC_ADJUST, DoZombieMove, &s_ZombieRun[4][2]},
        {PLAYER_NINJA_RUN_R4 + 2, ZOMBIE_RATE | SF_TIC_ADJUST, DoZombieMove, &s_ZombieRun[4][3]},
        {PLAYER_NINJA_RUN_R4 + 3, ZOMBIE_RATE | SF_TIC_ADJUST, DoZombieMove, &s_ZombieRun[4][0]},
    },
};

STATEp sg_ZombieRun[] =
{
    s_ZombieRun[0],
    s_ZombieRun[1],
    s_ZombieRun[2],
    s_ZombieRun[3],
    s_ZombieRun[4]
};

//////////////////////
//
// PLAYER_ZOMBIE STAND
//
//////////////////////

#define ZOMBIE_STAND_RATE 10

STATE s_ZombieStand[5][1] =
{
    {
        {PLAYER_NINJA_STAND_R0 + 0, ZOMBIE_STAND_RATE, NullZombie, &s_ZombieStand[0][0]},
    },
    {
        {PLAYER_NINJA_STAND_R1 + 0, ZOMBIE_STAND_RATE, NullZombie, &s_ZombieStand[1][0]},
    },
    {
        {PLAYER_NINJA_STAND_R2 + 0, ZOMBIE_STAND_RATE, NullZombie, &s_ZombieStand[2][0]},
    },
    {
        {PLAYER_NINJA_STAND_R3 + 0, ZOMBIE_STAND_RATE, NullZombie, &s_ZombieStand[3][0]},
    },
    {
        {PLAYER_NINJA_STAND_R4 + 0, ZOMBIE_STAND_RATE, NullZombie, &s_ZombieStand[4][0]},
    },
};

STATEp sg_ZombieStand[] =
{
    s_ZombieStand[0],
    s_ZombieStand[1],
    s_ZombieStand[2],
    s_ZombieStand[3],
    s_ZombieStand[4]
};

//////////////////////
//
// ZOMBIE PAIN
//
//////////////////////

#define ZOMBIE_PAIN_RATE 15
ANIMATOR DoZombiePain;

STATE s_ZombiePain[5][2] =
{
    {
        {PLAYER_NINJA_STAND_R0 + 0, ZOMBIE_PAIN_RATE, DoZombiePain, &s_ZombiePain[0][1]},
        {PLAYER_NINJA_STAND_R0 + 1, ZOMBIE_PAIN_RATE, DoZombiePain, &s_ZombiePain[0][1]},
    },
    {
        {PLAYER_NINJA_STAND_R1 + 0, ZOMBIE_PAIN_RATE, DoZombiePain, &s_ZombiePain[1][1]},
        {PLAYER_NINJA_STAND_R1 + 0, ZOMBIE_PAIN_RATE, DoZombiePain, &s_ZombiePain[1][1]},
    },
    {
        {PLAYER_NINJA_STAND_R2 + 0, ZOMBIE_PAIN_RATE, DoZombiePain, &s_ZombiePain[2][1]},
        {PLAYER_NINJA_STAND_R2 + 0, ZOMBIE_PAIN_RATE, DoZombiePain, &s_ZombiePain[2][1]},
    },
    {
        {PLAYER_NINJA_STAND_R3 + 0, ZOMBIE_PAIN_RATE, DoZombiePain, &s_ZombiePain[3][1]},
        {PLAYER_NINJA_STAND_R3 + 0, ZOMBIE_PAIN_RATE, DoZombiePain, &s_ZombiePain[3][1]},
    },
    {
        {PLAYER_NINJA_STAND_R4 + 0, ZOMBIE_PAIN_RATE, DoZombiePain, &s_ZombiePain[4][1]},
        {PLAYER_NINJA_STAND_R4 + 0, ZOMBIE_PAIN_RATE, DoZombiePain, &s_ZombiePain[4][1]},
    },
};

STATEp sg_ZombiePain[] =
{
    s_ZombiePain[0],
    s_ZombiePain[1],
    s_ZombiePain[2],
    s_ZombiePain[3],
    s_ZombiePain[4]
};

//////////////////////
//
// ZOMBIE NUKE
//
//////////////////////

#define ZOMBIE_NUKE_RATE 18
ANIMATOR InitEnemyNuke;

STATE s_ZombieNuke[5][6] =
{
    {
        {PLAYER_NINJA_SHOOT_R0 + 0, ZOMBIE_NUKE_RATE * 2, NullZombie, &s_ZombieNuke[0][1]},
        {PLAYER_NINJA_SHOOT_R0 + 0, ZOMBIE_NUKE_RATE, NullZombie, &s_ZombieNuke[0][2]},
        {PLAYER_NINJA_SHOOT_R0 + 0, 0 | SF_QUICK_CALL, InitEnemyNuke, &s_ZombieNuke[0][3]},
        {PLAYER_NINJA_SHOOT_R0 + 0, ZOMBIE_NUKE_RATE * 2, NullZombie, &s_ZombieNuke[0][4]},
        {PLAYER_NINJA_SHOOT_R0 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZombieNuke[0][5]},
        {PLAYER_NINJA_SHOOT_R0 + 0, ZOMBIE_NUKE_RATE, DoZombieMove, &s_ZombieNuke[0][5]},
    },
    {
        {PLAYER_NINJA_SHOOT_R1 + 0, ZOMBIE_NUKE_RATE * 2, NullZombie, &s_ZombieNuke[1][1]},
        {PLAYER_NINJA_SHOOT_R1 + 0, ZOMBIE_NUKE_RATE, NullZombie, &s_ZombieNuke[1][2]},
        {PLAYER_NINJA_SHOOT_R1 + 0, 0 | SF_QUICK_CALL, InitEnemyNuke, &s_ZombieNuke[1][3]},
        {PLAYER_NINJA_SHOOT_R1 + 0, ZOMBIE_NUKE_RATE * 2, NullZombie, &s_ZombieNuke[1][4]},
        {PLAYER_NINJA_SHOOT_R1 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZombieNuke[1][5]},
        {PLAYER_NINJA_SHOOT_R1 + 0, ZOMBIE_NUKE_RATE, DoZombieMove, &s_ZombieNuke[1][5]},
    },
    {
        {PLAYER_NINJA_SHOOT_R2 + 0, ZOMBIE_NUKE_RATE * 2, NullZombie, &s_ZombieNuke[2][1]},
        {PLAYER_NINJA_SHOOT_R2 + 0, ZOMBIE_NUKE_RATE, NullZombie, &s_ZombieNuke[2][2]},
        {PLAYER_NINJA_SHOOT_R2 + 0, 0 | SF_QUICK_CALL, InitEnemyNuke, &s_ZombieNuke[2][3]},
        {PLAYER_NINJA_SHOOT_R2 + 0, ZOMBIE_NUKE_RATE * 2, NullZombie, &s_ZombieNuke[2][4]},
        {PLAYER_NINJA_SHOOT_R2 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZombieNuke[2][5]},
        {PLAYER_NINJA_SHOOT_R2 + 0, ZOMBIE_NUKE_RATE, DoZombieMove, &s_ZombieNuke[2][5]},
    },
    {
        {PLAYER_NINJA_SHOOT_R2 + 0, ZOMBIE_NUKE_RATE * 2, NullZombie, &s_ZombieNuke[3][1]},
        {PLAYER_NINJA_SHOOT_R2 + 0, ZOMBIE_NUKE_RATE, NullZombie, &s_ZombieNuke[3][2]},
        {PLAYER_NINJA_SHOOT_R2 + 0, 0 | SF_QUICK_CALL, InitEnemyNuke, &s_ZombieNuke[3][3]},
        {PLAYER_NINJA_SHOOT_R2 + 0, ZOMBIE_NUKE_RATE * 2, NullZombie, &s_ZombieNuke[3][4]},
        {PLAYER_NINJA_SHOOT_R2 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZombieNuke[3][5]},
        {PLAYER_NINJA_SHOOT_R2 + 0, ZOMBIE_NUKE_RATE, DoZombieMove, &s_ZombieNuke[3][5]},
    },
    {
        {PLAYER_NINJA_SHOOT_R2 + 0, ZOMBIE_NUKE_RATE * 2, NullZombie, &s_ZombieNuke[4][1]},
        {PLAYER_NINJA_SHOOT_R2 + 0, ZOMBIE_NUKE_RATE, NullZombie, &s_ZombieNuke[4][2]},
        {PLAYER_NINJA_SHOOT_R2 + 0, 0 | SF_QUICK_CALL, InitEnemyNuke, &s_ZombieNuke[4][3]},
        {PLAYER_NINJA_SHOOT_R2 + 0, ZOMBIE_NUKE_RATE * 2, NullZombie, &s_ZombieNuke[4][4]},
        {PLAYER_NINJA_SHOOT_R2 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZombieNuke[4][5]},
        {PLAYER_NINJA_SHOOT_R2 + 0, ZOMBIE_NUKE_RATE, DoZombieMove, &s_ZombieNuke[4][5]},
    },
};

STATEp sg_ZombieNuke[] =
{
    s_ZombieNuke[0],
    s_ZombieNuke[1],
    s_ZombieNuke[2],
    s_ZombieNuke[3],
    s_ZombieNuke[4]
};

//////////////////////
//
// ZOMBIE ROCKET
//
//////////////////////

#define ZOMBIE_ROCKET_RATE 14
ANIMATOR InitEnemyRocket;

STATE s_ZombieRocket[5][5] =
{
    {
        {PLAYER_NINJA_STAND_R0 + 0, ZOMBIE_ROCKET_RATE * 2, NullZombie, &s_ZombieRocket[0][1]},
        {PLAYER_NINJA_STAND_R0 + 0, 0 | SF_QUICK_CALL, InitEnemyRocket, &s_ZombieRocket[0][2]},
        {PLAYER_NINJA_STAND_R0 + 0, ZOMBIE_ROCKET_RATE, NullZombie, &s_ZombieRocket[0][3]},
        {PLAYER_NINJA_STAND_R0 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZombieRocket[0][4]},
        {PLAYER_NINJA_STAND_R0 + 0, ZOMBIE_ROCKET_RATE, DoZombieMove, &s_ZombieRocket[0][4]},
    },
    {
        {PLAYER_NINJA_STAND_R1 + 0, ZOMBIE_ROCKET_RATE * 2, NullZombie, &s_ZombieRocket[1][1]},
        {PLAYER_NINJA_STAND_R1 + 0, 0 | SF_QUICK_CALL, InitEnemyRocket, &s_ZombieRocket[1][2]},
        {PLAYER_NINJA_STAND_R1 + 0, ZOMBIE_ROCKET_RATE, NullZombie, &s_ZombieRocket[1][3]},
        {PLAYER_NINJA_STAND_R1 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZombieRocket[1][4]},
        {PLAYER_NINJA_STAND_R1 + 0, ZOMBIE_ROCKET_RATE, DoZombieMove, &s_ZombieRocket[1][4]},
    },
    {
        {PLAYER_NINJA_STAND_R2 + 0, ZOMBIE_ROCKET_RATE * 2, NullZombie, &s_ZombieRocket[2][1]},
        {PLAYER_NINJA_STAND_R2 + 0, 0 | SF_QUICK_CALL, InitEnemyRocket, &s_ZombieRocket[2][2]},
        {PLAYER_NINJA_STAND_R2 + 0, ZOMBIE_ROCKET_RATE, NullZombie, &s_ZombieRocket[2][3]},
        {PLAYER_NINJA_STAND_R2 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZombieRocket[2][4]},
        {PLAYER_NINJA_STAND_R2 + 0, ZOMBIE_ROCKET_RATE, DoZombieMove, &s_ZombieRocket[2][4]},
    },
    {
        {PLAYER_NINJA_STAND_R3 + 0, ZOMBIE_ROCKET_RATE * 2, NullZombie, &s_ZombieRocket[3][1]},
        {PLAYER_NINJA_STAND_R3 + 0, 0 | SF_QUICK_CALL, InitEnemyRocket, &s_ZombieRocket[3][2]},
        {PLAYER_NINJA_STAND_R3 + 0, ZOMBIE_ROCKET_RATE, NullZombie, &s_ZombieRocket[3][3]},
        {PLAYER_NINJA_STAND_R3 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZombieRocket[3][4]},
        {PLAYER_NINJA_STAND_R3 + 0, ZOMBIE_ROCKET_RATE, DoZombieMove, &s_ZombieRocket[3][4]},
    },
    {
        {PLAYER_NINJA_STAND_R4 + 0, ZOMBIE_ROCKET_RATE * 2, NullZombie, &s_ZombieRocket[4][1]},
        {PLAYER_NINJA_STAND_R4 + 0, 0 | SF_QUICK_CALL, InitEnemyRocket, &s_ZombieRocket[4][2]},
        {PLAYER_NINJA_STAND_R4 + 0, ZOMBIE_ROCKET_RATE, NullZombie, &s_ZombieRocket[4][3]},
        {PLAYER_NINJA_STAND_R4 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZombieRocket[4][4]},
        {PLAYER_NINJA_STAND_R4 + 0, ZOMBIE_ROCKET_RATE, DoZombieMove, &s_ZombieRocket[4][4]},
    },
};

STATEp sg_ZombieRocket[] =
{
    s_ZombieRocket[0],
    s_ZombieRocket[1],
    s_ZombieRocket[2],
    s_ZombieRocket[3],
    s_ZombieRocket[4]
};

//////////////////////
//
// ZOMBIE ROCKET
//
//////////////////////

#define ZOMBIE_RAIL_RATE 14
ANIMATOR InitEnemyRail;

STATE s_ZombieRail[5][5] =
{
    {
        {PLAYER_NINJA_STAND_R0 + 0, ZOMBIE_RAIL_RATE * 2, NullZombie, &s_ZombieRail[0][1]},
        {PLAYER_NINJA_STAND_R0 + 0, 0 | SF_QUICK_CALL, InitEnemyRail, &s_ZombieRail[0][2]},
        {PLAYER_NINJA_STAND_R0 + 0, ZOMBIE_RAIL_RATE, NullZombie, &s_ZombieRail[0][3]},
        {PLAYER_NINJA_STAND_R0 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZombieRail[0][4]},
        {PLAYER_NINJA_STAND_R0 + 0, ZOMBIE_RAIL_RATE, DoZombieMove, &s_ZombieRail[0][4]},
    },
    {
        {PLAYER_NINJA_STAND_R1 + 0, ZOMBIE_RAIL_RATE * 2, NullZombie, &s_ZombieRail[1][1]},
        {PLAYER_NINJA_STAND_R1 + 0, 0 | SF_QUICK_CALL, InitEnemyRail, &s_ZombieRail[1][2]},
        {PLAYER_NINJA_STAND_R1 + 0, ZOMBIE_RAIL_RATE, NullZombie, &s_ZombieRail[1][3]},
        {PLAYER_NINJA_STAND_R1 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZombieRail[1][4]},
        {PLAYER_NINJA_STAND_R1 + 0, ZOMBIE_RAIL_RATE, DoZombieMove, &s_ZombieRail[1][4]},
    },
    {
        {PLAYER_NINJA_STAND_R2 + 0, ZOMBIE_RAIL_RATE * 2, NullZombie, &s_ZombieRail[2][1]},
        {PLAYER_NINJA_STAND_R2 + 0, 0 | SF_QUICK_CALL, InitEnemyRail, &s_ZombieRail[2][2]},
        {PLAYER_NINJA_STAND_R2 + 0, ZOMBIE_RAIL_RATE, NullZombie, &s_ZombieRail[2][3]},
        {PLAYER_NINJA_STAND_R2 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZombieRail[2][4]},
        {PLAYER_NINJA_STAND_R2 + 0, ZOMBIE_RAIL_RATE, DoZombieMove, &s_ZombieRail[2][4]},
    },
    {
        {PLAYER_NINJA_STAND_R3 + 0, ZOMBIE_RAIL_RATE * 2, NullZombie, &s_ZombieRail[3][1]},
        {PLAYER_NINJA_STAND_R3 + 0, 0 | SF_QUICK_CALL, InitEnemyRail, &s_ZombieRail[3][2]},
        {PLAYER_NINJA_STAND_R3 + 0, ZOMBIE_RAIL_RATE, NullZombie, &s_ZombieRail[3][3]},
        {PLAYER_NINJA_STAND_R3 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZombieRail[3][4]},
        {PLAYER_NINJA_STAND_R3 + 0, ZOMBIE_RAIL_RATE, DoZombieMove, &s_ZombieRail[3][4]},
    },
    {
        {PLAYER_NINJA_STAND_R4 + 0, ZOMBIE_RAIL_RATE * 2, NullZombie, &s_ZombieRail[4][1]},
        {PLAYER_NINJA_STAND_R4 + 0, 0 | SF_QUICK_CALL, InitEnemyRail, &s_ZombieRail[4][2]},
        {PLAYER_NINJA_STAND_R4 + 0, ZOMBIE_RAIL_RATE, NullZombie, &s_ZombieRail[4][3]},
        {PLAYER_NINJA_STAND_R4 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZombieRail[4][4]},
        {PLAYER_NINJA_STAND_R4 + 0, ZOMBIE_RAIL_RATE, DoZombieMove, &s_ZombieRail[4][4]},
    },
};

STATEp sg_ZombieRail[] =
{
    s_ZombieRail[0],
    s_ZombieRail[1],
    s_ZombieRail[2],
    s_ZombieRail[3],
    s_ZombieRail[4]
};

//////////////////////
//
// ZOMBIE GRENADE
//
//////////////////////

#define ZOMBIE_ROCKET_RATE 14
ANIMATOR InitSpriteGrenade;

STATE s_ZombieGrenade[5][5] =
{
    {
        {PLAYER_NINJA_STAND_R0 + 0, ZOMBIE_ROCKET_RATE * 2, NullZombie, &s_ZombieGrenade[0][1]},
        {PLAYER_NINJA_STAND_R0 + 0, 0 | SF_QUICK_CALL, InitSpriteGrenade, &s_ZombieGrenade[0][2]},
        {PLAYER_NINJA_STAND_R0 + 0, ZOMBIE_ROCKET_RATE, NullZombie, &s_ZombieGrenade[0][3]},
        {PLAYER_NINJA_STAND_R0 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZombieGrenade[0][4]},
        {PLAYER_NINJA_STAND_R0 + 0, ZOMBIE_ROCKET_RATE, DoZombieMove, &s_ZombieGrenade[0][4]},
    },
    {
        {PLAYER_NINJA_STAND_R1 + 0, ZOMBIE_ROCKET_RATE * 2, NullZombie, &s_ZombieGrenade[1][1]},
        {PLAYER_NINJA_STAND_R1 + 0, 0 | SF_QUICK_CALL, InitSpriteGrenade, &s_ZombieGrenade[1][2]},
        {PLAYER_NINJA_STAND_R1 + 0, ZOMBIE_ROCKET_RATE, NullZombie, &s_ZombieGrenade[1][3]},
        {PLAYER_NINJA_STAND_R1 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZombieGrenade[1][4]},
        {PLAYER_NINJA_STAND_R1 + 0, ZOMBIE_ROCKET_RATE, DoZombieMove, &s_ZombieGrenade[1][4]},
    },
    {
        {PLAYER_NINJA_STAND_R2 + 0, ZOMBIE_ROCKET_RATE * 2, NullZombie, &s_ZombieGrenade[2][1]},
        {PLAYER_NINJA_STAND_R2 + 0, 0 | SF_QUICK_CALL, InitSpriteGrenade, &s_ZombieGrenade[2][2]},
        {PLAYER_NINJA_STAND_R2 + 0, ZOMBIE_ROCKET_RATE, NullZombie, &s_ZombieGrenade[2][3]},
        {PLAYER_NINJA_STAND_R2 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZombieGrenade[2][4]},
        {PLAYER_NINJA_STAND_R2 + 0, ZOMBIE_ROCKET_RATE, DoZombieMove, &s_ZombieGrenade[2][4]},
    },
    {
        {PLAYER_NINJA_STAND_R3 + 0, ZOMBIE_ROCKET_RATE * 2, NullZombie, &s_ZombieGrenade[3][1]},
        {PLAYER_NINJA_STAND_R3 + 0, 0 | SF_QUICK_CALL, InitSpriteGrenade, &s_ZombieGrenade[3][2]},
        {PLAYER_NINJA_STAND_R3 + 0, ZOMBIE_ROCKET_RATE, NullZombie, &s_ZombieGrenade[3][3]},
        {PLAYER_NINJA_STAND_R3 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZombieGrenade[3][4]},
        {PLAYER_NINJA_STAND_R3 + 0, ZOMBIE_ROCKET_RATE, DoZombieMove, &s_ZombieGrenade[3][4]},
    },
    {
        {PLAYER_NINJA_STAND_R4 + 0, ZOMBIE_ROCKET_RATE * 2, NullZombie, &s_ZombieGrenade[4][1]},
        {PLAYER_NINJA_STAND_R4 + 0, 0 | SF_QUICK_CALL, InitSpriteGrenade, &s_ZombieGrenade[4][2]},
        {PLAYER_NINJA_STAND_R4 + 0, ZOMBIE_ROCKET_RATE, NullZombie, &s_ZombieGrenade[4][3]},
        {PLAYER_NINJA_STAND_R4 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZombieGrenade[4][4]},
        {PLAYER_NINJA_STAND_R4 + 0, ZOMBIE_ROCKET_RATE, DoZombieMove, &s_ZombieGrenade[4][4]},
    },
};

STATEp sg_ZombieGrenade[] =
{
    s_ZombieGrenade[0],
    s_ZombieGrenade[1],
    s_ZombieGrenade[2],
    s_ZombieGrenade[3],
    s_ZombieGrenade[4]
};

//////////////////////
//
// ZOMBIE FLASHBOMB
//
//////////////////////

#define ZOMBIE_FLASHBOMB_RATE 14
ANIMATOR InitFlashBomb;

STATE s_ZombieFlashBomb[5][5] =
{
    {
        {PLAYER_NINJA_STAND_R0 + 0, ZOMBIE_FLASHBOMB_RATE * 2, NullZombie, &s_ZombieFlashBomb[0][1]},
        {PLAYER_NINJA_STAND_R0 + 0, 0 | SF_QUICK_CALL, InitFlashBomb, &s_ZombieFlashBomb[0][2]},
        {PLAYER_NINJA_STAND_R0 + 0, ZOMBIE_FLASHBOMB_RATE, NullZombie, &s_ZombieFlashBomb[0][3]},
        {PLAYER_NINJA_STAND_R0 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZombieFlashBomb[0][4]},
        {PLAYER_NINJA_STAND_R0 + 0, ZOMBIE_FLASHBOMB_RATE, DoZombieMove, &s_ZombieFlashBomb[0][4]},
    },
    {
        {PLAYER_NINJA_STAND_R1 + 0, ZOMBIE_FLASHBOMB_RATE * 2, NullZombie, &s_ZombieFlashBomb[1][1]},
        {PLAYER_NINJA_STAND_R1 + 0, 0 | SF_QUICK_CALL, InitFlashBomb, &s_ZombieFlashBomb[1][2]},
        {PLAYER_NINJA_STAND_R1 + 0, ZOMBIE_FLASHBOMB_RATE, NullZombie, &s_ZombieFlashBomb[1][3]},
        {PLAYER_NINJA_STAND_R1 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZombieFlashBomb[1][4]},
        {PLAYER_NINJA_STAND_R1 + 0, ZOMBIE_FLASHBOMB_RATE, DoZombieMove, &s_ZombieFlashBomb[1][4]},
    },
    {
        {PLAYER_NINJA_STAND_R2 + 0, ZOMBIE_FLASHBOMB_RATE * 2, NullZombie, &s_ZombieFlashBomb[2][1]},
        {PLAYER_NINJA_STAND_R2 + 0, 0 | SF_QUICK_CALL, InitFlashBomb, &s_ZombieFlashBomb[2][2]},
        {PLAYER_NINJA_STAND_R2 + 0, ZOMBIE_FLASHBOMB_RATE, NullZombie, &s_ZombieFlashBomb[2][3]},
        {PLAYER_NINJA_STAND_R2 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZombieFlashBomb[2][4]},
        {PLAYER_NINJA_STAND_R2 + 0, ZOMBIE_FLASHBOMB_RATE, DoZombieMove, &s_ZombieFlashBomb[2][4]},
    },
    {
        {PLAYER_NINJA_STAND_R3 + 0, ZOMBIE_FLASHBOMB_RATE * 2, NullZombie, &s_ZombieFlashBomb[3][1]},
        {PLAYER_NINJA_STAND_R3 + 0, 0 | SF_QUICK_CALL, InitFlashBomb, &s_ZombieFlashBomb[3][2]},
        {PLAYER_NINJA_STAND_R3 + 0, ZOMBIE_FLASHBOMB_RATE, NullZombie, &s_ZombieFlashBomb[3][3]},
        {PLAYER_NINJA_STAND_R3 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZombieFlashBomb[3][4]},
        {PLAYER_NINJA_STAND_R3 + 0, ZOMBIE_FLASHBOMB_RATE, DoZombieMove, &s_ZombieFlashBomb[3][4]},
    },
    {
        {PLAYER_NINJA_STAND_R4 + 0, ZOMBIE_FLASHBOMB_RATE * 2, NullZombie, &s_ZombieFlashBomb[4][1]},
        {PLAYER_NINJA_STAND_R4 + 0, 0 | SF_QUICK_CALL, InitFlashBomb, &s_ZombieFlashBomb[4][2]},
        {PLAYER_NINJA_STAND_R4 + 0, ZOMBIE_FLASHBOMB_RATE, NullZombie, &s_ZombieFlashBomb[4][3]},
        {PLAYER_NINJA_STAND_R4 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZombieFlashBomb[4][4]},
        {PLAYER_NINJA_STAND_R4 + 0, ZOMBIE_FLASHBOMB_RATE, DoZombieMove, &s_ZombieFlashBomb[4][4]},
    },
};

STATEp sg_ZombieFlashBomb[] =
{
    s_ZombieFlashBomb[0],
    s_ZombieFlashBomb[1],
    s_ZombieFlashBomb[2],
    s_ZombieFlashBomb[3],
    s_ZombieFlashBomb[4]
};

//////////////////////
//
// ZOMBIE UZI
//
//////////////////////

#define ZOMBIE_UZI_RATE 8
ANIMATOR InitEnemyUzi,CheckFire;

STATE s_ZombieUzi[5][17] =
{
    {
        {PLAYER_NINJA_SHOOT_R0 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[0][1]},
        {PLAYER_NINJA_SHOOT_R0 + 0, 0 | SF_QUICK_CALL, CheckFire, &s_ZombieUzi[0][2]},
        {PLAYER_NINJA_SHOOT_R0 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[0][3]},
        {PLAYER_NINJA_SHOOT_R0 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[0][4]},
        {PLAYER_NINJA_SHOOT_R0 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[0][5]},
        {PLAYER_NINJA_SHOOT_R0 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[0][6]},
        {PLAYER_NINJA_SHOOT_R0 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[0][7]},
        {PLAYER_NINJA_SHOOT_R0 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[0][8]},
        {PLAYER_NINJA_SHOOT_R0 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[0][9]},
        {PLAYER_NINJA_SHOOT_R0 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[0][10]},
        {PLAYER_NINJA_SHOOT_R0 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[0][11]},
        {PLAYER_NINJA_SHOOT_R0 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[0][12]},
        {PLAYER_NINJA_SHOOT_R0 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[0][13]},
        {PLAYER_NINJA_SHOOT_R0 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[0][14]},
        {PLAYER_NINJA_SHOOT_R0 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[0][15]},
        {PLAYER_NINJA_SHOOT_R0 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[0][16]},
        {PLAYER_NINJA_SHOOT_R0 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZombieUzi[0][16]},
    },
    {
        {PLAYER_NINJA_SHOOT_R1 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[1][1]},
        {PLAYER_NINJA_SHOOT_R1 + 0, 0 | SF_QUICK_CALL, CheckFire, &s_ZombieUzi[1][2]},
        {PLAYER_NINJA_SHOOT_R1 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[1][3]},
        {PLAYER_NINJA_SHOOT_R1 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[1][4]},
        {PLAYER_NINJA_SHOOT_R1 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[1][5]},
        {PLAYER_NINJA_SHOOT_R1 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[1][6]},
        {PLAYER_NINJA_SHOOT_R1 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[1][7]},
        {PLAYER_NINJA_SHOOT_R1 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[1][8]},
        {PLAYER_NINJA_SHOOT_R1 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[1][9]},
        {PLAYER_NINJA_SHOOT_R1 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[1][10]},
        {PLAYER_NINJA_SHOOT_R1 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[1][11]},
        {PLAYER_NINJA_SHOOT_R1 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[1][12]},
        {PLAYER_NINJA_SHOOT_R1 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[1][13]},
        {PLAYER_NINJA_SHOOT_R1 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[1][14]},
        {PLAYER_NINJA_SHOOT_R1 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[1][15]},
        {PLAYER_NINJA_SHOOT_R1 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[1][16]},
        {PLAYER_NINJA_SHOOT_R1 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZombieUzi[1][16]},
    },
    {
        {PLAYER_NINJA_SHOOT_R2 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[2][1]},
        {PLAYER_NINJA_SHOOT_R2 + 0, 0 | SF_QUICK_CALL, CheckFire, &s_ZombieUzi[2][2]},
        {PLAYER_NINJA_SHOOT_R2 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[2][3]},
        {PLAYER_NINJA_SHOOT_R2 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[2][4]},
        {PLAYER_NINJA_SHOOT_R2 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[2][5]},
        {PLAYER_NINJA_SHOOT_R2 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[2][6]},
        {PLAYER_NINJA_SHOOT_R2 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[2][7]},
        {PLAYER_NINJA_SHOOT_R2 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[2][8]},
        {PLAYER_NINJA_SHOOT_R2 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[2][9]},
        {PLAYER_NINJA_SHOOT_R2 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[2][10]},
        {PLAYER_NINJA_SHOOT_R2 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[2][11]},
        {PLAYER_NINJA_SHOOT_R2 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[2][12]},
        {PLAYER_NINJA_SHOOT_R2 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[2][13]},
        {PLAYER_NINJA_SHOOT_R2 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[2][14]},
        {PLAYER_NINJA_SHOOT_R2 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[2][15]},
        {PLAYER_NINJA_SHOOT_R2 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[2][16]},
        {PLAYER_NINJA_SHOOT_R2 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZombieUzi[2][16]},
    },
    {
        {PLAYER_NINJA_SHOOT_R3 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[3][1]},
        {PLAYER_NINJA_SHOOT_R3 + 0, 0 | SF_QUICK_CALL, CheckFire, &s_ZombieUzi[3][2]},
        {PLAYER_NINJA_SHOOT_R3 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[3][3]},
        {PLAYER_NINJA_SHOOT_R3 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[3][4]},
        {PLAYER_NINJA_SHOOT_R3 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[3][5]},
        {PLAYER_NINJA_SHOOT_R3 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[3][6]},
        {PLAYER_NINJA_SHOOT_R3 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[3][7]},
        {PLAYER_NINJA_SHOOT_R3 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[3][8]},
        {PLAYER_NINJA_SHOOT_R3 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[3][9]},
        {PLAYER_NINJA_SHOOT_R3 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[3][10]},
        {PLAYER_NINJA_SHOOT_R3 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[3][11]},
        {PLAYER_NINJA_SHOOT_R3 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[3][12]},
        {PLAYER_NINJA_SHOOT_R3 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[3][13]},
        {PLAYER_NINJA_SHOOT_R3 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[3][14]},
        {PLAYER_NINJA_SHOOT_R3 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[3][15]},
        {PLAYER_NINJA_SHOOT_R3 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[3][16]},
        {PLAYER_NINJA_SHOOT_R3 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZombieUzi[3][16]},
    },
    {
        {PLAYER_NINJA_SHOOT_R4 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[4][1]},
        {PLAYER_NINJA_SHOOT_R4 + 0, 0 | SF_QUICK_CALL, CheckFire, &s_ZombieUzi[4][2]},
        {PLAYER_NINJA_SHOOT_R4 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[4][3]},
        {PLAYER_NINJA_SHOOT_R4 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[4][4]},
        {PLAYER_NINJA_SHOOT_R4 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[4][5]},
        {PLAYER_NINJA_SHOOT_R4 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[4][6]},
        {PLAYER_NINJA_SHOOT_R4 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[4][7]},
        {PLAYER_NINJA_SHOOT_R4 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[4][8]},
        {PLAYER_NINJA_SHOOT_R4 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[4][9]},
        {PLAYER_NINJA_SHOOT_R4 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[4][10]},
        {PLAYER_NINJA_SHOOT_R4 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[4][11]},
        {PLAYER_NINJA_SHOOT_R4 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[4][12]},
        {PLAYER_NINJA_SHOOT_R4 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[4][13]},
        {PLAYER_NINJA_SHOOT_R4 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[4][14]},
        {PLAYER_NINJA_SHOOT_R4 + 0, ZOMBIE_UZI_RATE, NullZombie, &s_ZombieUzi[4][15]},
        {PLAYER_NINJA_SHOOT_R4 + 0, 0 | SF_QUICK_CALL, InitEnemyUzi, &s_ZombieUzi[4][16]},
        {PLAYER_NINJA_SHOOT_R4 + 0, 0 | SF_QUICK_CALL, InitActorDecide, &s_ZombieUzi[4][16]},
    },
};

STATEp sg_ZombieUzi[] =
{
    s_ZombieUzi[0],
    s_ZombieUzi[1],
    s_ZombieUzi[2],
    s_ZombieUzi[3],
    s_ZombieUzi[4]
};

//////////////////////
//
// ZOMBIE FALL
//
//////////////////////

#define ZOMBIE_FALL_RATE 25

STATE s_ZombieFall[5][1] =
{
    {
        {PLAYER_NINJA_JUMP_R0 + 3, ZOMBIE_FALL_RATE, DoZombieMove, &s_ZombieFall[0][0]},
    },
    {
        {PLAYER_NINJA_JUMP_R1 + 3, ZOMBIE_FALL_RATE, DoZombieMove, &s_ZombieFall[1][0]},
    },
    {
        {PLAYER_NINJA_JUMP_R2 + 3, ZOMBIE_FALL_RATE, DoZombieMove, &s_ZombieFall[2][0]},
    },
    {
        {PLAYER_NINJA_JUMP_R3 + 3, ZOMBIE_FALL_RATE, DoZombieMove, &s_ZombieFall[3][0]},
    },
    {
        {PLAYER_NINJA_JUMP_R4 + 3, ZOMBIE_FALL_RATE, DoZombieMove, &s_ZombieFall[4][0]},
    }
};

STATEp sg_ZombieFall[] =
{
    &s_ZombieFall[0][0],
    &s_ZombieFall[1][0],
    &s_ZombieFall[2][0],
    &s_ZombieFall[3][0],
    &s_ZombieFall[4][0]
};

/*
STATEp *Stand[MAX_WEAPONS];
STATEp *Run;
STATEp *Jump;
STATEp *Fall;
STATEp *Crawl;
STATEp *Swim;
STATEp *Fly;
STATEp *Rise;
STATEp *Sit;
STATEp *Look;
STATEp *Climb;
STATEp *Pain;
STATEp *Death1;
STATEp *Death2;
STATEp *Dead;
STATEp *DeathJump;
STATEp *DeathFall;
STATEp *CloseAttack[2];
STATEp *Attack[6];
STATEp *Special[2];
*/

ACTOR_ACTION_SET ZombieActionSet =
{
    sg_ZombieStand,
    sg_ZombieRun,
    NULL,
    sg_ZombieFall,
    NULL,
    NULL,
    NULL,
    sg_ZombieRun,
    sg_ZombieRun,
    NULL,
    NULL,
    sg_ZombiePain,
    sg_ZombieRun,
    NULL,
    NULL,
    NULL,
    NULL,
#if 0
    {sg_ZombieUzi},
    {1024},
    {sg_ZombieUzi, sg_ZombieRocket, sg_ZombieGrenade, sg_ZombieNuke},
    {400, 750, 1000, 1024},
#endif
    {sg_ZombieRail},
    {1024},
    {sg_ZombieRail},
    {1024},
    {NULL},
    NULL,
    NULL
};

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

    u->Health = 100;
    u->StateEnd = &s_ZombiePain[0][0];
    u->Rot = sg_ZombieRun;
    sp->xrepeat = PLAYER_NINJA_XREPEAT;
    sp->yrepeat = PLAYER_NINJA_YREPEAT;

    u->Attrib = &ZombieAttrib;
    EnemyDefaults(SpriteNum, &ZombieActionSet, &ZombiePersonality);

    ChangeState(SpriteNum, s_ZombieRun[0]);
    DoActorSetSpeed(SpriteNum, NORM_SPEED);

    u->Radius = 280;
    SET(u->Flags, SPR_XFLIP_TOGGLE);

    return 0;
}

int
SpawnZombie(PLAYERp pp, short Weapon)
{
    short New;
    SPRITEp np;
    USERp nu;
    short owner;

    owner = sprite[Weapon].owner;

    if (owner < 0)
        return -1;

    //Zombies++;

    New = SpawnSprite(STAT_ENEMY, ZOMBIE_RUN_R0, s_ZombieRun[0], pp->cursectnum, pp->posx, pp->posy, pp->posz, fix16_to_int(pp->q16ang), 0);
    np = &sprite[New];
    nu = User[New];
    np->sectnum = pp->cursectnum;
    np->owner = owner;
    np->pal = nu->spal = User[owner]->spal;
    np->ang = RANDOM_P2(2048);
    SetupZombie(New);
    //np->shade = sprite[pp->PlayerSprite].shade;
    np->shade = -10;
    SET(nu->Flags2, SPR2_DONT_TARGET_OWNER);
    SET(np->cstat, CSTAT_SPRITE_TRANSLUCENT);

    DoActorPickClosePlayer(New);
    //nu->tgt_sp = pp->SpriteP; // Make it target last killed player initially

    // make immediately active
    SET(nu->Flags, SPR_ACTIVE);

    RESET(nu->Flags, SPR_JUMPING);
    RESET(nu->Flags, SPR_FALLING);

    // if I didn't do this here they get stuck in the air sometimes
    DoActorZrange(New);

    return New;
}

int
SpawnZombie2(short Weapon)
{
    SPRITEp sp = &sprite[Weapon];
    short New;
    SPRITEp np;
    USERp nu;
    short owner;
    SECT_USERp sectu = SectUser[sp->sectnum];
    SECTORp sectp = &sector[sp->sectnum];

    owner = sprite[Weapon].owner;

    if (owner < 0)
        return -1;

    if (sectu && (TEST(sectp->extra, SECTFX_LIQUID_MASK) != SECTFX_LIQUID_NONE))
        return -1;

    if (SectorIsUnderwaterArea(sp->sectnum))
        return -1;

    //if (FAF_ConnectArea(sp->sectnum))
    //    return(-1);

    if (FAF_ConnectArea(sp->sectnum))
    {
        short sectnum = sp->sectnum;
        updatesectorz(sp->x, sp->y, sp->z + Z(10), &sectnum);
        if (sectnum >= 0 && SectorIsUnderwaterArea(sectnum))
            return -1;
    }

    //Zombies++;
    New = SpawnSprite(STAT_ENEMY, ZOMBIE_RUN_R0, s_ZombieRun[0], sp->sectnum, sp->x, sp->y, sp->z, sp->ang, 0);
    np = &sprite[New];
    nu = User[New];
    nu->Counter3 = 0;
    np->owner = owner;
    np->pal = nu->spal = User[owner]->spal;
    np->ang = RANDOM_P2(2048);
    SetupZombie(New);
    //np->shade = sprite[pp->PlayerSprite].shade;
    np->shade = -10;
    SET(nu->Flags2, SPR2_DONT_TARGET_OWNER);
    SET(np->cstat, CSTAT_SPRITE_TRANSLUCENT);

    DoActorPickClosePlayer(New);
    //nu->tgt_sp = pp->SpriteP; // Make it target last killed player initially

    // make immediately active
    SET(nu->Flags, SPR_ACTIVE);

    RESET(nu->Flags, SPR_JUMPING);
    RESET(nu->Flags, SPR_FALLING);

    // if I didn't do this here they get stuck in the air sometimes
    DoActorZrange(New);

    return New;
}

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

    if (u->Counter3++ >= ZOMBIE_TIME_LIMIT)
    {
        InitBloodSpray(SpriteNum,TRUE,105);
        InitBloodSpray(SpriteNum,TRUE,105);
        InitBloodSpray(SpriteNum,TRUE,105);
        SetSuicide(SpriteNum);
        return 0;
    }

    if (u->tgt_sp && User[u->tgt_sp-sprite] && TEST(User[u->tgt_sp-sprite]->Flags, PF_DEAD))    // JBF: added User[] null check
        DoActorPickClosePlayer(SpriteNum);

    // jumping and falling
    if (TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
    {
        if (TEST(u->Flags, SPR_JUMPING))
            DoActorJump(SpriteNum);
        else if (TEST(u->Flags, SPR_FALLING))
            DoActorFall(SpriteNum);
    }

    // sliding
    if (TEST(u->Flags, SPR_SLIDING))
        DoActorSlide(SpriteNum);

    // Do track or call current action function - such as DoActorMoveCloser()
    if (u->track >= 0)
        ActorFollowTrack(SpriteNum, ACTORMOVETICS);
    else
    {
        (*u->ActorActionFunc)(SpriteNum);
    }

    // stay on floor unless doing certain things
    if (!TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
    {
        KeepActorOnFloor(SpriteNum);
    }

    // take damage from environment
    DoActorSectorDamage(SpriteNum);

    return 0;
}

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

    if (u->Counter3++ >= ZOMBIE_TIME_LIMIT)
    {
        InitBloodSpray(SpriteNum,TRUE,105);
        InitBloodSpray(SpriteNum,TRUE,105);
        InitBloodSpray(SpriteNum,TRUE,105);
        SetSuicide(SpriteNum);
        return 0;
    }

    if (u->tgt_sp && User[u->tgt_sp-sprite] && TEST(User[u->tgt_sp-sprite]->Flags, PF_DEAD))
        DoActorPickClosePlayer(SpriteNum);

    if (u->WaitTics > 0)
        u->WaitTics -= ACTORMOVETICS;

    if (TEST(u->Flags, SPR_SLIDING) && !TEST(u->Flags, SPR_JUMPING|SPR_FALLING))
        DoActorSlide(SpriteNum);

    if (!TEST(u->Flags, SPR_JUMPING|SPR_FALLING))
        KeepActorOnFloor(SpriteNum);

    DoActorSectorDamage(SpriteNum);

    return 0;
}

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

    NullZombie(SpriteNum);

    if ((u->WaitTics -= ACTORMOVETICS) <= 0)
        InitActorDecide(SpriteNum);

    return 0;
}

#include "saveable.h"

static saveable_code saveable_zombie_code[] =
{
    SAVE_CODE(SetupZombie),
    SAVE_CODE(SpawnZombie),
    SAVE_CODE(SpawnZombie2),
    SAVE_CODE(DoZombieMove),
    SAVE_CODE(NullZombie),
    SAVE_CODE(DoZombiePain),
};

static saveable_data saveable_zombie_data[] =
{
    SAVE_DATA(ZombieBattle),
    SAVE_DATA(ZombieOffense),
    SAVE_DATA(ZombieBroadcast),
    SAVE_DATA(ZombieSurprised),
    SAVE_DATA(ZombieEvasive),
    SAVE_DATA(ZombieLostTarget),
    SAVE_DATA(ZombieCloseRange),

    SAVE_DATA(ZombiePersonality),

    SAVE_DATA(ZombieAttrib),

    SAVE_DATA(s_ZombieRun),
    SAVE_DATA(sg_ZombieRun),
    SAVE_DATA(s_ZombieStand),
    SAVE_DATA(sg_ZombieStand),
    SAVE_DATA(s_ZombiePain),
    SAVE_DATA(sg_ZombiePain),
    SAVE_DATA(s_ZombieNuke),
    SAVE_DATA(sg_ZombieNuke),
    SAVE_DATA(s_ZombieRocket),
    SAVE_DATA(sg_ZombieRocket),
    SAVE_DATA(s_ZombieRail),
    SAVE_DATA(sg_ZombieRail),
    SAVE_DATA(s_ZombieGrenade),
    SAVE_DATA(sg_ZombieGrenade),
    SAVE_DATA(s_ZombieFlashBomb),
    SAVE_DATA(sg_ZombieFlashBomb),
    SAVE_DATA(s_ZombieUzi),
    SAVE_DATA(sg_ZombieUzi),
    SAVE_DATA(s_ZombieFall),
    SAVE_DATA(sg_ZombieFall),

    SAVE_DATA(ZombieActionSet),
};

saveable_module saveable_zombie =
{
    // code
    saveable_zombie_code,
    SIZ(saveable_zombie_code),

    // data
    saveable_zombie_data,
    SIZ(saveable_zombie_data)
};


code: #include "eduke32_icon.c"


code:
#define NEED_COMMCTRL_H
#include "../../build/include/windows_inc.h"
#include "../../build/include/startwin.editor.h"

RSRC_ICON ICON "build_icon.ico"
RSRC_BMP BITMAP "build.bmp"

WIN_STARTWIN DIALOGEX DISCARDABLE  20, 40, 260, 200
STYLE DS_MODALFRAME | DS_CENTER | DS_SETFONT | DS_FIXEDSYS | WS_OVERLAPPED | WS_CAPTION | WS_VISIBLE | WS_SYSMENU
CAPTION "Startup"
FONT 8, "MS Shell Dlg"
BEGIN
	CONTROL "", WIN_STARTWIN_BITMAP, "STATIC", SS_BITMAP | SS_CENTERIMAGE | WS_CHILD | WS_VISIBLE, 0, 0, 66, 172
	CONTROL "", WIN_STARTWIN_TABCTL, WC_TABCONTROL, WS_CLIPSIBLINGS | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 5, 5, 250, 170
	CONTROL "&Start", WIN_STARTWIN_START, "BUTTON", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 154, 180, 48, 14
	CONTROL "&Cancel", WIN_STARTWIN_CANCEL, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 207, 180, 48, 14

	CONTROL "", WIN_STARTWIN_MESSAGES, "EDIT", ES_MULTILINE | ES_READONLY | WS_CHILD | WS_VSCROLL, 0, 0, 32, 32
END

WIN_STARTWINPAGE_CONFIG DIALOGEX DISCARDABLE  20, 40, 279, 168
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
CAPTION "Dialog"
FONT 8, "MS Shell Dlg"
BEGIN
	CONTROL "&2D Video mode:",   -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 8, 50, 8
	CONTROL "",            IDC2DVMODE, "COMBOBOX", CBS_DROPDOWNLIST | WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP, 60, 6, 80, 56
	CONTROL "&Fullscreen", IDCFULLSCREEN, "BUTTON", BS_CHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 148, 8, 49, 10
	CONTROL "&3D Video mode:",   -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 24, 50, 8
	CONTROL "",            IDC3DVMODE, "COMBOBOX", CBS_DROPDOWNLIST | WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP, 60, 22, 80, 56
	CONTROL "&Always show this window at startup", IDCALWAYSSHOW, "BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 118, 116, 140, 8
END

#define FILEVER        1,9,9,9
#define PRODUCTVER     1,9,9,9
#define STRFILEVER     "2.0.0devel\0"
#define STRPRODUCTVER  "2.0.0devel\0"

VS_VERSION_INFO VERSIONINFO
 FILEVERSION FILEVER
 PRODUCTVERSION PRODUCTVER
 FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
 FILEFLAGS 0x3L
#else
 FILEFLAGS 0x2L
#endif
 FILEOS 0x40004L
 FILETYPE 0x1L
 FILESUBTYPE 0x0L
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904b0"
        BEGIN
            VALUE "FileDescription", "Mapster32 for EDuke32"
            VALUE "FileVersion", STRFILEVER
            VALUE "InternalName", "Mapster32"
            VALUE "LegalCopyright", "Copyright � 2018 EDuke32 Developers, 1996, 2003 3D Realms Entertainment"
            VALUE "LegalTrademarks", "Duke Nukem� is a Registered Trademark of Gearbox Software, LLC."
            VALUE "OriginalFilename", "mapster32.exe"
            VALUE "ProductName", "Mapster32"
            VALUE "ProductVersion", STRPRODUCTVER
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x409, 1200
    END
END

1 24 "manifest.build.xml"


code:
#include "sdl_inc.h"
#include "sdlappicon.h"

static Uint8 sdlappicon_pixels[] = {
#if defined _WIN32 && SDL_MAJOR_VERSION==1
# include "eduke32_icon_32px.c"
#else
# include "eduke32_icon_48px.c"
#endif
};

struct sdlappicon sdlappicon = {
#if defined _WIN32 && SDL_MAJOR_VERSION==1
	32,32,
#else
	48,48,
#endif
	sdlappicon_pixels
};


code:
#define NEED_COMMCTRL_H
#include "../../build/include/windows_inc.h"
#include "../src/startwin.game.h"

RSRC_ICON ICON "game_icon.ico"
RSRC_BMP BITMAP "game.bmp"

WIN_STARTWIN DIALOGEX DISCARDABLE  20, 40, 260, 200
STYLE DS_MODALFRAME | DS_CENTER | DS_SETFONT | DS_FIXEDSYS | WS_OVERLAPPED | WS_CAPTION | WS_VISIBLE | WS_SYSMENU
CAPTION "Startup"
FONT 8, "MS Shell Dlg"
BEGIN
    CONTROL "", WIN_STARTWIN_BITMAP, "STATIC", SS_BITMAP | SS_CENTERIMAGE | WS_CHILD | WS_VISIBLE, 0, 0, 66, 172
    CONTROL "", WIN_STARTWIN_TABCTL, WC_TABCONTROL, WS_CLIPSIBLINGS | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 5, 5, 250, 170
    CONTROL "&Start", WIN_STARTWIN_START, "BUTTON", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 154, 180, 48, 14
    CONTROL "&Cancel", WIN_STARTWIN_CANCEL, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 207, 180, 48, 14

    CONTROL "", WIN_STARTWIN_MESSAGES, "EDIT", ES_MULTILINE | ES_READONLY | WS_CHILD | WS_VSCROLL, 0, 0, 32, 32
END
WIN_STARTWINPAGE_CONFIG DIALOGEX DISCARDABLE  20, 40, 279, 168
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
CAPTION "Dialog"
FONT 8, "MS Shell Dlg"
BEGIN
    CONTROL "&Video mode:",   -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 6, 50, 8
    CONTROL "",               IDCVMODE, "COMBOBOX", CBS_DROPDOWNLIST | WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP, 60, 4, 86, 56
    CONTROL "&Fullscreen",    IDCFULLSCREEN, "BUTTON", BS_CHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 154, 6, 46, 10
#if defined POLYMER && POLYMER != 0
    CONTROL "&Polymer",       IDCPOLYMER, "BUTTON", BS_CHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 203, 6, 40, 10
#endif
    CONTROL "Input devices:", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 20, 50, 8
    CONTROL "",               IDCINPUT, "COMBOBOX", CBS_DROPDOWNLIST | WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP, 60, 19, 86, 56
    CONTROL "&Game:", 	  -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 35, 100, 8
    CONTROL "",               IDCDATA, "LISTBOX", LBS_NOINTEGRALHEIGHT | LBS_USETABSTOPS | LBS_STANDARD | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 10, 45, 226, 43

    CONTROL "Custom game content &directory:", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE, 5, 90, 160, 8
    CONTROL "",               IDCGAMEDIR, "COMBOBOX", CBS_DROPDOWNLIST | WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP, 10, 99, 226, 156
    CONTROL "&Enable ""autoload"" folder", IDCAUTOLOAD, "BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 5, 116, 100, 8
    CONTROL "&Always show this window at startup", IDCALWAYSSHOW, "BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 118, 116, 140, 8
END

#define FILEVER        1,9,9,9
#define PRODUCTVER     1,9,9,9
#define STRFILEVER     "2.0.0devel\0"
#define STRPRODUCTVER  "2.0.0devel\0"

VS_VERSION_INFO VERSIONINFO
 FILEVERSION FILEVER
 PRODUCTVERSION PRODUCTVER
 FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
 FILEFLAGS 0x3L
#else
 FILEFLAGS 0x2L
#endif
 FILEOS 0x40004L
 FILETYPE 0x1L
 FILESUBTYPE 0x0L
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904b0"
        BEGIN
            VALUE "FileDescription", "EDuke32"
            VALUE "FileVersion", STRFILEVER
            VALUE "InternalName", "EDuke32"
            VALUE "LegalCopyright", "Copyright � 2018 EDuke32 Developers, 1996, 2003 3D Realms Entertainment"
            VALUE "LegalTrademarks", "Duke Nukem� is a Registered Trademark of Gearbox Software, LLC."
            VALUE "OriginalFilename", "eduke32.exe"
            VALUE "ProductName", "EDuke32"
            VALUE "ProductVersion", STRPRODUCTVER
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x409, 1200
    END
END

1 24 "manifest.game.xml"


code:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
  <asmv3:application>
    <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>true</dpiAware>
      <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
    </asmv3:windowsSettings>
  </asmv3:application>
  <assemblyIdentity
      version="1.0.0.0"
      processorArchitecture="*"
      name="EDuke32.Mapster32"
      type="win32"
/>
  <description>Mapster32 for EDuke32</description>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity
          type="win32"
          name="Microsoft.Windows.Common-Controls"
          version="6.0.0.0"
          processorArchitecture="*"
          publicKeyToken="6595b64144ccf1df"
          language="*"
        />
    </dependentAssembly>
  </dependency>
  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
      <!-- Windows Vista -->
      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
      <!-- Windows 7 -->
      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
      <!-- Windows 8 -->
      <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
      <!-- Windows 8.1 -->
      <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
      <!-- Windows 10 -->
      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
    </application>
  </compatibility>
</assembly>


code:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
  <asmv3:application>
    <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>true</dpiAware>
      <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
    </asmv3:windowsSettings>
  </asmv3:application>
  <assemblyIdentity
      version="1.0.0.0"
      processorArchitecture="*"
      name="EDuke32"
      type="win32"
/>
  <description>EDuke32</description>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity
          type="win32"
          name="Microsoft.Windows.Common-Controls"
          version="6.0.0.0"
          processorArchitecture="*"
          publicKeyToken="6595b64144ccf1df"
          language="*"
        />
    </dependentAssembly>
  </dependency>
  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
      <!-- Windows Vista -->
      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
      <!-- Windows 7 -->
      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
      <!-- Windows 8 -->
      <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
      <!-- Windows 8.1 -->
      <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
      <!-- Windows 10 -->
      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
    </application>
  </compatibility>
</assembly>


code:
#import <Cocoa/Cocoa.h>

#include "compat.h"
#include "baselayer.h"
#include "build.h"

static struct {
	int fullscreen;
	int xdim3d, ydim3d, bpp3d;
	int forcesetup;
} settings;

@interface StartupWinController : NSWindowController
{
	NSMutableArray *modeslist3d;

	IBOutlet NSButton *alwaysShowButton;
	IBOutlet NSButton *fullscreenButton;
	IBOutlet NSTextView *messagesView;
	IBOutlet NSTabView *tabView;
	IBOutlet NSPopUpButton *videoMode3DPUButton;

	IBOutlet NSButton *cancelButton;
	IBOutlet NSButton *startButton;
}

- (void)dealloc;
- (void)populateVideoModes:(BOOL)firstTime;

- (IBAction)alwaysShowClicked:(id)sender;
- (IBAction)fullscreenClicked:(id)sender;

- (IBAction)cancel:(id)sender;
- (IBAction)start:(id)sender;

- (void)setupRunMode;
- (void)setupMessagesMode;
- (void)putsMessage:(NSString *)str;
- (void)setTitle:(NSString *)str;
@end

@implementation StartupWinController

- (void)dealloc
{
	[modeslist3d release];
	[super dealloc];
}

- (void)populateVideoModes:(BOOL)firstTime
{
	int i, mode3d, fullscreen = ([fullscreenButton state] == NSOnState);
	int idx3d = -1;
	int xdim, ydim, bpp = 8;

	if (firstTime) {
		xdim = settings.xdim3d;
		ydim = settings.ydim3d;
		bpp  = settings.bpp3d;
	} else {
		mode3d = [[modeslist3d objectAtIndex:[videoMode3DPUButton indexOfSelectedItem]] intValue];
		if (mode3d >= 0) {
			xdim = validmode[mode3d].xdim;
			ydim = validmode[mode3d].ydim;
			bpp = validmode[mode3d].bpp;
		}
	}
	mode3d = checkvideomode(&xdim, &ydim, bpp, fullscreen, 1);
	if (mode3d < 0) {
		int i, cd[] = { 32, 24, 16, 15, 8, 0 };
		for (i=0; cd[i]; ) { if (cd[i] >= bpp) i++; else break; }
		for ( ; cd[i]; i++) {
			mode3d = checkvideomode(&xdim, &ydim, cd[i], fullscreen, 1);
			if (mode3d < 0) continue;
			break;
		}
	}

	[modeslist3d release];
	[videoMode3DPUButton removeAllItems];

	modeslist3d = [[NSMutableArray alloc] init];

	for (i = 0; i < validmodecnt; i++) {
		if (fullscreen == validmode[i].fs) {
			if (i == mode3d) idx3d = [modeslist3d count];
			[modeslist3d addObject:[NSNumber numberWithInt:i]];
			[videoMode3DPUButton addItemWithTitle:[NSString stringWithFormat:@"%d %C %d %d-bpp",
				validmode[i].xdim, 0xd7, validmode[i].ydim, validmode[i].bpp]];
		}
	}

	if (idx3d >= 0) [videoMode3DPUButton selectItemAtIndex:idx3d];
}

- (IBAction)alwaysShowClicked:(id)sender
{
}

- (IBAction)fullscreenClicked:(id)sender
{
	[self populateVideoModes:NO];
}

- (IBAction)cancel:(id)sender
{
	[NSApp abortModal];
}

- (IBAction)start:(id)sender
{
	int mode = [[modeslist3d objectAtIndex:[videoMode3DPUButton indexOfSelectedItem]] intValue];
	if (mode >= 0) {
		settings.xdim3d = validmode[mode].xdim;
		settings.ydim3d = validmode[mode].ydim;
		settings.bpp3d = validmode[mode].bpp;
		settings.fullscreen = validmode[mode].fs;
	}

	settings.forcesetup = [alwaysShowButton state] == NSOnState;

	[NSApp stopModal];
}

- (void)setupRunMode
{
	getvalidmodes();

	[fullscreenButton setState: (settings.fullscreen ? NSOnState : NSOffState)];
	[alwaysShowButton setState: (settings.forcesetup ? NSOnState : NSOffState)];
	[self populateVideoModes:YES];

	// enable all the controls on the Configuration page
	NSEnumerator *enumerator = [[[[tabView tabViewItemAtIndex:0] view] subviews] objectEnumerator];
	NSControl *control;
	while (control = [enumerator nextObject]) [control setEnabled:true];

	[cancelButton setEnabled:true];
	[startButton setEnabled:true];

	[tabView selectTabViewItemAtIndex:0];
	[NSCursor unhide];	// Why should I need to do this?
}

- (void)setupMessagesMode
{
	[tabView selectTabViewItemAtIndex:1];

	// disable all the controls on the Configuration page except "always show", so the
	// user can enable it if they want to while waiting for something else to happen
	NSEnumerator *enumerator = [[[[tabView tabViewItemAtIndex:0] view] subviews] objectEnumerator];
	NSControl *control;
	while (control = [enumerator nextObject]) {
		if (control == alwaysShowButton) continue;
		[control setEnabled:false];
	}

	[cancelButton setEnabled:false];
	[startButton setEnabled:false];
}

- (void)putsMessage:(NSString *)str
{
	NSRange end;
	NSTextStorage *text = [messagesView textStorage];
	BOOL shouldAutoScroll;

	shouldAutoScroll = ((int)NSMaxY([messagesView bounds]) == (int)NSMaxY([messagesView visibleRect]));

	end.location = [text length];
	end.length = 0;

	[text beginEditing];
	[messagesView replaceCharactersInRange:end withString:str];
	[text endEditing];

	if (shouldAutoScroll) {
		end.location = [text length];
		end.length = 0;
		[messagesView scrollRangeToVisible:end];
	}
}

- (void)setTitle:(NSString *)str
{
	[[self window] setTitle:str];
}

@end

static StartupWinController *startwin = nil;

int startwin_open(void)
{
	if (startwin != nil) return 1;

	startwin = [[StartupWinController alloc] initWithWindowNibName:@"startwin.game"];
	if (startwin == nil) return -1;

	[startwin setupMessagesMode];
	[startwin showWindow:nil];

	return 0;
}

int startwin_close(void)
{
	if (startwin == nil) return 1;

	[startwin close];
	[startwin release];
	startwin = nil;

	return 0;
}

int startwin_puts(const char *s)
{
	NSString *ns;

	if (!s) return -1;
	if (startwin == nil) return 1;

    ns = [[NSString alloc] initWithCString:s encoding:NSUTF8StringEncoding];
	[startwin putsMessage:ns];
	[ns release];

	return 0;
}

int startwin_settitle(const char *s)
{
	NSString *ns;

	if (!s) return -1;
	if (startwin == nil) return 1;

	ns = [[NSString alloc] initWithCString:s encoding:NSUTF8StringEncoding];
	[startwin setTitle:ns];
	[ns release];

	return 0;
}

int startwin_idle(void * UNUSED(v))
{
	if (startwin) [[startwin window] displayIfNeeded];
	return 0;
}

int startwin_run(void)
{
	int retval;

	if (startwin == nil) return 0;

	settings.fullscreen = fullscreen;
	settings.xdim3d = xres;
	settings.ydim3d = yres;
	settings.bpp3d = bpp;
	//settings.forcesetup = forcesetup;

	[startwin setupRunMode];

	switch ([NSApp runModalForWindow:[startwin window]]) {
		case NSRunStoppedResponse: retval = 1; break;
		case NSRunAbortedResponse: retval = 0; break;
		default: retval = -1;
	}

	[startwin setupMessagesMode];

	if (retval) {
		fullscreen = settings.fullscreen;
		xres = settings.xdim3d;
		yres = settings.ydim3d;
		bpp = settings.bpp3d;
		//forcesetup = settings.forcesetup;
	}

	return retval;
}


code:
#include "build.h"
#include "common_game.h"

void permanentwritesprite(int thex, int they, short tilenum, signed char shade,
        int cx1, int cy1, int cx2, int cy2, unsigned char dapalnum) {
    rotatesprite(thex<<16,they<<16,65536L,0,tilenum,shade,
                 dapalnum,8+16,cx1,cy1,cx2,cy2);
}

void permanentwritespritetile(int UNUSED(thex), int UNUSED(they), short tilenum, signed char shade,
        int cx1, int cy1, int cx2, int cy2, unsigned char dapalnum) {
    int x, y, xsiz, ysiz, tx1, ty1, tx2, ty2;

    xsiz = tilesiz[tilenum].x; tx1 = cx1/xsiz; tx2 = cx2/xsiz;
    ysiz = tilesiz[tilenum].y; ty1 = cy1/ysiz; ty2 = cy2/ysiz;

    for (x=tx1;x<=tx2;x++) {
        for (y=ty1;y<=ty2;y++) {
            rotatesprite(x*xsiz<<16,y*ysiz<<16,65536L,0,tilenum,shade,
                         dapalnum,8+16+64+128,cx1,cy1,cx2,cy2);
        }
    }
}

void overwritesprite(int thex, int they, short tilenum, signed char shade,
        char stat, unsigned char dapalnum) {
    rotatesprite(thex << 16, they << 16, 65536L, (stat & 8) << 7, tilenum, shade, dapalnum,
        (((stat & 1) ^ 1) << 4) + (stat & 2) + ((stat & 4) >> 2) + (((stat & 16) >> 2) ^ ((stat & 8) >> 1)),
        windowxy1.x, windowxy1.y, windowxy2.x, windowxy2.y);
}

void printext(int x, int y, const char *buffer, short tilenum, char UNUSED(invisiblecol))
{
    int i;
    unsigned char ch;

    for(i=0;buffer[i]!=0;i++) {
        ch = (unsigned char)buffer[i];
        rotatesprite((x-((ch&15)<<3))<<16,(y-((ch>>4)<<3))<<16,65536L,0,tilenum,0,0,8+16+128,x,y,x+7,y+7);
        x += 8;
    }
}

void resettiming()
{
    totalclock = 0;
}

void precache()
{
}

void setbrightness(int32_t brightness)
{
    videoSetPalette(brightness, BASEPAL, 2 | 8 | 32);
}