raze/source/games/sw/src/serp.cpp
Christoph Oelckers 84ca96c52c eliminated STATEp
2021-12-31 16:00:14 +01:00

867 lines
31 KiB
C++

//-------------------------------------------------------------------------
/*
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 "misc.h"
#include "sector.h"
#include "gamecontrol.h"
#include "mapinfo.h"
BEGIN_SW_NS
DECISION SerpBattle[] =
{
{670, InitActorMoveCloser },
{700, InitActorAmbientNoise },
{710, InitActorRunAway },
{1024, InitActorAttack }
};
DECISION SerpOffense[] =
{
{775, InitActorMoveCloser },
{800, InitActorAmbientNoise },
{1024, InitActorAttack }
};
DECISION SerpBroadcast[] =
{
//{21, InitActorAlertNoise },
{10, InitActorAmbientNoise },
{1024, InitActorDecide }
};
DECISION SerpSurprised[] =
{
{701, InitActorMoveCloser },
{1024, InitActorDecide }
};
DECISION SerpEvasive[] =
{
{10, InitActorEvade },
{1024, nullptr }
};
DECISION SerpLostTarget[] =
{
{900, InitActorFindPlayer },
{921, InitActorAmbientNoise },
{1024, InitActorWanderAround }
};
DECISION SerpCloseRange[] =
{
{700, InitActorAttack },
{1024, InitActorReposition }
};
PERSONALITY SerpPersonality =
{
SerpBattle,
SerpOffense,
SerpBroadcast,
SerpSurprised,
SerpEvasive,
SerpLostTarget,
SerpCloseRange,
SerpCloseRange
};
ATTRIBUTE SerpAttrib =
{
{200, 220, 240, 270}, // Speeds
{3, 0, -2, -3}, // Tic Adjusts
3, // MaxWeapons;
{
DIGI_SERPAMBIENT, DIGI_SERPALERT, DIGI_SERPSWORDATTACK,
DIGI_SERPPAIN, DIGI_SERPSCREAM, DIGI_SERPMAGICLAUNCH,
DIGI_SERPSUMMONHEADS,DIGI_SERPTAUNTYOU,DIGI_SERPDEATHEXPLODE,0
}
};
ATTRIBUTE SerpPissedAttrib =
{
{200, 220, 240, 270}, // Speeds
{3, 0, -2, -3}, // Tic Adjusts
3, // MaxWeapons;
{
DIGI_SERPAMBIENT, DIGI_SERPALERT, DIGI_SERPSWORDATTACK,
DIGI_SERPPAIN, DIGI_SERPSCREAM, DIGI_SERPMAGICLAUNCH,
DIGI_SERPSUMMONHEADS,DIGI_SERPTAUNTYOU,DIGI_SERPDEATHEXPLODE,0
}
};
//////////////////////
//
// SERP RUN
//
//////////////////////
#define SERP_RUN_RATE 24
ANIMATOR DoSerpMove,NullSerp,DoActorDebris,NullSerp;
STATE s_SerpRun[5][4] =
{
{
{SERP_RUN_R0 + 0, SERP_RUN_RATE, DoSerpMove, &s_SerpRun[0][1]},
{SERP_RUN_R0 + 1, SERP_RUN_RATE, DoSerpMove, &s_SerpRun[0][2]},
{SERP_RUN_R0 + 2, SERP_RUN_RATE, DoSerpMove, &s_SerpRun[0][3]},
{SERP_RUN_R0 + 1, SERP_RUN_RATE, DoSerpMove, &s_SerpRun[0][0]},
},
{
{SERP_RUN_R1 + 0, SERP_RUN_RATE, DoSerpMove, &s_SerpRun[1][1]},
{SERP_RUN_R1 + 1, SERP_RUN_RATE, DoSerpMove, &s_SerpRun[1][2]},
{SERP_RUN_R1 + 2, SERP_RUN_RATE, DoSerpMove, &s_SerpRun[1][3]},
{SERP_RUN_R1 + 1, SERP_RUN_RATE, DoSerpMove, &s_SerpRun[1][0]},
},
{
{SERP_RUN_R2 + 0, SERP_RUN_RATE, DoSerpMove, &s_SerpRun[2][1]},
{SERP_RUN_R2 + 1, SERP_RUN_RATE, DoSerpMove, &s_SerpRun[2][2]},
{SERP_RUN_R2 + 2, SERP_RUN_RATE, DoSerpMove, &s_SerpRun[2][3]},
{SERP_RUN_R2 + 1, SERP_RUN_RATE, DoSerpMove, &s_SerpRun[2][0]},
},
{
{SERP_RUN_R3 + 0, SERP_RUN_RATE, DoSerpMove, &s_SerpRun[3][1]},
{SERP_RUN_R3 + 1, SERP_RUN_RATE, DoSerpMove, &s_SerpRun[3][2]},
{SERP_RUN_R3 + 2, SERP_RUN_RATE, DoSerpMove, &s_SerpRun[3][3]},
{SERP_RUN_R3 + 1, SERP_RUN_RATE, DoSerpMove, &s_SerpRun[3][0]},
},
{
{SERP_RUN_R4 + 0, SERP_RUN_RATE, DoSerpMove, &s_SerpRun[4][1]},
{SERP_RUN_R4 + 1, SERP_RUN_RATE, DoSerpMove, &s_SerpRun[4][2]},
{SERP_RUN_R4 + 2, SERP_RUN_RATE, DoSerpMove, &s_SerpRun[4][3]},
{SERP_RUN_R4 + 1, SERP_RUN_RATE, DoSerpMove, &s_SerpRun[4][0]},
}
};
STATE* sg_SerpRun[] =
{
&s_SerpRun[0][0],
&s_SerpRun[1][0],
&s_SerpRun[2][0],
&s_SerpRun[3][0],
&s_SerpRun[4][0]
};
//////////////////////
//
// SERP SLASH
//
//////////////////////
#define SERP_SLASH_RATE 9
ANIMATOR InitActorDecide;
ANIMATOR InitSerpSlash;
STATE s_SerpSlash[5][10] =
{
{
{SERP_SLASH_R0 + 2, SERP_SLASH_RATE, NullSerp, &s_SerpSlash[0][1]},
{SERP_SLASH_R0 + 1, SERP_SLASH_RATE, NullSerp, &s_SerpSlash[0][2]},
{SERP_SLASH_R0 + 0, SERP_SLASH_RATE*2, NullSerp, &s_SerpSlash[0][3]},
{SERP_SLASH_R0 + 1, SERP_SLASH_RATE, NullSerp, &s_SerpSlash[0][4]},
{SERP_SLASH_R0 + 2, SERP_SLASH_RATE, NullSerp, &s_SerpSlash[0][5]},
{SERP_SLASH_R0 + 3, SF_QUICK_CALL, InitSerpSlash, &s_SerpSlash[0][6]},
{SERP_SLASH_R0 + 3, SERP_SLASH_RATE, NullSerp, &s_SerpSlash[0][7]},
{SERP_SLASH_R0 + 4, SERP_SLASH_RATE, NullSerp, &s_SerpSlash[0][8]},
{SERP_SLASH_R0 + 4, 0|SF_QUICK_CALL, InitActorDecide, &s_SerpSlash[0][9]},
{SERP_SLASH_R0 + 4, SERP_SLASH_RATE, DoSerpMove, &s_SerpSlash[0][9]},
},
{
{SERP_SLASH_R1 + 2, SERP_SLASH_RATE, NullSerp, &s_SerpSlash[1][1]},
{SERP_SLASH_R1 + 1, SERP_SLASH_RATE, NullSerp, &s_SerpSlash[1][2]},
{SERP_SLASH_R1 + 0, SERP_SLASH_RATE*2, NullSerp, &s_SerpSlash[1][3]},
{SERP_SLASH_R1 + 1, SERP_SLASH_RATE, NullSerp, &s_SerpSlash[1][4]},
{SERP_SLASH_R1 + 2, SERP_SLASH_RATE, NullSerp, &s_SerpSlash[1][5]},
{SERP_SLASH_R1 + 3, SF_QUICK_CALL, InitSerpSlash, &s_SerpSlash[1][6]},
{SERP_SLASH_R1 + 3, SERP_SLASH_RATE, NullSerp, &s_SerpSlash[1][7]},
{SERP_SLASH_R1 + 4, SERP_SLASH_RATE, NullSerp, &s_SerpSlash[1][8]},
{SERP_SLASH_R1 + 4, 0|SF_QUICK_CALL, InitActorDecide, &s_SerpSlash[1][9]},
{SERP_SLASH_R1 + 4, SERP_SLASH_RATE, DoSerpMove, &s_SerpSlash[1][9]},
},
{
{SERP_SLASH_R2 + 2, SERP_SLASH_RATE, NullSerp, &s_SerpSlash[2][1]},
{SERP_SLASH_R2 + 1, SERP_SLASH_RATE, NullSerp, &s_SerpSlash[2][2]},
{SERP_SLASH_R2 + 0, SERP_SLASH_RATE*2, NullSerp, &s_SerpSlash[2][3]},
{SERP_SLASH_R2 + 1, SERP_SLASH_RATE, NullSerp, &s_SerpSlash[2][4]},
{SERP_SLASH_R2 + 2, SERP_SLASH_RATE, NullSerp, &s_SerpSlash[2][5]},
{SERP_SLASH_R2 + 3, SF_QUICK_CALL, InitSerpSlash, &s_SerpSlash[2][6]},
{SERP_SLASH_R2 + 3, SERP_SLASH_RATE, NullSerp, &s_SerpSlash[2][7]},
{SERP_SLASH_R2 + 4, SERP_SLASH_RATE, NullSerp, &s_SerpSlash[2][8]},
{SERP_SLASH_R2 + 4, 0|SF_QUICK_CALL, InitActorDecide, &s_SerpSlash[2][9]},
{SERP_SLASH_R2 + 4, SERP_SLASH_RATE, DoSerpMove, &s_SerpSlash[2][9]},
},
{
{SERP_SLASH_R3 + 2, SERP_SLASH_RATE, NullSerp, &s_SerpSlash[3][1]},
{SERP_SLASH_R3 + 1, SERP_SLASH_RATE, NullSerp, &s_SerpSlash[3][2]},
{SERP_SLASH_R3 + 0, SERP_SLASH_RATE*2, NullSerp, &s_SerpSlash[3][3]},
{SERP_SLASH_R3 + 1, SERP_SLASH_RATE, NullSerp, &s_SerpSlash[3][4]},
{SERP_SLASH_R3 + 2, SERP_SLASH_RATE, NullSerp, &s_SerpSlash[3][5]},
{SERP_SLASH_R3 + 3, SF_QUICK_CALL, InitSerpSlash, &s_SerpSlash[3][6]},
{SERP_SLASH_R3 + 3, SERP_SLASH_RATE, NullSerp, &s_SerpSlash[3][7]},
{SERP_SLASH_R3 + 4, SERP_SLASH_RATE, NullSerp, &s_SerpSlash[3][8]},
{SERP_SLASH_R3 + 4, 0|SF_QUICK_CALL, InitActorDecide, &s_SerpSlash[3][9]},
{SERP_SLASH_R3 + 4, SERP_SLASH_RATE, DoSerpMove, &s_SerpSlash[3][9]},
},
{
{SERP_SLASH_R4 + 2, SERP_SLASH_RATE, NullSerp, &s_SerpSlash[4][1]},
{SERP_SLASH_R4 + 1, SERP_SLASH_RATE, NullSerp, &s_SerpSlash[4][2]},
{SERP_SLASH_R4 + 0, SERP_SLASH_RATE*2, NullSerp, &s_SerpSlash[4][3]},
{SERP_SLASH_R4 + 1, SERP_SLASH_RATE, NullSerp, &s_SerpSlash[4][4]},
{SERP_SLASH_R4 + 2, SERP_SLASH_RATE, NullSerp, &s_SerpSlash[4][5]},
{SERP_SLASH_R4 + 3, SF_QUICK_CALL, InitSerpSlash, &s_SerpSlash[4][6]},
{SERP_SLASH_R4 + 3, SERP_SLASH_RATE, NullSerp, &s_SerpSlash[4][7]},
{SERP_SLASH_R4 + 4, SERP_SLASH_RATE, NullSerp, &s_SerpSlash[4][8]},
{SERP_SLASH_R4 + 4, 0|SF_QUICK_CALL, InitActorDecide, &s_SerpSlash[4][9]},
{SERP_SLASH_R4 + 4, SERP_SLASH_RATE, DoSerpMove, &s_SerpSlash[4][9]},
}
};
STATE* sg_SerpSlash[] =
{
&s_SerpSlash[0][0],
&s_SerpSlash[1][0],
&s_SerpSlash[2][0],
&s_SerpSlash[3][0],
&s_SerpSlash[4][0]
};
//////////////////////
//
// SERP SKULL SPELL
//
//////////////////////
#define SERP_SKULL_SPELL_RATE 18
ANIMATOR InitSerpSkullSpell;
ANIMATOR InitSerpRing;
STATE s_SerpSkullSpell[5][8] =
{
{
{SERP_SPELL_R0 + 2, SERP_SKULL_SPELL_RATE*2, NullSerp, &s_SerpSkullSpell[0][1]},
{SERP_SPELL_R0 + 1, SERP_SKULL_SPELL_RATE, NullSerp, &s_SerpSkullSpell[0][2]},
{SERP_SPELL_R0 + 0, SERP_SKULL_SPELL_RATE*2, NullSerp, &s_SerpSkullSpell[0][3]},
{SERP_SPELL_R0 + 0, SF_QUICK_CALL, InitSerpRing, &s_SerpSkullSpell[0][4]},
{SERP_SPELL_R0 + 0, SERP_SKULL_SPELL_RATE, NullSerp, &s_SerpSkullSpell[0][5]},
{SERP_SPELL_R0 + 1, SERP_SKULL_SPELL_RATE, NullSerp, &s_SerpSkullSpell[0][6]},
{SERP_SPELL_R0 + 1, SF_QUICK_CALL, InitActorDecide, &s_SerpSkullSpell[0][7]},
{SERP_SPELL_R0 + 1, SERP_SKULL_SPELL_RATE, DoSerpMove, &s_SerpSkullSpell[0][7]},
},
{
{SERP_SPELL_R1 + 2, SERP_SKULL_SPELL_RATE*2, NullSerp, &s_SerpSkullSpell[1][1]},
{SERP_SPELL_R1 + 1, SERP_SKULL_SPELL_RATE, NullSerp, &s_SerpSkullSpell[1][2]},
{SERP_SPELL_R1 + 0, SERP_SKULL_SPELL_RATE*2, NullSerp, &s_SerpSkullSpell[1][3]},
{SERP_SPELL_R1 + 0, SF_QUICK_CALL, InitSerpRing, &s_SerpSkullSpell[1][4]},
{SERP_SPELL_R1 + 0, SERP_SKULL_SPELL_RATE, NullSerp, &s_SerpSkullSpell[1][5]},
{SERP_SPELL_R1 + 1, SERP_SKULL_SPELL_RATE, NullSerp, &s_SerpSkullSpell[1][6]},
{SERP_SPELL_R1 + 1, SF_QUICK_CALL, InitActorDecide, &s_SerpSkullSpell[1][7]},
{SERP_SPELL_R1 + 1, SERP_SKULL_SPELL_RATE, DoSerpMove, &s_SerpSkullSpell[1][7]},
},
{
{SERP_SPELL_R2 + 2, SERP_SKULL_SPELL_RATE*2, NullSerp, &s_SerpSkullSpell[2][1]},
{SERP_SPELL_R2 + 1, SERP_SKULL_SPELL_RATE, NullSerp, &s_SerpSkullSpell[2][2]},
{SERP_SPELL_R2 + 0, SERP_SKULL_SPELL_RATE*2, NullSerp, &s_SerpSkullSpell[2][3]},
{SERP_SPELL_R2 + 0, SF_QUICK_CALL, InitSerpRing, &s_SerpSkullSpell[2][4]},
{SERP_SPELL_R2 + 0, SERP_SKULL_SPELL_RATE, NullSerp, &s_SerpSkullSpell[2][5]},
{SERP_SPELL_R2 + 1, SERP_SKULL_SPELL_RATE, NullSerp, &s_SerpSkullSpell[2][6]},
{SERP_SPELL_R2 + 1, SF_QUICK_CALL, InitActorDecide, &s_SerpSkullSpell[2][7]},
{SERP_SPELL_R2 + 1, SERP_SKULL_SPELL_RATE, DoSerpMove, &s_SerpSkullSpell[2][7]},
},
{
{SERP_SPELL_R3 + 2, SERP_SKULL_SPELL_RATE*2, NullSerp, &s_SerpSkullSpell[3][1]},
{SERP_SPELL_R3 + 1, SERP_SKULL_SPELL_RATE, NullSerp, &s_SerpSkullSpell[3][2]},
{SERP_SPELL_R3 + 0, SERP_SKULL_SPELL_RATE*2, NullSerp, &s_SerpSkullSpell[3][3]},
{SERP_SPELL_R3 + 0, SF_QUICK_CALL, InitSerpRing, &s_SerpSkullSpell[3][4]},
{SERP_SPELL_R3 + 0, SERP_SKULL_SPELL_RATE, NullSerp, &s_SerpSkullSpell[3][5]},
{SERP_SPELL_R3 + 1, SERP_SKULL_SPELL_RATE, NullSerp, &s_SerpSkullSpell[3][6]},
{SERP_SPELL_R3 + 1, SF_QUICK_CALL, InitActorDecide, &s_SerpSkullSpell[3][7]},
{SERP_SPELL_R3 + 1, SERP_SKULL_SPELL_RATE, DoSerpMove, &s_SerpSkullSpell[3][7]},
},
{
{SERP_SPELL_R4 + 2, SERP_SKULL_SPELL_RATE*2, NullSerp, &s_SerpSkullSpell[4][1]},
{SERP_SPELL_R4 + 1, SERP_SKULL_SPELL_RATE, NullSerp, &s_SerpSkullSpell[4][2]},
{SERP_SPELL_R4 + 0, SERP_SKULL_SPELL_RATE*2, NullSerp, &s_SerpSkullSpell[4][3]},
{SERP_SPELL_R4 + 0, SF_QUICK_CALL, InitSerpRing, &s_SerpSkullSpell[4][4]},
{SERP_SPELL_R4 + 0, SERP_SKULL_SPELL_RATE, NullSerp, &s_SerpSkullSpell[4][5]},
{SERP_SPELL_R4 + 1, SERP_SKULL_SPELL_RATE, NullSerp, &s_SerpSkullSpell[4][6]},
{SERP_SPELL_R4 + 1, SF_QUICK_CALL, InitActorDecide, &s_SerpSkullSpell[4][7]},
{SERP_SPELL_R4 + 1, SERP_SKULL_SPELL_RATE, DoSerpMove, &s_SerpSkullSpell[4][7]},
}
};
STATE* sg_SerpSkullSpell[] =
{
&s_SerpSkullSpell[0][0],
&s_SerpSkullSpell[1][0],
&s_SerpSkullSpell[2][0],
&s_SerpSkullSpell[3][0],
&s_SerpSkullSpell[4][0]
};
//////////////////////
//
// SERP SPELL
//
//////////////////////
#define SERP_SPELL_RATE 18
ANIMATOR InitSerpSpell;
STATE s_SerpSpell[5][8] =
{
{
{SERP_SPELL_R0 + 2, SERP_SPELL_RATE*2, NullSerp, &s_SerpSpell[0][1]},
{SERP_SPELL_R0 + 1, SERP_SPELL_RATE, NullSerp, &s_SerpSpell[0][2]},
{SERP_SPELL_R0 + 0, SERP_SPELL_RATE*2, NullSerp, &s_SerpSpell[0][3]},
{SERP_SPELL_R0 + 0, SF_QUICK_CALL, InitSerpSpell, &s_SerpSpell[0][4]},
{SERP_SPELL_R0 + 0, SERP_SPELL_RATE, NullSerp, &s_SerpSpell[0][5]},
{SERP_SPELL_R0 + 1, SERP_SPELL_RATE, NullSerp, &s_SerpSpell[0][6]},
{SERP_SPELL_R0 + 1, SF_QUICK_CALL, InitActorDecide, &s_SerpSpell[0][7]},
{SERP_SPELL_R0 + 1, SERP_SPELL_RATE, DoSerpMove, &s_SerpSpell[0][7]},
},
{
{SERP_SPELL_R1 + 2, SERP_SPELL_RATE*2, NullSerp, &s_SerpSpell[1][1]},
{SERP_SPELL_R1 + 1, SERP_SPELL_RATE, NullSerp, &s_SerpSpell[1][2]},
{SERP_SPELL_R1 + 0, SERP_SPELL_RATE*2, NullSerp, &s_SerpSpell[1][3]},
{SERP_SPELL_R1 + 0, SF_QUICK_CALL, InitSerpSpell, &s_SerpSpell[1][4]},
{SERP_SPELL_R1 + 0, SERP_SPELL_RATE, NullSerp, &s_SerpSpell[1][5]},
{SERP_SPELL_R1 + 1, SERP_SPELL_RATE, NullSerp, &s_SerpSpell[1][6]},
{SERP_SPELL_R1 + 1, SF_QUICK_CALL, InitActorDecide, &s_SerpSpell[1][7]},
{SERP_SPELL_R1 + 1, SERP_SPELL_RATE, DoSerpMove, &s_SerpSpell[1][7]},
},
{
{SERP_SPELL_R2 + 2, SERP_SPELL_RATE*2, NullSerp, &s_SerpSpell[2][1]},
{SERP_SPELL_R2 + 1, SERP_SPELL_RATE, NullSerp, &s_SerpSpell[2][2]},
{SERP_SPELL_R2 + 0, SERP_SPELL_RATE*2, NullSerp, &s_SerpSpell[2][3]},
{SERP_SPELL_R2 + 0, SF_QUICK_CALL, InitSerpSpell, &s_SerpSpell[2][4]},
{SERP_SPELL_R2 + 0, SERP_SPELL_RATE, NullSerp, &s_SerpSpell[2][5]},
{SERP_SPELL_R2 + 1, SERP_SPELL_RATE, NullSerp, &s_SerpSpell[2][6]},
{SERP_SPELL_R2 + 1, SF_QUICK_CALL, InitActorDecide, &s_SerpSpell[2][7]},
{SERP_SPELL_R2 + 1, SERP_SPELL_RATE, DoSerpMove, &s_SerpSpell[2][7]},
},
{
{SERP_SPELL_R3 + 2, SERP_SPELL_RATE*2, NullSerp, &s_SerpSpell[3][1]},
{SERP_SPELL_R3 + 1, SERP_SPELL_RATE, NullSerp, &s_SerpSpell[3][2]},
{SERP_SPELL_R3 + 0, SERP_SPELL_RATE*2, NullSerp, &s_SerpSpell[3][3]},
{SERP_SPELL_R3 + 0, SF_QUICK_CALL, InitSerpSpell, &s_SerpSpell[3][4]},
{SERP_SPELL_R3 + 0, SERP_SPELL_RATE, NullSerp, &s_SerpSpell[3][5]},
{SERP_SPELL_R3 + 1, SERP_SPELL_RATE, NullSerp, &s_SerpSpell[3][6]},
{SERP_SPELL_R3 + 1, SF_QUICK_CALL, InitActorDecide, &s_SerpSpell[3][7]},
{SERP_SPELL_R3 + 1, SERP_SPELL_RATE, DoSerpMove, &s_SerpSpell[3][7]},
},
{
{SERP_SPELL_R4 + 2, SERP_SPELL_RATE*2, NullSerp, &s_SerpSpell[4][1]},
{SERP_SPELL_R4 + 1, SERP_SPELL_RATE, NullSerp, &s_SerpSpell[4][2]},
{SERP_SPELL_R4 + 0, SERP_SPELL_RATE*2, NullSerp, &s_SerpSpell[4][3]},
{SERP_SPELL_R4 + 0, SF_QUICK_CALL, InitSerpSpell, &s_SerpSpell[4][4]},
{SERP_SPELL_R4 + 0, SERP_SPELL_RATE, NullSerp, &s_SerpSpell[4][5]},
{SERP_SPELL_R4 + 1, SERP_SPELL_RATE, NullSerp, &s_SerpSpell[4][6]},
{SERP_SPELL_R4 + 1, SF_QUICK_CALL, InitActorDecide, &s_SerpSpell[4][7]},
{SERP_SPELL_R4 + 1, SERP_SPELL_RATE, DoSerpMove, &s_SerpSpell[4][7]},
}
};
STATE* sg_SerpSpell[] =
{
&s_SerpSpell[0][0],
&s_SerpSpell[1][0],
&s_SerpSpell[2][0],
&s_SerpSpell[3][0],
&s_SerpSpell[4][0]
};
//////////////////////
//
// SERP SPELL MONSTER
//
//////////////////////
ANIMATOR InitSerpMonstSpell;
STATE s_SerpMonstSpell[5][8] =
{
{
{SERP_SPELL_R0 + 2, SERP_SPELL_RATE*2, NullSerp, &s_SerpMonstSpell[0][1]},
{SERP_SPELL_R0 + 1, SERP_SPELL_RATE, NullSerp, &s_SerpMonstSpell[0][2]},
{SERP_SPELL_R0 + 0, SERP_SPELL_RATE*2, NullSerp, &s_SerpMonstSpell[0][3]},
{SERP_SPELL_R0 + 0, SF_QUICK_CALL, InitSerpMonstSpell, &s_SerpMonstSpell[0][4]},
{SERP_SPELL_R0 + 0, SERP_SPELL_RATE, NullSerp, &s_SerpMonstSpell[0][5]},
{SERP_SPELL_R0 + 1, SERP_SPELL_RATE, NullSerp, &s_SerpMonstSpell[0][6]},
{SERP_SPELL_R0 + 1, SF_QUICK_CALL, InitActorDecide, &s_SerpMonstSpell[0][7]},
{SERP_SPELL_R0 + 1, SERP_SPELL_RATE, DoSerpMove, &s_SerpMonstSpell[0][7]},
},
{
{SERP_SPELL_R1 + 2, SERP_SPELL_RATE*2, NullSerp, &s_SerpMonstSpell[1][1]},
{SERP_SPELL_R1 + 1, SERP_SPELL_RATE, NullSerp, &s_SerpMonstSpell[1][2]},
{SERP_SPELL_R1 + 0, SERP_SPELL_RATE*2, NullSerp, &s_SerpMonstSpell[1][3]},
{SERP_SPELL_R1 + 0, SF_QUICK_CALL, InitSerpMonstSpell, &s_SerpMonstSpell[1][4]},
{SERP_SPELL_R1 + 0, SERP_SPELL_RATE, NullSerp, &s_SerpMonstSpell[1][5]},
{SERP_SPELL_R1 + 1, SERP_SPELL_RATE, NullSerp, &s_SerpMonstSpell[1][6]},
{SERP_SPELL_R1 + 1, SF_QUICK_CALL, InitActorDecide, &s_SerpMonstSpell[1][7]},
{SERP_SPELL_R1 + 1, SERP_SPELL_RATE, DoSerpMove, &s_SerpMonstSpell[1][7]},
},
{
{SERP_SPELL_R2 + 2, SERP_SPELL_RATE*2, NullSerp, &s_SerpMonstSpell[2][1]},
{SERP_SPELL_R2 + 1, SERP_SPELL_RATE, NullSerp, &s_SerpMonstSpell[2][2]},
{SERP_SPELL_R2 + 0, SERP_SPELL_RATE*2, NullSerp, &s_SerpMonstSpell[2][3]},
{SERP_SPELL_R2 + 0, SF_QUICK_CALL, InitSerpMonstSpell, &s_SerpMonstSpell[2][4]},
{SERP_SPELL_R2 + 0, SERP_SPELL_RATE, NullSerp, &s_SerpMonstSpell[2][5]},
{SERP_SPELL_R2 + 1, SERP_SPELL_RATE, NullSerp, &s_SerpMonstSpell[2][6]},
{SERP_SPELL_R2 + 1, SF_QUICK_CALL, InitActorDecide, &s_SerpMonstSpell[2][7]},
{SERP_SPELL_R2 + 1, SERP_SPELL_RATE, DoSerpMove, &s_SerpMonstSpell[2][7]},
},
{
{SERP_SPELL_R3 + 2, SERP_SPELL_RATE*2, NullSerp, &s_SerpMonstSpell[3][1]},
{SERP_SPELL_R3 + 1, SERP_SPELL_RATE, NullSerp, &s_SerpMonstSpell[3][2]},
{SERP_SPELL_R3 + 0, SERP_SPELL_RATE*2, NullSerp, &s_SerpMonstSpell[3][3]},
{SERP_SPELL_R3 + 0, SF_QUICK_CALL, InitSerpMonstSpell, &s_SerpMonstSpell[3][4]},
{SERP_SPELL_R3 + 0, SERP_SPELL_RATE, NullSerp, &s_SerpMonstSpell[3][5]},
{SERP_SPELL_R3 + 1, SERP_SPELL_RATE, NullSerp, &s_SerpMonstSpell[3][6]},
{SERP_SPELL_R3 + 1, SF_QUICK_CALL, InitActorDecide, &s_SerpMonstSpell[3][7]},
{SERP_SPELL_R3 + 1, SERP_SPELL_RATE, DoSerpMove, &s_SerpMonstSpell[3][7]},
},
{
{SERP_SPELL_R4 + 2, SERP_SPELL_RATE*2, NullSerp, &s_SerpMonstSpell[4][1]},
{SERP_SPELL_R4 + 1, SERP_SPELL_RATE, NullSerp, &s_SerpMonstSpell[4][2]},
{SERP_SPELL_R4 + 0, SERP_SPELL_RATE*2, NullSerp, &s_SerpMonstSpell[4][3]},
{SERP_SPELL_R4 + 0, SF_QUICK_CALL, InitSerpMonstSpell, &s_SerpMonstSpell[4][4]},
{SERP_SPELL_R4 + 0, SERP_SPELL_RATE, NullSerp, &s_SerpMonstSpell[4][5]},
{SERP_SPELL_R4 + 1, SERP_SPELL_RATE, NullSerp, &s_SerpMonstSpell[4][6]},
{SERP_SPELL_R4 + 1, SF_QUICK_CALL, InitActorDecide, &s_SerpMonstSpell[4][7]},
{SERP_SPELL_R4 + 1, SERP_SPELL_RATE, DoSerpMove, &s_SerpMonstSpell[4][7]},
}
};
STATE* sg_SerpMonstSpell[] =
{
&s_SerpMonstSpell[0][0],
&s_SerpMonstSpell[1][0],
&s_SerpMonstSpell[2][0],
&s_SerpMonstSpell[3][0],
&s_SerpMonstSpell[4][0]
};
//////////////////////
//
// SERP RAPID SPELL
//
//////////////////////
#define SERP_SPELL_RATE 18
ANIMATOR InitSerpRapidSpell;
STATE s_SerpRapidSpell[5][10] =
{
{
{SERP_SPELL_R0 + 2, SERP_SPELL_RATE*2, NullSerp, &s_SerpRapidSpell[0][1]},
{SERP_SPELL_R0 + 1, SERP_SPELL_RATE, NullSerp, &s_SerpRapidSpell[0][2]},
{SERP_SPELL_R0 + 0, SERP_SPELL_RATE*2, NullSerp, &s_SerpRapidSpell[0][3]},
{SERP_SPELL_R0 + 0, SF_QUICK_CALL, InitSerpSpell, &s_SerpRapidSpell[0][4]},
{SERP_SPELL_R0 + 0, SERP_SPELL_RATE*2, NullSerp, &s_SerpRapidSpell[0][5]},
{SERP_SPELL_R0 + 0, SF_QUICK_CALL, InitSerpSpell, &s_SerpRapidSpell[0][6]},
{SERP_SPELL_R0 + 0, SERP_SPELL_RATE, NullSerp, &s_SerpRapidSpell[0][7]},
{SERP_SPELL_R0 + 1, SERP_SPELL_RATE, NullSerp, &s_SerpRapidSpell[0][8]},
{SERP_SPELL_R0 + 1, SF_QUICK_CALL, InitActorDecide, &s_SerpRapidSpell[0][9]},
{SERP_SPELL_R0 + 1, SERP_SPELL_RATE, DoSerpMove, &s_SerpRapidSpell[0][9]},
},
{
{SERP_SPELL_R1 + 2, SERP_SPELL_RATE*2, NullSerp, &s_SerpRapidSpell[1][1]},
{SERP_SPELL_R1 + 1, SERP_SPELL_RATE, NullSerp, &s_SerpRapidSpell[1][2]},
{SERP_SPELL_R1 + 0, SERP_SPELL_RATE*2, NullSerp, &s_SerpRapidSpell[1][3]},
{SERP_SPELL_R1 + 0, SF_QUICK_CALL, InitSerpSpell, &s_SerpRapidSpell[1][4]},
{SERP_SPELL_R1 + 0, SERP_SPELL_RATE*2, NullSerp, &s_SerpRapidSpell[1][5]},
{SERP_SPELL_R1 + 0, SF_QUICK_CALL, InitSerpSpell, &s_SerpRapidSpell[1][6]},
{SERP_SPELL_R1 + 0, SERP_SPELL_RATE, NullSerp, &s_SerpRapidSpell[1][7]},
{SERP_SPELL_R1 + 1, SERP_SPELL_RATE, NullSerp, &s_SerpRapidSpell[1][8]},
{SERP_SPELL_R1 + 1, SF_QUICK_CALL, InitActorDecide, &s_SerpRapidSpell[1][9]},
{SERP_SPELL_R1 + 1, SERP_SPELL_RATE, DoSerpMove, &s_SerpRapidSpell[1][9]},
},
{
{SERP_SPELL_R2 + 2, SERP_SPELL_RATE*2, NullSerp, &s_SerpRapidSpell[2][1]},
{SERP_SPELL_R2 + 1, SERP_SPELL_RATE, NullSerp, &s_SerpRapidSpell[2][2]},
{SERP_SPELL_R2 + 0, SERP_SPELL_RATE*2, NullSerp, &s_SerpRapidSpell[2][3]},
{SERP_SPELL_R2 + 0, SF_QUICK_CALL, InitSerpSpell, &s_SerpRapidSpell[2][4]},
{SERP_SPELL_R2 + 0, SERP_SPELL_RATE*2, NullSerp, &s_SerpRapidSpell[2][5]},
{SERP_SPELL_R2 + 0, SF_QUICK_CALL, InitSerpSpell, &s_SerpRapidSpell[2][6]},
{SERP_SPELL_R2 + 0, SERP_SPELL_RATE, NullSerp, &s_SerpRapidSpell[2][7]},
{SERP_SPELL_R2 + 1, SERP_SPELL_RATE, NullSerp, &s_SerpRapidSpell[2][8]},
{SERP_SPELL_R2 + 1, SF_QUICK_CALL, InitActorDecide, &s_SerpRapidSpell[2][9]},
{SERP_SPELL_R2 + 1, SERP_SPELL_RATE, DoSerpMove, &s_SerpRapidSpell[2][9]},
},
{
{SERP_SPELL_R3 + 2, SERP_SPELL_RATE*2, NullSerp, &s_SerpRapidSpell[3][1]},
{SERP_SPELL_R3 + 1, SERP_SPELL_RATE, NullSerp, &s_SerpRapidSpell[3][2]},
{SERP_SPELL_R3 + 0, SERP_SPELL_RATE*2, NullSerp, &s_SerpRapidSpell[3][3]},
{SERP_SPELL_R3 + 0, SF_QUICK_CALL, InitSerpSpell, &s_SerpRapidSpell[3][4]},
{SERP_SPELL_R3 + 0, SERP_SPELL_RATE*2, NullSerp, &s_SerpRapidSpell[3][5]},
{SERP_SPELL_R3 + 0, SF_QUICK_CALL, InitSerpSpell, &s_SerpRapidSpell[3][6]},
{SERP_SPELL_R3 + 0, SERP_SPELL_RATE, NullSerp, &s_SerpRapidSpell[3][7]},
{SERP_SPELL_R3 + 1, SERP_SPELL_RATE, NullSerp, &s_SerpRapidSpell[3][8]},
{SERP_SPELL_R3 + 1, SF_QUICK_CALL, InitActorDecide, &s_SerpRapidSpell[3][9]},
{SERP_SPELL_R3 + 1, SERP_SPELL_RATE, DoSerpMove, &s_SerpRapidSpell[3][9]},
},
{
{SERP_SPELL_R4 + 2, SERP_SPELL_RATE*2, NullSerp, &s_SerpRapidSpell[4][1]},
{SERP_SPELL_R4 + 1, SERP_SPELL_RATE, NullSerp, &s_SerpRapidSpell[4][2]},
{SERP_SPELL_R4 + 0, SERP_SPELL_RATE*2, NullSerp, &s_SerpRapidSpell[4][3]},
{SERP_SPELL_R4 + 0, SF_QUICK_CALL, InitSerpSpell, &s_SerpRapidSpell[4][4]},
{SERP_SPELL_R4 + 0, SERP_SPELL_RATE*2, NullSerp, &s_SerpRapidSpell[4][5]},
{SERP_SPELL_R4 + 0, SF_QUICK_CALL, InitSerpSpell, &s_SerpRapidSpell[4][6]},
{SERP_SPELL_R4 + 0, SERP_SPELL_RATE, NullSerp, &s_SerpRapidSpell[4][7]},
{SERP_SPELL_R4 + 1, SERP_SPELL_RATE, NullSerp, &s_SerpRapidSpell[4][8]},
{SERP_SPELL_R4 + 1, SF_QUICK_CALL, InitActorDecide, &s_SerpRapidSpell[4][9]},
{SERP_SPELL_R4 + 1, SERP_SPELL_RATE, DoSerpMove, &s_SerpRapidSpell[4][9]},
}
};
STATE* sg_SerpRapidSpell[] =
{
&s_SerpRapidSpell[0][0],
&s_SerpRapidSpell[1][0],
&s_SerpRapidSpell[2][0],
&s_SerpRapidSpell[3][0],
&s_SerpRapidSpell[4][0]
};
//////////////////////
//
// SERP STAND
//
//////////////////////
#define SERP_STAND_RATE 12
STATE s_SerpStand[5][1] =
{
{
{SERP_RUN_R0 + 0, SERP_STAND_RATE, DoSerpMove, &s_SerpStand[0][0]},
},
{
{SERP_RUN_R1 + 0, SERP_STAND_RATE, DoSerpMove, &s_SerpStand[1][0]},
},
{
{SERP_RUN_R2 + 0, SERP_STAND_RATE, DoSerpMove, &s_SerpStand[2][0]},
},
{
{SERP_RUN_R3 + 0, SERP_STAND_RATE, DoSerpMove, &s_SerpStand[3][0]},
},
{
{SERP_RUN_R4 + 0, SERP_STAND_RATE, DoSerpMove, &s_SerpStand[4][0]},
},
};
STATE* sg_SerpStand[] =
{
s_SerpStand[0],
s_SerpStand[1],
s_SerpStand[2],
s_SerpStand[3],
s_SerpStand[4]
};
//////////////////////
//
// SERP DIE
//
//////////////////////
#define SERP_DIE_RATE 20
ANIMATOR DoDeathSpecial;
STATE s_SerpDie[] =
{
{SERP_DIE + 0, SERP_DIE_RATE, NullSerp, &s_SerpDie[1]},
{SERP_DIE + 1, SERP_DIE_RATE, NullSerp, &s_SerpDie[2]},
{SERP_DIE + 2, SERP_DIE_RATE, NullSerp, &s_SerpDie[3]},
{SERP_DIE + 3, SERP_DIE_RATE, NullSerp, &s_SerpDie[4]},
{SERP_DIE + 4, SERP_DIE_RATE, NullSerp, &s_SerpDie[5]},
{SERP_DIE + 5, SERP_DIE_RATE, NullSerp, &s_SerpDie[6]},
{SERP_DIE + 6, SERP_DIE_RATE, NullSerp, &s_SerpDie[7]},
{SERP_DIE + 7, SERP_DIE_RATE, NullSerp, &s_SerpDie[8]},
{SERP_DIE + 8, SERP_DIE_RATE, NullSerp, &s_SerpDie[9]},
{SERP_DIE + 8, SF_QUICK_CALL, DoDeathSpecial, &s_SerpDie[10]},
{SERP_DEAD, SERP_DIE_RATE, DoActorDebris, &s_SerpDie[10]}
};
STATE s_SerpDead[] =
{
{SERP_DEAD, SERP_DIE_RATE, DoActorDebris, &s_SerpDead[0]},
};
STATE* sg_SerpDie[] =
{
s_SerpDie
};
STATE* sg_SerpDead[] =
{
s_SerpDead
};
/*
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 SerpActionSet =
{
sg_SerpStand,
sg_SerpRun,
nullptr, //sg_SerpJump,
nullptr, //sg_SerpFall,
nullptr, //sg_SerpCrawl,
nullptr, //sg_SerpSwim,
nullptr, //sg_SerpFly,
nullptr, //sg_SerpRise,
nullptr, //sg_SerpSit,
nullptr, //sg_SerpLook,
nullptr, //climb
nullptr, //pain
sg_SerpDie,
nullptr, //sg_SerpHariKari,
sg_SerpDead,
nullptr, //sg_SerpDeathJump,
nullptr, //sg_SerpDeathFall,
{sg_SerpSlash},
{1024},
{sg_SerpSlash, sg_SerpSpell, sg_SerpRapidSpell, sg_SerpRapidSpell},
{256, 724, 900, 1024},
{nullptr},
nullptr,
nullptr
};
int SetupSerp(DSWActor* actor)
{
ANIMATOR DoActorDecide;
if (!(actor->spr.cstat & CSTAT_SPRITE_RESTORE))
{
SpawnUser(actor,SERP_RUN_R0,s_SerpRun[0]);
actor->user.Health = HEALTH_SERP_GOD;
}
if (Skill == 0) actor->user.Health = 1100;
if (Skill == 1) actor->user.Health = 2200;
ChangeState(actor, s_SerpRun[0]);
actor->user.Attrib = &SerpAttrib;
DoActorSetSpeed(actor, NORM_SPEED);
actor->user.StateEnd = s_SerpDie;
actor->user.Rot = sg_SerpRun;
EnemyDefaults(actor, &SerpActionSet, &SerpPersonality);
// Mini-Boss Serp
if (actor->spr.pal == 16)
{
actor->user.Health = 1000;
actor->spr.yrepeat = 74;
actor->spr.xrepeat = 74;
}
else
{
actor->spr.yrepeat = 100;
actor->spr.xrepeat = 128;
}
actor->spr.clipdist = (512) >> 2;
actor->user.Flags |= (SPR_XFLIP_TOGGLE|SPR_ELECTRO_TOLERANT);
actor->user.loz = actor->spr.pos.Z;
// amount to move up for clipmove
actor->user.zclip = Z(80);
// size of step can walk off of
actor->user.lo_step = Z(40);
actor->user.floor_dist = actor->user.zclip - actor->user.lo_step;
actor->user.ceiling_dist = ActorSizeZ(actor) - actor->user.zclip;
return 0;
}
int NullSerp(DSWActor* actor)
{
if (actor->user.Flags & (SPR_SLIDING))
DoActorSlide(actor);
KeepActorOnFloor(actor);
//DoActorSectorDamage(actor);
return 0;
}
int DoSerpMove(DSWActor* actor)
{
if (actor->user.Flags & (SPR_SLIDING))
DoActorSlide(actor);
if (actor->user.track >= 0)
ActorFollowTrack(actor, ACTORMOVETICS);
else
(*actor->user.ActorActionFunc)(actor);
// serp ring
if (actor->spr.pal != 16)
{
switch (actor->user.Counter2)
{
case 0:
if (actor->user.Health != actor->user.MaxHealth)
{
NewStateGroup(actor, sg_SerpSkullSpell);
actor->user.Counter2++;
}
break;
case 1:
{
if (actor->user.Counter <= 0)
NewStateGroup(actor, sg_SerpSkullSpell);
}
break;
}
}
KeepActorOnFloor(actor);
//DoActorSectorDamage(actor);
return 0;
}
int DoDeathSpecial(DSWActor* actor)
{
DoMatchEverything(nullptr, actor->spr.lotag, 1);
if (!SW_SHAREWARE)
{
// Resume the regular music - in a hack-free fashion.
PlaySong(currentLevel->music, currentLevel->cdSongId);
}
BossSpriteNum[0] = nullptr;
return 0;
}
#include "saveable.h"
static saveable_code saveable_serp_code[] =
{
SAVE_CODE(NullSerp),
SAVE_CODE(DoSerpMove),
SAVE_CODE(DoDeathSpecial),
};
static saveable_data saveable_serp_data[] =
{
SAVE_DATA(SerpBattle),
SAVE_DATA(SerpOffense),
SAVE_DATA(SerpBroadcast),
SAVE_DATA(SerpSurprised),
SAVE_DATA(SerpEvasive),
SAVE_DATA(SerpLostTarget),
SAVE_DATA(SerpCloseRange),
SAVE_DATA(SerpPersonality),
SAVE_DATA(SerpAttrib),
SAVE_DATA(SerpPissedAttrib),
SAVE_DATA(s_SerpRun),
SAVE_DATA(sg_SerpRun),
SAVE_DATA(s_SerpSlash),
SAVE_DATA(sg_SerpSlash),
SAVE_DATA(s_SerpSkullSpell),
SAVE_DATA(sg_SerpSkullSpell),
SAVE_DATA(s_SerpSpell),
SAVE_DATA(sg_SerpSpell),
SAVE_DATA(s_SerpMonstSpell),
SAVE_DATA(sg_SerpMonstSpell),
SAVE_DATA(s_SerpRapidSpell),
SAVE_DATA(sg_SerpRapidSpell),
SAVE_DATA(s_SerpStand),
SAVE_DATA(sg_SerpStand),
SAVE_DATA(s_SerpDie),
SAVE_DATA(s_SerpDead),
SAVE_DATA(sg_SerpDie),
SAVE_DATA(sg_SerpDead),
SAVE_DATA(SerpActionSet),
};
saveable_module saveable_serp =
{
// code
saveable_serp_code,
SIZ(saveable_serp_code),
// data
saveable_serp_data,
SIZ(saveable_serp_data)
};
END_SW_NS