Merge branch 'vada_flickies' into 'master'

Hardcoded VAda Flickies

Many thanks to MI for his help, even if he has sinful opinions on what the collection of creatures should be called. ;P

* Flickies are now handled via A_FlickySpawn instead of hardcoded in P_KillMobj, so there can be mobjtypes with MF_ENEMY which don't create flickies, or other mechanisms which can much easier.
* Added map header "FlickyList" (aka "AnimalList") parameter, which can either be set to:
    * A species (eg: "Rabbit" or "Bluebird", amongst 17 currently supported types in dehacked.c table FLICKYTYPES - including the seed from Sonic CD, which isn't limited to 'soniccd on' in the console now)
    * Any valid mobjtype that isn't MT_NULL (eg: "MT_FLICKY_GHOST")
    * A comma-seperated list of either of the above, up to 64 entries long (eg: "Cow,MT_FLICKY_SPIDER,Chicken")
    * "All" - sets behind-the-scenes stuff to use every 'normal' type of flicky in FLICKYTYPES (a distinction which can be utilised to hide secret level flickies where they wouldn't be appropriate for the main game)
    * "Demo" - sets behind-the-scenes stuff to use the five flickies closest to the species used in the game's long history.
    * "None" - prevents any flickies from spawning.

"Demo" is functionally the default value if you don't include a FlickyList parameter in the header at all.

Of note, a bunch of functions are now created:
* A_FlickySpawn - spawns flicky.
* A_FlickyAim - aims for area near target, but not directly on them - turns around when hitting wall
* A_FlickyFly -  flies/swims around target (calls A_FlickyAim)
* A_FlickySoar - hacky alternate fly (calls A_FlickyAim)
* A_FlickyCoast - slowing down before going off again
* A_FlickyHop - fracunit-scale precision for A_BunnyHop
* A_FlickyFlounder - A_FlickyHop with randomisation
* A_FlickyCheck - State-setter for falling, or being on-ground
* A_FlickyHeightCheck - State-setter for falling, or being below a certain height relative to target
* A_FlickyFlutter - A_FlickyCheck, but with a slow fall/movement (calls A_FlickyCheck and A_FlickyAim)

I don't need to enumerate the object types and states that have been added, do I?

Oh yeah, I also made it so get_mobjtype's failure value was MT_NULL and prohibited SOC from editing the properties of it to compensate.

IN ADDITION: Killed "soniccd" console command, since it made things more complicated and honestly being able to specify Sonic CD seeds in the level header is a better option.

See merge request !60
This commit is contained in:
Monster Iestyn 2017-01-08 17:36:25 -05:00
commit 3d07915be2
15 changed files with 1556 additions and 399 deletions

View File

@ -101,7 +101,6 @@ extern consvar_t cv_recycler;
extern consvar_t cv_itemfinder;
extern consvar_t cv_inttime, cv_advancemap, cv_playersforexit;
extern consvar_t cv_soniccd;
extern consvar_t cv_match_scoring;
extern consvar_t cv_overtime;
extern consvar_t cv_startinglives;

View File

@ -371,7 +371,9 @@ static void clear_levels(void)
// (no need to set num to 0, we're freeing the entire header shortly)
Z_Free(mapheaderinfo[i]->customopts);
P_DeleteFlickies(i);
P_DeleteGrades(i);
Z_Free(mapheaderinfo[i]);
mapheaderinfo[i] = NULL;
}
@ -990,6 +992,34 @@ static const struct {
{NULL, 0}
};
static const struct {
const char *name;
const mobjtype_t type;
} FLICKYTYPES[] = {
{"BLUEBIRD", MT_FLICKY_01},
{"RABBIT", MT_FLICKY_02},
{"CHICKEN", MT_FLICKY_03},
{"SEAL", MT_FLICKY_04},
{"PIG", MT_FLICKY_05},
{"CHIPMUNK", MT_FLICKY_06},
{"PENGUIN", MT_FLICKY_07},
{"FISH", MT_FLICKY_08},
{"RAM", MT_FLICKY_09},
{"PUFFIN", MT_FLICKY_10},
{"COW", MT_FLICKY_11},
{"RAT", MT_FLICKY_12},
{"BEAR", MT_FLICKY_13},
{"DOVE", MT_FLICKY_14},
{"CAT", MT_FLICKY_15},
{"CANARY", MT_FLICKY_16},
{"a", 0}, // End of normal flickies - a lower case character so will never fastcmp valid with uppercase tmp
//{"FLICKER", MT_FLICKER},
{"SEED", MT_SEED},
{NULL, 0}
};
#define MAXFLICKIES 64
static void readlevelheader(MYFILE *f, INT32 num)
{
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
@ -1088,8 +1118,82 @@ static void readlevelheader(MYFILE *f, INT32 num)
// Now go to uppercase
strupr(word2);
// List of flickies that are be freed in this map
if (fastcmp(word, "FLICKYLIST") || fastcmp(word, "ANIMALLIST"))
{
if (fastcmp(word2, "NONE"))
P_DeleteFlickies(num-1);
else if (fastcmp(word2, "DEMO"))
P_SetDemoFlickies(num-1);
else if (fastcmp(word2, "ALL"))
{
mobjtype_t tmpflickies[MAXFLICKIES];
for (mapheaderinfo[num-1]->numFlickies = 0;
((mapheaderinfo[num-1]->numFlickies < MAXFLICKIES) && FLICKYTYPES[mapheaderinfo[num-1]->numFlickies].type);
mapheaderinfo[num-1]->numFlickies++)
tmpflickies[mapheaderinfo[num-1]->numFlickies] = FLICKYTYPES[mapheaderinfo[num-1]->numFlickies].type;
if (mapheaderinfo[num-1]->numFlickies) // just in case...
{
size_t newsize = sizeof(mobjtype_t) * mapheaderinfo[num-1]->numFlickies;
mapheaderinfo[num-1]->flickies = Z_Realloc(mapheaderinfo[num-1]->flickies, newsize, PU_STATIC, NULL);
M_Memcpy(mapheaderinfo[num-1]->flickies, tmpflickies, newsize);
}
}
else
{
mobjtype_t tmpflickies[MAXFLICKIES];
mapheaderinfo[num-1]->numFlickies = 0;
tmp = strtok(word2,",");
// get up to the first MAXFLICKIES flickies
do {
if (mapheaderinfo[num-1]->numFlickies == MAXFLICKIES) // never going to get above that number
{
deh_warning("Level header %d: too many flickies\n", num);
break;
}
if (fastncmp(tmp, "MT_", 3)) // support for specified mobjtypes...
{
i = get_mobjtype(tmp);
if (!i)
{
//deh_warning("Level header %d: unknown flicky mobj type %s\n", num, tmp); -- no need for this line as get_mobjtype complains too
continue;
}
tmpflickies[mapheaderinfo[num-1]->numFlickies] = i;
}
else // ...or a quick, limited selection of default flickies!
{
for (i = 0; FLICKYTYPES[i].name; i++)
if (fastcmp(tmp, FLICKYTYPES[i].name))
break;
if (!FLICKYTYPES[i].name)
{
deh_warning("Level header %d: unknown flicky selection %s\n", num, tmp);
continue;
}
tmpflickies[mapheaderinfo[num-1]->numFlickies] = FLICKYTYPES[i].type;
}
mapheaderinfo[num-1]->numFlickies++;
} while ((tmp = strtok(NULL,",")) != NULL);
if (mapheaderinfo[num-1]->numFlickies)
{
size_t newsize = sizeof(mobjtype_t) * mapheaderinfo[num-1]->numFlickies;
mapheaderinfo[num-1]->flickies = Z_Realloc(mapheaderinfo[num-1]->flickies, newsize, PU_STATIC, NULL);
// now we add them to the list!
M_Memcpy(mapheaderinfo[num-1]->flickies, tmpflickies, newsize);
}
else
deh_warning("Level header %d: no valid flicky types found\n", num);
}
}
// NiGHTS grades
if (fastncmp(word, "GRADES", 6))
else if (fastncmp(word, "GRADES", 6))
{
UINT8 mare = (UINT8)atoi(word + 6);
@ -1322,6 +1426,8 @@ static void readlevelheader(MYFILE *f, INT32 num)
Z_Free(s);
}
#undef MAXFLICKIES
static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum)
{
char *s = Z_Calloc(MAXLINELEN, PU_STATIC, NULL);
@ -1845,6 +1951,16 @@ static actionpointer_t actionpointers[] =
{{A_BrakLobShot}, "A_BRAKLOBSHOT"},
{{A_NapalmScatter}, "A_NAPALMSCATTER"},
{{A_SpawnFreshCopy}, "A_SPAWNFRESHCOPY"},
{{A_FlickySpawn}, "A_FLICKYSPAWN"},
{{A_FlickyAim}, "A_FLICKYAIM"},
{{A_FlickyFly}, "A_FLICKYFLY"},
{{A_FlickySoar}, "A_FLICKYSOAR"},
{{A_FlickyCoast}, "A_FLICKYCOAST"},
{{A_FlickyHop}, "A_FLICKYHOP"},
{{A_FlickyFlounder}, "A_FLICKYFLOUNDER"},
{{A_FlickyCheck}, "A_FLICKYCHECK"},
{{A_FlickyHeightCheck}, "A_FLICKYHEIGHTCHECK"},
{{A_FlickyFlutter}, "A_FLICKYFLUTTER"},
{{NULL}, "NONE"},
@ -3381,11 +3497,11 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
{
if (i == 0 && word2[0] != '0') // If word2 isn't a number
i = get_mobjtype(word2); // find a thing by name
if (i < NUMMOBJTYPES && i >= 0)
if (i < NUMMOBJTYPES && i > 0)
readthing(f, i);
else
{
deh_warning("Thing %d out of range (0 - %d)", i, NUMMOBJTYPES-1);
deh_warning("Thing %d out of range (1 - %d)", i, NUMMOBJTYPES-1);
ignorelines(f);
}
DEH_WriteUndoline(word, word2, UNDO_HEADER);
@ -5520,43 +5636,133 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_SSPK4",
"S_SSPK5",
// Freed Birdie
"S_BIRD1",
"S_BIRD2",
"S_BIRD3",
// Flicky-sized bubble
"S_FLICKY_BUBBLE",
// Freed Bunny
"S_BUNNY1",
"S_BUNNY2",
"S_BUNNY3",
"S_BUNNY4",
"S_BUNNY5",
"S_BUNNY6",
"S_BUNNY7",
"S_BUNNY8",
"S_BUNNY9",
"S_BUNNY10",
// Bluebird
"S_FLICKY_01_OUT",
"S_FLICKY_01_FLAP1",
"S_FLICKY_01_FLAP2",
"S_FLICKY_01_FLAP3",
// Freed Mouse
"S_MOUSE1",
"S_MOUSE2",
// Rabbit
"S_FLICKY_02_OUT",
"S_FLICKY_02_AIM",
"S_FLICKY_02_HOP",
"S_FLICKY_02_UP",
"S_FLICKY_02_DOWN",
// Freed Chicken
"S_CHICKEN1",
"S_CHICKENHOP",
"S_CHICKENFLY1",
"S_CHICKENFLY2",
// Chicken
"S_FLICKY_03_OUT",
"S_FLICKY_03_AIM",
"S_FLICKY_03_HOP",
"S_FLICKY_03_UP",
"S_FLICKY_03_FLAP1",
"S_FLICKY_03_FLAP2",
// Freed Cow
"S_COW1",
"S_COW2",
"S_COW3",
"S_COW4",
// Seal
"S_FLICKY_04_OUT",
"S_FLICKY_04_AIM",
"S_FLICKY_04_HOP",
"S_FLICKY_04_UP",
"S_FLICKY_04_DOWN",
"S_FLICKY_04_SWIM1",
"S_FLICKY_04_SWIM2",
"S_FLICKY_04_SWIM3",
"S_FLICKY_04_SWIM4",
// Red Birdie in Bubble
"S_RBIRD1",
"S_RBIRD2",
"S_RBIRD3",
// Pig
"S_FLICKY_05_OUT",
"S_FLICKY_05_AIM",
"S_FLICKY_05_HOP",
"S_FLICKY_05_UP",
"S_FLICKY_05_DOWN",
// Chipmunk
"S_FLICKY_06_OUT",
"S_FLICKY_06_AIM",
"S_FLICKY_06_HOP",
"S_FLICKY_06_UP",
"S_FLICKY_06_DOWN",
// Penguin
"S_FLICKY_07_OUT",
"S_FLICKY_07_AIML",
"S_FLICKY_07_HOPL",
"S_FLICKY_07_UPL",
"S_FLICKY_07_DOWNL",
"S_FLICKY_07_AIMR",
"S_FLICKY_07_HOPR",
"S_FLICKY_07_UPR",
"S_FLICKY_07_DOWNR",
"S_FLICKY_07_SWIM1",
"S_FLICKY_07_SWIM2",
"S_FLICKY_07_SWIM3",
// Fish
"S_FLICKY_08_OUT",
"S_FLICKY_08_AIM",
"S_FLICKY_08_HOP",
"S_FLICKY_08_FLAP1",
"S_FLICKY_08_FLAP2",
"S_FLICKY_08_FLAP3",
"S_FLICKY_08_FLAP4",
"S_FLICKY_08_SWIM1",
"S_FLICKY_08_SWIM2",
"S_FLICKY_08_SWIM3",
"S_FLICKY_08_SWIM4",
// Ram
"S_FLICKY_09_OUT",
"S_FLICKY_09_AIM",
"S_FLICKY_09_HOP",
"S_FLICKY_09_UP",
"S_FLICKY_09_DOWN",
// Puffin
"S_FLICKY_10_OUT",
"S_FLICKY_10_FLAP1",
"S_FLICKY_10_FLAP2",
// Cow
"S_FLICKY_11_OUT",
"S_FLICKY_11_AIM",
"S_FLICKY_11_RUN1",
"S_FLICKY_11_RUN2",
"S_FLICKY_11_RUN3",
// Rat
"S_FLICKY_12_OUT",
"S_FLICKY_12_AIM",
"S_FLICKY_12_RUN1",
"S_FLICKY_12_RUN2",
"S_FLICKY_12_RUN3",
// Bear
"S_FLICKY_13_OUT",
"S_FLICKY_13_AIM",
"S_FLICKY_13_HOP",
"S_FLICKY_13_UP",
"S_FLICKY_13_DOWN",
// Dove
"S_FLICKY_14_OUT",
"S_FLICKY_14_FLAP1",
"S_FLICKY_14_FLAP2",
"S_FLICKY_14_FLAP3",
// Cat
"S_FLICKY_15_OUT",
"S_FLICKY_15_AIM",
"S_FLICKY_15_HOP",
"S_FLICKY_15_UP",
"S_FLICKY_15_DOWN",
// Canary
"S_FLICKY_16_OUT",
"S_FLICKY_16_FLAP1",
"S_FLICKY_16_FLAP2",
"S_FLICKY_16_FLAP3",
"S_YELLOWSPRING",
"S_YELLOWSPRING2",
@ -6056,6 +6262,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_NIGHTOPIANHELPER6",
"S_NIGHTOPIANHELPER7",
"S_NIGHTOPIANHELPER8",
"S_NIGHTOPIANHELPER9",
"S_CRUMBLE1",
"S_CRUMBLE2",
@ -6079,10 +6286,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_SPRK16",
// Robot Explosion
"S_XPLD_FLICKY",
"S_XPLD1",
"S_XPLD2",
"S_XPLD3",
"S_XPLD4",
"S_XPLD_EGGTRAP",
// Underwater Explosion
"S_WPLD1",
@ -6490,13 +6697,23 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_IVSP", // Invincibility sparkles
"MT_SUPERSPARK", // Super Sonic Spark
// Freed Animals
"MT_BIRD", // Birdie freed!
"MT_BUNNY", // Bunny freed!
"MT_MOUSE", // Mouse
"MT_CHICKEN", // Chicken
"MT_COW", // Cow
"MT_REDBIRD", // Red Birdie in Bubble
// Flickies
"MT_FLICKY_01", // Bluebird
"MT_FLICKY_02", // Rabbit
"MT_FLICKY_03", // Chicken
"MT_FLICKY_04", // Seal
"MT_FLICKY_05", // Pig
"MT_FLICKY_06", // Chipmunk
"MT_FLICKY_07", // Penguin
"MT_FLICKY_08", // Fish
"MT_FLICKY_09", // Ram
"MT_FLICKY_10", // Puffin
"MT_FLICKY_11", // Cow
"MT_FLICKY_12", // Rat
"MT_FLICKY_13", // Bear
"MT_FLICKY_14", // Dove
"MT_FLICKY_15", // Cat
"MT_FLICKY_16", // Canary
// Environmental Effects
"MT_RAIN", // Rain
@ -7506,7 +7723,7 @@ static mobjtype_t get_mobjtype(const char *word)
if (fastcmp(word, MOBJTYPE_LIST[i]+3))
return i;
deh_warning("Couldn't find mobjtype named 'MT_%s'",word);
return MT_BLUECRAWLA;
return MT_NULL;
}
static statenum_t get_state(const char *word)

View File

@ -241,6 +241,10 @@ typedef struct
UINT8 levelflags; ///< LF_flags: merged eight booleans into one UINT8 for space, see below
UINT8 menuflags; ///< LF2_flags: options that affect record attack / nights mode menus
// Freed animals stuff.
UINT8 numFlickies; ///< Internal. For freed flicky support.
mobjtype_t *flickies; ///< List of freeable flickies in this level. Allocated dynamically for space reasons. Be careful.
// NiGHTS stuff.
UINT8 numGradedMares; ///< Internal. For grade support.
nightsgrades_t *grades; ///< NiGHTS grades. Allocated dynamically for space reasons. Be careful.

View File

@ -4728,7 +4728,7 @@ void G_BeginRecording(void)
// Don't do it.
WRITEFIXED(demo_p, player->jumpfactor);
// Save netvar data (SONICCD, etc)
// Save netvar data
CV_SaveNetVars(&demo_p);
memset(&oldcmd,0,sizeof(oldcmd));

View File

@ -370,13 +370,24 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_GOAL
// Freed Animals
&lspr[NOLIGHT], // SPR_BIRD
&lspr[NOLIGHT], // SPR_BUNY
&lspr[NOLIGHT], // SPR_MOUS
&lspr[NOLIGHT], // SPR_CHIC
&lspr[NOLIGHT], // SPR_COWZ
&lspr[NOLIGHT], // SPR_RBRD
// Flickies
&lspr[NOLIGHT], // SPR_FBUB
&lspr[NOLIGHT], // SPR_FL01
&lspr[NOLIGHT], // SPR_FL02
&lspr[NOLIGHT], // SPR_FL03
&lspr[NOLIGHT], // SPR_FL04
&lspr[NOLIGHT], // SPR_FL05
&lspr[NOLIGHT], // SPR_FL06
&lspr[NOLIGHT], // SPR_FL07
&lspr[NOLIGHT], // SPR_FL08
&lspr[NOLIGHT], // SPR_FL09
&lspr[NOLIGHT], // SPR_FL10
&lspr[NOLIGHT], // SPR_FL11
&lspr[NOLIGHT], // SPR_FL12
&lspr[NOLIGHT], // SPR_FL13
&lspr[NOLIGHT], // SPR_FL14
&lspr[NOLIGHT], // SPR_FL15
&lspr[NOLIGHT], // SPR_FL16
// Springs
&lspr[NOLIGHT], // SPR_SPRY

File diff suppressed because it is too large Load Diff

View File

@ -214,6 +214,16 @@ void A_BrakFireShot();
void A_BrakLobShot();
void A_NapalmScatter();
void A_SpawnFreshCopy();
void A_FlickySpawn();
void A_FlickyAim();
void A_FlickyFly();
void A_FlickySoar();
void A_FlickyCoast();
void A_FlickyHop();
void A_FlickyFlounder();
void A_FlickyCheck();
void A_FlickyHeightCheck();
void A_FlickyFlutter();
// ratio of states to sprites to mobj types is roughly 6 : 1 : 1
#define NUMMOBJFREESLOTS 256
@ -449,13 +459,24 @@ typedef enum sprite
SPR_GOAL, // Special Stage goal (here because lol NiGHTS)
// Freed Animals
SPR_BIRD, // Birdie freed!
SPR_BUNY, // Bunny freed!
SPR_MOUS, // Mouse
SPR_CHIC, // Chicken
SPR_COWZ, // Cow
SPR_RBRD, // Red Birdie in Bubble
// Flickies
SPR_FBUB, // Flicky-sized bubble
SPR_FL01, // Bluebird
SPR_FL02, // Rabbit
SPR_FL03, // Chicken
SPR_FL04, // Seal
SPR_FL05, // Pig
SPR_FL06, // Chipmunk
SPR_FL07, // Penguin
SPR_FL08, // Fish
SPR_FL09, // Ram
SPR_FL10, // Puffin
SPR_FL11, // Cow
SPR_FL12, // Rat
SPR_FL13, // Bear
SPR_FL14, // Dove
SPR_FL15, // Cat
SPR_FL16, // Canary
// Springs
SPR_SPRY, // yellow spring
@ -2419,43 +2440,133 @@ typedef enum state
S_SSPK4,
S_SSPK5,
// Freed Birdie
S_BIRD1,
S_BIRD2,
S_BIRD3,
// Flicky-sized bubble
S_FLICKY_BUBBLE,
// Freed Bunny
S_BUNNY1,
S_BUNNY2,
S_BUNNY3,
S_BUNNY4,
S_BUNNY5,
S_BUNNY6,
S_BUNNY7,
S_BUNNY8,
S_BUNNY9,
S_BUNNY10,
// Bluebird
S_FLICKY_01_OUT,
S_FLICKY_01_FLAP1,
S_FLICKY_01_FLAP2,
S_FLICKY_01_FLAP3,
// Freed Mouse
S_MOUSE1,
S_MOUSE2,
// Rabbit
S_FLICKY_02_OUT,
S_FLICKY_02_AIM,
S_FLICKY_02_HOP,
S_FLICKY_02_UP,
S_FLICKY_02_DOWN,
// Freed Chicken
S_CHICKEN1,
S_CHICKENHOP,
S_CHICKENFLY1,
S_CHICKENFLY2,
// Chicken
S_FLICKY_03_OUT,
S_FLICKY_03_AIM,
S_FLICKY_03_HOP,
S_FLICKY_03_UP,
S_FLICKY_03_FLAP1,
S_FLICKY_03_FLAP2,
// Freed Cow
S_COW1,
S_COW2,
S_COW3,
S_COW4,
// Seal
S_FLICKY_04_OUT,
S_FLICKY_04_AIM,
S_FLICKY_04_HOP,
S_FLICKY_04_UP,
S_FLICKY_04_DOWN,
S_FLICKY_04_SWIM1,
S_FLICKY_04_SWIM2,
S_FLICKY_04_SWIM3,
S_FLICKY_04_SWIM4,
// Red Birdie in Bubble
S_RBIRD1,
S_RBIRD2,
S_RBIRD3,
// Pig
S_FLICKY_05_OUT,
S_FLICKY_05_AIM,
S_FLICKY_05_HOP,
S_FLICKY_05_UP,
S_FLICKY_05_DOWN,
// Chipmunk
S_FLICKY_06_OUT,
S_FLICKY_06_AIM,
S_FLICKY_06_HOP,
S_FLICKY_06_UP,
S_FLICKY_06_DOWN,
// Penguin
S_FLICKY_07_OUT,
S_FLICKY_07_AIML,
S_FLICKY_07_HOPL,
S_FLICKY_07_UPL,
S_FLICKY_07_DOWNL,
S_FLICKY_07_AIMR,
S_FLICKY_07_HOPR,
S_FLICKY_07_UPR,
S_FLICKY_07_DOWNR,
S_FLICKY_07_SWIM1,
S_FLICKY_07_SWIM2,
S_FLICKY_07_SWIM3,
// Fish
S_FLICKY_08_OUT,
S_FLICKY_08_AIM,
S_FLICKY_08_HOP,
S_FLICKY_08_FLAP1,
S_FLICKY_08_FLAP2,
S_FLICKY_08_FLAP3,
S_FLICKY_08_FLAP4,
S_FLICKY_08_SWIM1,
S_FLICKY_08_SWIM2,
S_FLICKY_08_SWIM3,
S_FLICKY_08_SWIM4,
// Ram
S_FLICKY_09_OUT,
S_FLICKY_09_AIM,
S_FLICKY_09_HOP,
S_FLICKY_09_UP,
S_FLICKY_09_DOWN,
// Puffin
S_FLICKY_10_OUT,
S_FLICKY_10_FLAP1,
S_FLICKY_10_FLAP2,
// Cow
S_FLICKY_11_OUT,
S_FLICKY_11_AIM,
S_FLICKY_11_RUN1,
S_FLICKY_11_RUN2,
S_FLICKY_11_RUN3,
// Rat
S_FLICKY_12_OUT,
S_FLICKY_12_AIM,
S_FLICKY_12_RUN1,
S_FLICKY_12_RUN2,
S_FLICKY_12_RUN3,
// Bear
S_FLICKY_13_OUT,
S_FLICKY_13_AIM,
S_FLICKY_13_HOP,
S_FLICKY_13_UP,
S_FLICKY_13_DOWN,
// Dove
S_FLICKY_14_OUT,
S_FLICKY_14_FLAP1,
S_FLICKY_14_FLAP2,
S_FLICKY_14_FLAP3,
// Cat
S_FLICKY_15_OUT,
S_FLICKY_15_AIM,
S_FLICKY_15_HOP,
S_FLICKY_15_UP,
S_FLICKY_15_DOWN,
// Canary
S_FLICKY_16_OUT,
S_FLICKY_16_FLAP1,
S_FLICKY_16_FLAP2,
S_FLICKY_16_FLAP3,
S_YELLOWSPRING,
S_YELLOWSPRING2,
@ -2955,6 +3066,7 @@ typedef enum state
S_NIGHTOPIANHELPER6,
S_NIGHTOPIANHELPER7,
S_NIGHTOPIANHELPER8,
S_NIGHTOPIANHELPER9,
S_CRUMBLE1,
S_CRUMBLE2,
@ -2978,10 +3090,10 @@ typedef enum state
S_SPRK16,
// Robot Explosion
S_XPLD_FLICKY,
S_XPLD1,
S_XPLD2,
S_XPLD3,
S_XPLD4,
S_XPLD_EGGTRAP,
// Underwater Explosion
S_WPLD1,
@ -3408,13 +3520,23 @@ typedef enum mobj_type
MT_IVSP, // Invincibility sparkles
MT_SUPERSPARK, // Super Sonic Spark
// Freed Animals
MT_BIRD, // Birdie freed!
MT_BUNNY, // Bunny freed!
MT_MOUSE, // Mouse
MT_CHICKEN, // Chicken
MT_COW, // Cow
MT_REDBIRD, // Red Birdie in Bubble
// Flickies
MT_FLICKY_01, // Bluebird
MT_FLICKY_02, // Rabbit
MT_FLICKY_03, // Chicken
MT_FLICKY_04, // Seal
MT_FLICKY_05, // Pig
MT_FLICKY_06, // Chipmunk
MT_FLICKY_07, // Penguin
MT_FLICKY_08, // Fish
MT_FLICKY_09, // Ram
MT_FLICKY_10, // Puffin
MT_FLICKY_11, // Cow
MT_FLICKY_12, // Rat
MT_FLICKY_13, // Bear
MT_FLICKY_14, // Dove
MT_FLICKY_15, // Cat
MT_FLICKY_16, // Canary
// Environmental Effects
MT_RAIN, // Rain

View File

@ -242,6 +242,16 @@ void A_BrakFireShot(mobj_t *actor);
void A_BrakLobShot(mobj_t *actor);
void A_NapalmScatter(mobj_t *actor);
void A_SpawnFreshCopy(mobj_t *actor);
void A_FlickySpawn(mobj_t *actor);
void A_FlickyAim(mobj_t *actor);
void A_FlickyFly(mobj_t *actor);
void A_FlickySoar(mobj_t *actor);
void A_FlickyCoast(mobj_t *actor);
void A_FlickyHop(mobj_t *actor);
void A_FlickyFlounder(mobj_t *actor);
void A_FlickyCheck(mobj_t *actor);
void A_FlickyHeightCheck(mobj_t *actor);
void A_FlickyFlutter(mobj_t *actor);
//
// ENEMY THINKING
@ -10336,3 +10346,392 @@ void A_SpawnFreshCopy(mobj_t *actor)
if (newObject->info->seesound)
S_StartSound(newObject, newObject->info->seesound);
}
// Internal Flicky spawning function.
mobj_t *P_InternalFlickySpawn(mobj_t *actor, mobjtype_t flickytype, fixed_t momz, boolean lookforplayers)
{
mobj_t *flicky;
if (!flickytype)
{
if (!mapheaderinfo[gamemap-1] || !mapheaderinfo[gamemap-1]->numFlickies) // No mapheader, no shoes, no service.
return NULL;
else
{
INT32 prandom = P_RandomKey(mapheaderinfo[gamemap-1]->numFlickies);
flickytype = mapheaderinfo[gamemap-1]->flickies[prandom];
}
}
flicky = P_SpawnMobjFromMobj(actor, 0, 0, 0, flickytype);
flicky->angle = actor->angle;
if (flickytype == MT_SEED)
flicky->z += P_MobjFlip(actor)*(actor->height - flicky->height)/2;
if (actor->eflags & MFE_UNDERWATER)
momz = FixedDiv(momz, FixedSqrt(3*FRACUNIT));
P_SetObjectMomZ(flicky, momz, false);
flicky->movedir = (P_RandomChance(FRACUNIT/2) ? -1 : 1);
flicky->fuse = P_RandomRange(595, 700); // originally 300, 350
flicky->threshold = 0;
if (lookforplayers)
P_LookForPlayers(flicky, true, false, 0);
return flicky;
}
// Function: A_FlickySpawn
//
// Description: Flicky spawning function.
//
// var1:
// lower 16 bits: if 0, spawns random flicky based on level header. Else, spawns the designated thing type.
// upper 16 bits: if 0, no sound is played. Else, A_Scream is called.
// var2 = upwards thrust for spawned flicky. If zero, default value is provided.
//
void A_FlickySpawn(mobj_t *actor)
{
INT32 locvar1 = var1;
INT32 locvar2 = var2;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_FlickySpawn", actor))
return;
#endif
if (locvar1 >> 16) {
A_Scream(actor); // A shortcut for the truly lazy.
locvar1 &= 65535;
}
P_InternalFlickySpawn(actor, locvar1, ((locvar2) ? locvar2 : 8*FRACUNIT), true);
}
// Internal Flicky bubbling function.
void P_InternalFlickyBubble(mobj_t *actor)
{
if (actor->eflags & MFE_UNDERWATER)
{
mobj_t *overlay;
if (!((actor->z + 3*actor->height/2) < actor->watertop) || !mobjinfo[actor->type].raisestate || actor->tracer)
return;
overlay = P_SpawnMobj(actor->x, actor->y, actor->z, MT_OVERLAY);
P_SetMobjStateNF(overlay, mobjinfo[actor->type].raisestate);
P_SetTarget(&actor->tracer, overlay);
P_SetTarget(&overlay->target, actor);
return;
}
if (!actor->tracer || P_MobjWasRemoved(actor->tracer))
return;
P_RemoveMobj(actor->tracer);
P_SetTarget(&actor->tracer, NULL);
}
// Function: A_FlickyAim
//
// Description: Flicky aiming function.
//
// var1 = how far around the target (in angle constants) the flicky should look
// var2 = distance from target to aim for
//
void A_FlickyAim(mobj_t *actor)
{
INT32 locvar1 = var1;
INT32 locvar2 = var2;
boolean flickyhitwall = false;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_FlickyAim", actor))
return;
#endif
if (actor->momx == actor->momy && actor->momy == 0)
flickyhitwall = true;
P_InternalFlickyBubble(actor);
P_InstaThrust(actor, 0, 0);
if (!actor->target)
{
P_LookForPlayers(actor, true, false, 0);
actor->angle = P_RandomKey(36)*ANG10;
return;
}
if (actor->fuse > 2*TICRATE)
{
angle_t posvar;
fixed_t chasevar, chasex, chasey;
if (flickyhitwall)
actor->movedir *= -1;
posvar = ((R_PointToAngle2(actor->target->x, actor->target->y, actor->x, actor->y) + actor->movedir*locvar1) >> ANGLETOFINESHIFT) & FINEMASK;
chasevar = FixedSqrt(max(FRACUNIT, P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y) - locvar2)) + locvar2;
chasex = actor->target->x + FixedMul(FINECOSINE(posvar), chasevar);
chasey = actor->target->y + FixedMul(FINESINE(posvar), chasevar);
if (P_AproxDistance(chasex - actor->x, chasey - actor->y))
actor->angle = R_PointToAngle2(actor->x, actor->y, chasex, chasey);
}
else if (flickyhitwall)
{
actor->angle += ANGLE_180;
actor->threshold = 0;
}
}
//Internal Flicky flying function. Also usuable as an underwater swim thrust.
void P_InternalFlickyFly(mobj_t *actor, fixed_t flyspeed, fixed_t targetdist, fixed_t chasez)
{
angle_t vertangle;
flyspeed = FixedMul(flyspeed, actor->scale);
actor->flags |= MF_NOGRAVITY;
var1 = ANG30;
var2 = 32*FRACUNIT;
A_FlickyAim(actor);
chasez *= 8;
if (!actor->target || !(actor->fuse > 2*TICRATE))
chasez += ((actor->eflags & MFE_VERTICALFLIP) ? actor->ceilingz - 24*FRACUNIT : actor->floorz + 24*FRACUNIT);
else
{
fixed_t add = actor->target->z + (actor->target->height - actor->height)/2;
if (add > (actor->ceilingz - 24*actor->scale - actor->height))
add = actor->ceilingz - 24*actor->scale - actor->height;
else if (add < (actor->floorz + 24*actor->scale))
add = actor->floorz + 24*actor->scale;
chasez += add;
}
if (!targetdist)
targetdist = 16*FRACUNIT; //Default!
if (actor->target && abs(chasez - actor->z) > targetdist)
targetdist = P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y);
vertangle = (R_PointToAngle2(0, actor->z, targetdist, chasez) >> ANGLETOFINESHIFT) & FINEMASK;
P_InstaThrust(actor, actor->angle, FixedMul(FINECOSINE(vertangle), flyspeed));
actor->momz = FixedMul(FINESINE(vertangle), flyspeed);
}
// Function: A_FlickyFly
//
// Description: Flicky flying function.
//
// var1 = how fast to fly
// var2 = how far ahead the target should be considered
//
void A_FlickyFly(mobj_t *actor)
{
// We're not setting up locvars here - it passes var1 and var2 through to P_InternalFlickyFly instead.
//INT32 locvar1 = var1;
//INT32 locvar2 = var2;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_FlickyFly", actor))
return;
#endif
P_InternalFlickyFly(actor, var1, var2,
FINECOSINE((((actor->fuse % 36) * ANG10) >> ANGLETOFINESHIFT) & FINEMASK)
);
}
// Function: A_FlickySoar
//
// Description: Flicky soaring function - specific to puffin.
//
// var1 = how fast to fly
// var2 = how far ahead the target should be considered
//
void A_FlickySoar(mobj_t *actor)
{
// We're not setting up locvars here - it passes var1 and var2 through to P_InternalFlickyFly instead.
//INT32 locvar1 = var1;
//INT32 locvar2 = var2;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_FlickySoar", actor))
return;
#endif
P_InternalFlickyFly(actor, var1, var2,
2*(FRACUNIT/2 - abs(FINECOSINE((((actor->fuse % 144) * 5*ANG1/2) >> ANGLETOFINESHIFT) & FINEMASK)))
);
if (P_MobjFlip(actor)*actor->momz > 0 && actor->frame == 1 && actor->sprite == SPR_FL10)
actor->frame = 3;
}
//Function: A_FlickyCoast
//
// Description: Flicky swim-coasting function.
//
// var1 = speed to change state upon reaching
// var2 = state to change to upon slowing down
// the spawnstate of the mobj = state to change to when above water
//
void A_FlickyCoast(mobj_t *actor)
{
INT32 locvar1 = var1;
INT32 locvar2 = var2;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_FlickyCoast", actor))
return;
#endif
if (actor->eflags & MFE_UNDERWATER)
{
actor->momx = (11*actor->momx)/12;
actor->momy = (11*actor->momy)/12;
actor->momz = (11*actor->momz)/12;
if (P_AproxDistance(P_AproxDistance(actor->momx, actor->momy), actor->momz) < locvar1)
P_SetMobjState(actor, locvar2);
return;
}
actor->flags &= ~MF_NOGRAVITY;
P_SetMobjState(actor, mobjinfo[actor->type].spawnstate);
}
// Internal Flicky hopping function.
void P_InternalFlickyHop(mobj_t *actor, fixed_t momz, fixed_t momh, angle_t angle)
{
if (((!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz)
|| ((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz)))
{
if (momz)
{
if (actor->eflags & MFE_UNDERWATER)
momz = FixedDiv(momz, FixedSqrt(3*FRACUNIT));
P_SetObjectMomZ(actor, momz, false);
}
P_InstaThrust(actor, angle, FixedMul(momh, actor->scale));
}
}
// Function: A_FlickyHop
//
// Description: Flicky hopping function.
//
// var1 = vertical thrust
// var2 = horizontal thrust
//
void A_FlickyHop(mobj_t *actor)
{
// We're not setting up locvars here - it passes var1 and var2 through to P_InternalFlickyHop instead.
//INT32 locvar1 = var1;
//INT32 locvar2 = var2;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_FlickyHop", actor))
return;
#endif
P_InternalFlickyHop(actor, var1, var2, actor->angle);
}
// Function: A_FlickyFlounder
//
// Description: Flicky floundering function.
//
// var1 = intended vertical thrust
// var2 = intended horizontal thrust
//
void A_FlickyFlounder(mobj_t *actor)
{
INT32 locvar1 = var1;
INT32 locvar2 = var2;
angle_t hopangle;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_FlickyFlounder", actor))
return;
#endif
locvar1 *= (P_RandomKey(2) + 1);
locvar2 *= (P_RandomKey(2) + 1);
hopangle = (actor->angle + (P_RandomKey(9) - 4)*ANG2);
P_InternalFlickyHop(actor, locvar1, locvar2, hopangle);
}
// Function: A_FlickyCheck
//
// Description: Flicky airtime check function.
//
// var1 = state to change to upon touching the floor
// var2 = state to change to upon falling
// the meleestate of the mobj = state to change to when underwater
//
void A_FlickyCheck(mobj_t *actor)
{
INT32 locvar1 = var1;
INT32 locvar2 = var2;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_FlickyCheck", actor))
return;
#endif
if (locvar2 && P_MobjFlip(actor)*actor->momz < 1)
P_SetMobjState(actor, locvar2);
else if (locvar1 && ((!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz)
|| ((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz)))
P_SetMobjState(actor, locvar1);
else if (mobjinfo[actor->type].meleestate && (actor->eflags & MFE_UNDERWATER))
P_SetMobjState(actor, mobjinfo[actor->type].meleestate);
P_InternalFlickyBubble(actor);
}
// Function: A_FlickyHeightCheck
//
// Description: Flicky height check function.
//
// var1 = state to change to when falling below height relative to target
// var2 = height relative to target to change state at
//
void A_FlickyHeightCheck(mobj_t *actor)
{
INT32 locvar1 = var1;
INT32 locvar2 = var2;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_FlickyHeightCheck", actor))
return;
#endif
if (locvar1 && actor->target && P_MobjFlip(actor)*actor->momz < 1
&& ((P_MobjFlip(actor)*((actor->z + actor->height/2) - (actor->target->z + actor->target->height/2)) < locvar2)
|| (actor->z - actor->height < actor->floorz) || (actor->z + 2*actor->height > actor->ceilingz)))
P_SetMobjState(actor, locvar1);
P_InternalFlickyBubble(actor);
}
// Function: A_FlickyFlutter
//
// Description: Flicky fluttering function - specific to chicken.
//
// var1 = state to change to upon touching the floor
// var2 = state to change to upon falling
// the meleestate of the mobj = state to change to when underwater
//
void A_FlickyFlutter(mobj_t *actor)
{
// We're not setting up locvars here - it passes var1 and var2 through to A_FlickyCheck instead.
//INT32 locvar1 = var1;
//INT32 locvar2 = var2;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_FlickyFlutter", actor))
return;
#endif
A_FlickyCheck(actor);
var1 = ANG30;
var2 = 32*FRACUNIT;
A_FlickyAim(actor);
P_InstaThrust(actor, actor->angle, 2*actor->scale);
if (P_MobjFlip(actor)*actor->momz < -FRACUNIT/2)
actor->momz = -P_MobjFlip(actor)*actor->scale/2;
}
#undef FLICKYHITWALL

View File

@ -2043,7 +2043,6 @@ boolean P_CheckRacers(void)
*/
void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype)
{
mobjtype_t item;
mobj_t *mo;
if (inflictor && (inflictor->type == MT_SHELL || inflictor->type == MT_FIREBALL))
@ -2259,81 +2258,80 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
if (source && target && target->player && source->player)
P_PlayVictorySound(source); // Killer laughs at you. LAUGHS! BWAHAHAHA!
#ifdef OLDANIMALSPAWNING
// Drop stuff.
// This determines the kind of object spawned
// during the death frame of a thing.
if (!mariomode // Don't show birds, etc. in Mario Mode Tails 12-23-2001
&& target->flags & MF_ENEMY)
{
if (cv_soniccd.value)
item = MT_SEED;
else
mobjtype_t item;
INT32 prandom;
switch (target->type)
{
INT32 prandom;
case MT_REDCRAWLA:
case MT_GOLDBUZZ:
case MT_SKIM:
case MT_UNIDUS:
item = MT_FLICKY_02/*MT_BUNNY*/;
break;
switch (target->type)
{
case MT_REDCRAWLA:
case MT_GOLDBUZZ:
case MT_SKIM:
case MT_UNIDUS:
item = MT_BUNNY;
break;
case MT_BLUECRAWLA:
case MT_JETTBOMBER:
case MT_GFZFISH:
item = MT_FLICKY_01/*MT_BIRD*/;
break;
case MT_BLUECRAWLA:
case MT_JETTBOMBER:
case MT_GFZFISH:
item = MT_BIRD;
break;
case MT_JETTGUNNER:
case MT_CRAWLACOMMANDER:
case MT_REDBUZZ:
case MT_DETON:
item = MT_FLICKY_12/*MT_MOUSE*/;
break;
case MT_JETTGUNNER:
case MT_CRAWLACOMMANDER:
case MT_REDBUZZ:
case MT_DETON:
item = MT_MOUSE;
break;
case MT_GSNAPPER:
case MT_EGGGUARD:
case MT_SPRINGSHELL:
item = MT_FLICKY_11/*MT_COW*/;
break;
case MT_GSNAPPER:
case MT_EGGGUARD:
case MT_SPRINGSHELL:
item = MT_COW;
break;
case MT_MINUS:
case MT_VULTURE:
case MT_POINTY:
case MT_YELLOWSHELL:
item = MT_FLICKY_03/*MT_CHICKEN*/;
break;
case MT_MINUS:
case MT_VULTURE:
case MT_POINTY:
case MT_YELLOWSHELL:
item = MT_CHICKEN;
break;
case MT_AQUABUZZ:
item = MT_FLICKY_01/*MT_REDBIRD*/;
break;
case MT_AQUABUZZ:
item = MT_REDBIRD;
break;
default:
if (target->info->doomednum)
prandom = target->info->doomednum%5; // "Random" animal for new enemies.
else
prandom = P_RandomKey(5); // No placable object, just use a random number.
default:
if (target->info->doomednum)
prandom = target->info->doomednum%5; // "Random" animal for new enemies.
else
prandom = P_RandomKey(5); // No placable object, just use a random number.
switch(prandom)
{
default: item = MT_BUNNY; break;
case 1: item = MT_BIRD; break;
case 2: item = MT_MOUSE; break;
case 3: item = MT_COW; break;
case 4: item = MT_CHICKEN; break;
}
break;
}
switch(prandom)
{
default: item = MT_FLICKY_02/*MT_BUNNY*/; break;
case 1: item = MT_FLICKY_01/*MT_BIRD*/; break;
case 2: item = MT_FLICKY_12/*MT_MOUSE*/; break;
case 3: item = MT_FLICKY_11/*MT_COW*/; break;
case 4: item = MT_FLICKY_03/*MT_CHICKEN*/; break;
}
break;
}
mo = P_SpawnMobj(target->x, target->y, target->z + (target->height / 2) - FixedMul(mobjinfo[item].height / 2, target->scale), item);
mo->destscale = target->scale;
P_SetScale(mo, mo->destscale);
}
else
#endif
// Other death animation effects
else switch(target->type)
switch(target->type)
{
case MT_BOUNCEPICKUP:
case MT_RAILPICKUP:

View File

@ -295,6 +295,11 @@ boolean P_CheckMissileRange(mobj_t *actor);
void P_NewChaseDir(mobj_t *actor);
boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed_t dist);
mobj_t *P_InternalFlickySpawn(mobj_t *actor, mobjtype_t flickytype, fixed_t momz, boolean lookforplayers);
void P_InternalFlickyBubble(mobj_t *actor);
void P_InternalFlickyFly(mobj_t *actor, fixed_t flyspeed, fixed_t targetdist, fixed_t chasez);
void P_InternalFlickyHop(mobj_t *actor, fixed_t momz, fixed_t momh, angle_t angle);
//
// P_MAP
//

View File

@ -3482,17 +3482,14 @@ static boolean P_SceneryZMovement(mobj_t *mo)
if ((!(mo->eflags & MFE_VERTICALFLIP) && mo->z <= mo->floorz)
|| (mo->eflags & MFE_VERTICALFLIP && mo->z+mo->height >= mo->ceilingz))
{
// DO NOT use random numbers here.
// SonicCD mode is console togglable and
// affects demos.
UINT8 rltime = (leveltime & 4);
if (!rltime)
P_SpawnMobj(mo->x, mo->y, mo->floorz, MT_GFZFLOWER3);
else if (rltime == 2)
P_SpawnMobj(mo->x, mo->y, mo->floorz, MT_GFZFLOWER2);
else
P_SpawnMobj(mo->x, mo->y, mo->floorz, MT_GFZFLOWER1);
mobjtype_t flowertype = ((P_RandomChance(FRACUNIT/2)) ? MT_GFZFLOWER1 : MT_GFZFLOWER3);
mobj_t *flower = P_SpawnMobjFromMobj(mo, 0, 0, 0, flowertype);
if (flower)
{
P_SetScale(flower, mo->scale/16);
flower->destscale = mo->scale;
flower->scalespeed = mo->scale/8;
}
P_RemoveMobj(mo);
return false;
@ -7049,7 +7046,8 @@ void P_MobjThinker(mobj_t *mobj)
}
break;
case MT_SEED:
mobj->momz = mobj->info->speed;
if (P_MobjFlip(mobj)*mobj->momz < mobj->info->speed)
mobj->momz = P_MobjFlip(mobj)*mobj->info->speed;
break;
case MT_ROCKCRUMBLE1:
case MT_ROCKCRUMBLE2:
@ -7198,14 +7196,14 @@ void P_MobjThinker(mobj_t *mobj)
if (mobj->fuse > 0 && mobj->fuse < 2*TICRATE-(TICRATE/7)
&& (mobj->fuse & 3))
{
INT32 i,j;
INT32 i;
fixed_t x,y,z;
fixed_t ns;
mobj_t *mo2;
mobj_t *flicky;
i = P_RandomByte();
z = mobj->subsector->sector->floorheight + ((P_RandomByte()&63)*FRACUNIT);
for (j = 0; j < 2; j++)
for (i = 0; i < 2; i++)
{
const angle_t fa = (P_RandomByte()*FINEANGLES/16) & FINEMASK;
ns = 64 * FRACUNIT;
@ -7213,25 +7211,22 @@ void P_MobjThinker(mobj_t *mobj)
y = mobj->y + FixedMul(FINECOSINE(fa),ns);
mo2 = P_SpawnMobj(x, y, z, MT_EXPLODE);
P_SetMobjStateNF(mo2, S_XPLD_EGGTRAP); // so the flickies don't lose their target if they spawn
ns = 4 * FRACUNIT;
mo2->momx = FixedMul(FINESINE(fa),ns);
mo2->momy = FixedMul(FINECOSINE(fa),ns);
mo2->angle = fa << ANGLETOFINESHIFT;
i = P_RandomByte();
if (i % 5 == 0)
P_SpawnMobj(x, y, z, MT_CHICKEN);
else if (i % 4 == 0)
P_SpawnMobj(x, y, z, MT_COW);
else if (i % 3 == 0)
{
P_SpawnMobj(x, y, z, MT_BIRD);
if (P_RandomChance(FRACUNIT/4)) // I filled a spreadsheet trying to get the equivalent chance to the original P_RandomByte hack!
S_StartSound(mo2, mobj->info->deathsound);
}
else if ((i & 1) == 0)
P_SpawnMobj(x, y, z, MT_BUNNY);
else
P_SpawnMobj(x, y, z, MT_MOUSE);
flicky = P_InternalFlickySpawn(mo2, 0, 8*FRACUNIT, false);
if (!flicky)
break;
P_SetTarget(&flicky->target, mo2);
flicky->momx = mo2->momx;
flicky->momy = mo2->momy;
}
mobj->fuse--;
@ -7292,6 +7287,8 @@ void P_MobjThinker(mobj_t *mobj)
}
break;
case MT_AQUABUZZ:
P_MobjCheckWater(mobj); // solely for MFE_UNDERWATER for A_FlickySpawn
// no break here on purpose
case MT_BIGAIRMINE:
{
if (mobj->tracer && mobj->tracer->player && mobj->tracer->health > 0
@ -8402,13 +8399,8 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
// Special condition for the 2nd boss.
mobj->watertop = mobj->info->speed;
break;
case MT_BIRD:
case MT_BUNNY:
case MT_MOUSE:
case MT_CHICKEN:
case MT_COW:
case MT_REDBIRD:
mobj->fuse = P_RandomRange(300, 350);
case MT_FLICKY_08:
mobj->color = (P_RandomChance(FRACUNIT/2) ? SKINCOLOR_RED : SKINCOLOR_AQUA);
break;
case MT_REDRING: // Make MT_REDRING red by default
mobj->color = skincolor_redring;

View File

@ -160,6 +160,33 @@ FUNCNORETURN static ATTRNORETURN void CorruptMapError(const char *msg)
I_Error("Invalid or corrupt map.\nLook in log file or text console for technical details.");
}
/** Sets a header's flickies to be equivalent to the original Freed Animals
*
* \param i The header to set flickies for
*/
void P_SetDemoFlickies(INT16 i)
{
mapheaderinfo[i]->numFlickies = 5;
mapheaderinfo[i]->flickies = Z_Realloc(mapheaderinfo[i]->flickies, 5*sizeof(mobjtype_t), PU_STATIC, NULL);
mapheaderinfo[i]->flickies[0] = MT_FLICKY_02/*MT_BUNNY*/;
mapheaderinfo[i]->flickies[1] = MT_FLICKY_01/*MT_BIRD*/;
mapheaderinfo[i]->flickies[2] = MT_FLICKY_12/*MT_MOUSE*/;
mapheaderinfo[i]->flickies[3] = MT_FLICKY_11/*MT_COW*/;
mapheaderinfo[i]->flickies[4] = MT_FLICKY_03/*MT_CHICKEN*/;
}
/** Clears a header's flickies
*
* \param i The header to clear flickies for
*/
void P_DeleteFlickies(INT16 i)
{
if (mapheaderinfo[i]->flickies)
Z_Free(mapheaderinfo[i]->flickies);
mapheaderinfo[i]->flickies = NULL;
mapheaderinfo[i]->numFlickies = 0;
}
#define NUMLAPS_DEFAULT 4
/** Clears the data from a single map header.
@ -223,6 +250,12 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
mapheaderinfo[num]->levelflags = 0;
DEH_WriteUndoline("MENUFLAGS", va("%d", mapheaderinfo[num]->menuflags), UNDO_NONE);
mapheaderinfo[num]->menuflags = 0;
// Flickies. Nope, no delfile support here either
#if 1 // equivalent to "FlickyList = DEMO"
P_SetDemoFlickies(num);
#else // equivalent to "FlickyList = NONE"
P_DeleteFlickies(num);
#endif
// TODO grades support for delfile (pfft yeah right)
P_DeleteGrades(num);
// an even further impossibility, delfile custom opts support
@ -241,6 +274,7 @@ void P_AllocMapHeader(INT16 i)
if (!mapheaderinfo[i])
{
mapheaderinfo[i] = Z_Malloc(sizeof(mapheader_t), PU_STATIC, NULL);
mapheaderinfo[i]->flickies = NULL;
mapheaderinfo[i]->grades = NULL;
}
P_ClearSingleMapHeaderInfo(i + 1);

View File

@ -68,6 +68,9 @@ void P_WriteThings(lumpnum_t lump);
size_t P_PrecacheLevelFlats(void);
void P_AllocMapHeader(INT16 i);
void P_SetDemoFlickies(INT16 i);
void P_DeleteFlickies(INT16 i);
// Needed for NiGHTS
void P_ReloadRings(void);
void P_DeleteGrades(INT16 i);

View File

@ -5640,11 +5640,13 @@ static void P_DoNiGHTSCapsule(player_t *player)
}
else
{
fixed_t z;
z = player->capsule->z + player->capsule->height/2;
for (i = 0; i < 16; i++)
P_SpawnMobj(player->capsule->x, player->capsule->y, z, MT_BIRD);
{
mobj_t *flicky = P_InternalFlickySpawn(player->capsule, 0, ((i%4) + 1)*2*FRACUNIT, true);
flicky->z += player->capsule->height/2;
flicky->angle = (i*(ANGLE_MAX/16));
P_InstaThrust(flicky, flicky->angle, 8*FRACUNIT);
}
}
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mare == player->mare)

View File

@ -148,7 +148,6 @@ consvar_t cv_flipcam2 = {"flipcam2", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo,
consvar_t cv_shadow = {"shadow", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_shadowoffs = {"offsetshadows", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_skybox = {"skybox", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_soniccd = {"soniccd", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_allowmlook = {"allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_showhud = {"showhud", "Yes", CV_CALL, CV_YesNo, R_SetViewSize, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_translucenthud = {"translucenthud", "10", CV_SAVE, translucenthud_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -1361,7 +1360,6 @@ void R_RegisterEngineStuff(void)
{
CV_RegisterVar(&cv_gravity);
CV_RegisterVar(&cv_tailspickup);
CV_RegisterVar(&cv_soniccd);
CV_RegisterVar(&cv_allowmlook);
CV_RegisterVar(&cv_homremoval);
CV_RegisterVar(&cv_flipcam);