raze/source/sw/src/bunny.cpp
Christoph Oelckers 75c76ccf66 - changed SW's PlaySound interface to take pointers to objects instead of pointers to coordinates.
With pointers to coordinates the sound engine cannot work, so this had to be changed globally.
2019-12-18 11:09:01 +01:00

1634 lines
43 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 "keys.h"
#include "names2.h"
#include "panel.h"
#include "tags.h"
#include "ai.h"
#include "pal.h"
#include "sprite.h"
#include "actor.h"
#include "weapon.h"
#include "track.h"
BEGIN_SW_NS
short Bunny_Count = 0;
ANIMATOR DoActorMoveJump;
ANIMATOR DoBunnyMoveJump;
ANIMATOR DoBunnyQuickJump;
DECISION BunnyBattle[] =
{
{748, InitActorMoveCloser},
{750, InitActorAlertNoise},
{760, InitActorAttackNoise},
{1024, InitActorMoveCloser}
};
DECISION BunnyOffense[] =
{
{600, InitActorMoveCloser},
{700, InitActorAlertNoise},
{1024, InitActorMoveCloser}
};
DECISION BunnyBroadcast[] =
{
{21, InitActorAlertNoise},
{51, InitActorAmbientNoise},
{1024, InitActorDecide}
};
DECISION BunnySurprised[] =
{
{500, InitActorRunAway},
{701, InitActorMoveCloser},
{1024, InitActorDecide}
};
DECISION BunnyEvasive[] =
{
{500, InitActorWanderAround},
{1020, InitActorRunAway},
{1024, InitActorAmbientNoise}
};
DECISION BunnyLostTarget[] =
{
{900, InitActorFindPlayer},
{1024, InitActorWanderAround}
};
DECISION BunnyCloseRange[] =
{
{1024, InitActorAttack },
// {1024, InitActorReposition }
};
DECISION BunnyWander[] =
{
{1024, InitActorReposition}
};
PERSONALITY WhiteBunnyPersonality =
{
BunnyBattle,
BunnyOffense,
BunnyBroadcast,
BunnySurprised,
BunnyEvasive,
BunnyLostTarget,
BunnyCloseRange,
BunnyCloseRange
};
PERSONALITY BunnyPersonality =
{
BunnyEvasive,
BunnyEvasive,
BunnyEvasive,
BunnyWander,
BunnyWander,
BunnyWander,
BunnyEvasive,
BunnyEvasive
};
ATTRIBUTE BunnyAttrib =
{
{100, 120, 140, 180}, // Speeds
{5, 0, -2, -4}, // Tic Adjusts
3, // MaxWeapons;
{
DIGI_BUNNYAMBIENT, 0, DIGI_BUNNYATTACK,
DIGI_BUNNYATTACK, DIGI_BUNNYDIE2, 0,
0,0,0,0
}
};
ATTRIBUTE WhiteBunnyAttrib =
{
{200, 220, 340, 380}, // Speeds
{5, 0, -2, -4}, // Tic Adjusts
3, // MaxWeapons;
{
DIGI_BUNNYAMBIENT, 0, DIGI_BUNNYATTACK,
DIGI_BUNNYATTACK, DIGI_BUNNYDIE2, 0,
0,0,0,0
}
};
//////////////////////
//
// BUNNY RUN
//
//////////////////////
#define BUNNY_RUN_RATE 10
ANIMATOR DoBunnyMove, NullBunny, DoActorDebris, DoBunnyGrowUp;
STATE s_BunnyRun[5][6] =
{
{
{BUNNY_RUN_R0 + 0, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[0][1]},
{BUNNY_RUN_R0 + 1, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[0][2]},
{BUNNY_RUN_R0 + 2, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[0][3]},
{BUNNY_RUN_R0 + 3, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[0][4]},
{BUNNY_RUN_R0 + 4, SF_QUICK_CALL, DoBunnyGrowUp, &s_BunnyRun[0][5]},
{BUNNY_RUN_R0 + 4, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[0][0]},
},
{
{BUNNY_RUN_R1 + 0, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[1][1]},
{BUNNY_RUN_R1 + 1, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[1][2]},
{BUNNY_RUN_R1 + 2, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[1][3]},
{BUNNY_RUN_R1 + 3, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[1][4]},
{BUNNY_RUN_R1 + 4, SF_QUICK_CALL, DoBunnyGrowUp, &s_BunnyRun[1][5]},
{BUNNY_RUN_R1 + 4, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[1][0]},
},
{
{BUNNY_RUN_R2 + 0, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[2][1]},
{BUNNY_RUN_R2 + 1, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[2][2]},
{BUNNY_RUN_R2 + 2, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[2][3]},
{BUNNY_RUN_R2 + 3, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[2][4]},
{BUNNY_RUN_R2 + 4, SF_QUICK_CALL, DoBunnyGrowUp, &s_BunnyRun[2][5]},
{BUNNY_RUN_R2 + 4, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[2][0]},
},
{
{BUNNY_RUN_R3 + 0, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[3][1]},
{BUNNY_RUN_R3 + 1, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[3][2]},
{BUNNY_RUN_R3 + 2, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[3][3]},
{BUNNY_RUN_R3 + 3, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[3][4]},
{BUNNY_RUN_R3 + 4, SF_QUICK_CALL, DoBunnyGrowUp, &s_BunnyRun[3][5]},
{BUNNY_RUN_R3 + 4, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[3][0]},
},
{
{BUNNY_RUN_R4 + 0, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[4][1]},
{BUNNY_RUN_R4 + 1, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[4][2]},
{BUNNY_RUN_R4 + 2, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[4][3]},
{BUNNY_RUN_R4 + 3, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[4][4]},
{BUNNY_RUN_R4 + 4, SF_QUICK_CALL, DoBunnyGrowUp, &s_BunnyRun[4][5]},
{BUNNY_RUN_R4 + 4, BUNNY_RUN_RATE | SF_TIC_ADJUST, DoBunnyMove, &s_BunnyRun[4][0]},
}
};
STATEp sg_BunnyRun[] =
{
&s_BunnyRun[0][0],
&s_BunnyRun[1][0],
&s_BunnyRun[2][0],
&s_BunnyRun[3][0],
&s_BunnyRun[4][0]
};
//////////////////////
//
// BUNNY STAND
//
//////////////////////
#define BUNNY_STAND_RATE 12
ANIMATOR DoBunnyEat;
STATE s_BunnyStand[5][3] =
{
{
{BUNNY_STAND_R0 + 0, BUNNY_STAND_RATE, DoBunnyEat, &s_BunnyStand[0][1]},
{BUNNY_STAND_R0 + 4, SF_QUICK_CALL, DoBunnyGrowUp, &s_BunnyStand[0][2]},
{BUNNY_STAND_R0 + 4, BUNNY_STAND_RATE, DoBunnyEat, &s_BunnyStand[0][0]},
},
{
{BUNNY_STAND_R1 + 0, BUNNY_STAND_RATE, DoBunnyEat, &s_BunnyStand[1][1]},
{BUNNY_STAND_R1 + 4, SF_QUICK_CALL, DoBunnyGrowUp, &s_BunnyStand[1][2]},
{BUNNY_STAND_R1 + 4, BUNNY_STAND_RATE, DoBunnyEat, &s_BunnyStand[1][0]},
},
{
{BUNNY_STAND_R2 + 0, BUNNY_STAND_RATE, DoBunnyEat, &s_BunnyStand[2][1]},
{BUNNY_STAND_R2 + 4, SF_QUICK_CALL, DoBunnyGrowUp, &s_BunnyStand[2][2]},
{BUNNY_STAND_R2 + 4, BUNNY_STAND_RATE, DoBunnyEat, &s_BunnyStand[2][0]},
},
{
{BUNNY_STAND_R3 + 0, BUNNY_STAND_RATE, DoBunnyEat, &s_BunnyStand[3][1]},
{BUNNY_STAND_R3 + 4, SF_QUICK_CALL, DoBunnyGrowUp, &s_BunnyStand[3][2]},
{BUNNY_STAND_R3 + 4, BUNNY_STAND_RATE, DoBunnyEat, &s_BunnyStand[3][0]},
},
{
{BUNNY_STAND_R4 + 0, BUNNY_STAND_RATE, DoBunnyEat, &s_BunnyStand[4][1]},
{BUNNY_STAND_R4 + 4, SF_QUICK_CALL, DoBunnyGrowUp, &s_BunnyStand[4][2]},
{BUNNY_STAND_R4 + 4, BUNNY_STAND_RATE, DoBunnyEat, &s_BunnyStand[4][0]},
},
};
STATEp sg_BunnyStand[] =
{
s_BunnyStand[0],
s_BunnyStand[1],
s_BunnyStand[2],
s_BunnyStand[3],
s_BunnyStand[4]
};
//////////////////////
//
// BUNNY GET LAYED
//
//////////////////////
#define BUNNY_SCREW_RATE 16
ANIMATOR DoBunnyScrew;
STATE s_BunnyScrew[5][2] =
{
{
{BUNNY_STAND_R0 + 0, BUNNY_SCREW_RATE, DoBunnyScrew, &s_BunnyScrew[0][1]},
{BUNNY_STAND_R0 + 2, BUNNY_SCREW_RATE, DoBunnyScrew, &s_BunnyScrew[0][0]},
},
{
{BUNNY_STAND_R1 + 0, BUNNY_SCREW_RATE, DoBunnyScrew, &s_BunnyScrew[1][1]},
{BUNNY_STAND_R1 + 2, BUNNY_SCREW_RATE, DoBunnyScrew, &s_BunnyScrew[1][0]},
},
{
{BUNNY_STAND_R2 + 0, BUNNY_SCREW_RATE, DoBunnyScrew, &s_BunnyScrew[2][1]},
{BUNNY_STAND_R2 + 2, BUNNY_SCREW_RATE, DoBunnyScrew, &s_BunnyScrew[2][0]},
},
{
{BUNNY_STAND_R3 + 0, BUNNY_SCREW_RATE, DoBunnyScrew, &s_BunnyScrew[3][1]},
{BUNNY_STAND_R3 + 2, BUNNY_SCREW_RATE, DoBunnyScrew, &s_BunnyScrew[3][0]},
},
{
{BUNNY_STAND_R4 + 0, BUNNY_SCREW_RATE, DoBunnyScrew, &s_BunnyScrew[4][1]},
{BUNNY_STAND_R4 + 2, BUNNY_SCREW_RATE, DoBunnyScrew, &s_BunnyScrew[4][0]},
},
};
STATEp sg_BunnyScrew[] =
{
s_BunnyScrew[0],
s_BunnyScrew[1],
s_BunnyScrew[2],
s_BunnyScrew[3],
s_BunnyScrew[4]
};
//////////////////////
//
// BUNNY SWIPE
//
//////////////////////
#define BUNNY_SWIPE_RATE 8
ANIMATOR InitActorDecide;
ANIMATOR InitBunnySlash;
STATE s_BunnySwipe[5][8] =
{
{
{BUNNY_SWIPE_R0 + 0, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[0][1]},
{BUNNY_SWIPE_R0 + 1, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[0][2]},
{BUNNY_SWIPE_R0 + 1, 0 | SF_QUICK_CALL, InitBunnySlash, &s_BunnySwipe[0][3]},
{BUNNY_SWIPE_R0 + 2, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[0][4]},
{BUNNY_SWIPE_R0 + 3, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[0][5]},
{BUNNY_SWIPE_R0 + 3, 0 | SF_QUICK_CALL, InitBunnySlash, &s_BunnySwipe[0][6]},
{BUNNY_SWIPE_R0 + 3, 0 | SF_QUICK_CALL, InitActorDecide, &s_BunnySwipe[0][7]},
{BUNNY_SWIPE_R0 + 3, BUNNY_SWIPE_RATE, DoBunnyMove, &s_BunnySwipe[0][7]},
},
{
{BUNNY_SWIPE_R1 + 0, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[1][1]},
{BUNNY_SWIPE_R1 + 1, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[1][2]},
{BUNNY_SWIPE_R1 + 1, 0 | SF_QUICK_CALL, InitBunnySlash, &s_BunnySwipe[1][3]},
{BUNNY_SWIPE_R1 + 2, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[1][4]},
{BUNNY_SWIPE_R1 + 3, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[1][5]},
{BUNNY_SWIPE_R1 + 3, 0 | SF_QUICK_CALL, InitBunnySlash, &s_BunnySwipe[1][6]},
{BUNNY_SWIPE_R1 + 3, 0 | SF_QUICK_CALL, InitActorDecide, &s_BunnySwipe[1][7]},
{BUNNY_SWIPE_R1 + 3, BUNNY_SWIPE_RATE, DoBunnyMove, &s_BunnySwipe[1][7]},
},
{
{BUNNY_SWIPE_R2 + 0, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[2][1]},
{BUNNY_SWIPE_R2 + 1, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[2][2]},
{BUNNY_SWIPE_R2 + 1, 0 | SF_QUICK_CALL, InitBunnySlash, &s_BunnySwipe[2][3]},
{BUNNY_SWIPE_R2 + 2, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[2][4]},
{BUNNY_SWIPE_R2 + 3, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[2][5]},
{BUNNY_SWIPE_R2 + 3, 0 | SF_QUICK_CALL, InitBunnySlash, &s_BunnySwipe[2][6]},
{BUNNY_SWIPE_R2 + 3, 0 | SF_QUICK_CALL, InitActorDecide, &s_BunnySwipe[2][7]},
{BUNNY_SWIPE_R2 + 3, BUNNY_SWIPE_RATE, DoBunnyMove, &s_BunnySwipe[2][7]},
},
{
{BUNNY_SWIPE_R3 + 0, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[3][1]},
{BUNNY_SWIPE_R3 + 1, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[3][2]},
{BUNNY_SWIPE_R3 + 1, 0 | SF_QUICK_CALL, InitBunnySlash, &s_BunnySwipe[3][3]},
{BUNNY_SWIPE_R3 + 2, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[3][4]},
{BUNNY_SWIPE_R3 + 3, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[3][5]},
{BUNNY_SWIPE_R3 + 3, 0 | SF_QUICK_CALL, InitBunnySlash, &s_BunnySwipe[3][6]},
{BUNNY_SWIPE_R3 + 3, 0 | SF_QUICK_CALL, InitActorDecide, &s_BunnySwipe[3][7]},
{BUNNY_SWIPE_R3 + 3, BUNNY_SWIPE_RATE, DoBunnyMove, &s_BunnySwipe[3][7]},
},
{
{BUNNY_SWIPE_R4 + 0, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[4][1]},
{BUNNY_SWIPE_R4 + 1, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[4][2]},
{BUNNY_SWIPE_R4 + 1, 0 | SF_QUICK_CALL, InitBunnySlash, &s_BunnySwipe[4][3]},
{BUNNY_SWIPE_R4 + 2, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[4][4]},
{BUNNY_SWIPE_R4 + 3, BUNNY_SWIPE_RATE, NullBunny, &s_BunnySwipe[4][5]},
{BUNNY_SWIPE_R4 + 3, 0 | SF_QUICK_CALL, InitBunnySlash, &s_BunnySwipe[4][6]},
{BUNNY_SWIPE_R4 + 3, 0 | SF_QUICK_CALL, InitActorDecide, &s_BunnySwipe[4][7]},
{BUNNY_SWIPE_R4 + 3, BUNNY_SWIPE_RATE, DoBunnyMove, &s_BunnySwipe[4][7]},
}
};
STATEp sg_BunnySwipe[] =
{
&s_BunnySwipe[0][0],
&s_BunnySwipe[1][0],
&s_BunnySwipe[2][0],
&s_BunnySwipe[3][0],
&s_BunnySwipe[4][0]
};
//////////////////////
//
// BUNNY HEART - show players heart
//
//////////////////////
#define BUNNY_HEART_RATE 14
ANIMATOR DoBunnyStandKill;
STATE s_BunnyHeart[5][4] =
{
{
{BUNNY_SWIPE_R0 + 0, BUNNY_HEART_RATE, DoBunnyStandKill, &s_BunnyHeart[0][0]},
},
{
{BUNNY_SWIPE_R1 + 0, BUNNY_HEART_RATE, DoBunnyStandKill, &s_BunnyHeart[1][0]},
},
{
{BUNNY_SWIPE_R2 + 0, BUNNY_HEART_RATE, DoBunnyStandKill, &s_BunnyHeart[2][0]},
},
{
{BUNNY_SWIPE_R3 + 0, BUNNY_HEART_RATE, DoBunnyStandKill, &s_BunnyHeart[3][0]},
},
{
{BUNNY_SWIPE_R4 + 0, BUNNY_HEART_RATE, DoBunnyStandKill, &s_BunnyHeart[4][0]},
}
};
STATEp sg_BunnyHeart[] =
{
&s_BunnyHeart[0][0],
&s_BunnyHeart[1][0],
&s_BunnyHeart[2][0],
&s_BunnyHeart[3][0],
&s_BunnyHeart[4][0]
};
//////////////////////
//
// BUNNY PAIN
//
//////////////////////
#define BUNNY_PAIN_RATE 38
ANIMATOR DoBunnyPain;
STATE s_BunnyPain[5][1] =
{
{
{BUNNY_SWIPE_R0 + 0, BUNNY_PAIN_RATE, DoBunnyPain, &s_BunnyPain[0][0]},
},
{
{BUNNY_SWIPE_R0 + 0, BUNNY_PAIN_RATE, DoBunnyPain, &s_BunnyPain[1][0]},
},
{
{BUNNY_SWIPE_R0 + 0, BUNNY_PAIN_RATE, DoBunnyPain, &s_BunnyPain[2][0]},
},
{
{BUNNY_SWIPE_R0 + 0, BUNNY_PAIN_RATE, DoBunnyPain, &s_BunnyPain[3][0]},
},
{
{BUNNY_SWIPE_R0 + 0, BUNNY_PAIN_RATE, DoBunnyPain, &s_BunnyPain[4][0]},
}
};
STATEp sg_BunnyPain[] =
{
&s_BunnyPain[0][0],
&s_BunnyPain[1][0],
&s_BunnyPain[2][0],
&s_BunnyPain[3][0],
&s_BunnyPain[4][0]
};
//////////////////////
//
// BUNNY JUMP
//
//////////////////////
#define BUNNY_JUMP_RATE 25
STATE s_BunnyJump[5][6] =
{
{
{BUNNY_RUN_R0 + 1, BUNNY_JUMP_RATE, DoBunnyMoveJump, &s_BunnyJump[0][1]},
{BUNNY_RUN_R0 + 2, BUNNY_JUMP_RATE, DoBunnyMoveJump, &s_BunnyJump[0][1]},
},
{
{BUNNY_RUN_R1 + 1, BUNNY_JUMP_RATE, DoBunnyMoveJump, &s_BunnyJump[1][1]},
{BUNNY_RUN_R1 + 2, BUNNY_JUMP_RATE, DoBunnyMoveJump, &s_BunnyJump[1][1]},
},
{
{BUNNY_RUN_R2 + 1, BUNNY_JUMP_RATE, DoBunnyMoveJump, &s_BunnyJump[2][1]},
{BUNNY_RUN_R2 + 2, BUNNY_JUMP_RATE, DoBunnyMoveJump, &s_BunnyJump[2][1]},
},
{
{BUNNY_RUN_R3 + 1, BUNNY_JUMP_RATE, DoBunnyMoveJump, &s_BunnyJump[3][1]},
{BUNNY_RUN_R3 + 2, BUNNY_JUMP_RATE, DoBunnyMoveJump, &s_BunnyJump[3][1]},
},
{
{BUNNY_RUN_R4 + 1, BUNNY_JUMP_RATE, DoBunnyMoveJump, &s_BunnyJump[4][1]},
{BUNNY_RUN_R4 + 2, BUNNY_JUMP_RATE, DoBunnyMoveJump, &s_BunnyJump[4][1]},
}
};
STATEp sg_BunnyJump[] =
{
&s_BunnyJump[0][0],
&s_BunnyJump[1][0],
&s_BunnyJump[2][0],
&s_BunnyJump[3][0],
&s_BunnyJump[4][0]
};
//////////////////////
//
// BUNNY FALL
//
//////////////////////
#define BUNNY_FALL_RATE 25
STATE s_BunnyFall[5][6] =
{
{
{BUNNY_RUN_R0 + 3, BUNNY_FALL_RATE, DoBunnyMoveJump, &s_BunnyFall[0][0]},
},
{
{BUNNY_RUN_R1 + 3, BUNNY_FALL_RATE, DoBunnyMoveJump, &s_BunnyFall[1][0]},
},
{
{BUNNY_RUN_R2 + 3, BUNNY_FALL_RATE, DoBunnyMoveJump, &s_BunnyFall[2][0]},
},
{
{BUNNY_RUN_R3 + 3, BUNNY_FALL_RATE, DoBunnyMoveJump, &s_BunnyFall[3][0]},
},
{
{BUNNY_RUN_R4 + 3, BUNNY_FALL_RATE, DoBunnyMoveJump, &s_BunnyFall[4][0]},
}
};
STATEp sg_BunnyFall[] =
{
&s_BunnyFall[0][0],
&s_BunnyFall[1][0],
&s_BunnyFall[2][0],
&s_BunnyFall[3][0],
&s_BunnyFall[4][0]
};
//////////////////////
//
// BUNNY JUMP ATTACK
//
//////////////////////
#define BUNNY_JUMP_ATTACK_RATE 35
int DoBunnyBeginJumpAttack(short SpriteNum);
STATE s_BunnyJumpAttack[5][6] =
{
{
{BUNNY_RUN_R0 + 1, BUNNY_JUMP_ATTACK_RATE, NullBunny, &s_BunnyJumpAttack[0][1]},
{BUNNY_RUN_R0 + 1, 0 | SF_QUICK_CALL, DoBunnyBeginJumpAttack, &s_BunnyJumpAttack[0][2]},
{BUNNY_RUN_R0 + 2, BUNNY_JUMP_ATTACK_RATE, DoBunnyMoveJump, &s_BunnyJumpAttack[0][2]},
},
{
{BUNNY_RUN_R1 + 1, BUNNY_JUMP_ATTACK_RATE, NullBunny, &s_BunnyJumpAttack[1][1]},
{BUNNY_RUN_R1 + 1, 0 | SF_QUICK_CALL, DoBunnyBeginJumpAttack, &s_BunnyJumpAttack[1][2]},
{BUNNY_RUN_R1 + 2, BUNNY_JUMP_ATTACK_RATE, DoBunnyMoveJump, &s_BunnyJumpAttack[1][2]},
},
{
{BUNNY_RUN_R2 + 1, BUNNY_JUMP_ATTACK_RATE, NullBunny, &s_BunnyJumpAttack[2][1]},
{BUNNY_RUN_R2 + 1, 0 | SF_QUICK_CALL, DoBunnyBeginJumpAttack, &s_BunnyJumpAttack[2][2]},
{BUNNY_RUN_R2 + 2, BUNNY_JUMP_ATTACK_RATE, DoBunnyMoveJump, &s_BunnyJumpAttack[2][2]},
},
{
{BUNNY_RUN_R3 + 1, BUNNY_JUMP_ATTACK_RATE, NullBunny, &s_BunnyJumpAttack[3][1]},
{BUNNY_RUN_R3 + 1, 0 | SF_QUICK_CALL, DoBunnyBeginJumpAttack, &s_BunnyJumpAttack[3][2]},
{BUNNY_RUN_R3 + 2, BUNNY_JUMP_ATTACK_RATE, DoBunnyMoveJump, &s_BunnyJumpAttack[3][2]},
},
{
{BUNNY_RUN_R4 + 1, BUNNY_JUMP_ATTACK_RATE, NullBunny, &s_BunnyJumpAttack[4][1]},
{BUNNY_RUN_R4 + 1, 0 | SF_QUICK_CALL, DoBunnyBeginJumpAttack, &s_BunnyJumpAttack[4][2]},
{BUNNY_RUN_R4 + 2, BUNNY_JUMP_ATTACK_RATE, DoBunnyMoveJump, &s_BunnyJumpAttack[4][2]},
}
};
STATEp sg_BunnyJumpAttack[] =
{
&s_BunnyJumpAttack[0][0],
&s_BunnyJumpAttack[1][0],
&s_BunnyJumpAttack[2][0],
&s_BunnyJumpAttack[3][0],
&s_BunnyJumpAttack[4][0]
};
//////////////////////
//
// BUNNY DIE
//
//////////////////////
#define BUNNY_DIE_RATE 16
ANIMATOR BunnySpew;
STATE s_BunnyDie[] =
{
{BUNNY_DIE + 0, BUNNY_DIE_RATE, NullBunny, &s_BunnyDie[1]},
{BUNNY_DIE + 0, SF_QUICK_CALL, BunnySpew, &s_BunnyDie[2]},
{BUNNY_DIE + 1, BUNNY_DIE_RATE, NullBunny, &s_BunnyDie[3]},
{BUNNY_DIE + 2, BUNNY_DIE_RATE, NullBunny, &s_BunnyDie[4]},
{BUNNY_DIE + 2, BUNNY_DIE_RATE, NullBunny, &s_BunnyDie[5]},
{BUNNY_DEAD, BUNNY_DIE_RATE, DoActorDebris, &s_BunnyDie[5]},
};
#define BUNNY_DEAD_RATE 8
STATE s_BunnyDead[] =
{
{BUNNY_DIE + 0, BUNNY_DEAD_RATE, NullAnimator, &s_BunnyDie[1]},
{BUNNY_DIE + 0, SF_QUICK_CALL, BunnySpew, &s_BunnyDie[2]},
{BUNNY_DIE + 1, BUNNY_DEAD_RATE, NullAnimator, &s_BunnyDead[3]},
{BUNNY_DIE + 2, BUNNY_DEAD_RATE, NullAnimator, &s_BunnyDead[4]},
{BUNNY_DEAD, SF_QUICK_CALL, QueueFloorBlood, &s_BunnyDead[5]},
{BUNNY_DEAD, BUNNY_DEAD_RATE, DoActorDebris, &s_BunnyDead[5]},
};
STATEp sg_BunnyDie[] =
{
s_BunnyDie
};
STATEp sg_BunnyDead[] =
{
s_BunnyDead
};
STATE s_BunnyDeathJump[] =
{
{BUNNY_DIE + 0, BUNNY_DIE_RATE, DoActorDeathMove, &s_BunnyDeathJump[0]}
};
STATE s_BunnyDeathFall[] =
{
{BUNNY_DIE + 1, BUNNY_DIE_RATE, DoActorDeathMove, &s_BunnyDeathFall[0]}
};
STATEp sg_BunnyDeathJump[] =
{
s_BunnyDeathJump
};
STATEp sg_BunnyDeathFall[] =
{
s_BunnyDeathFall
};
/*
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 BunnyActionSet =
{
sg_BunnyStand,
sg_BunnyRun,
sg_BunnyJump,
sg_BunnyFall,
NULL, // sg_BunnyCrawl,
NULL, // sg_BunnySwim,
NULL, // sg_BunnyFly,
NULL, // sg_BunnyRise,
NULL, // sg_BunnySit,
NULL, // sg_BunnyLook,
NULL, // climb
sg_BunnyPain,
sg_BunnyDie,
NULL,
sg_BunnyDead,
sg_BunnyDeathJump,
sg_BunnyDeathFall,
{NULL},
{1024},
{NULL},
{1024},
{sg_BunnyHeart, sg_BunnyRun},
NULL,
NULL
};
ACTOR_ACTION_SET BunnyWhiteActionSet =
{
sg_BunnyStand,
sg_BunnyRun,
sg_BunnyJump,
sg_BunnyFall,
NULL, // sg_BunnyCrawl,
NULL, // sg_BunnySwim,
NULL, // sg_BunnyFly,
NULL, // sg_BunnyRise,
NULL, // sg_BunnySit,
NULL, // sg_BunnyLook,
NULL, // climb
sg_BunnyPain, // pain
sg_BunnyDie,
NULL,
sg_BunnyDead,
sg_BunnyDeathJump,
sg_BunnyDeathFall,
{sg_BunnySwipe},
{1024},
// {sg_BunnyJumpAttack, sg_BunnySwipe},
// {800, 1024},
{sg_BunnySwipe},
{1024},
{sg_BunnyHeart, sg_BunnySwipe},
NULL,
NULL
};
int
SetupBunny(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, BUNNY_RUN_R0, s_BunnyRun[0]);
u->Health = 10;
}
Bunny_Count++;
//if(Bunny_Count > 20)
// {
// KillSprite(SpriteNum);
// Bunny_Count--;
// return(0);
// }
ChangeState(SpriteNum, s_BunnyRun[0]);
u->StateEnd = s_BunnyDie;
u->Rot = sg_BunnyRun;
//sp->xrepeat = 64;
//sp->yrepeat = 64;
u->ShellNum = 0; // Not Pregnant right now
u->FlagOwner = 0;
sp->clipdist = (150) >> 2;
if (sp->pal == PALETTE_PLAYER1)
{
EnemyDefaults(SpriteNum, &BunnyWhiteActionSet, &WhiteBunnyPersonality);
u->Attrib = &WhiteBunnyAttrib;
sp->xrepeat = 96;
sp->yrepeat = 90;
sp->clipdist = 200>>2;
if (!TEST(sp->cstat, CSTAT_SPRITE_RESTORE))
u->Health = 60;
}
else if (sp->pal == PALETTE_PLAYER8) // Male Rabbit
{
EnemyDefaults(SpriteNum, &BunnyActionSet, &BunnyPersonality);
u->Attrib = &BunnyAttrib;
//sp->xrepeat = 76;
//sp->yrepeat = 70;
//sp->shade = 0; // darker
if (!TEST(sp->cstat, CSTAT_SPRITE_RESTORE))
u->Health = 20;
u->Flag1 = 0;
}
else
{
// Female Rabbit
EnemyDefaults(SpriteNum, &BunnyActionSet, &BunnyPersonality);
u->Attrib = &BunnyAttrib;
u->spal = sp->pal = PALETTE_PLAYER0;
u->Flag1 = SEC(5);
//sp->shade = 0; // darker
}
DoActorSetSpeed(SpriteNum, FAST_SPEED);
SET(u->Flags, SPR_XFLIP_TOGGLE);
u->zclip = Z(16);
u->floor_dist = Z(8);
u->ceiling_dist = Z(8);
u->lo_step = Z(16);
return 0;
}
int
GetBunnyJumpHeight(short jump_speed, short jump_grav)
{
int jump_iterations;
int height;
jump_speed = labs(jump_speed);
jump_iterations = jump_speed / (jump_grav * ACTORMOVETICS);
height = jump_speed * jump_iterations * ACTORMOVETICS;
height = DIV256(height);
return DIV2(height);
}
int
PickBunnyJumpSpeed(short SpriteNum, int pix_height)
{
SPRITEp sp = &sprite[SpriteNum];
USERp u = User[SpriteNum];
ASSERT(pix_height < 128);
u->jump_speed = -600;
u->jump_grav = 8;
while (TRUE)
{
if (GetBunnyJumpHeight(u->jump_speed, u->jump_grav) > pix_height + 20)
break;
u->jump_speed -= 100;
ASSERT(u->jump_speed > -3000);
}
return u->jump_speed;
}
//
// JUMP ATTACK
//
int
DoBunnyBeginJumpAttack(short SpriteNum)
{
SPRITEp sp = &sprite[SpriteNum];
USERp u = User[SpriteNum];
SPRITEp psp = User[SpriteNum]->tgt_sp;
int dist;
int CanSeePlayer(short SpriteNum);
short tang;
#define RANDOM_NEG(x) (RANDOM_P2((x)<<1) - (x))
tang = getangle(psp->x - sp->x, psp->y - sp->y);
if (move_sprite(SpriteNum, sintable[NORM_ANGLE(tang+512)] >> 7, sintable[tang] >> 7,
0L, u->ceiling_dist, u->floor_dist, CLIPMASK_ACTOR, ACTORMOVETICS))
sp->ang = NORM_ANGLE(sp->ang + 1024) + (RANDOM_NEG(256 << 6) >> 6);
else
sp->ang = NORM_ANGLE(tang + (RANDOM_NEG(256 << 6) >> 6));
DoActorSetSpeed(SpriteNum, FAST_SPEED);
//u->jump_speed = -800;
PickJumpMaxSpeed(SpriteNum, -400); // was -800
SET(u->Flags, SPR_JUMPING);
RESET(u->Flags, SPR_FALLING);
// set up individual actor jump gravity
u->jump_grav = 17; // was 8
// if I didn't do this here they get stuck in the air sometimes
DoActorZrange(SpriteNum);
DoJump(SpriteNum);
return 0;
}
int
DoBunnyMoveJump(short SpriteNum)
{
SPRITEp sp = &sprite[SpriteNum];
USERp u = User[SpriteNum];
if (TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
{
int nx, ny;
// Move while jumping
nx = sp->xvel * (int) sintable[NORM_ANGLE(sp->ang + 512)] >> 14;
ny = sp->xvel * (int) sintable[sp->ang] >> 14;
move_actor(SpriteNum, nx, ny, 0L);
if (TEST(u->Flags, SPR_JUMPING))
DoActorJump(SpriteNum);
else
DoActorFall(SpriteNum);
}
DoActorZrange(SpriteNum);
if (!TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
{
// if (DoBunnyQuickJump(SpriteNum))
// return (0);
InitActorDecide(SpriteNum);
}
return 0;
}
int
DoPickCloseBunny(short SpriteNum)
{
USERp u = User[SpriteNum],tu;
SPRITEp sp = &sprite[SpriteNum],tsp;
int dist, near_dist = 1000, a,b,c;
short i, nexti;
//short BunnyCount=0, Bunny_Result = -1;
// if actor can still see the player
int look_height = SPRITEp_TOS(sp);
SWBOOL ICanSee = FALSE;
TRAVERSE_SPRITE_STAT(headspritestat[STAT_ENEMY], i, nexti)
{
tsp = &sprite[i];
tu = User[i];
if (sp == tsp) continue;
if (tu->ID != BUNNY_RUN_R0) continue;
DISTANCE(tsp->x, tsp->y, sp->x, sp->y, dist, a, b, c);
if (dist > near_dist) continue;
ICanSee = FAFcansee(sp->x, sp->y, look_height, sp->sectnum, tsp->x, tsp->y, SPRITEp_UPPER(tsp), tsp->sectnum);
if (ICanSee && dist < near_dist && tu->ID == BUNNY_RUN_R0)
{
near_dist = dist;
u->tgt_sp = u->lo_sp = tsp;
//Bunny_Result = i;
return i;
}
}
return -1;
}
int
DoBunnyQuickJump(short SpriteNum)
{
SPRITEp sp = &sprite[SpriteNum];
USERp u = User[SpriteNum];
if (u->spal != PALETTE_PLAYER8) return FALSE;
if (!u->lo_sp && u->spal == PALETTE_PLAYER8 && MoveSkip4)
DoPickCloseBunny(SpriteNum);
// Random Chance of like sexes fighting
if (u->lo_sp)
{
short hit_sprite = u->lo_sp - sprite;
SPRITEp tsp = u->lo_sp;
USERp tu = User[hit_sprite];
if (!tu || tu->ID != BUNNY_RUN_R0) return FALSE;
// Not mature enough yet
if (sp->xrepeat != 64 || sp->yrepeat != 64) return FALSE;
if (tsp->xrepeat != 64 || tsp->yrepeat != 64) return FALSE;
// Kill a rival
// Only males fight
if (tu->spal == sp->pal && RANDOM_RANGE(1000) > 995)
{
if (u->spal == PALETTE_PLAYER8 && tu->spal == PALETTE_PLAYER8)
{
PlaySound(DIGI_BUNNYATTACK, sp, v3df_follow);
PlaySound(DIGI_BUNNYDIE2, tsp, v3df_follow);
tu->Health = 0;
// Blood fountains
InitBloodSpray(hit_sprite,TRUE,-1);
if (SpawnShrap(hit_sprite, SpriteNum))
{
SetSuicide(hit_sprite);
}
else
DoActorDie(hit_sprite, SpriteNum);
Bunny_Count--; // Bunny died
u->lo_sp = NULL;
return TRUE;
}
}
}
// Get layed!
if (u->lo_sp && u->spal == PALETTE_PLAYER8) // Only males check this
{
short hit_sprite = u->lo_sp - sprite;
SPRITEp tsp = u->lo_sp;
USERp tu = User[hit_sprite];
if (!tu || tu->ID != BUNNY_RUN_R0) return FALSE;
// Not mature enough to mate yet
if (sp->xrepeat != 64 || sp->yrepeat != 64) return FALSE;
if (tsp->xrepeat != 64 || tsp->yrepeat != 64) return FALSE;
if (tu->ShellNum <= 0 && tu->WaitTics <= 0 && u->WaitTics <= 0)
{
if (TEST(tsp->extra, SPRX_PLAYER_OR_ENEMY))
{
PLAYERp pp = NULL;
if (RANDOM_RANGE(1000) < 995 && tu->spal != PALETTE_PLAYER0) return FALSE;
DoActorPickClosePlayer(SpriteNum);
if (User[u->tgt_sp-sprite]->PlayerP)
pp = User[u->tgt_sp-sprite]->PlayerP;
if (tu->spal != PALETTE_PLAYER0)
{
if (tu->Flag1 > 0) return FALSE;
tu->FlagOwner = 1; // FAG!
tu->Flag1 = SEC(10);
if (pp)
{
short choose_snd;
int fagsnds[] = {DIGI_FAGRABBIT1,DIGI_FAGRABBIT2,DIGI_FAGRABBIT3};
if (pp == Player+myconnectindex)
{
choose_snd = STD_RANDOM_RANGE(2<<8)>>8;
if (FAFcansee(sp->x,sp->y,SPRITEp_TOS(sp),sp->sectnum,pp->posx, pp->posy, pp->posz, pp->cursectnum) && FACING(sp, u->tgt_sp))
PlayerSound(fagsnds[choose_snd], v3df_doppler|v3df_follow|v3df_dontpan,pp);
}
}
}
else
{
if (pp && RANDOM_RANGE(1000) > 200)
{
short choose_snd;
int straightsnds[] = {DIGI_RABBITHUMP1,DIGI_RABBITHUMP2,
DIGI_RABBITHUMP3,DIGI_RABBITHUMP4};
if (pp == Player+myconnectindex)
{
choose_snd = STD_RANDOM_RANGE(3<<8)>>8;
if (FAFcansee(sp->x,sp->y,SPRITEp_TOS(sp),sp->sectnum,pp->posx, pp->posy, pp->posz, pp->cursectnum) && FACING(sp, u->tgt_sp))
PlayerSound(straightsnds[choose_snd], v3df_doppler|v3df_follow|v3df_dontpan,pp);
}
}
}
sp->x = tsp->x; // Mount up little bunny
sp->y = tsp->y;
sp->ang = tsp->ang;
sp->ang = NORM_ANGLE(sp->ang + 1024);
HelpMissileLateral(SpriteNum, 2000L);
sp->ang = tsp->ang;
u->Vis = sp->ang; // Remember angles for later
tu->Vis = tsp->ang;
NewStateGroup(SpriteNum, sg_BunnyScrew);
NewStateGroup(hit_sprite, sg_BunnyScrew);
if (adult_lockout || Global_PLock)
{
SET(sp->cstat, CSTAT_SPRITE_INVISIBLE); // Turn em' invisible
SET(tsp->cstat, CSTAT_SPRITE_INVISIBLE); // Turn em' invisible
}
u->WaitTics = tu->WaitTics = SEC(10); // Mate for this long
return TRUE;
}
}
}
return FALSE;
}
int
NullBunny(short SpriteNum)
{
SPRITEp sp = &sprite[SpriteNum];
USERp u = User[SpriteNum];
if (TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
{
if (TEST(u->Flags, SPR_JUMPING))
DoActorJump(SpriteNum);
else
DoActorFall(SpriteNum);
}
// stay on floor unless doing certain things
if (!TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
KeepActorOnFloor(SpriteNum);
if (TEST(u->Flags,SPR_SLIDING))
DoActorSlide(SpriteNum);
DoActorSectorDamage(SpriteNum);
return 0;
}
int DoBunnyPain(short SpriteNum)
{
SPRITEp sp = &sprite[SpriteNum];
USERp u = User[SpriteNum];
NullBunny(SpriteNum);
if ((u->WaitTics -= ACTORMOVETICS) <= 0)
InitActorDecide(SpriteNum);
return 0;
}
int DoBunnyRipHeart(short SpriteNum)
{
SPRITEp sp = &sprite[SpriteNum];
USERp u = User[SpriteNum];
SPRITEp tsp = u->tgt_sp;
NewStateGroup(SpriteNum, sg_BunnyHeart);
u->WaitTics = 6 * 120;
// player face bunny
tsp->ang = getangle(sp->x - tsp->x, sp->y - tsp->y);
return 0;
}
int DoBunnyStandKill(short SpriteNum)
{
SPRITEp sp = &sprite[SpriteNum];
USERp u = User[SpriteNum];
NullBunny(SpriteNum);
// Growl like the bad ass bunny you are!
if (RANDOM_RANGE(1000) > 800)
PlaySound(DIGI_BUNNYATTACK, sp, v3df_none);
if ((u->WaitTics -= ACTORMOVETICS) <= 0)
NewStateGroup(SpriteNum, sg_BunnyRun);
return 0;
}
void BunnyHatch(short Weapon)
{
SPRITEp wp = &sprite[Weapon];
USERp wu = User[Weapon];
short New,i;
SPRITEp np;
USERp nu;
#define MAX_BUNNYS 1
short rip_ang[MAX_BUNNYS];
rip_ang[0] = RANDOM_P2(2048);
for (i = 0; i < MAX_BUNNYS; i++)
{
New = COVERinsertsprite(wp->sectnum, STAT_DEFAULT);
np = &sprite[New];
memset(np,0,sizeof(SPRITE));
np->sectnum = wp->sectnum;
np->statnum = STAT_DEFAULT;
np->x = wp->x;
np->y = wp->y;
np->z = wp->z;
np->owner = -1;
np->xrepeat = 30; // Baby size
np->yrepeat = 24;
np->ang = rip_ang[i];
np->pal = 0;
SetupBunny(New);
nu = User[New];
np->shade = wp->shade;
// make immediately active
SET(nu->Flags, SPR_ACTIVE);
if (RANDOM_RANGE(1000) > 500) // Boy or Girl?
nu->spal = np->pal = PALETTE_PLAYER0; // Girl
else
{
nu->spal = np->pal = PALETTE_PLAYER8; // Boy
// Oops, mommy died giving birth to a boy
if (RANDOM_RANGE(1000) > 500)
{
wu->Health = 0;
Bunny_Count--; // Bunny died
// Blood fountains
InitBloodSpray(Weapon,TRUE,-1);
if (SpawnShrap(Weapon, New))
{
SetSuicide(Weapon);
}
else
DoActorDie(Weapon, New);
}
}
nu->ShellNum = 0; // Not Pregnant right now
NewStateGroup(New, nu->ActorActionSet->Jump);
nu->ActorActionFunc = DoActorMoveJump;
DoActorSetSpeed(New, FAST_SPEED);
PickJumpMaxSpeed(New, -600);
SET(nu->Flags, SPR_JUMPING);
RESET(nu->Flags, SPR_FALLING);
nu->jump_grav = 8;
// if I didn't do this here they get stuck in the air sometimes
DoActorZrange(New);
DoActorJump(New);
}
}
int BunnyHatch2(short Weapon)
{
SPRITEp wp = &sprite[Weapon];
USERp wu = User[Weapon];
short New,i;
SPRITEp np;
USERp nu;
New = COVERinsertsprite(wp->sectnum, STAT_DEFAULT);
np = &sprite[New];
memset(np,0,sizeof(SPRITE));
np->sectnum = wp->sectnum;
np->statnum = STAT_DEFAULT;
np->x = wp->x;
np->y = wp->y;
np->z = wp->z;
np->owner = -1;
np->xrepeat = 30; // Baby size
np->yrepeat = 24;
np->ang = RANDOM_P2(2048);
np->pal = 0;
SetupBunny(New);
nu = User[New];
np->shade = wp->shade;
// make immediately active
SET(nu->Flags, SPR_ACTIVE);
if (RANDOM_RANGE(1000) > 500) // Boy or Girl?
{
nu->spal = np->pal = PALETTE_PLAYER0; // Girl
nu->Flag1 = SEC(5);
}
else
{
nu->spal = np->pal = PALETTE_PLAYER8; // Boy
nu->Flag1 = 0;
}
nu->ShellNum = 0; // Not Pregnant right now
NewStateGroup(New, nu->ActorActionSet->Jump);
nu->ActorActionFunc = DoActorMoveJump;
DoActorSetSpeed(New, FAST_SPEED);
if (TEST_BOOL3(wp))
{
PickJumpMaxSpeed(New, -600-RANDOM_RANGE(600));
np->xrepeat = np->yrepeat = 64;
np->xvel = 150 + RANDOM_RANGE(1000);
nu->Health = 1; // Easy to pop. Like shootn' skeet.
np->ang -= RANDOM_RANGE(128);
np->ang += RANDOM_RANGE(128);
}
else
PickJumpMaxSpeed(New, -600);
SET(nu->Flags, SPR_JUMPING);
RESET(nu->Flags, SPR_FALLING);
nu->jump_grav = 8;
nu->FlagOwner = 0;
nu->active_range = 75000; // Set it far
// if I didn't do this here they get stuck in the air sometimes
DoActorZrange(New);
DoActorJump(New);
return New;
}
int
DoBunnyMove(short SpriteNum)
{
SPRITEp sp = &sprite[SpriteNum];
USERp u = User[SpriteNum];
// Parental lock crap
if (TEST(sp->cstat, CSTAT_SPRITE_INVISIBLE))
RESET(sp->cstat, CSTAT_SPRITE_INVISIBLE); // Turn em' back on
// Sometimes they just won't die!
if (u->Health <= 0)
SetSuicide(SpriteNum);
if (u->scale_speed)
{
DoScaleSprite(SpriteNum);
}
if (TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
{
if (TEST(u->Flags, SPR_JUMPING))
DoActorJump(SpriteNum);
else
DoActorFall(SpriteNum);
}
// if on a player/enemy sprite jump quickly
if (!TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
{
DoBunnyQuickJump(SpriteNum);
}
if (TEST(u->Flags, SPR_SLIDING))
DoActorSlide(SpriteNum);
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);
DoActorSectorDamage(SpriteNum);
if (RANDOM_RANGE(1000) > 985 && sp->pal != PALETTE_PLAYER1 && u->track < 0)
{
switch (sector[sp->sectnum].floorpicnum)
{
case 153:
case 154:
case 193:
case 219:
case 2636:
case 2689:
case 3561:
case 3562:
case 3563:
case 3564:
NewStateGroup(SpriteNum,sg_BunnyStand);
break;
default:
sp->ang = NORM_ANGLE(RANDOM_RANGE(2048 << 6) >> 6);
u->jump_speed = -350;
DoActorBeginJump(SpriteNum);
u->ActorActionFunc = DoActorMoveJump;
break;
}
}
return 0;
}
int
BunnySpew(short SpriteNum)
{
//InitBloodSpray(SpriteNum,TRUE,-1);
InitBloodSpray(SpriteNum,TRUE,-1);
return 0;
}
int
DoBunnyEat(short SpriteNum)
{
SPRITEp sp = &sprite[SpriteNum];
USERp u = User[SpriteNum];
if (TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
{
if (TEST(u->Flags, SPR_JUMPING))
DoActorJump(SpriteNum);
else
DoActorFall(SpriteNum);
}
// if on a player/enemy sprite jump quickly
if (!TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
{
DoBunnyQuickJump(SpriteNum);
}
if (TEST(u->Flags, SPR_SLIDING))
DoActorSlide(SpriteNum);
// stay on floor unless doing certain things
if (!TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
KeepActorOnFloor(SpriteNum);
DoActorSectorDamage(SpriteNum);
switch (sector[sp->sectnum].floorpicnum)
{
case 153:
case 154:
case 193:
case 219:
case 2636:
case 2689:
case 3561:
case 3562:
case 3563:
case 3564:
if (RANDOM_RANGE(1000) > 970)
NewStateGroup(SpriteNum,sg_BunnyRun);
break;
default:
NewStateGroup(SpriteNum,sg_BunnyRun);
break;
}
return 0;
}
int
DoBunnyScrew(short SpriteNum)
{
SPRITEp sp = &sprite[SpriteNum];
USERp u = User[SpriteNum];
int dist;
if (TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
{
if (TEST(u->Flags, SPR_JUMPING))
DoActorJump(SpriteNum);
else
DoActorFall(SpriteNum);
}
if (TEST(u->Flags, SPR_SLIDING))
DoActorSlide(SpriteNum);
// stay on floor unless doing certain things
if (!TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
KeepActorOnFloor(SpriteNum);
DoActorSectorDamage(SpriteNum);
if (RANDOM_RANGE(1000) > 990) // Bunny sex sounds
{
if (!adult_lockout && !Global_PLock)
PlaySound(DIGI_BUNNYATTACK, sp, v3df_follow);
}
u->WaitTics -= ACTORMOVETICS;
if ((u->FlagOwner || u->spal == PALETTE_PLAYER0) && u->WaitTics > 0) // Keep Girl still
NewStateGroup(SpriteNum,sg_BunnyScrew);
if (u->spal == PALETTE_PLAYER0 && u->WaitTics <= 0) // Female has baby
{
u->Flag1 = SEC(5); // Count down to babies
u->ShellNum = 1; // She's pregnant now
}
if (u->WaitTics <= 0)
{
RESET(sp->cstat, CSTAT_SPRITE_INVISIBLE); // Turn em' back on
u->FlagOwner = 0;
NewStateGroup(SpriteNum,sg_BunnyRun);
}
return 0;
}
int
DoBunnyGrowUp(short SpriteNum)
{
SPRITEp sp = &sprite[SpriteNum];
USERp u = User[SpriteNum];
if (sp->pal == PALETTE_PLAYER1) return 0; // Don't bother white bunnies
if ((u->Counter -= ACTORMOVETICS) <= 0)
{
if ((++sp->xrepeat) > 64) sp->xrepeat = 64;
if ((++sp->yrepeat) > 64) sp->yrepeat = 64;
u->Counter = 60;
}
// Don't go homo too much!
if (sp->pal != PALETTE_PLAYER0 && u->Flag1 > 0)
u->Flag1 -= ACTORMOVETICS;
// Gestation period for female rabbits
if (sp->pal == PALETTE_PLAYER0 && u->ShellNum > 0)
{
if ((u->Flag1 -= ACTORMOVETICS) <= 0)
{
if (Bunny_Count < 20)
{
PlaySound(DIGI_BUNNYDIE2, sp, v3df_follow);
BunnyHatch(SpriteNum); // Baby time
}
u->ShellNum = 0; // Not pregnent anymore
}
}
return 0;
}
#include "saveable.h"
static saveable_code saveable_bunny_code[] =
{
SAVE_CODE(SetupBunny),
SAVE_CODE(GetBunnyJumpHeight),
SAVE_CODE(PickBunnyJumpSpeed),
SAVE_CODE(DoBunnyBeginJumpAttack),
SAVE_CODE(DoBunnyMoveJump),
SAVE_CODE(DoPickCloseBunny),
SAVE_CODE(DoBunnyQuickJump),
SAVE_CODE(NullBunny),
SAVE_CODE(DoBunnyPain),
SAVE_CODE(DoBunnyRipHeart),
SAVE_CODE(DoBunnyStandKill),
SAVE_CODE(BunnyHatch),
SAVE_CODE(BunnyHatch2),
SAVE_CODE(DoBunnyMove),
SAVE_CODE(BunnySpew),
SAVE_CODE(DoBunnyEat),
SAVE_CODE(DoBunnyScrew),
SAVE_CODE(DoBunnyGrowUp),
};
static saveable_data saveable_bunny_data[] =
{
SAVE_DATA(BunnyBattle),
SAVE_DATA(BunnyOffense),
SAVE_DATA(BunnyBroadcast),
SAVE_DATA(BunnySurprised),
SAVE_DATA(BunnyEvasive),
SAVE_DATA(BunnyLostTarget),
SAVE_DATA(BunnyCloseRange),
SAVE_DATA(BunnyWander),
SAVE_DATA(WhiteBunnyPersonality),
SAVE_DATA(BunnyPersonality),
SAVE_DATA(WhiteBunnyAttrib),
SAVE_DATA(BunnyAttrib),
SAVE_DATA(s_BunnyRun),
SAVE_DATA(sg_BunnyRun),
SAVE_DATA(s_BunnyStand),
SAVE_DATA(sg_BunnyStand),
SAVE_DATA(s_BunnyScrew),
SAVE_DATA(sg_BunnyScrew),
SAVE_DATA(s_BunnySwipe),
SAVE_DATA(sg_BunnySwipe),
SAVE_DATA(s_BunnyHeart),
SAVE_DATA(sg_BunnyHeart),
SAVE_DATA(s_BunnyPain),
SAVE_DATA(sg_BunnyPain),
SAVE_DATA(s_BunnyJump),
SAVE_DATA(sg_BunnyJump),
SAVE_DATA(s_BunnyFall),
SAVE_DATA(sg_BunnyFall),
SAVE_DATA(s_BunnyJumpAttack),
SAVE_DATA(sg_BunnyJumpAttack),
SAVE_DATA(s_BunnyDie),
SAVE_DATA(sg_BunnyDie),
SAVE_DATA(s_BunnyDead),
SAVE_DATA(sg_BunnyDead),
SAVE_DATA(s_BunnyDeathJump),
SAVE_DATA(sg_BunnyDeathJump),
SAVE_DATA(s_BunnyDeathFall),
SAVE_DATA(sg_BunnyDeathFall),
SAVE_DATA(BunnyActionSet),
SAVE_DATA(BunnyWhiteActionSet),
};
saveable_module saveable_bunny =
{
// code
saveable_bunny_code,
SIZ(saveable_bunny_code),
// data
saveable_bunny_data,
SIZ(saveable_bunny_data)
};
END_SW_NS