raze/source/games/sw/src/eel.cpp

660 lines
17 KiB
C++
Raw Normal View History

//-------------------------------------------------------------------------
/*
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 "ns.h"
#include "build.h"
#include "names2.h"
#include "game.h"
#include "tags.h"
#include "ai.h"
#include "weapon.h"
2020-08-05 22:18:45 +00:00
#include "misc.h"
BEGIN_SW_NS
DECISION EelBattle[] =
{
{649, InitActorMoveCloser },
{650, InitActorAlertNoise },
{1024, InitActorMoveCloser }
};
DECISION EelOffense[] =
{
{649, InitActorMoveCloser },
{750, InitActorAlertNoise },
{1024, InitActorMoveCloser }
};
DECISION EelBroadcast[] =
{
{3, InitActorAlertNoise },
{6, InitActorAmbientNoise },
{1024, InitActorDecide }
};
DECISION EelSurprised[] =
{
{701, InitActorMoveCloser },
{1024, InitActorDecide }
};
DECISION EelEvasive[] =
{
{ 790, InitActorRunAway },
{1024, InitActorMoveCloser },
};
DECISION EelLostTarget[] =
{
{900, InitActorFindPlayer },
{1024, InitActorWanderAround }
};
DECISION EelCloseRange[] =
{
{950, InitActorAttack },
{1024, InitActorReposition }
};
ANIMATOR InitEelFire;
DECISION EelTouchTarget[] =
{
{1024, InitActorAttack },
};
PERSONALITY EelPersonality =
{
EelBattle,
EelOffense,
EelBroadcast,
EelSurprised,
EelEvasive,
EelLostTarget,
EelCloseRange,
EelTouchTarget
};
ATTRIBUTE EelAttrib =
{
{100, 110, 120, 130}, // Speeds
{3, 0, -2, -3}, // Tic Adjusts
3, // MaxWeapons;
{
0, 0, 0,
0, 0, 0,
0,0,0,0
}
};
//////////////////////
// EEL RUN
//////////////////////
#define EEL_RUN_RATE 20
ANIMATOR DoEelMove,DoStayOnFloor, DoActorDebris, NullEel;
STATE s_EelRun[5][4] =
{
{
{EEL_RUN_R0 + 0, EEL_RUN_RATE, DoEelMove, &s_EelRun[0][1]},
{EEL_RUN_R0 + 1, EEL_RUN_RATE, DoEelMove, &s_EelRun[0][2]},
{EEL_RUN_R0 + 2, EEL_RUN_RATE, DoEelMove, &s_EelRun[0][3]},
{EEL_RUN_R0 + 1, EEL_RUN_RATE, DoEelMove, &s_EelRun[0][0]},
},
{
{EEL_RUN_R1 + 0, EEL_RUN_RATE, DoEelMove, &s_EelRun[1][1]},
{EEL_RUN_R1 + 1, EEL_RUN_RATE, DoEelMove, &s_EelRun[1][2]},
{EEL_RUN_R1 + 2, EEL_RUN_RATE, DoEelMove, &s_EelRun[1][3]},
{EEL_RUN_R1 + 1, EEL_RUN_RATE, DoEelMove, &s_EelRun[1][0]},
},
{
{EEL_RUN_R2 + 0, EEL_RUN_RATE, DoEelMove, &s_EelRun[2][1]},
{EEL_RUN_R2 + 1, EEL_RUN_RATE, DoEelMove, &s_EelRun[2][2]},
{EEL_RUN_R2 + 2, EEL_RUN_RATE, DoEelMove, &s_EelRun[2][3]},
{EEL_RUN_R2 + 1, EEL_RUN_RATE, DoEelMove, &s_EelRun[2][0]},
},
{
{EEL_RUN_R3 + 0, EEL_RUN_RATE, DoEelMove, &s_EelRun[3][1]},
{EEL_RUN_R3 + 1, EEL_RUN_RATE, DoEelMove, &s_EelRun[3][2]},
{EEL_RUN_R3 + 2, EEL_RUN_RATE, DoEelMove, &s_EelRun[3][3]},
{EEL_RUN_R3 + 1, EEL_RUN_RATE, DoEelMove, &s_EelRun[3][0]},
},
{
{EEL_RUN_R4 + 0, EEL_RUN_RATE, DoEelMove, &s_EelRun[4][1]},
{EEL_RUN_R4 + 1, EEL_RUN_RATE, DoEelMove, &s_EelRun[4][2]},
{EEL_RUN_R4 + 2, EEL_RUN_RATE, DoEelMove, &s_EelRun[4][3]},
{EEL_RUN_R4 + 1, EEL_RUN_RATE, DoEelMove, &s_EelRun[4][0]},
}
};
2021-12-31 15:00:14 +00:00
STATE* sg_EelRun[] =
{
&s_EelRun[0][0],
&s_EelRun[1][0],
&s_EelRun[2][0],
&s_EelRun[3][0],
&s_EelRun[4][0]
};
//////////////////////
//
// EEL STAND
//
//////////////////////
STATE s_EelStand[5][1] =
{
{
{EEL_RUN_R0 + 0, EEL_RUN_RATE, DoEelMove, &s_EelStand[0][0]},
},
{
{EEL_RUN_R1 + 0, EEL_RUN_RATE, DoEelMove, &s_EelStand[1][0]},
},
{
{EEL_RUN_R2 + 0, EEL_RUN_RATE, DoEelMove, &s_EelStand[2][0]},
},
{
{EEL_RUN_R3 + 0, EEL_RUN_RATE, DoEelMove, &s_EelStand[3][0]},
},
{
{EEL_RUN_R4 + 0, EEL_RUN_RATE, DoEelMove, &s_EelStand[4][0]},
}
};
2021-12-31 15:00:14 +00:00
STATE* sg_EelStand[] =
{
&s_EelStand[0][0],
&s_EelStand[1][0],
&s_EelStand[2][0],
&s_EelStand[3][0],
&s_EelStand[4][0]
};
//////////////////////
//
// EEL FIRE
//
//////////////////////
ANIMATOR InitEelFire, EelShock;
#define EEL_FIRE_RATE 12
STATE s_EelAttack[5][7] =
{
{
{EEL_FIRE_R0 + 0, EEL_FIRE_RATE*2, NullEel, &s_EelAttack[0][1]},
{EEL_FIRE_R0 + 1, EEL_FIRE_RATE*2, NullEel, &s_EelAttack[0][2]},
{EEL_FIRE_R0 + 2, EEL_FIRE_RATE*2, NullEel, &s_EelAttack[0][3]},
{EEL_FIRE_R0 + 2, 0|SF_QUICK_CALL, InitEelFire, &s_EelAttack[0][4]},
{EEL_FIRE_R0 + 2, EEL_FIRE_RATE, NullEel, &s_EelAttack[0][5]},
{EEL_FIRE_R0 + 3, 0|SF_QUICK_CALL, InitActorDecide, &s_EelAttack[0][6]},
{EEL_RUN_R0 + 3, EEL_FIRE_RATE, DoEelMove, &s_EelAttack[0][6]}
},
{
{EEL_FIRE_R1 + 0, EEL_FIRE_RATE*2, NullEel, &s_EelAttack[1][1]},
{EEL_FIRE_R1 + 1, EEL_FIRE_RATE*2, NullEel, &s_EelAttack[1][2]},
{EEL_FIRE_R1 + 2, EEL_FIRE_RATE*2, NullEel, &s_EelAttack[1][3]},
{EEL_FIRE_R1 + 2, 0|SF_QUICK_CALL, InitEelFire, &s_EelAttack[1][5]},
{EEL_FIRE_R1 + 2, EEL_FIRE_RATE, NullEel, &s_EelAttack[1][6]},
{EEL_FIRE_R1 + 3, 0|SF_QUICK_CALL, InitActorDecide, &s_EelAttack[1][7]},
{EEL_RUN_R0 + 3, EEL_FIRE_RATE, DoEelMove, &s_EelAttack[1][7]}
},
{
{EEL_FIRE_R2 + 0, EEL_FIRE_RATE*2, NullEel, &s_EelAttack[2][1]},
{EEL_FIRE_R2 + 1, EEL_FIRE_RATE*2, NullEel, &s_EelAttack[2][2]},
{EEL_FIRE_R2 + 2, EEL_FIRE_RATE*2, NullEel, &s_EelAttack[2][3]},
{EEL_FIRE_R2 + 2, 0|SF_QUICK_CALL, InitEelFire, &s_EelAttack[2][4]},
{EEL_FIRE_R2 + 2, EEL_FIRE_RATE, NullEel, &s_EelAttack[2][5]},
{EEL_FIRE_R2 + 3, 0|SF_QUICK_CALL, InitActorDecide, &s_EelAttack[2][6]},
{EEL_RUN_R0 + 3, EEL_FIRE_RATE, DoEelMove, &s_EelAttack[2][6]}
},
{
{EEL_RUN_R3 + 0, EEL_FIRE_RATE*2, NullEel, &s_EelAttack[3][1]},
{EEL_RUN_R3 + 1, EEL_FIRE_RATE*2, NullEel, &s_EelAttack[3][2]},
{EEL_RUN_R3 + 2, EEL_FIRE_RATE*2, NullEel, &s_EelAttack[3][3]},
{EEL_RUN_R3 + 2, 0|SF_QUICK_CALL, InitEelFire, &s_EelAttack[3][4]},
{EEL_RUN_R3 + 2, EEL_FIRE_RATE, NullEel, &s_EelAttack[3][5]},
{EEL_RUN_R3 + 3, 0|SF_QUICK_CALL, InitActorDecide, &s_EelAttack[3][6]},
{EEL_RUN_R0 + 3, EEL_FIRE_RATE, DoEelMove, &s_EelAttack[3][6]}
},
{
{EEL_RUN_R4 + 0, EEL_FIRE_RATE*2, NullEel, &s_EelAttack[4][1]},
{EEL_RUN_R4 + 1, EEL_FIRE_RATE*2, NullEel, &s_EelAttack[4][2]},
{EEL_RUN_R4 + 2, EEL_FIRE_RATE*2, NullEel, &s_EelAttack[4][3]},
{EEL_RUN_R4 + 2, 0|SF_QUICK_CALL, InitEelFire, &s_EelAttack[4][4]},
{EEL_RUN_R4 + 2, EEL_FIRE_RATE, NullEel, &s_EelAttack[4][5]},
{EEL_RUN_R4 + 3, 0|SF_QUICK_CALL, InitActorDecide, &s_EelAttack[4][6]},
{EEL_RUN_R0 + 3, EEL_FIRE_RATE, DoEelMove, &s_EelAttack[4][6]}
}
};
2021-12-31 15:00:14 +00:00
STATE* sg_EelAttack[] =
{
&s_EelAttack[0][0],
&s_EelAttack[1][0],
&s_EelAttack[2][0],
&s_EelAttack[3][0],
&s_EelAttack[4][0]
};
//////////////////////
//
// EEL DIE
//
//////////////////////
#define EEL_DIE_RATE 20
ANIMATOR DoEelDeath;
STATE s_EelDie[] =
{
{EEL_DIE + 0, EEL_DIE_RATE, DoEelDeath, &s_EelDie[1]},
{EEL_DIE + 0, EEL_DIE_RATE, DoEelDeath, &s_EelDie[2]},
{EEL_DIE + 0, EEL_DIE_RATE, DoEelDeath, &s_EelDie[3]},
{EEL_DIE + 0, EEL_DIE_RATE, DoEelDeath, &s_EelDie[4]},
{EEL_DIE + 0, EEL_DIE_RATE, DoEelDeath, &s_EelDie[5]},
{EEL_DIE + 0, EEL_DIE_RATE, DoEelDeath, &s_EelDie[5]},
};
2021-12-31 15:00:14 +00:00
STATE* sg_EelDie[] =
{
s_EelDie
};
STATE s_EelDead[] =
{
// {EEL_DEAD, SF_QUICK_CALL , QueueFloorBlood, &s_EelDead[1]},
{EEL_DEAD, EEL_DIE_RATE, DoActorDebris, &s_EelDead[0]},
};
2021-12-31 15:00:14 +00:00
STATE* sg_EelDead[] =
{
s_EelDead
};
/*
2021-12-31 15:00:14 +00:00
STATE* *Stand[MAX_WEAPONS];
STATE* *Run;
STATE* *Jump;
STATE* *Fall;
STATE* *Crawl;
STATE* *Swim;
STATE* *Fly;
STATE* *Rise;
STATE* *Sit;
STATE* *Look;
STATE* *Climb;
STATE* *Pain;
STATE* *Death1;
STATE* *Death2;
STATE* *Dead;
STATE* *DeathJump;
STATE* *DeathFall;
STATE* *CloseAttack[2];
STATE* *Attack[6];
STATE* *Special[2];
*/
ACTOR_ACTION_SET EelActionSet =
{
sg_EelStand,
sg_EelRun,
nullptr,
nullptr,
nullptr,
sg_EelRun,
nullptr,
nullptr,
sg_EelStand,
nullptr,
nullptr, //climb
sg_EelStand, //pain
sg_EelDie,
nullptr,
sg_EelDead,
nullptr,
nullptr,
{sg_EelAttack},
{1024},
{sg_EelAttack},
{1024},
{nullptr,nullptr},
nullptr,
nullptr
};
int DoEelMatchPlayerZ(DSWActor* actor);
2022-09-04 20:52:03 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-10-31 22:05:31 +00:00
void EelCommon(DSWActor* actor)
{
2022-09-09 16:24:22 +00:00
actor->set_const_clipdist((100) >> 2);
actor->user.floor_dist = (16);
actor->user.floor_dist = (16);
actor->user.ceiling_dist = (20);
2022-08-21 07:54:55 +00:00
actor->user.pos.Z = actor->spr.pos.Z;
2021-12-24 12:21:49 +00:00
actor->spr.xrepeat = 35;
actor->spr.yrepeat = 27;
2021-12-25 20:04:48 +00:00
actor->user.Radius = 400;
}
2022-09-04 20:52:03 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-10-31 22:05:31 +00:00
int SetupEel(DSWActor* actor)
{
ANIMATOR DoActorDecide;
if (!(actor->spr.cstat & CSTAT_SPRITE_RESTORE))
{
2021-12-25 20:05:29 +00:00
SpawnUser(actor,EEL_RUN_R0,s_EelRun[0]);
2021-12-25 20:04:48 +00:00
actor->user.Health = 40;
}
2021-10-30 18:11:31 +00:00
ChangeState(actor, s_EelRun[0]);
2021-12-25 20:04:48 +00:00
actor->user.Attrib = &EelAttrib;
2021-10-30 10:09:34 +00:00
DoActorSetSpeed(actor, NORM_SPEED);
2021-12-25 20:04:48 +00:00
actor->user.StateEnd = s_EelDie;
actor->user.Rot = sg_EelRun;
2021-10-31 20:17:31 +00:00
EnemyDefaults(actor, &EelActionSet, &EelPersonality);
actor->user.Flags |= (SPR_NO_SCAREDZ|SPR_XFLIP_TOGGLE);
2021-10-31 22:05:31 +00:00
EelCommon(actor);
2021-12-27 17:58:15 +00:00
actor->user.Flags &= ~(SPR_SHADOW); // Turn off shadows
2022-08-20 22:01:00 +00:00
actor->user.zclip = (8);
return 0;
}
2022-09-04 20:52:03 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
int NullEel(DSWActor* actor)
{
2021-12-27 18:34:06 +00:00
if (actor->user.Flags & (SPR_SLIDING))
DoActorSlide(actor);
DoEelMatchPlayerZ(actor);
DoActorSectorDamage(actor);
return 0;
}
2022-09-04 20:52:03 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
int DoEelMatchPlayerZ(DSWActor* actor)
{
if (FAF_ConnectArea(actor->sector()))
{
2021-12-25 20:04:48 +00:00
if (actor->user.hi_sectp)
{
2022-08-20 20:06:00 +00:00
actor->user.hiz = actor->sector()->ceilingz + 16;
actor->user.hi_sectp = actor->sector();
}
else
{
2022-08-20 20:06:00 +00:00
if (actor->user.hiz < actor->sector()->ceilingz + 16)
actor->user.hiz = actor->sector()->ceilingz + 16;
}
}
2021-12-25 20:04:48 +00:00
// actor does a sine wave about actor->user.sz - this is the z mid point
2022-08-21 07:54:55 +00:00
double zdiff = ActorZOfBottom(actor->user.targetActor) - 8 - actor->user.pos.Z;
// check z diff of the player and the sprite
2022-08-21 07:54:55 +00:00
double zdist = 20 + RandomRange(64); // put a random amount
if (abs(zdiff) > zdist)
{
if (zdiff > 0)
// manipulate the z midpoint
actor->user.pos.Z += 160 * ACTORMOVETICS * zmaptoworld;
else
actor->user.pos.Z -= 160 * ACTORMOVETICS * zmaptoworld;
}
2022-08-21 07:54:55 +00:00
const int EEL_BOB_AMT = 4;
// save off lo and hi z
2022-08-21 07:54:55 +00:00
double loz = actor->user.loz;
double hiz = actor->user.hiz;
// adjust loz/hiz for water depth
2021-12-25 20:04:48 +00:00
if (actor->user.lo_sectp && actor->user.lo_sectp->hasU() && FixedToInt(actor->user.lo_sectp->depth_fixed))
2022-08-21 07:54:55 +00:00
loz -= FixedToInt(actor->user.lo_sectp->depth_fixed) - 8;
// lower bound
2022-08-21 07:54:55 +00:00
double bound;
2021-12-25 20:04:48 +00:00
if (actor->user.lowActor && actor->user.targetActor == actor->user.highActor) // this doesn't look right...
{
2022-09-04 20:55:13 +00:00
double dist = (actor->spr.pos.XY() - actor->user.lowActor->spr.pos.XY()).Length();
if (dist <= 18.75)
2022-08-21 07:54:55 +00:00
bound = actor->user.pos.Z;
else
2022-08-21 07:54:55 +00:00
bound = loz - actor->user.floor_dist;
}
else
2022-08-21 07:54:55 +00:00
bound = loz - actor->user.floor_dist - EEL_BOB_AMT;
2022-08-21 07:54:55 +00:00
if (actor->user.pos.Z > bound)
{
2022-08-21 07:54:55 +00:00
actor->user.pos.Z = bound;
}
// upper bound
2021-12-25 20:04:48 +00:00
if (actor->user.highActor && actor->user.targetActor == actor->user.highActor)
{
2022-09-04 20:55:13 +00:00
double dist = (actor->spr.pos.XY() - actor->user.highActor->spr.pos.XY()).Length();
if (dist <= 18.75)
2022-08-21 07:54:55 +00:00
bound = actor->user.pos.Z;
else
2022-08-21 07:54:55 +00:00
bound = hiz + actor->user.ceiling_dist;
}
else
2022-08-21 07:54:55 +00:00
bound = hiz + actor->user.ceiling_dist + EEL_BOB_AMT;
2022-08-21 07:54:55 +00:00
if (actor->user.pos.Z < bound)
{
2022-08-21 07:54:55 +00:00
actor->user.pos.Z = bound;
}
2022-08-21 07:54:55 +00:00
actor->user.pos.Z = min(actor->user.pos.Z, loz - actor->user.floor_dist);
actor->user.pos.Z = max(actor->user.pos.Z, hiz + actor->user.ceiling_dist);
2021-12-25 20:04:48 +00:00
actor->user.Counter = (actor->user.Counter + (ACTORMOVETICS << 3) + (ACTORMOVETICS << 1)) & 2047;
actor->spr.pos.Z = actor->user.pos.Z + EEL_BOB_AMT * BobVal(actor->user.Counter);
2022-08-21 07:54:55 +00:00
bound = actor->user.hiz + actor->user.ceiling_dist + EEL_BOB_AMT;
if (actor->spr.pos.Z < bound)
{
// bumped something
2022-08-21 07:54:55 +00:00
actor->spr.pos.Z = bound + EEL_BOB_AMT;
actor->user.pos.Z = actor->spr.pos.Z;
}
return 0;
}
2022-09-04 20:52:03 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2021-10-31 22:05:31 +00:00
int DoEelDeath(DSWActor* actor)
{
2021-12-27 18:34:06 +00:00
if (actor->user.Flags & (SPR_FALLING))
{
2021-10-29 21:41:33 +00:00
DoFall(actor);
}
else
{
DoFindGroundPoint(actor);
actor->user.floor_dist = 0;
2021-10-29 21:41:33 +00:00
DoBeginFall(actor);
}
2021-12-27 18:34:06 +00:00
if (actor->user.Flags & (SPR_SLIDING))
DoActorSlide(actor);
// slide while falling
auto vec = actor->spr.angle.ToVector() * actor->vel.X;
2022-08-30 22:47:02 +00:00
actor->user.coll = move_sprite(actor, DVector3(vec, 0), actor->user.ceiling_dist, actor->user.floor_dist, CLIPMASK_MISSILE, ACTORMOVETICS);
DoFindGroundPoint(actor);
// on the ground
2022-08-20 20:49:30 +00:00
if (actor->spr.pos.Z >= actor->user.loz)
{
2021-12-27 17:58:15 +00:00
actor->user.Flags &= ~(SPR_FALLING|SPR_SLIDING);
if (RandomRange(1000) > 500)
actor->spr.cstat |= (CSTAT_SPRITE_XFLIP);
if (RandomRange(1000) > 500)
actor->spr.cstat |= (CSTAT_SPRITE_YFLIP);
2021-12-25 20:04:48 +00:00
NewStateGroup(actor, actor->user.ActorActionSet->Dead);
return 0;
}
return 0;
}
2022-09-04 20:52:03 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
int DoEelMove(DSWActor* actor)
{
2021-12-25 20:04:48 +00:00
ASSERT(actor->user.Rot != nullptr);
2021-12-25 20:04:48 +00:00
if (SpriteOverlap(actor, actor->user.targetActor))
NewStateGroup(actor, actor->user.ActorActionSet->CloseAttack[0]);
2021-12-27 18:34:06 +00:00
if (actor->user.Flags & (SPR_SLIDING))
DoActorSlide(actor);
2021-12-25 20:04:48 +00:00
if (actor->user.track >= 0)
2021-11-01 13:36:46 +00:00
ActorFollowTrack(actor, ACTORMOVETICS);
else
2021-12-25 20:04:48 +00:00
(*actor->user.ActorActionFunc)(actor);
DoEelMatchPlayerZ(actor);
DoActorSectorDamage(actor);
return 0;
}
2022-09-04 20:52:03 +00:00
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
#include "saveable.h"
static saveable_code saveable_eel_code[] =
{
SAVE_CODE(DoEelMatchPlayerZ),
SAVE_CODE(DoEelDeath),
SAVE_CODE(DoEelMove)
};
static saveable_data saveable_eel_data[] =
{
SAVE_DATA(EelBattle),
SAVE_DATA(EelOffense),
SAVE_DATA(EelBroadcast),
SAVE_DATA(EelSurprised),
SAVE_DATA(EelEvasive),
SAVE_DATA(EelLostTarget),
SAVE_DATA(EelCloseRange),
SAVE_DATA(EelTouchTarget),
SAVE_DATA(EelPersonality),
SAVE_DATA(EelAttrib),
SAVE_DATA(s_EelRun),
SAVE_DATA(sg_EelRun),
SAVE_DATA(s_EelStand),
SAVE_DATA(sg_EelStand),
SAVE_DATA(s_EelAttack),
SAVE_DATA(sg_EelAttack),
SAVE_DATA(s_EelDie),
SAVE_DATA(sg_EelDie),
SAVE_DATA(s_EelDead),
SAVE_DATA(sg_EelDead),
SAVE_DATA(EelActionSet)
};
saveable_module saveable_eel =
{
// code
saveable_eel_code,
SIZ(saveable_eel_code),
// data
saveable_eel_data,
SIZ(saveable_eel_data)
};
END_SW_NS