Merge branch 'musicplus-core' into musicplus-feature-postboss

This commit is contained in:
mazmazz 2018-09-16 23:32:18 -04:00
commit c5d4ff5712
44 changed files with 1957 additions and 1722 deletions

View file

@ -811,6 +811,7 @@ void D_RegisterClientCommands(void)
COM_AddCommand("writethings", Command_Writethings_f); COM_AddCommand("writethings", Command_Writethings_f);
CV_RegisterVar(&cv_speed); CV_RegisterVar(&cv_speed);
CV_RegisterVar(&cv_opflags); CV_RegisterVar(&cv_opflags);
CV_RegisterVar(&cv_ophoopflags);
CV_RegisterVar(&cv_mapthingnum); CV_RegisterVar(&cv_mapthingnum);
// CV_RegisterVar(&cv_grid); // CV_RegisterVar(&cv_grid);
// CV_RegisterVar(&cv_snapto); // CV_RegisterVar(&cv_snapto);
@ -822,7 +823,6 @@ void D_RegisterClientCommands(void)
COM_AddCommand("getallemeralds", Command_Getallemeralds_f); COM_AddCommand("getallemeralds", Command_Getallemeralds_f);
COM_AddCommand("resetemeralds", Command_Resetemeralds_f); COM_AddCommand("resetemeralds", Command_Resetemeralds_f);
COM_AddCommand("setrings", Command_Setrings_f); COM_AddCommand("setrings", Command_Setrings_f);
COM_AddCommand("setspheres", Command_Setspheres_f);
COM_AddCommand("setlives", Command_Setlives_f); COM_AddCommand("setlives", Command_Setlives_f);
COM_AddCommand("setcontinues", Command_Setcontinues_f); COM_AddCommand("setcontinues", Command_Setcontinues_f);
COM_AddCommand("devmode", Command_Devmode_f); COM_AddCommand("devmode", Command_Devmode_f);
@ -2766,6 +2766,12 @@ static void Command_Login_f(void)
UINT8 finalmd5[16]; UINT8 finalmd5[16];
const char *pw; const char *pw;
if (!netgame)
{
CONS_Printf(M_GetText("This only works in a netgame.\n"));
return;
}
// If the server uses login, it will effectively just remove admin privileges // If the server uses login, it will effectively just remove admin privileges
// from whoever has them. This is good. // from whoever has them. This is good.
if (COM_Argc() != 2) if (COM_Argc() != 2)
@ -2833,6 +2839,12 @@ static void Command_Verify_f(void)
return; return;
} }
if (!netgame)
{
CONS_Printf(M_GetText("This only works in a netgame.\n"));
return;
}
if (COM_Argc() != 2) if (COM_Argc() != 2)
{ {
CONS_Printf(M_GetText("verify <node>: give admin privileges to a node\n")); CONS_Printf(M_GetText("verify <node>: give admin privileges to a node\n"));
@ -3144,7 +3156,7 @@ static void Command_Addfile(void)
WRITEMEM(buf_p, md5sum, 16); WRITEMEM(buf_p, md5sum, 16);
} }
if (adminplayer == consoleplayer) // Request to add file if (adminplayer == consoleplayer && (!server)) // Request to add file
SendNetXCmd(XD_REQADDFILE, buf, buf_p - buf); SendNetXCmd(XD_REQADDFILE, buf, buf_p - buf);
else else
SendNetXCmd(XD_ADDFILE, buf, buf_p - buf); SendNetXCmd(XD_ADDFILE, buf, buf_p - buf);
@ -4039,7 +4051,7 @@ static void Command_Tunes_f(void)
mapmusflags = (track & MUSIC_TRACKMASK); mapmusflags = (track & MUSIC_TRACKMASK);
mapmusposition = position; mapmusposition = position;
S_ChangeMusicAdvanced(mapmusname, mapmusflags, true, mapmusposition, 0, 0); S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
if (argc > 3) if (argc > 3)
{ {
@ -4055,6 +4067,7 @@ static void Command_RestartAudio_f(void)
return; return;
S_StopMusic(); S_StopMusic();
S_StopSounds();
I_ShutdownMusic(); I_ShutdownMusic();
I_ShutdownSound(); I_ShutdownSound();
I_StartupSound(); I_StartupSound();

View file

@ -382,7 +382,7 @@ typedef struct player_s
fixed_t height; // Bounding box changes. fixed_t height; // Bounding box changes.
fixed_t spinheight; fixed_t spinheight;
SINT8 lives; SINT8 lives; // number of lives - if == INFLIVES, the player has infinite lives
SINT8 continues; // continues that player has acquired SINT8 continues; // continues that player has acquired
SINT8 xtralife; // Ring Extra Life counter SINT8 xtralife; // Ring Extra Life counter
@ -456,16 +456,25 @@ typedef struct player_s
boolean bonustime; // Capsule destroyed, now it's bonus time! boolean bonustime; // Capsule destroyed, now it's bonus time!
mobj_t *capsule; // Go inside the capsule mobj_t *capsule; // Go inside the capsule
UINT8 mare; // Current mare UINT8 mare; // Current mare
UINT8 marelap; // Current mare lap
UINT8 marebonuslap; // Current mare lap starting from bonus time
// Statistical purposes. // Statistical purposes.
tic_t marebegunat; // Leveltime when mare begun tic_t marebegunat; // Leveltime when mare begun
tic_t startedtime; // Time which you started this mare with. tic_t startedtime; // Time which you started this mare with.
tic_t finishedtime; // Time it took you to finish the mare (used for display) tic_t finishedtime; // Time it took you to finish the mare (used for display)
tic_t lapbegunat; // Leveltime when lap begun
tic_t lapstartedtime; // Time which you started this lap with.
INT16 finishedspheres; // The spheres you had left upon finishing the mare INT16 finishedspheres; // The spheres you had left upon finishing the mare
INT16 finishedrings; // The rings/stars you had left upon finishing the mare INT16 finishedrings; // The rings/stars you had left upon finishing the mare
UINT32 marescore; // score for this nights stage UINT32 marescore; // score for this nights stage
UINT32 lastmarescore; // score for the last mare UINT32 lastmarescore; // score for the last mare
UINT32 totalmarescore; // score for all mares
UINT8 lastmare; // previous mare UINT8 lastmare; // previous mare
UINT8 lastmarelap; // previous mare lap
UINT8 lastmarebonuslap; // previous mare bonus lap
UINT8 totalmarelap; // total mare lap
UINT8 totalmarebonuslap; // total mare bonus lap
INT32 maxlink; // maximum link obtained INT32 maxlink; // maximum link obtained
UINT8 texttimer; // nights_texttime should not be local UINT8 texttimer; // nights_texttime should not be local
UINT8 textvar; // which line of NiGHTS text to show -- let's not use cheap hacks UINT8 textvar; // which line of NiGHTS text to show -- let's not use cheap hacks
@ -491,4 +500,7 @@ typedef struct player_s
#endif #endif
} player_t; } player_t;
// Value for infinite lives
#define INFLIVES 0x7F
#endif #endif

View file

@ -1214,6 +1214,8 @@ static void readlevelheader(MYFILE *f, INT32 num)
deh_warning("Level header %d: invalid bonus type number %d", num, i); deh_warning("Level header %d: invalid bonus type number %d", num, i);
} }
else if (fastcmp(word, "MAXBONUSLIVES"))
mapheaderinfo[num-1]->maxbonuslives = (SINT8)i;
else if (fastcmp(word, "LEVELFLAGS")) else if (fastcmp(word, "LEVELFLAGS"))
mapheaderinfo[num-1]->levelflags = (UINT8)i; mapheaderinfo[num-1]->levelflags = (UINT8)i;
else if (fastcmp(word, "MENUFLAGS")) else if (fastcmp(word, "MENUFLAGS"))
@ -2745,11 +2747,14 @@ static void readmaincfg(MYFILE *f)
{ {
extralifetics = (UINT16)get_number(word2); extralifetics = (UINT16)get_number(word2);
} }
else if (fastcmp(word, "NIGHTSLINKTICS"))
{
nightslinktics = (UINT16)get_number(word2);
}
else if (fastcmp(word, "GAMEOVERTICS")) else if (fastcmp(word, "GAMEOVERTICS"))
{ {
gameovertics = get_number(word2); gameovertics = get_number(word2);
} }
else if (fastcmp(word, "INTROTOPLAY")) else if (fastcmp(word, "INTROTOPLAY"))
{ {
introtoplay = (UINT8)get_number(word2); introtoplay = (UINT8)get_number(word2);
@ -4937,6 +4942,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_SUSPICIOUSFACESTABBERSTATUE_WAIT", "S_SUSPICIOUSFACESTABBERSTATUE_WAIT",
"S_SUSPICIOUSFACESTABBERSTATUE_BURST1", "S_SUSPICIOUSFACESTABBERSTATUE_BURST1",
"S_SUSPICIOUSFACESTABBERSTATUE_BURST2", "S_SUSPICIOUSFACESTABBERSTATUE_BURST2",
"S_BRAMBLES",
// Big Tumbleweed // Big Tumbleweed
"S_BIGTUMBLEWEED", "S_BIGTUMBLEWEED",
@ -5408,6 +5414,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_FLICKY_01_FLAP1", "S_FLICKY_01_FLAP1",
"S_FLICKY_01_FLAP2", "S_FLICKY_01_FLAP2",
"S_FLICKY_01_FLAP3", "S_FLICKY_01_FLAP3",
"S_FLICKY_01_STAND",
"S_FLICKY_01_CENTER",
// Rabbit // Rabbit
"S_FLICKY_02_OUT", "S_FLICKY_02_OUT",
@ -5415,6 +5423,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_FLICKY_02_HOP", "S_FLICKY_02_HOP",
"S_FLICKY_02_UP", "S_FLICKY_02_UP",
"S_FLICKY_02_DOWN", "S_FLICKY_02_DOWN",
"S_FLICKY_02_STAND",
"S_FLICKY_02_CENTER",
// Chicken // Chicken
"S_FLICKY_03_OUT", "S_FLICKY_03_OUT",
@ -5423,6 +5433,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_FLICKY_03_UP", "S_FLICKY_03_UP",
"S_FLICKY_03_FLAP1", "S_FLICKY_03_FLAP1",
"S_FLICKY_03_FLAP2", "S_FLICKY_03_FLAP2",
"S_FLICKY_03_STAND",
"S_FLICKY_03_CENTER",
// Seal // Seal
"S_FLICKY_04_OUT", "S_FLICKY_04_OUT",
@ -5434,6 +5446,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_FLICKY_04_SWIM2", "S_FLICKY_04_SWIM2",
"S_FLICKY_04_SWIM3", "S_FLICKY_04_SWIM3",
"S_FLICKY_04_SWIM4", "S_FLICKY_04_SWIM4",
"S_FLICKY_04_STAND",
"S_FLICKY_04_CENTER",
// Pig // Pig
"S_FLICKY_05_OUT", "S_FLICKY_05_OUT",
@ -5441,6 +5455,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_FLICKY_05_HOP", "S_FLICKY_05_HOP",
"S_FLICKY_05_UP", "S_FLICKY_05_UP",
"S_FLICKY_05_DOWN", "S_FLICKY_05_DOWN",
"S_FLICKY_05_STAND",
"S_FLICKY_05_CENTER",
// Chipmunk // Chipmunk
"S_FLICKY_06_OUT", "S_FLICKY_06_OUT",
@ -5448,6 +5464,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_FLICKY_06_HOP", "S_FLICKY_06_HOP",
"S_FLICKY_06_UP", "S_FLICKY_06_UP",
"S_FLICKY_06_DOWN", "S_FLICKY_06_DOWN",
"S_FLICKY_06_STAND",
"S_FLICKY_06_CENTER",
// Penguin // Penguin
"S_FLICKY_07_OUT", "S_FLICKY_07_OUT",
@ -5462,6 +5480,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_FLICKY_07_SWIM1", "S_FLICKY_07_SWIM1",
"S_FLICKY_07_SWIM2", "S_FLICKY_07_SWIM2",
"S_FLICKY_07_SWIM3", "S_FLICKY_07_SWIM3",
"S_FLICKY_07_STAND",
"S_FLICKY_07_CENTER",
// Fish // Fish
"S_FLICKY_08_OUT", "S_FLICKY_08_OUT",
@ -5475,6 +5495,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_FLICKY_08_SWIM2", "S_FLICKY_08_SWIM2",
"S_FLICKY_08_SWIM3", "S_FLICKY_08_SWIM3",
"S_FLICKY_08_SWIM4", "S_FLICKY_08_SWIM4",
"S_FLICKY_08_STAND",
"S_FLICKY_08_CENTER",
// Ram // Ram
"S_FLICKY_09_OUT", "S_FLICKY_09_OUT",
@ -5482,11 +5504,15 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_FLICKY_09_HOP", "S_FLICKY_09_HOP",
"S_FLICKY_09_UP", "S_FLICKY_09_UP",
"S_FLICKY_09_DOWN", "S_FLICKY_09_DOWN",
"S_FLICKY_09_STAND",
"S_FLICKY_09_CENTER",
// Puffin // Puffin
"S_FLICKY_10_OUT", "S_FLICKY_10_OUT",
"S_FLICKY_10_FLAP1", "S_FLICKY_10_FLAP1",
"S_FLICKY_10_FLAP2", "S_FLICKY_10_FLAP2",
"S_FLICKY_10_STAND",
"S_FLICKY_10_CENTER",
// Cow // Cow
"S_FLICKY_11_OUT", "S_FLICKY_11_OUT",
@ -5494,6 +5520,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_FLICKY_11_RUN1", "S_FLICKY_11_RUN1",
"S_FLICKY_11_RUN2", "S_FLICKY_11_RUN2",
"S_FLICKY_11_RUN3", "S_FLICKY_11_RUN3",
"S_FLICKY_11_STAND",
"S_FLICKY_11_CENTER",
// Rat // Rat
"S_FLICKY_12_OUT", "S_FLICKY_12_OUT",
@ -5501,6 +5529,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_FLICKY_12_RUN1", "S_FLICKY_12_RUN1",
"S_FLICKY_12_RUN2", "S_FLICKY_12_RUN2",
"S_FLICKY_12_RUN3", "S_FLICKY_12_RUN3",
"S_FLICKY_12_STAND",
"S_FLICKY_12_CENTER",
// Bear // Bear
"S_FLICKY_13_OUT", "S_FLICKY_13_OUT",
@ -5508,12 +5538,16 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_FLICKY_13_HOP", "S_FLICKY_13_HOP",
"S_FLICKY_13_UP", "S_FLICKY_13_UP",
"S_FLICKY_13_DOWN", "S_FLICKY_13_DOWN",
"S_FLICKY_13_STAND",
"S_FLICKY_13_CENTER",
// Dove // Dove
"S_FLICKY_14_OUT", "S_FLICKY_14_OUT",
"S_FLICKY_14_FLAP1", "S_FLICKY_14_FLAP1",
"S_FLICKY_14_FLAP2", "S_FLICKY_14_FLAP2",
"S_FLICKY_14_FLAP3", "S_FLICKY_14_FLAP3",
"S_FLICKY_14_STAND",
"S_FLICKY_14_CENTER",
// Cat // Cat
"S_FLICKY_15_OUT", "S_FLICKY_15_OUT",
@ -5521,12 +5555,16 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_FLICKY_15_HOP", "S_FLICKY_15_HOP",
"S_FLICKY_15_UP", "S_FLICKY_15_UP",
"S_FLICKY_15_DOWN", "S_FLICKY_15_DOWN",
"S_FLICKY_15_STAND",
"S_FLICKY_15_CENTER",
// Canary // Canary
"S_FLICKY_16_OUT", "S_FLICKY_16_OUT",
"S_FLICKY_16_FLAP1", "S_FLICKY_16_FLAP1",
"S_FLICKY_16_FLAP2", "S_FLICKY_16_FLAP2",
"S_FLICKY_16_FLAP3", "S_FLICKY_16_FLAP3",
"S_FLICKY_16_STAND",
"S_FLICKY_16_CENTER",
// Spider // Spider
"S_SECRETFLICKY_01_OUT", "S_SECRETFLICKY_01_OUT",
@ -5534,12 +5572,16 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_SECRETFLICKY_01_HOP", "S_SECRETFLICKY_01_HOP",
"S_SECRETFLICKY_01_UP", "S_SECRETFLICKY_01_UP",
"S_SECRETFLICKY_01_DOWN", "S_SECRETFLICKY_01_DOWN",
"S_SECRETFLICKY_01_STAND",
"S_SECRETFLICKY_01_CENTER",
// Bat // Bat
"S_SECRETFLICKY_02_OUT", "S_SECRETFLICKY_02_OUT",
"S_SECRETFLICKY_02_FLAP1", "S_SECRETFLICKY_02_FLAP1",
"S_SECRETFLICKY_02_FLAP2", "S_SECRETFLICKY_02_FLAP2",
"S_SECRETFLICKY_02_FLAP3", "S_SECRETFLICKY_02_FLAP3",
"S_SECRETFLICKY_02_STAND",
"S_SECRETFLICKY_02_CENTER",
// Fan // Fan
"S_FAN", "S_FAN",
@ -6593,6 +6635,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_CRAWLASTATUE", // Crawla statue "MT_CRAWLASTATUE", // Crawla statue
"MT_FACESTABBERSTATUE", // Facestabber statue "MT_FACESTABBERSTATUE", // Facestabber statue
"MT_SUSPICIOUSFACESTABBERSTATUE", // :eggthinking: "MT_SUSPICIOUSFACESTABBERSTATUE", // :eggthinking:
"MT_BRAMBLES", // Brambles
// Arid Canyon Scenery // Arid Canyon Scenery
"MT_BIGTUMBLEWEED", "MT_BIGTUMBLEWEED",
@ -6737,23 +6780,41 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
// Flickies // Flickies
"MT_FLICKY_01", // Bluebird "MT_FLICKY_01", // Bluebird
"MT_FLICKY_01_CENTER",
"MT_FLICKY_02", // Rabbit "MT_FLICKY_02", // Rabbit
"MT_FLICKY_02_CENTER",
"MT_FLICKY_03", // Chicken "MT_FLICKY_03", // Chicken
"MT_FLICKY_03_CENTER",
"MT_FLICKY_04", // Seal "MT_FLICKY_04", // Seal
"MT_FLICKY_04_CENTER",
"MT_FLICKY_05", // Pig "MT_FLICKY_05", // Pig
"MT_FLICKY_05_CENTER",
"MT_FLICKY_06", // Chipmunk "MT_FLICKY_06", // Chipmunk
"MT_FLICKY_06_CENTER",
"MT_FLICKY_07", // Penguin "MT_FLICKY_07", // Penguin
"MT_FLICKY_07_CENTER",
"MT_FLICKY_08", // Fish "MT_FLICKY_08", // Fish
"MT_FLICKY_08_CENTER",
"MT_FLICKY_09", // Ram "MT_FLICKY_09", // Ram
"MT_FLICKY_09_CENTER",
"MT_FLICKY_10", // Puffin "MT_FLICKY_10", // Puffin
"MT_FLICKY_10_CENTER",
"MT_FLICKY_11", // Cow "MT_FLICKY_11", // Cow
"MT_FLICKY_11_CENTER",
"MT_FLICKY_12", // Rat "MT_FLICKY_12", // Rat
"MT_FLICKY_12_CENTER",
"MT_FLICKY_13", // Bear "MT_FLICKY_13", // Bear
"MT_FLICKY_13_CENTER",
"MT_FLICKY_14", // Dove "MT_FLICKY_14", // Dove
"MT_FLICKY_14_CENTER",
"MT_FLICKY_15", // Cat "MT_FLICKY_15", // Cat
"MT_FLICKY_15_CENTER",
"MT_FLICKY_16", // Canary "MT_FLICKY_16", // Canary
"MT_FLICKY_16_CENTER",
"MT_SECRETFLICKY_01", // Spider "MT_SECRETFLICKY_01", // Spider
"MT_SECRETFLICKY_01_CENTER",
"MT_SECRETFLICKY_02", // Bat "MT_SECRETFLICKY_02", // Bat
"MT_SECRETFLICKY_02_CENTER",
"MT_SEED", "MT_SEED",
// Environmental Effects // Environmental Effects
@ -7330,6 +7391,8 @@ struct {
{"CODEBASE",CODEBASE}, // or what release of SRB2 this is. {"CODEBASE",CODEBASE}, // or what release of SRB2 this is.
{"VERSION",VERSION}, // Grab the game's version! {"VERSION",VERSION}, // Grab the game's version!
{"SUBVERSION",SUBVERSION}, // more precise version number {"SUBVERSION",SUBVERSION}, // more precise version number
{"NEWTICRATE",NEWTICRATE}, // TICRATE*NEWTICRATERATIO
{"NEWTICRATERATIO",NEWTICRATERATIO},
// Special linedef executor tag numbers! // Special linedef executor tag numbers!
{"LE_PINCHPHASE",LE_PINCHPHASE}, // A boss entered pinch phase (and, in most cases, is preparing their pinch phase attack!) {"LE_PINCHPHASE",LE_PINCHPHASE}, // A boss entered pinch phase (and, in most cases, is preparing their pinch phase attack!)
@ -7624,6 +7687,9 @@ struct {
{"WEP_RAIL",WEP_RAIL}, {"WEP_RAIL",WEP_RAIL},
{"NUM_WEAPONS",NUM_WEAPONS}, {"NUM_WEAPONS",NUM_WEAPONS},
// Value for infinite lives
{"INFLIVES", INFLIVES},
// Got Flags, for player->gotflag! // Got Flags, for player->gotflag!
// Used to be MF_ for some stupid reason, now they're GF_ to stop them looking like mobjflags // Used to be MF_ for some stupid reason, now they're GF_ to stop them looking like mobjflags
{"GF_REDFLAG",GF_REDFLAG}, {"GF_REDFLAG",GF_REDFLAG},

View file

@ -245,6 +245,7 @@ typedef struct
SINT8 unlockrequired; ///< Is an unlockable required to play this level? -1 if no. SINT8 unlockrequired; ///< Is an unlockable required to play this level? -1 if no.
UINT8 levelselect; ///< Is this map available in the level select? If so, which map list is it available in? UINT8 levelselect; ///< Is this map available in the level select? If so, which map list is it available in?
SINT8 bonustype; ///< What type of bonus does this level have? (-1 for null.) SINT8 bonustype; ///< What type of bonus does this level have? (-1 for null.)
SINT8 maxbonuslives; ///< How many bonus lives to award at Intermission? (-1 for unlimited.)
UINT8 levelflags; ///< LF_flags: merged eight booleans into one UINT8 for space, see below 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 UINT8 menuflags; ///< LF2_flags: options that affect record attack / nights mode menus
@ -420,6 +421,7 @@ extern UINT16 tailsflytics;
extern UINT16 underwatertics; extern UINT16 underwatertics;
extern UINT16 spacetimetics; extern UINT16 spacetimetics;
extern UINT16 extralifetics; extern UINT16 extralifetics;
extern UINT16 nightslinktics;
extern UINT8 introtoplay; extern UINT8 introtoplay;
extern UINT8 creditscutscene; extern UINT8 creditscutscene;

View file

@ -1831,7 +1831,7 @@ static void F_AdvanceToNextScene(void)
picypos = cutscenes[cutnum]->scene[scenenum].ycoord[picnum]; picypos = cutscenes[cutnum]->scene[scenenum].ycoord[picnum];
if (cutscenes[cutnum]->scene[scenenum].musswitch[0]) if (cutscenes[cutnum]->scene[scenenum].musswitch[0])
S_ChangeMusicAdvanced(cutscenes[cutnum]->scene[scenenum].musswitch, S_ChangeMusicEx(cutscenes[cutnum]->scene[scenenum].musswitch,
cutscenes[cutnum]->scene[scenenum].musswitchflags, cutscenes[cutnum]->scene[scenenum].musswitchflags,
cutscenes[cutnum]->scene[scenenum].musicloop, cutscenes[cutnum]->scene[scenenum].musicloop,
cutscenes[cutnum]->scene[scenenum].musswitchposition, 0, 0); cutscenes[cutnum]->scene[scenenum].musswitchposition, 0, 0);
@ -1905,7 +1905,7 @@ void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean reset
stoptimer = 0; stoptimer = 0;
if (cutscenes[cutnum]->scene[0].musswitch[0]) if (cutscenes[cutnum]->scene[0].musswitch[0])
S_ChangeMusicAdvanced(cutscenes[cutnum]->scene[0].musswitch, S_ChangeMusicEx(cutscenes[cutnum]->scene[0].musswitch,
cutscenes[cutnum]->scene[0].musswitchflags, cutscenes[cutnum]->scene[0].musswitchflags,
cutscenes[cutnum]->scene[0].musicloop, cutscenes[cutnum]->scene[0].musicloop,
cutscenes[cutnum]->scene[scenenum].musswitchposition, 0, 0); cutscenes[cutnum]->scene[scenenum].musswitchposition, 0, 0);

View file

@ -202,6 +202,7 @@ UINT16 tailsflytics = 8*TICRATE;
UINT16 underwatertics = 30*TICRATE; UINT16 underwatertics = 30*TICRATE;
UINT16 spacetimetics = 11*TICRATE + (TICRATE/2); UINT16 spacetimetics = 11*TICRATE + (TICRATE/2);
UINT16 extralifetics = 4*TICRATE; UINT16 extralifetics = 4*TICRATE;
UINT16 nightslinktics = 2*TICRATE;
INT32 gameovertics = 15*TICRATE; INT32 gameovertics = 15*TICRATE;
@ -2220,6 +2221,8 @@ void G_PlayerReborn(INT32 player)
if (p->mare == 255) if (p->mare == 255)
p->mare = 0; p->mare = 0;
p->marelap = p->marebonuslap = 0;
// Check to make sure their color didn't change somehow... // Check to make sure their color didn't change somehow...
if (G_GametypeHasTeams()) if (G_GametypeHasTeams())
{ {
@ -4654,6 +4657,7 @@ void G_GhostTicker(void)
p->next = g->next; p->next = g->next;
else else
ghosts = g->next; ghosts = g->next;
Z_Free(g);
continue; continue;
} }
p = g; p = g;
@ -5654,29 +5658,28 @@ void G_AddGhost(char *defdemoname)
mthing = playerstarts[0]; mthing = playerstarts[0];
I_Assert(mthing); I_Assert(mthing);
{ // A bit more complex than P_SpawnPlayer because ghosts aren't solid and won't just push themselves out of the ceiling. { // A bit more complex than P_SpawnPlayer because ghosts aren't solid and won't just push themselves out of the ceiling.
fixed_t x,y,z; fixed_t z,f,c;
sector_t *sector; gh->mo = P_SpawnMobj(mthing->x << FRACBITS, mthing->y << FRACBITS, 0, MT_GHOST);
x = mthing->x << FRACBITS; gh->mo->angle = FixedAngle(mthing->angle*FRACUNIT);
y = mthing->y << FRACBITS; f = gh->mo->floorz;
sector = R_PointInSubsector(x, y)->sector; c = gh->mo->ceilingz - mobjinfo[MT_PLAYER].height;
if (!!(mthing->options & MTF_AMBUSH) ^ !!(mthing->options & MTF_OBJECTFLIP)) if (!!(mthing->options & MTF_AMBUSH) ^ !!(mthing->options & MTF_OBJECTFLIP))
{ {
z = sector->ceilingheight - mobjinfo[MT_PLAYER].height; z = c;
if (mthing->options >> ZSHIFT) if (mthing->options >> ZSHIFT)
z -= ((mthing->options >> ZSHIFT) << FRACBITS); z -= ((mthing->options >> ZSHIFT) << FRACBITS);
if (z < sector->floorheight) if (z < f)
z = sector->floorheight; z = f;
} }
else else
{ {
z = sector->floorheight; z = f;
if (mthing->options >> ZSHIFT) if (mthing->options >> ZSHIFT)
z += ((mthing->options >> ZSHIFT) << FRACBITS); z += ((mthing->options >> ZSHIFT) << FRACBITS);
if (z > sector->ceilingheight - mobjinfo[MT_PLAYER].height) if (z > c)
z = sector->ceilingheight - mobjinfo[MT_PLAYER].height; z = c;
} }
gh->mo = P_SpawnMobj(x, y, z, MT_GHOST); gh->mo->z = z;
gh->mo->angle = FixedAngle(mthing->angle*FRACUNIT);
} }
gh->oldmo.x = gh->mo->x; gh->oldmo.x = gh->mo->x;
@ -5875,8 +5878,14 @@ boolean G_CheckDemoStatus(void)
{ {
boolean saved; boolean saved;
if(ghosts) // ... ... ... while (ghosts)
ghosts = NULL; // :) {
demoghost *next = ghosts->next;
Z_Free(ghosts);
ghosts = next;
}
ghosts = NULL;
// DO NOT end metal sonic demos here // DO NOT end metal sonic demos here

View file

@ -1275,7 +1275,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
} }
} }
if (G_GametypeUsesLives() && !(gametype == GT_COOP && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != 0x7f)) //show lives if (G_GametypeUsesLives() && !(gametype == GT_COOP && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives
V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE|(greycheck ? V_60TRANS : 0), va("%dx", players[tab[i].num].lives)); V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE|(greycheck ? V_60TRANS : 0), va("%dx", players[tab[i].num].lives));
else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT) else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT)
{ {
@ -1413,7 +1413,7 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline
| (greycheck ? V_TRANSLUCENT : 0) | (greycheck ? V_TRANSLUCENT : 0)
| V_ALLOWLOWERCASE, name); | V_ALLOWLOWERCASE, name);
if (G_GametypeUsesLives() && !(gametype == GT_COOP && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != 0x7f)) //show lives if (G_GametypeUsesLives() && !(gametype == GT_COOP && (cv_cooplives.value == 0 || cv_cooplives.value == 3)) && (players[tab[i].num].lives != INFLIVES)) //show lives
V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE, va("%dx", players[tab[i].num].lives)); V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE, va("%dx", players[tab[i].num].lives));
else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT) else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT)
V_DrawSmallScaledPatch(x-28, y-4, 0, tagico); V_DrawSmallScaledPatch(x-28, y-4, 0, tagico);

View file

@ -649,14 +649,29 @@ static boolean SOCK_CanGet(void)
#endif #endif
#ifndef NONET #ifndef NONET
static void SOCK_Send(void) static inline ssize_t SOCK_SendToAddr(SOCKET_TYPE socket, mysockaddr_t *sockaddr)
{ {
ssize_t c = ERRSOCKET;
socklen_t d4 = (socklen_t)sizeof(struct sockaddr_in); socklen_t d4 = (socklen_t)sizeof(struct sockaddr_in);
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
socklen_t d6 = (socklen_t)sizeof(struct sockaddr_in6); socklen_t d6 = (socklen_t)sizeof(struct sockaddr_in6);
#endif #endif
socklen_t d, da = (socklen_t)sizeof(mysockaddr_t); socklen_t d, da = (socklen_t)sizeof(mysockaddr_t);
switch (sockaddr->any.sa_family)
{
case AF_INET: d = d4; break;
#ifdef HAVE_IPV6
case AF_INET6: d = d6; break;
#endif
default: d = da; break;
}
return sendto(socket, (char *)&doomcom->data, doomcom->datalength, 0, &sockaddr->any, d);
}
static void SOCK_Send(void)
{
ssize_t c = ERRSOCKET;
size_t i, j; size_t i, j;
if (!nodeconnected[doomcom->remotenode]) if (!nodeconnected[doomcom->remotenode])
@ -669,19 +684,7 @@ static void SOCK_Send(void)
for (j = 0; j < broadcastaddresses; j++) for (j = 0; j < broadcastaddresses; j++)
{ {
if (myfamily[i] == broadcastaddress[j].any.sa_family) if (myfamily[i] == broadcastaddress[j].any.sa_family)
{ SOCK_SendToAddr(mysockets[i], &broadcastaddress[j]);
if (broadcastaddress[i].any.sa_family == AF_INET)
d = d4;
#ifdef HAVE_IPV6
else if (broadcastaddress[i].any.sa_family == AF_INET6)
d = d6;
#endif
else
d = da;
c = sendto(mysockets[i], (char *)&doomcom->data, doomcom->datalength, 0,
&broadcastaddress[j].any, d);
}
} }
} }
return; return;
@ -691,35 +694,13 @@ static void SOCK_Send(void)
for (i = 0; i < mysocketses; i++) for (i = 0; i < mysocketses; i++)
{ {
if (myfamily[i] == clientaddress[doomcom->remotenode].any.sa_family) if (myfamily[i] == clientaddress[doomcom->remotenode].any.sa_family)
{ SOCK_SendToAddr(mysockets[i], &clientaddress[doomcom->remotenode]);
if (clientaddress[doomcom->remotenode].any.sa_family == AF_INET)
d = d4;
#ifdef HAVE_IPV6
else if (clientaddress[doomcom->remotenode].any.sa_family == AF_INET6)
d = d6;
#endif
else
d = da;
sendto(mysockets[i], (char *)&doomcom->data, doomcom->datalength, 0,
&clientaddress[doomcom->remotenode].any, d);
}
} }
return; return;
} }
else else
{ {
if (clientaddress[doomcom->remotenode].any.sa_family == AF_INET) c = SOCK_SendToAddr(nodesocket[doomcom->remotenode], &clientaddress[doomcom->remotenode]);
d = d4;
#ifdef HAVE_IPV6
else if (clientaddress[doomcom->remotenode].any.sa_family == AF_INET6)
d = d6;
#endif
else
d = da;
c = sendto(nodesocket[doomcom->remotenode], (char *)&doomcom->data, doomcom->datalength, 0,
&clientaddress[doomcom->remotenode].any, d);
} }
if (c == ERRSOCKET && errno != ECONNREFUSED && errno != EWOULDBLOCK) if (c == ERRSOCKET && errno != ECONNREFUSED && errno != EWOULDBLOCK)
@ -1007,7 +988,7 @@ static boolean UDP_Socket(void)
if (gaie == 0) if (gaie == 0)
{ {
runp = ai; runp = ai;
while (runp != NULL) while (runp != NULL && s < MAXNETNODES+1)
{ {
memcpy(&clientaddress[s], runp->ai_addr, runp->ai_addrlen); memcpy(&clientaddress[s], runp->ai_addr, runp->ai_addrlen);
s++; s++;
@ -1022,12 +1003,15 @@ static boolean UDP_Socket(void)
clientaddress[s].ip4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); //GetLocalAddress(); // my own ip clientaddress[s].ip4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); //GetLocalAddress(); // my own ip
s++; s++;
} }
s = 0;
// setup broadcast adress to BROADCASTADDR entry // setup broadcast adress to BROADCASTADDR entry
gaie = I_getaddrinfo("255.255.255.255", "0", &hints, &ai); gaie = I_getaddrinfo("255.255.255.255", "0", &hints, &ai);
if (gaie == 0) if (gaie == 0)
{ {
runp = ai; runp = ai;
while (runp != NULL) while (runp != NULL && s < MAXNETNODES+1)
{ {
memcpy(&broadcastaddress[s], runp->ai_addr, runp->ai_addrlen); memcpy(&broadcastaddress[s], runp->ai_addr, runp->ai_addrlen);
s++; s++;
@ -1050,7 +1034,7 @@ static boolean UDP_Socket(void)
if (gaie == 0) if (gaie == 0)
{ {
runp = ai; runp = ai;
while (runp != NULL) while (runp != NULL && s < MAXNETNODES+1)
{ {
memcpy(&broadcastaddress[s], runp->ai_addr, runp->ai_addrlen); memcpy(&broadcastaddress[s], runp->ai_addr, runp->ai_addrlen);
s++; s++;

View file

@ -232,6 +232,7 @@ char sprnames[NUMSPRITES + 1][5] =
"CFLG", // Waving flag/segment "CFLG", // Waving flag/segment
"CSTA", // Crawla statue "CSTA", // Crawla statue
"CBBS", // Facestabber statue "CBBS", // Facestabber statue
"CABR", // Brambles
// Arid Canyon Scenery // Arid Canyon Scenery
"BTBL", // Big tumbleweed "BTBL", // Big tumbleweed
@ -2158,6 +2159,8 @@ state_t states[NUMSTATES] =
{SPR_CBBS, FF_ANIMATE, 23, {NULL}, 6, 1, S_SUSPICIOUSFACESTABBERSTATUE_BURST2}, // S_SUSPICIOUSFACESTABBERSTATUE_BURST1 {SPR_CBBS, FF_ANIMATE, 23, {NULL}, 6, 1, S_SUSPICIOUSFACESTABBERSTATUE_BURST2}, // S_SUSPICIOUSFACESTABBERSTATUE_BURST1
{SPR_NULL, 0, 40, {A_StatueBurst}, MT_FACESTABBER, S_FACESTABBER_CHARGE2, S_NULL}, // S_SUSPICIOUSFACESTABBERSTATUE_BURST2 {SPR_NULL, 0, 40, {A_StatueBurst}, MT_FACESTABBER, S_FACESTABBER_CHARGE2, S_NULL}, // S_SUSPICIOUSFACESTABBERSTATUE_BURST2
{SPR_CABR, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BRAMBLES
// Big Tumbleweed // Big Tumbleweed
{SPR_BTBL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BIGTUMBLEWEED {SPR_BTBL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BIGTUMBLEWEED
{SPR_BTBL, 0, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL2}, // S_BIGTUMBLEWEED_ROLL1 {SPR_BTBL, 0, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL2}, // S_BIGTUMBLEWEED_ROLL1
@ -2638,6 +2641,8 @@ state_t states[NUMSTATES] =
{SPR_FL01, 1, 3, {A_FlickyFly}, 4*FRACUNIT, 16*FRACUNIT, S_FLICKY_01_FLAP2}, // S_FLICKY_01_FLAP1 {SPR_FL01, 1, 3, {A_FlickyFly}, 4*FRACUNIT, 16*FRACUNIT, S_FLICKY_01_FLAP2}, // S_FLICKY_01_FLAP1
{SPR_FL01, 2, 3, {A_FlickyFly}, 4*FRACUNIT, 16*FRACUNIT, S_FLICKY_01_FLAP3}, // S_FLICKY_01_FLAP2 {SPR_FL01, 2, 3, {A_FlickyFly}, 4*FRACUNIT, 16*FRACUNIT, S_FLICKY_01_FLAP3}, // S_FLICKY_01_FLAP2
{SPR_FL01, 3, 3, {A_FlickyFly}, 4*FRACUNIT, 16*FRACUNIT, S_FLICKY_01_FLAP1}, // S_FLICKY_01_FLAP3 {SPR_FL01, 3, 3, {A_FlickyFly}, 4*FRACUNIT, 16*FRACUNIT, S_FLICKY_01_FLAP1}, // S_FLICKY_01_FLAP3
{SPR_FL01, FF_ANIMATE|1, -1, {NULL}, 2, 3, S_NULL}, // S_FLICKY_01_STAND
{SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_01, 384*FRACUNIT, S_FLICKY_01_CENTER}, // S_FLICKY_01_CENTER
// Rabbit // Rabbit
{SPR_FL02, 0, 2, {A_FlickyCheck}, S_FLICKY_02_AIM, 0, S_FLICKY_02_OUT}, // S_FLICKY_02_OUT {SPR_FL02, 0, 2, {A_FlickyCheck}, S_FLICKY_02_AIM, 0, S_FLICKY_02_OUT}, // S_FLICKY_02_OUT
@ -2645,6 +2650,8 @@ state_t states[NUMSTATES] =
{SPR_FL02, 1, 1, {A_FlickyHop}, 6*FRACUNIT, 4*FRACUNIT, S_FLICKY_02_UP}, // S_FLICKY_02_HOP {SPR_FL02, 1, 1, {A_FlickyHop}, 6*FRACUNIT, 4*FRACUNIT, S_FLICKY_02_UP}, // S_FLICKY_02_HOP
{SPR_FL02, 2, 2, {A_FlickyCheck}, S_FLICKY_02_AIM, S_FLICKY_02_DOWN, S_FLICKY_02_UP}, // S_FLICKY_02_UP {SPR_FL02, 2, 2, {A_FlickyCheck}, S_FLICKY_02_AIM, S_FLICKY_02_DOWN, S_FLICKY_02_UP}, // S_FLICKY_02_UP
{SPR_FL02, 3, 2, {A_FlickyCheck}, S_FLICKY_02_AIM, 0, S_FLICKY_02_DOWN}, // S_FLICKY_02_DOWN {SPR_FL02, 3, 2, {A_FlickyCheck}, S_FLICKY_02_AIM, 0, S_FLICKY_02_DOWN}, // S_FLICKY_02_DOWN
{SPR_FL02, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL}, // S_FLICKY_02_STAND
{SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_02, 384*FRACUNIT, S_FLICKY_02_CENTER}, // S_FLICKY_02_CENTER
// Chicken // Chicken
{SPR_FL03, 0, 2, {A_FlickyCheck}, S_FLICKY_03_AIM, S_FLICKY_03_FLAP1, S_FLICKY_03_OUT}, // S_FLICKY_03_OUT {SPR_FL03, 0, 2, {A_FlickyCheck}, S_FLICKY_03_AIM, S_FLICKY_03_FLAP1, S_FLICKY_03_OUT}, // S_FLICKY_03_OUT
@ -2653,6 +2660,8 @@ state_t states[NUMSTATES] =
{SPR_FL03, 2, 2, {A_FlickyFlutter}, S_FLICKY_03_HOP, S_FLICKY_03_FLAP1, S_FLICKY_03_UP}, // S_FLICKY_03_UP {SPR_FL03, 2, 2, {A_FlickyFlutter}, S_FLICKY_03_HOP, S_FLICKY_03_FLAP1, S_FLICKY_03_UP}, // S_FLICKY_03_UP
{SPR_FL03, 3, 2, {A_FlickyFlutter}, S_FLICKY_03_HOP, 0, S_FLICKY_03_FLAP2}, // S_FLICKY_03_FLAP1 {SPR_FL03, 3, 2, {A_FlickyFlutter}, S_FLICKY_03_HOP, 0, S_FLICKY_03_FLAP2}, // S_FLICKY_03_FLAP1
{SPR_FL03, 4, 2, {A_FlickyFlutter}, S_FLICKY_03_HOP, 0, S_FLICKY_03_FLAP1}, // S_FLICKY_03_FLAP2 {SPR_FL03, 4, 2, {A_FlickyFlutter}, S_FLICKY_03_HOP, 0, S_FLICKY_03_FLAP1}, // S_FLICKY_03_FLAP2
{SPR_FL03, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL}, // S_FLICKY_03_STAND
{SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_03, 384*FRACUNIT, S_FLICKY_03_CENTER}, // S_FLICKY_03_CENTER
// Seal // Seal
{SPR_FL04, 0, 2, {A_FlickyCheck}, S_FLICKY_04_AIM, 0, S_FLICKY_04_OUT}, // S_FLICKY_04_OUT {SPR_FL04, 0, 2, {A_FlickyCheck}, S_FLICKY_04_AIM, 0, S_FLICKY_04_OUT}, // S_FLICKY_04_OUT
@ -2664,6 +2673,8 @@ state_t states[NUMSTATES] =
{SPR_FL04, 4, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_04_SWIM1, S_FLICKY_04_SWIM3}, // S_FLICKY_04_SWIM2 {SPR_FL04, 4, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_04_SWIM1, S_FLICKY_04_SWIM3}, // S_FLICKY_04_SWIM2
{SPR_FL04, 3, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_04_SWIM1, S_FLICKY_04_SWIM4}, // S_FLICKY_04_SWIM3 {SPR_FL04, 3, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_04_SWIM1, S_FLICKY_04_SWIM4}, // S_FLICKY_04_SWIM3
{SPR_FL04, 5, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_04_SWIM1, S_FLICKY_04_SWIM1}, // S_FLICKY_04_SWIM4 {SPR_FL04, 5, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_04_SWIM1, S_FLICKY_04_SWIM1}, // S_FLICKY_04_SWIM4
{SPR_FL04, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL}, // S_FLICKY_04_STAND
{SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_04, 384*FRACUNIT, S_FLICKY_04_CENTER}, // S_FLICKY_04_CENTER
// Pig // Pig
{SPR_FL05, 0, 2, {A_FlickyCheck}, S_FLICKY_05_AIM, 0, S_FLICKY_05_OUT}, // S_FLICKY_05_OUT {SPR_FL05, 0, 2, {A_FlickyCheck}, S_FLICKY_05_AIM, 0, S_FLICKY_05_OUT}, // S_FLICKY_05_OUT
@ -2671,6 +2682,8 @@ state_t states[NUMSTATES] =
{SPR_FL05, 1, 1, {A_FlickyHop}, 4*FRACUNIT, 3*FRACUNIT, S_FLICKY_05_UP}, // S_FLICKY_05_HOP {SPR_FL05, 1, 1, {A_FlickyHop}, 4*FRACUNIT, 3*FRACUNIT, S_FLICKY_05_UP}, // S_FLICKY_05_HOP
{SPR_FL05, 2, 2, {A_FlickyCheck}, S_FLICKY_05_AIM, S_FLICKY_05_DOWN, S_FLICKY_05_UP}, // S_FLICKY_05_UP {SPR_FL05, 2, 2, {A_FlickyCheck}, S_FLICKY_05_AIM, S_FLICKY_05_DOWN, S_FLICKY_05_UP}, // S_FLICKY_05_UP
{SPR_FL05, 3, 2, {A_FlickyCheck}, S_FLICKY_05_AIM, 0, S_FLICKY_05_DOWN}, // S_FLICKY_05_DOWN {SPR_FL05, 3, 2, {A_FlickyCheck}, S_FLICKY_05_AIM, 0, S_FLICKY_05_DOWN}, // S_FLICKY_05_DOWN
{SPR_FL05, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL}, // S_FLICKY_05_STAND
{SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_05, 384*FRACUNIT, S_FLICKY_05_CENTER}, // S_FLICKY_05_CENTER
// Chipmunk // Chipmunk
{SPR_FL06, 0, 2, {A_FlickyCheck}, S_FLICKY_06_AIM, 0, S_FLICKY_06_OUT}, // S_FLICKY_06_OUT {SPR_FL06, 0, 2, {A_FlickyCheck}, S_FLICKY_06_AIM, 0, S_FLICKY_06_OUT}, // S_FLICKY_06_OUT
@ -2678,6 +2691,8 @@ state_t states[NUMSTATES] =
{SPR_FL06, 1, 1, {A_FlickyHop}, 5*FRACUNIT, 6*FRACUNIT, S_FLICKY_06_UP}, // S_FLICKY_06_HOP {SPR_FL06, 1, 1, {A_FlickyHop}, 5*FRACUNIT, 6*FRACUNIT, S_FLICKY_06_UP}, // S_FLICKY_06_HOP
{SPR_FL06, 2, 2, {A_FlickyCheck}, S_FLICKY_06_AIM, S_FLICKY_06_DOWN, S_FLICKY_06_UP}, // S_FLICKY_06_UP {SPR_FL06, 2, 2, {A_FlickyCheck}, S_FLICKY_06_AIM, S_FLICKY_06_DOWN, S_FLICKY_06_UP}, // S_FLICKY_06_UP
{SPR_FL06, 3, 2, {A_FlickyCheck}, S_FLICKY_06_AIM, 0, S_FLICKY_06_DOWN}, // S_FLICKY_06_DOWN {SPR_FL06, 3, 2, {A_FlickyCheck}, S_FLICKY_06_AIM, 0, S_FLICKY_06_DOWN}, // S_FLICKY_06_DOWN
{SPR_FL06, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL}, // S_FLICKY_06_STAND
{SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_06, 384*FRACUNIT, S_FLICKY_06_CENTER}, // S_FLICKY_06_CENTER
// Penguin // Penguin
{SPR_FL07, 0, 2, {A_FlickyCheck}, S_FLICKY_07_AIML, 0, S_FLICKY_07_OUT}, // S_FLICKY_07_OUT {SPR_FL07, 0, 2, {A_FlickyCheck}, S_FLICKY_07_AIML, 0, S_FLICKY_07_OUT}, // S_FLICKY_07_OUT
@ -2692,6 +2707,8 @@ state_t states[NUMSTATES] =
{SPR_FL07, 4, 4, {A_FlickyFly}, 3*FRACUNIT, 72*FRACUNIT, S_FLICKY_07_SWIM2}, // S_FLICKY_07_SWIM1 {SPR_FL07, 4, 4, {A_FlickyFly}, 3*FRACUNIT, 72*FRACUNIT, S_FLICKY_07_SWIM2}, // S_FLICKY_07_SWIM1
{SPR_FL07, 5, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_07_SWIM1, S_FLICKY_07_SWIM3}, // S_FLICKY_07_SWIM2 {SPR_FL07, 5, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_07_SWIM1, S_FLICKY_07_SWIM3}, // S_FLICKY_07_SWIM2
{SPR_FL07, 6, 4, {A_FlickyCoast}, 2*FRACUNIT, S_FLICKY_07_SWIM1, S_FLICKY_07_SWIM3}, // S_FLICKY_07_SWIM3 {SPR_FL07, 6, 4, {A_FlickyCoast}, 2*FRACUNIT, S_FLICKY_07_SWIM1, S_FLICKY_07_SWIM3}, // S_FLICKY_07_SWIM3
{SPR_FL07, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL}, // S_FLICKY_07_STAND
{SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_07, 384*FRACUNIT, S_FLICKY_07_CENTER}, // S_FLICKY_07_CENTER
// Fish // Fish
{SPR_FL08, 0, 2, {A_FlickyCheck}, S_FLICKY_08_AIM, 0, S_FLICKY_08_OUT}, // S_FLICKY_08_OUT {SPR_FL08, 0, 2, {A_FlickyCheck}, S_FLICKY_08_AIM, 0, S_FLICKY_08_OUT}, // S_FLICKY_08_OUT
@ -2705,6 +2722,8 @@ state_t states[NUMSTATES] =
{SPR_FL08, 1, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_08_SWIM1, S_FLICKY_08_SWIM3}, // S_FLICKY_08_SWIM2 {SPR_FL08, 1, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_08_SWIM1, S_FLICKY_08_SWIM3}, // S_FLICKY_08_SWIM2
{SPR_FL08, 0, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_08_SWIM1, S_FLICKY_08_SWIM4}, // S_FLICKY_08_SWIM3 {SPR_FL08, 0, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_08_SWIM1, S_FLICKY_08_SWIM4}, // S_FLICKY_08_SWIM3
{SPR_FL08, 2, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_08_SWIM1, S_FLICKY_08_SWIM4}, // S_FLICKY_08_SWIM4 {SPR_FL08, 2, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_08_SWIM1, S_FLICKY_08_SWIM4}, // S_FLICKY_08_SWIM4
{SPR_FL08, FF_ANIMATE, -1, {NULL}, 2, 4, S_NULL}, // S_FLICKY_08_STAND
{SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_08, 384*FRACUNIT, S_FLICKY_08_CENTER}, // S_FLICKY_08_CENTER
// Ram // Ram
{SPR_FL09, 0, 2, {A_FlickyCheck}, S_FLICKY_09_AIM, 0, S_FLICKY_09_OUT}, // S_FLICKY_09_OUT {SPR_FL09, 0, 2, {A_FlickyCheck}, S_FLICKY_09_AIM, 0, S_FLICKY_09_OUT}, // S_FLICKY_09_OUT
@ -2712,11 +2731,15 @@ state_t states[NUMSTATES] =
{SPR_FL09, 1, 1, {A_FlickyHop}, 7*FRACUNIT, 2*FRACUNIT, S_FLICKY_09_UP}, // S_FLICKY_09_HOP {SPR_FL09, 1, 1, {A_FlickyHop}, 7*FRACUNIT, 2*FRACUNIT, S_FLICKY_09_UP}, // S_FLICKY_09_HOP
{SPR_FL09, 2, 2, {A_FlickyCheck}, S_FLICKY_09_AIM, S_FLICKY_09_DOWN, S_FLICKY_09_UP}, // S_FLICKY_09_UP {SPR_FL09, 2, 2, {A_FlickyCheck}, S_FLICKY_09_AIM, S_FLICKY_09_DOWN, S_FLICKY_09_UP}, // S_FLICKY_09_UP
{SPR_FL09, 3, 2, {A_FlickyCheck}, S_FLICKY_09_AIM, 0, S_FLICKY_09_DOWN}, // S_FLICKY_09_DOWN {SPR_FL09, 3, 2, {A_FlickyCheck}, S_FLICKY_09_AIM, 0, S_FLICKY_09_DOWN}, // S_FLICKY_09_DOWN
{SPR_FL09, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL}, // S_FLICKY_09_STAND
{SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_09, 384*FRACUNIT, S_FLICKY_09_CENTER}, // S_FLICKY_09_CENTER
// Puffin // Puffin
{SPR_FL10, 0, 2, {A_FlickyCheck}, S_FLICKY_10_FLAP1, S_FLICKY_10_FLAP1, S_FLICKY_10_OUT}, // S_FLICKY_10_OUT {SPR_FL10, 0, 2, {A_FlickyCheck}, S_FLICKY_10_FLAP1, S_FLICKY_10_FLAP1, S_FLICKY_10_OUT}, // S_FLICKY_10_OUT
{SPR_FL10, 1, 3, {A_FlickySoar}, 4*FRACUNIT, 16*FRACUNIT, S_FLICKY_10_FLAP2}, // S_FLICKY_10_FLAP1 {SPR_FL10, 1, 3, {A_FlickySoar}, 4*FRACUNIT, 16*FRACUNIT, S_FLICKY_10_FLAP2}, // S_FLICKY_10_FLAP1
{SPR_FL10, 2, 3, {A_FlickySoar}, 4*FRACUNIT, 16*FRACUNIT, S_FLICKY_10_FLAP1}, // S_FLICKY_10_FLAP2 {SPR_FL10, 2, 3, {A_FlickySoar}, 4*FRACUNIT, 16*FRACUNIT, S_FLICKY_10_FLAP1}, // S_FLICKY_10_FLAP2
{SPR_FL10, FF_ANIMATE|1, -1, {NULL}, 1, 3, S_NULL}, // S_FLICKY_10_STAND
{SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_10, 384*FRACUNIT, S_FLICKY_10_CENTER}, // S_FLICKY_10_CENTER
// Cow // Cow
{SPR_FL11, 0, 2, {A_FlickyCheck}, S_FLICKY_11_AIM, 0, S_FLICKY_11_OUT}, // S_FLICKY_11_OUT {SPR_FL11, 0, 2, {A_FlickyCheck}, S_FLICKY_11_AIM, 0, S_FLICKY_11_OUT}, // S_FLICKY_11_OUT
@ -2724,6 +2747,8 @@ state_t states[NUMSTATES] =
{SPR_FL11, 1, 3, {A_FlickyHop}, FRACUNIT/2, 2*FRACUNIT, S_FLICKY_11_RUN2}, // S_FLICKY_11_RUN1 {SPR_FL11, 1, 3, {A_FlickyHop}, FRACUNIT/2, 2*FRACUNIT, S_FLICKY_11_RUN2}, // S_FLICKY_11_RUN1
{SPR_FL11, 2, 4, {A_FlickyHop}, FRACUNIT/2, 2*FRACUNIT, S_FLICKY_11_RUN3}, // S_FLICKY_11_RUN2 {SPR_FL11, 2, 4, {A_FlickyHop}, FRACUNIT/2, 2*FRACUNIT, S_FLICKY_11_RUN3}, // S_FLICKY_11_RUN2
{SPR_FL11, 3, 4, {A_FlickyHop}, FRACUNIT/2, 2*FRACUNIT, S_FLICKY_11_AIM}, // S_FLICKY_11_RUN3 {SPR_FL11, 3, 4, {A_FlickyHop}, FRACUNIT/2, 2*FRACUNIT, S_FLICKY_11_AIM}, // S_FLICKY_11_RUN3
{SPR_FL11, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL}, // S_FLICKY_11_STAND
{SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_11, 384*FRACUNIT, S_FLICKY_11_CENTER}, // S_FLICKY_11_CENTER
// Rat // Rat
{SPR_FL12, 0, 2, {A_FlickyCheck}, S_FLICKY_12_AIM, 0, S_FLICKY_12_OUT}, // S_FLICKY_12_OUT {SPR_FL12, 0, 2, {A_FlickyCheck}, S_FLICKY_12_AIM, 0, S_FLICKY_12_OUT}, // S_FLICKY_12_OUT
@ -2731,6 +2756,8 @@ state_t states[NUMSTATES] =
{SPR_FL12, 1, 2, {A_FlickyHop}, 1, 12*FRACUNIT, S_FLICKY_12_RUN2}, // S_FLICKY_12_RUN1 {SPR_FL12, 1, 2, {A_FlickyHop}, 1, 12*FRACUNIT, S_FLICKY_12_RUN2}, // S_FLICKY_12_RUN1
{SPR_FL12, 2, 3, {A_FlickyHop}, 1, 12*FRACUNIT, S_FLICKY_12_RUN3}, // S_FLICKY_12_RUN2 {SPR_FL12, 2, 3, {A_FlickyHop}, 1, 12*FRACUNIT, S_FLICKY_12_RUN3}, // S_FLICKY_12_RUN2
{SPR_FL12, 3, 3, {A_FlickyHop}, 1, 12*FRACUNIT, S_FLICKY_12_AIM}, // S_FLICKY_12_RUN3 {SPR_FL12, 3, 3, {A_FlickyHop}, 1, 12*FRACUNIT, S_FLICKY_12_AIM}, // S_FLICKY_12_RUN3
{SPR_FL12, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL}, // S_FLICKY_12_STAND
{SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_12, 384*FRACUNIT, S_FLICKY_12_CENTER}, // S_FLICKY_12_CENTER
// Bear // Bear
{SPR_FL13, 0, 2, {A_FlickyCheck}, S_FLICKY_13_AIM, 0, S_FLICKY_13_OUT}, // S_FLICKY_13_OUT {SPR_FL13, 0, 2, {A_FlickyCheck}, S_FLICKY_13_AIM, 0, S_FLICKY_13_OUT}, // S_FLICKY_13_OUT
@ -2738,12 +2765,16 @@ state_t states[NUMSTATES] =
{SPR_FL13, 1, 1, {A_FlickyHop}, 5*FRACUNIT, 3*FRACUNIT, S_FLICKY_13_UP}, // S_FLICKY_13_HOP {SPR_FL13, 1, 1, {A_FlickyHop}, 5*FRACUNIT, 3*FRACUNIT, S_FLICKY_13_UP}, // S_FLICKY_13_HOP
{SPR_FL13, 2, 2, {A_FlickyCheck}, S_FLICKY_13_AIM, S_FLICKY_13_DOWN, S_FLICKY_13_UP}, // S_FLICKY_13_UP {SPR_FL13, 2, 2, {A_FlickyCheck}, S_FLICKY_13_AIM, S_FLICKY_13_DOWN, S_FLICKY_13_UP}, // S_FLICKY_13_UP
{SPR_FL13, 3, 2, {A_FlickyCheck}, S_FLICKY_13_AIM, 0, S_FLICKY_13_DOWN}, // S_FLICKY_13_DOWN {SPR_FL13, 3, 2, {A_FlickyCheck}, S_FLICKY_13_AIM, 0, S_FLICKY_13_DOWN}, // S_FLICKY_13_DOWN
{SPR_FL13, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL}, // S_FLICKY_13_STAND
{SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_13, 384*FRACUNIT, S_FLICKY_13_CENTER}, // S_FLICKY_13_CENTER
// Dove // Dove
{SPR_FL14, 0, 2, {A_FlickyCheck}, S_FLICKY_14_FLAP1, S_FLICKY_14_FLAP1, S_FLICKY_14_OUT}, // S_FLICKY_14_OUT {SPR_FL14, 0, 2, {A_FlickyCheck}, S_FLICKY_14_FLAP1, S_FLICKY_14_FLAP1, S_FLICKY_14_OUT}, // S_FLICKY_14_OUT
{SPR_FL14, 1, 3, {A_FlickySoar}, 4*FRACUNIT, 32*FRACUNIT, S_FLICKY_14_FLAP2}, // S_FLICKY_14_FLAP1 {SPR_FL14, 1, 3, {A_FlickySoar}, 4*FRACUNIT, 32*FRACUNIT, S_FLICKY_14_FLAP2}, // S_FLICKY_14_FLAP1
{SPR_FL14, 2, 3, {A_FlickySoar}, 4*FRACUNIT, 32*FRACUNIT, S_FLICKY_14_FLAP3}, // S_FLICKY_14_FLAP2 {SPR_FL14, 2, 3, {A_FlickySoar}, 4*FRACUNIT, 32*FRACUNIT, S_FLICKY_14_FLAP3}, // S_FLICKY_14_FLAP2
{SPR_FL14, 3, 3, {A_FlickySoar}, 4*FRACUNIT, 32*FRACUNIT, S_FLICKY_14_FLAP1}, // S_FLICKY_14_FLAP3 {SPR_FL14, 3, 3, {A_FlickySoar}, 4*FRACUNIT, 32*FRACUNIT, S_FLICKY_14_FLAP1}, // S_FLICKY_14_FLAP3
{SPR_FL14, FF_ANIMATE|1, -1, {NULL}, 2, 3, S_NULL}, // S_FLICKY_14_STAND
{SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_14, 384*FRACUNIT, S_FLICKY_14_CENTER}, // S_FLICKY_14_CENTER
// Cat // Cat
{SPR_FL15, 0, 2, {A_FlickyCheck}, S_FLICKY_15_AIM, 0, S_FLICKY_15_OUT}, // S_FLICKY_15_OUT {SPR_FL15, 0, 2, {A_FlickyCheck}, S_FLICKY_15_AIM, 0, S_FLICKY_15_OUT}, // S_FLICKY_15_OUT
@ -2751,12 +2782,16 @@ state_t states[NUMSTATES] =
{SPR_FL15, 1, 1, {A_FlickyFlounder}, 2*FRACUNIT, 6*FRACUNIT, S_FLICKY_15_UP}, // S_FLICKY_15_HOP {SPR_FL15, 1, 1, {A_FlickyFlounder}, 2*FRACUNIT, 6*FRACUNIT, S_FLICKY_15_UP}, // S_FLICKY_15_HOP
{SPR_FL15, 2, 2, {A_FlickyCheck}, S_FLICKY_15_AIM, S_FLICKY_15_DOWN, S_FLICKY_15_UP}, // S_FLICKY_15_UP {SPR_FL15, 2, 2, {A_FlickyCheck}, S_FLICKY_15_AIM, S_FLICKY_15_DOWN, S_FLICKY_15_UP}, // S_FLICKY_15_UP
{SPR_FL15, 3, 2, {A_FlickyCheck}, S_FLICKY_15_AIM, 0, S_FLICKY_15_DOWN}, // S_FLICKY_15_DOWN {SPR_FL15, 3, 2, {A_FlickyCheck}, S_FLICKY_15_AIM, 0, S_FLICKY_15_DOWN}, // S_FLICKY_15_DOWN
{SPR_FL15, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL}, // S_FLICKY_15_STAND
{SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_15, 384*FRACUNIT, S_FLICKY_15_CENTER}, // S_FLICKY_15_CENTER
// Canary // Canary
{SPR_FL16, 0, 2, {A_FlickyHeightCheck}, S_FLICKY_16_FLAP1, 0, S_FLICKY_16_OUT}, // S_FLICKY_16_OUT {SPR_FL16, 0, 2, {A_FlickyHeightCheck}, S_FLICKY_16_FLAP1, 0, S_FLICKY_16_OUT}, // S_FLICKY_16_OUT
{SPR_FL16, 1, 3, {A_FlickyFly}, 4*FRACUNIT, 8*FRACUNIT, S_FLICKY_16_FLAP2}, // S_FLICKY_16_FLAP1 {SPR_FL16, 1, 3, {A_FlickyFly}, 4*FRACUNIT, 8*FRACUNIT, S_FLICKY_16_FLAP2}, // S_FLICKY_16_FLAP1
{SPR_FL16, 2, 3, {A_SetObjectFlags}, MF_NOGRAVITY, 1, S_FLICKY_16_FLAP3}, // S_FLICKY_16_FLAP2 {SPR_FL16, 2, 3, {A_SetObjectFlags}, MF_NOGRAVITY, 1, S_FLICKY_16_FLAP3}, // S_FLICKY_16_FLAP2
{SPR_FL16, 3, 3, {A_FlickyHeightCheck}, S_FLICKY_16_FLAP1, 0, S_FLICKY_16_FLAP3}, // S_FLICKY_16_FLAP3 {SPR_FL16, 3, 3, {A_FlickyHeightCheck}, S_FLICKY_16_FLAP1, 0, S_FLICKY_16_FLAP3}, // S_FLICKY_16_FLAP3
{SPR_FL16, FF_ANIMATE|1, -1, {NULL}, 2, 3, S_NULL}, // S_FLICKY_16_STAND
{SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_16, 384*FRACUNIT, S_FLICKY_16_CENTER}, // S_FLICKY_16_CENTER
// Spider // Spider
{SPR_FS01, 0, 2, {A_FlickyCheck}, S_SECRETFLICKY_01_AIM, 0, S_SECRETFLICKY_01_OUT}, // S_SECRETFLICKY_01_OUT {SPR_FS01, 0, 2, {A_FlickyCheck}, S_SECRETFLICKY_01_AIM, 0, S_SECRETFLICKY_01_OUT}, // S_SECRETFLICKY_01_OUT
@ -2764,12 +2799,16 @@ state_t states[NUMSTATES] =
{SPR_FS01, 1, 1, {A_FlickyFlounder}, 2*FRACUNIT, 6*FRACUNIT, S_SECRETFLICKY_01_UP}, // S_SECRETFLICKY_01_HOP {SPR_FS01, 1, 1, {A_FlickyFlounder}, 2*FRACUNIT, 6*FRACUNIT, S_SECRETFLICKY_01_UP}, // S_SECRETFLICKY_01_HOP
{SPR_FS01, 2, 2, {A_FlickyCheck}, S_SECRETFLICKY_01_AIM, S_SECRETFLICKY_01_DOWN, S_SECRETFLICKY_01_UP}, // S_SECRETFLICKY_01_UP {SPR_FS01, 2, 2, {A_FlickyCheck}, S_SECRETFLICKY_01_AIM, S_SECRETFLICKY_01_DOWN, S_SECRETFLICKY_01_UP}, // S_SECRETFLICKY_01_UP
{SPR_FS01, 3, 2, {A_FlickyCheck}, S_SECRETFLICKY_01_AIM, 0, S_SECRETFLICKY_01_DOWN}, // S_SECRETFLICKY_01_DOWN {SPR_FS01, 3, 2, {A_FlickyCheck}, S_SECRETFLICKY_01_AIM, 0, S_SECRETFLICKY_01_DOWN}, // S_SECRETFLICKY_01_DOWN
{SPR_FS01, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL}, // S_SECRETFLICKY_01_STAND
{SPR_NULL, 0, 15, {A_FlickyCenter}, MT_SECRETFLICKY_01, 384*FRACUNIT, S_SECRETFLICKY_01_CENTER}, // S_SECRETFLICKY_01_CENTER
// Bat // Bat
{SPR_FS02, 0, 2, {A_FlickyHeightCheck}, S_SECRETFLICKY_02_FLAP1, S_SECRETFLICKY_02_FLAP1, S_SECRETFLICKY_02_OUT}, // S_SECRETFLICKY_02_OUT {SPR_FS02, 0, 2, {A_FlickyHeightCheck}, S_SECRETFLICKY_02_FLAP1, S_SECRETFLICKY_02_FLAP1, S_SECRETFLICKY_02_OUT}, // S_SECRETFLICKY_02_OUT
{SPR_FS02, 1, 3, {A_FlickyFly}, 4*FRACUNIT, 16*FRACUNIT, S_SECRETFLICKY_02_FLAP2}, // S_SECRETFLICKY_02_FLAP1 {SPR_FS02, 1, 3, {A_FlickyFly}, 4*FRACUNIT, 16*FRACUNIT, S_SECRETFLICKY_02_FLAP2}, // S_SECRETFLICKY_02_FLAP1
{SPR_FS02, 2, 3, {A_FlickyFly}, 4*FRACUNIT, 16*FRACUNIT, S_SECRETFLICKY_02_FLAP3}, // S_SECRETFLICKY_02_FLAP2 {SPR_FS02, 2, 3, {A_FlickyFly}, 4*FRACUNIT, 16*FRACUNIT, S_SECRETFLICKY_02_FLAP3}, // S_SECRETFLICKY_02_FLAP2
{SPR_FS02, 3, 3, {A_FlickyFly}, 4*FRACUNIT, 16*FRACUNIT, S_SECRETFLICKY_02_FLAP1}, // S_SECRETFLICKY_02_FLAP3 {SPR_FS02, 3, 3, {A_FlickyFly}, 4*FRACUNIT, 16*FRACUNIT, S_SECRETFLICKY_02_FLAP1}, // S_SECRETFLICKY_02_FLAP3
{SPR_FS02, FF_ANIMATE|1, -1, {NULL}, 2, 2, S_NULL}, // S_SECRETFLICKY_02_STAND
{SPR_NULL, 0, 15, {A_FlickyCenter}, MT_SECRETFLICKY_02, 384*FRACUNIT, S_SECRETFLICKY_02_CENTER}, // S_SECRETFLICKY_02_CENTER
// Fan // Fan
{SPR_FANS, 0, 1, {A_FanBubbleSpawn}, 2048, 0, S_FAN2}, // S_FAN {SPR_FANS, 0, 1, {A_FanBubbleSpawn}, 2048, 0, S_FAN2}, // S_FAN
@ -10685,6 +10724,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
MT_ROCKCRUMBLE3 // raisestate MT_ROCKCRUMBLE3 // raisestate
}, },
{ // MT_BRAMBLES
1125, // doomednum
S_BRAMBLES, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
48*FRACUNIT, // radius
32*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_SCENERY|MF_NOBLOCKMAP, // flags
S_NULL // raisestate
},
{ // MT_BIGTUMBLEWEED { // MT_BIGTUMBLEWEED
1200, // doomednum 1200, // doomednum
S_BIGTUMBLEWEED,// spawnstate S_BIGTUMBLEWEED,// spawnstate
@ -13717,7 +13783,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
-1, // doomednum -1, // doomednum
S_FLICKY_01_OUT, // spawnstate S_FLICKY_01_OUT, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_NULL, // seestate S_FLICKY_01_STAND, // seestate
sfx_None, // seesound sfx_None, // seesound
8, // reactiontime 8, // reactiontime
sfx_None, // attacksound sfx_None, // attacksound
@ -13740,11 +13806,38 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_FLICKY_BUBBLE // raisestate S_FLICKY_BUBBLE // raisestate
}, },
{ // MT_FLICKY_01_CENTER
2200, // doomednum
S_FLICKY_01_CENTER, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
8, // speed
8*FRACUNIT, // radius
20*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
sfx_None, // activesound
MF_NOSECTOR|MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_SCENERY|MF_RUNSPAWNFUNC, // flags
S_NULL // raisestate
},
{ // MT_FLICKY_02 { // MT_FLICKY_02
-1, // doomednum -1, // doomednum
S_FLICKY_02_OUT, // spawnstate S_FLICKY_02_OUT, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_NULL, // seestate S_FLICKY_02_STAND, // seestate
sfx_None, // seesound sfx_None, // seesound
8, // reactiontime 8, // reactiontime
sfx_None, // attacksound sfx_None, // attacksound
@ -13767,11 +13860,38 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_FLICKY_BUBBLE // raisestate S_FLICKY_BUBBLE // raisestate
}, },
{ // MT_FLICKY_02_CENTER
2201, // doomednum
S_FLICKY_02_CENTER, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
8, // speed
8*FRACUNIT, // radius
20*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
sfx_None, // activesound
MF_NOSECTOR|MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_SCENERY|MF_RUNSPAWNFUNC, // flags
S_NULL // raisestate
},
{ // MT_FLICKY_03 { // MT_FLICKY_03
-1, // doomednum -1, // doomednum
S_FLICKY_03_OUT, // spawnstate S_FLICKY_03_OUT, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_NULL, // seestate S_FLICKY_03_STAND, // seestate
sfx_None, // seesound sfx_None, // seesound
8, // reactiontime 8, // reactiontime
sfx_None, // attacksound sfx_None, // attacksound
@ -13794,11 +13914,38 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_FLICKY_BUBBLE // raisestate S_FLICKY_BUBBLE // raisestate
}, },
{ // MT_FLICKY_03_CENTER
2202, // doomednum
S_FLICKY_03_CENTER, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
8, // speed
8*FRACUNIT, // radius
20*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
sfx_None, // activesound
MF_NOSECTOR|MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_SCENERY|MF_RUNSPAWNFUNC, // flags
S_NULL // raisestate
},
{ // MT_FLICKY_04 { // MT_FLICKY_04
-1, // doomednum -1, // doomednum
S_FLICKY_04_OUT, // spawnstate S_FLICKY_04_OUT, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_NULL, // seestate S_FLICKY_04_STAND, // seestate
sfx_None, // seesound sfx_None, // seesound
8, // reactiontime 8, // reactiontime
sfx_None, // attacksound sfx_None, // attacksound
@ -13821,9 +13968,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate S_NULL // raisestate
}, },
{ // MT_FLICKY_05 { // MT_FLICKY_04_CENTER
-1, // doomednum 2203, // doomednum
S_FLICKY_05_OUT, // spawnstate S_FLICKY_04_CENTER, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_NULL, // seestate S_NULL, // seestate
sfx_None, // seesound sfx_None, // seesound
@ -13844,15 +13991,69 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
16, // mass 16, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_NOSECTOR|MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_SCENERY|MF_RUNSPAWNFUNC, // flags
S_NULL // raisestate
},
{ // MT_FLICKY_05
-1, // doomednum
S_FLICKY_05_OUT, // spawnstate
1000, // spawnhealth
S_FLICKY_05_STAND, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
8, // speed
8*FRACUNIT, // radius
20*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
sfx_None, // activesound
MF_NOCLIPTHING, // flags MF_NOCLIPTHING, // flags
S_FLICKY_BUBBLE // raisestate S_FLICKY_BUBBLE // raisestate
}, },
{ // MT_FLICKY_05_CENTER
2204, // doomednum
S_FLICKY_05_CENTER, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
8, // speed
8*FRACUNIT, // radius
20*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
sfx_None, // activesound
MF_NOSECTOR|MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_SCENERY|MF_RUNSPAWNFUNC, // flags
S_NULL // raisestate
},
{ // MT_FLICKY_06 { // MT_FLICKY_06
-1, // doomednum -1, // doomednum
S_FLICKY_06_OUT, // spawnstate S_FLICKY_06_OUT, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_NULL, // seestate S_FLICKY_06_STAND, // seestate
sfx_None, // seesound sfx_None, // seesound
8, // reactiontime 8, // reactiontime
sfx_None, // attacksound sfx_None, // attacksound
@ -13875,11 +14076,38 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_FLICKY_BUBBLE // raisestate S_FLICKY_BUBBLE // raisestate
}, },
{ // MT_FLICKY_06_CENTER
2205, // doomednum
S_FLICKY_06_CENTER, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
8, // speed
8*FRACUNIT, // radius
20*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
sfx_None, // activesound
MF_NOSECTOR|MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_SCENERY|MF_RUNSPAWNFUNC, // flags
S_NULL // raisestate
},
{ // MT_FLICKY_07 { // MT_FLICKY_07
-1, // doomednum -1, // doomednum
S_FLICKY_07_OUT, // spawnstate S_FLICKY_07_OUT, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_NULL, // seestate S_FLICKY_07_STAND, // seestate
sfx_None, // seesound sfx_None, // seesound
8, // reactiontime 8, // reactiontime
sfx_None, // attacksound sfx_None, // attacksound
@ -13902,11 +14130,38 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate S_NULL // raisestate
}, },
{ // MT_FLICKY_07_CENTER
2206, // doomednum
S_FLICKY_07_CENTER, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
8, // speed
8*FRACUNIT, // radius
20*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
sfx_None, // activesound
MF_NOSECTOR|MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_SCENERY|MF_RUNSPAWNFUNC, // flags
S_NULL // raisestate
},
{ // MT_FLICKY_08 { // MT_FLICKY_08
-1, // doomednum -1, // doomednum
S_FLICKY_08_OUT, // spawnstate S_FLICKY_08_OUT, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_NULL, // seestate S_FLICKY_08_STAND, // seestate
sfx_None, // seesound sfx_None, // seesound
8, // reactiontime 8, // reactiontime
sfx_None, // attacksound sfx_None, // attacksound
@ -13929,9 +14184,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate S_NULL // raisestate
}, },
{ // MT_FLICKY_09 { // MT_FLICKY_08_CENTER
-1, // doomednum 2207, // doomednum
S_FLICKY_09_OUT, // spawnstate S_FLICKY_08_CENTER, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_NULL, // seestate S_NULL, // seestate
sfx_None, // seesound sfx_None, // seesound
@ -13952,15 +14207,69 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
16, // mass 16, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_NOSECTOR|MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_SCENERY|MF_RUNSPAWNFUNC, // flags
S_NULL // raisestate
},
{ // MT_FLICKY_09
-1, // doomednum
S_FLICKY_09_OUT, // spawnstate
1000, // spawnhealth
S_FLICKY_09_STAND, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
8, // speed
8*FRACUNIT, // radius
20*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
sfx_None, // activesound
MF_NOCLIPTHING, // flags MF_NOCLIPTHING, // flags
S_FLICKY_BUBBLE // raisestate S_FLICKY_BUBBLE // raisestate
}, },
{ // MT_FLICKY_09_CENTER
2208, // doomednum
S_FLICKY_09_CENTER, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
8, // speed
8*FRACUNIT, // radius
20*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
sfx_None, // activesound
MF_NOSECTOR|MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_SCENERY|MF_RUNSPAWNFUNC, // flags
S_NULL // raisestate
},
{ // MT_FLICKY_10 { // MT_FLICKY_10
-1, // doomednum -1, // doomednum
S_FLICKY_10_OUT, // spawnstate S_FLICKY_10_OUT, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_NULL, // seestate S_FLICKY_10_STAND, // seestate
sfx_None, // seesound sfx_None, // seesound
8, // reactiontime 8, // reactiontime
sfx_None, // attacksound sfx_None, // attacksound
@ -13983,11 +14292,38 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_FLICKY_BUBBLE // raisestate S_FLICKY_BUBBLE // raisestate
}, },
{ // MT_FLICKY_10_CENTER
2209, // doomednum
S_FLICKY_10_CENTER, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
8, // speed
8*FRACUNIT, // radius
20*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
sfx_None, // activesound
MF_NOSECTOR|MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_SCENERY|MF_RUNSPAWNFUNC, // flags
S_NULL // raisestate
},
{ // MT_FLICKY_11 { // MT_FLICKY_11
-1, // doomednum -1, // doomednum
S_FLICKY_11_OUT, // spawnstate S_FLICKY_11_OUT, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_NULL, // seestate S_FLICKY_11_STAND, // seestate
sfx_None, // seesound sfx_None, // seesound
8, // reactiontime 8, // reactiontime
sfx_None, // attacksound sfx_None, // attacksound
@ -14010,11 +14346,38 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_FLICKY_BUBBLE // raisestate S_FLICKY_BUBBLE // raisestate
}, },
{ // MT_FLICKY_11_CENTER
2210, // doomednum
S_FLICKY_11_CENTER, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
8, // speed
8*FRACUNIT, // radius
20*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
sfx_None, // activesound
MF_NOSECTOR|MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_SCENERY|MF_RUNSPAWNFUNC, // flags
S_NULL // raisestate
},
{ // MT_FLICKY_12 { // MT_FLICKY_12
-1, // doomednum -1, // doomednum
S_FLICKY_12_OUT, // spawnstate S_FLICKY_12_OUT, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_NULL, // seestate S_FLICKY_12_STAND, // seestate
sfx_None, // seesound sfx_None, // seesound
8, // reactiontime 8, // reactiontime
sfx_None, // attacksound sfx_None, // attacksound
@ -14037,11 +14400,38 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_FLICKY_BUBBLE // raisestate S_FLICKY_BUBBLE // raisestate
}, },
{ // MT_FLICKY_12_CENTER
2211, // doomednum
S_FLICKY_12_CENTER, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
8, // speed
8*FRACUNIT, // radius
20*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
sfx_None, // activesound
MF_NOSECTOR|MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_SCENERY|MF_RUNSPAWNFUNC, // flags
S_NULL // raisestate
},
{ // MT_FLICKY_13 { // MT_FLICKY_13
-1, // doomednum -1, // doomednum
S_FLICKY_13_OUT, // spawnstate S_FLICKY_13_OUT, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_NULL, // seestate S_FLICKY_13_STAND, // seestate
sfx_None, // seesound sfx_None, // seesound
8, // reactiontime 8, // reactiontime
sfx_None, // attacksound sfx_None, // attacksound
@ -14064,11 +14454,38 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_FLICKY_BUBBLE // raisestate S_FLICKY_BUBBLE // raisestate
}, },
{ // MT_FLICKY_13_CENTER
2212, // doomednum
S_FLICKY_13_CENTER, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
8, // speed
8*FRACUNIT, // radius
20*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
sfx_None, // activesound
MF_NOSECTOR|MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_SCENERY|MF_RUNSPAWNFUNC, // flags
S_NULL // raisestate
},
{ // MT_FLICKY_14 { // MT_FLICKY_14
-1, // doomednum -1, // doomednum
S_FLICKY_14_OUT, // spawnstate S_FLICKY_14_OUT, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_NULL, // seestate S_FLICKY_14_STAND, // seestate
sfx_None, // seesound sfx_None, // seesound
8, // reactiontime 8, // reactiontime
sfx_None, // attacksound sfx_None, // attacksound
@ -14091,11 +14508,38 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_FLICKY_BUBBLE // raisestate S_FLICKY_BUBBLE // raisestate
}, },
{ // MT_FLICKY_14_CENTER
2213, // doomednum
S_FLICKY_14_CENTER, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
8, // speed
8*FRACUNIT, // radius
20*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
sfx_None, // activesound
MF_NOSECTOR|MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_SCENERY|MF_RUNSPAWNFUNC, // flags
S_NULL // raisestate
},
{ // MT_FLICKY_15 { // MT_FLICKY_15
-1, // doomednum -1, // doomednum
S_FLICKY_15_OUT, // spawnstate S_FLICKY_15_OUT, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_NULL, // seestate S_FLICKY_15_STAND, // seestate
sfx_None, // seesound sfx_None, // seesound
8, // reactiontime 8, // reactiontime
sfx_None, // attacksound sfx_None, // attacksound
@ -14118,11 +14562,38 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_FLICKY_BUBBLE // raisestate S_FLICKY_BUBBLE // raisestate
}, },
{ // MT_FLICKY_15_CENTER
2214, // doomednum
S_FLICKY_15_CENTER, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
8, // speed
8*FRACUNIT, // radius
20*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
sfx_None, // activesound
MF_NOSECTOR|MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_SCENERY|MF_RUNSPAWNFUNC, // flags
S_NULL // raisestate
},
{ // MT_FLICKY_16 { // MT_FLICKY_16
-1, // doomednum -1, // doomednum
S_FLICKY_16_OUT, // spawnstate S_FLICKY_16_OUT, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_NULL, // seestate S_FLICKY_16_STAND, // seestate
sfx_None, // seesound sfx_None, // seesound
8, // reactiontime 8, // reactiontime
sfx_None, // attacksound sfx_None, // attacksound
@ -14145,11 +14616,38 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_FLICKY_BUBBLE // raisestate S_FLICKY_BUBBLE // raisestate
}, },
{ // MT_FLICKY_16_CENTER
2215, // doomednum
S_FLICKY_16_CENTER, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
8, // speed
8*FRACUNIT, // radius
20*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
sfx_None, // activesound
MF_NOSECTOR|MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_SCENERY|MF_RUNSPAWNFUNC, // flags
S_NULL // raisestate
},
{ // MT_SECRETFLICKY_01 { // MT_SECRETFLICKY_01
-1, // doomednum -1, // doomednum
S_SECRETFLICKY_01_OUT, // spawnstate S_SECRETFLICKY_01_OUT, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_NULL, // seestate S_SECRETFLICKY_01_STAND, // seestate
sfx_None, // seesound sfx_None, // seesound
8, // reactiontime 8, // reactiontime
sfx_None, // attacksound sfx_None, // attacksound
@ -14172,9 +14670,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_FLICKY_BUBBLE // raisestate S_FLICKY_BUBBLE // raisestate
}, },
{ // MT_SECRETFLICKY_02 { // MT_SECRETFLICKY_01_CENTER
-1, // doomednum 2216, // doomednum
S_SECRETFLICKY_02_OUT, // spawnstate S_SECRETFLICKY_01_CENTER, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_NULL, // seestate S_NULL, // seestate
sfx_None, // seesound sfx_None, // seesound
@ -14195,10 +14693,64 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
16, // mass 16, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_NOSECTOR|MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_SCENERY|MF_RUNSPAWNFUNC, // flags
S_NULL // raisestate
},
{ // MT_SECRETFLICKY_02
-1, // doomednum
S_SECRETFLICKY_02_OUT, // spawnstate
1000, // spawnhealth
S_SECRETFLICKY_02_STAND, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
8, // speed
8*FRACUNIT, // radius
20*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
sfx_None, // activesound
MF_NOCLIPTHING, // flags MF_NOCLIPTHING, // flags
S_FLICKY_BUBBLE // raisestate S_FLICKY_BUBBLE // raisestate
}, },
{ // MT_SECRETFLICKY_02_CENTER
2217, // doomednum
S_SECRETFLICKY_02_CENTER, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
8, // speed
8*FRACUNIT, // radius
20*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
sfx_None, // activesound
MF_NOSECTOR|MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_SCENERY|MF_RUNSPAWNFUNC, // flags
S_NULL // raisestate
},
{ // MT_SEED { // MT_SEED
-1, // doomednum -1, // doomednum
S_SEED, // spawnstate S_SEED, // spawnstate

View file

@ -216,6 +216,7 @@ void A_BrakLobShot();
void A_NapalmScatter(); void A_NapalmScatter();
void A_SpawnFreshCopy(); void A_SpawnFreshCopy();
void A_FlickySpawn(); void A_FlickySpawn();
void A_FlickyCenter();
void A_FlickyAim(); void A_FlickyAim();
void A_FlickyFly(); void A_FlickyFly();
void A_FlickySoar(); void A_FlickySoar();
@ -450,6 +451,7 @@ typedef enum sprite
SPR_CFLG, // Waving flag/segment SPR_CFLG, // Waving flag/segment
SPR_CSTA, // Crawla statue SPR_CSTA, // Crawla statue
SPR_CBBS, // Facestabber statue SPR_CBBS, // Facestabber statue
SPR_CABR, // Brambles
// Arid Canyon Scenery // Arid Canyon Scenery
SPR_BTBL, // Big tumbleweed SPR_BTBL, // Big tumbleweed
@ -2275,6 +2277,7 @@ typedef enum state
S_SUSPICIOUSFACESTABBERSTATUE_WAIT, S_SUSPICIOUSFACESTABBERSTATUE_WAIT,
S_SUSPICIOUSFACESTABBERSTATUE_BURST1, S_SUSPICIOUSFACESTABBERSTATUE_BURST1,
S_SUSPICIOUSFACESTABBERSTATUE_BURST2, S_SUSPICIOUSFACESTABBERSTATUE_BURST2,
S_BRAMBLES,
// Big Tumbleweed // Big Tumbleweed
S_BIGTUMBLEWEED, S_BIGTUMBLEWEED,
@ -2746,6 +2749,8 @@ typedef enum state
S_FLICKY_01_FLAP1, S_FLICKY_01_FLAP1,
S_FLICKY_01_FLAP2, S_FLICKY_01_FLAP2,
S_FLICKY_01_FLAP3, S_FLICKY_01_FLAP3,
S_FLICKY_01_STAND,
S_FLICKY_01_CENTER,
// Rabbit // Rabbit
S_FLICKY_02_OUT, S_FLICKY_02_OUT,
@ -2753,6 +2758,8 @@ typedef enum state
S_FLICKY_02_HOP, S_FLICKY_02_HOP,
S_FLICKY_02_UP, S_FLICKY_02_UP,
S_FLICKY_02_DOWN, S_FLICKY_02_DOWN,
S_FLICKY_02_STAND,
S_FLICKY_02_CENTER,
// Chicken // Chicken
S_FLICKY_03_OUT, S_FLICKY_03_OUT,
@ -2761,6 +2768,8 @@ typedef enum state
S_FLICKY_03_UP, S_FLICKY_03_UP,
S_FLICKY_03_FLAP1, S_FLICKY_03_FLAP1,
S_FLICKY_03_FLAP2, S_FLICKY_03_FLAP2,
S_FLICKY_03_STAND,
S_FLICKY_03_CENTER,
// Seal // Seal
S_FLICKY_04_OUT, S_FLICKY_04_OUT,
@ -2772,6 +2781,8 @@ typedef enum state
S_FLICKY_04_SWIM2, S_FLICKY_04_SWIM2,
S_FLICKY_04_SWIM3, S_FLICKY_04_SWIM3,
S_FLICKY_04_SWIM4, S_FLICKY_04_SWIM4,
S_FLICKY_04_STAND,
S_FLICKY_04_CENTER,
// Pig // Pig
S_FLICKY_05_OUT, S_FLICKY_05_OUT,
@ -2779,6 +2790,8 @@ typedef enum state
S_FLICKY_05_HOP, S_FLICKY_05_HOP,
S_FLICKY_05_UP, S_FLICKY_05_UP,
S_FLICKY_05_DOWN, S_FLICKY_05_DOWN,
S_FLICKY_05_STAND,
S_FLICKY_05_CENTER,
// Chipmunk // Chipmunk
S_FLICKY_06_OUT, S_FLICKY_06_OUT,
@ -2786,6 +2799,8 @@ typedef enum state
S_FLICKY_06_HOP, S_FLICKY_06_HOP,
S_FLICKY_06_UP, S_FLICKY_06_UP,
S_FLICKY_06_DOWN, S_FLICKY_06_DOWN,
S_FLICKY_06_STAND,
S_FLICKY_06_CENTER,
// Penguin // Penguin
S_FLICKY_07_OUT, S_FLICKY_07_OUT,
@ -2800,6 +2815,8 @@ typedef enum state
S_FLICKY_07_SWIM1, S_FLICKY_07_SWIM1,
S_FLICKY_07_SWIM2, S_FLICKY_07_SWIM2,
S_FLICKY_07_SWIM3, S_FLICKY_07_SWIM3,
S_FLICKY_07_STAND,
S_FLICKY_07_CENTER,
// Fish // Fish
S_FLICKY_08_OUT, S_FLICKY_08_OUT,
@ -2813,6 +2830,8 @@ typedef enum state
S_FLICKY_08_SWIM2, S_FLICKY_08_SWIM2,
S_FLICKY_08_SWIM3, S_FLICKY_08_SWIM3,
S_FLICKY_08_SWIM4, S_FLICKY_08_SWIM4,
S_FLICKY_08_STAND,
S_FLICKY_08_CENTER,
// Ram // Ram
S_FLICKY_09_OUT, S_FLICKY_09_OUT,
@ -2820,11 +2839,15 @@ typedef enum state
S_FLICKY_09_HOP, S_FLICKY_09_HOP,
S_FLICKY_09_UP, S_FLICKY_09_UP,
S_FLICKY_09_DOWN, S_FLICKY_09_DOWN,
S_FLICKY_09_STAND,
S_FLICKY_09_CENTER,
// Puffin // Puffin
S_FLICKY_10_OUT, S_FLICKY_10_OUT,
S_FLICKY_10_FLAP1, S_FLICKY_10_FLAP1,
S_FLICKY_10_FLAP2, S_FLICKY_10_FLAP2,
S_FLICKY_10_STAND,
S_FLICKY_10_CENTER,
// Cow // Cow
S_FLICKY_11_OUT, S_FLICKY_11_OUT,
@ -2832,6 +2855,8 @@ typedef enum state
S_FLICKY_11_RUN1, S_FLICKY_11_RUN1,
S_FLICKY_11_RUN2, S_FLICKY_11_RUN2,
S_FLICKY_11_RUN3, S_FLICKY_11_RUN3,
S_FLICKY_11_STAND,
S_FLICKY_11_CENTER,
// Rat // Rat
S_FLICKY_12_OUT, S_FLICKY_12_OUT,
@ -2839,6 +2864,8 @@ typedef enum state
S_FLICKY_12_RUN1, S_FLICKY_12_RUN1,
S_FLICKY_12_RUN2, S_FLICKY_12_RUN2,
S_FLICKY_12_RUN3, S_FLICKY_12_RUN3,
S_FLICKY_12_STAND,
S_FLICKY_12_CENTER,
// Bear // Bear
S_FLICKY_13_OUT, S_FLICKY_13_OUT,
@ -2846,12 +2873,16 @@ typedef enum state
S_FLICKY_13_HOP, S_FLICKY_13_HOP,
S_FLICKY_13_UP, S_FLICKY_13_UP,
S_FLICKY_13_DOWN, S_FLICKY_13_DOWN,
S_FLICKY_13_STAND,
S_FLICKY_13_CENTER,
// Dove // Dove
S_FLICKY_14_OUT, S_FLICKY_14_OUT,
S_FLICKY_14_FLAP1, S_FLICKY_14_FLAP1,
S_FLICKY_14_FLAP2, S_FLICKY_14_FLAP2,
S_FLICKY_14_FLAP3, S_FLICKY_14_FLAP3,
S_FLICKY_14_STAND,
S_FLICKY_14_CENTER,
// Cat // Cat
S_FLICKY_15_OUT, S_FLICKY_15_OUT,
@ -2859,12 +2890,16 @@ typedef enum state
S_FLICKY_15_HOP, S_FLICKY_15_HOP,
S_FLICKY_15_UP, S_FLICKY_15_UP,
S_FLICKY_15_DOWN, S_FLICKY_15_DOWN,
S_FLICKY_15_STAND,
S_FLICKY_15_CENTER,
// Canary // Canary
S_FLICKY_16_OUT, S_FLICKY_16_OUT,
S_FLICKY_16_FLAP1, S_FLICKY_16_FLAP1,
S_FLICKY_16_FLAP2, S_FLICKY_16_FLAP2,
S_FLICKY_16_FLAP3, S_FLICKY_16_FLAP3,
S_FLICKY_16_STAND,
S_FLICKY_16_CENTER,
// Spider // Spider
S_SECRETFLICKY_01_OUT, S_SECRETFLICKY_01_OUT,
@ -2872,12 +2907,16 @@ typedef enum state
S_SECRETFLICKY_01_HOP, S_SECRETFLICKY_01_HOP,
S_SECRETFLICKY_01_UP, S_SECRETFLICKY_01_UP,
S_SECRETFLICKY_01_DOWN, S_SECRETFLICKY_01_DOWN,
S_SECRETFLICKY_01_STAND,
S_SECRETFLICKY_01_CENTER,
// Bat // Bat
S_SECRETFLICKY_02_OUT, S_SECRETFLICKY_02_OUT,
S_SECRETFLICKY_02_FLAP1, S_SECRETFLICKY_02_FLAP1,
S_SECRETFLICKY_02_FLAP2, S_SECRETFLICKY_02_FLAP2,
S_SECRETFLICKY_02_FLAP3, S_SECRETFLICKY_02_FLAP3,
S_SECRETFLICKY_02_STAND,
S_SECRETFLICKY_02_CENTER,
// Fan // Fan
S_FAN, S_FAN,
@ -3951,6 +3990,7 @@ typedef enum mobj_type
MT_CRAWLASTATUE, // Crawla statue MT_CRAWLASTATUE, // Crawla statue
MT_FACESTABBERSTATUE, // Facestabber statue MT_FACESTABBERSTATUE, // Facestabber statue
MT_SUSPICIOUSFACESTABBERSTATUE, // :eggthinking: MT_SUSPICIOUSFACESTABBERSTATUE, // :eggthinking:
MT_BRAMBLES, // Brambles
// Arid Canyon Scenery // Arid Canyon Scenery
MT_BIGTUMBLEWEED, MT_BIGTUMBLEWEED,
@ -4095,23 +4135,41 @@ typedef enum mobj_type
// Flickies // Flickies
MT_FLICKY_01, // Bluebird MT_FLICKY_01, // Bluebird
MT_FLICKY_01_CENTER,
MT_FLICKY_02, // Rabbit MT_FLICKY_02, // Rabbit
MT_FLICKY_02_CENTER,
MT_FLICKY_03, // Chicken MT_FLICKY_03, // Chicken
MT_FLICKY_03_CENTER,
MT_FLICKY_04, // Seal MT_FLICKY_04, // Seal
MT_FLICKY_04_CENTER,
MT_FLICKY_05, // Pig MT_FLICKY_05, // Pig
MT_FLICKY_05_CENTER,
MT_FLICKY_06, // Chipmunk MT_FLICKY_06, // Chipmunk
MT_FLICKY_06_CENTER,
MT_FLICKY_07, // Penguin MT_FLICKY_07, // Penguin
MT_FLICKY_07_CENTER,
MT_FLICKY_08, // Fish MT_FLICKY_08, // Fish
MT_FLICKY_08_CENTER,
MT_FLICKY_09, // Ram MT_FLICKY_09, // Ram
MT_FLICKY_09_CENTER,
MT_FLICKY_10, // Puffin MT_FLICKY_10, // Puffin
MT_FLICKY_10_CENTER,
MT_FLICKY_11, // Cow MT_FLICKY_11, // Cow
MT_FLICKY_11_CENTER,
MT_FLICKY_12, // Rat MT_FLICKY_12, // Rat
MT_FLICKY_12_CENTER,
MT_FLICKY_13, // Bear MT_FLICKY_13, // Bear
MT_FLICKY_13_CENTER,
MT_FLICKY_14, // Dove MT_FLICKY_14, // Dove
MT_FLICKY_14_CENTER,
MT_FLICKY_15, // Cat MT_FLICKY_15, // Cat
MT_FLICKY_15_CENTER,
MT_FLICKY_16, // Canary MT_FLICKY_16, // Canary
MT_FLICKY_16_CENTER,
MT_SECRETFLICKY_01, // Spider MT_SECRETFLICKY_01, // Spider
MT_SECRETFLICKY_01_CENTER,
MT_SECRETFLICKY_02, // Bat MT_SECRETFLICKY_02, // Bat
MT_SECRETFLICKY_02_CENTER,
MT_SEED, MT_SEED,
// Environmental Effects // Environmental Effects

View file

@ -2242,7 +2242,7 @@ static int lib_sChangeMusic(lua_State *L)
if (!player || P_IsLocalPlayer(player)) if (!player || P_IsLocalPlayer(player))
{ {
S_ChangeMusicAdvanced(music_name, music_flags, looping, position, prefadems, fadeinms); S_ChangeMusicEx(music_name, music_flags, looping, position, prefadems, fadeinms);
lua_pushboolean(L, true); lua_pushboolean(L, true);
} }
else else
@ -2269,392 +2269,6 @@ static int lib_sSpeedMusic(lua_State *L)
return 1; return 1;
} }
#ifdef HAVE_LUA_MUSICPLUS
static int lib_sMusicType(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
lua_pushinteger(L, S_MusicType());
else
lua_pushnil(L);
return 1;
}
static int lib_sMusicPlaying(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
lua_pushboolean(L, S_MusicPlaying());
else
lua_pushnil(L);
return 1;
}
static int lib_sMusicPaused(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
lua_pushboolean(L, S_MusicPaused());
else
lua_pushnil(L);
return 1;
}
static int lib_sMusicName(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
lua_pushstring(L, S_MusicName());
else
lua_pushnil(L);
return 1;
}
static int lib_sMusicInfo(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
{
char mname[7];
UINT16 mflags;
boolean looping;
if (S_MusicInfo(mname, &mflags, &looping))
{
lua_pushstring(L, mname);
lua_pushinteger(L, mflags);
lua_pushboolean(L, looping);
}
else
lua_pushboolean(L, false);
}
else
lua_pushnil(L);
return 1;
}
static int lib_sMusicExists(lua_State *L)
{
#ifdef MUSICSLOT_COMPATIBILITY
const char *music_name;
UINT32 music_num;
char music_compat_name[7];
UINT16 music_flags = 0;
NOHUD
if (lua_isnumber(L, 1))
{
music_num = (UINT32)luaL_checkinteger(L, 1);
music_flags = (UINT16)(music_num & 0x0000FFFF);
if (music_flags && music_flags <= 1035)
snprintf(music_compat_name, 7, "%sM", G_BuildMapName((INT32)music_flags));
else if (music_flags && music_flags <= 1050)
strncpy(music_compat_name, compat_special_music_slots[music_flags - 1036], 7);
else
music_compat_name[0] = 0; // becomes empty string
music_compat_name[6] = 0;
music_name = (const char *)&music_compat_name;
}
else
{
music_num = 0;
music_name = luaL_checkstring(L, 1);
}
#else
const char *music_name = luaL_checkstring(L, 1);
#endif
boolean checkMIDI = lua_opttrueboolean(L, 2);
boolean checkDigi = lua_opttrueboolean(L, 3);
NOHUD
lua_pushboolean(L, S_MusicExists(music_name, checkMIDI, checkDigi));
return 1;
}
static int lib_sGetMusicLength(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
lua_pushinteger(L, (int)S_GetMusicLength());
else
lua_pushnil(L);
return 1;
}
static int lib_sSetMusicLoopPoint(lua_State *L)
{
UINT32 looppoint = (UINT32)luaL_checkinteger(L, 1);
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
{
player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
lua_pushboolean(L, S_SetMusicLoopPoint(looppoint));
else
lua_pushnil(L);
return 1;
}
static int lib_sGetMusicLoopPoint(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
lua_pushinteger(L, (int)S_GetMusicLoopPoint());
else
lua_pushnil(L);
return 1;
}
static int lib_sSetMusicPosition(lua_State *L)
{
UINT32 position = (UINT32)luaL_checkinteger(L, 1);
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
{
player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
lua_pushboolean(L, S_SetMusicPosition(position));
else
lua_pushnil(L);
return 1;
}
static int lib_sGetMusicPosition(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
lua_pushinteger(L, (int)S_GetMusicPosition());
else
lua_pushnil(L);
return 1;
}
static int lib_sStopMusic(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
{
S_StopMusic();
lua_pushboolean(L, true);
}
else
lua_pushnil(L);
return 1;
}
static int lib_sPauseMusic(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
{
S_PauseAudio();
lua_pushboolean(L, true);
}
else
lua_pushnil(L);
return 1;
}
static int lib_sResumeMusic(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
{
S_ResumeAudio();
lua_pushboolean(L, true);
}
else
lua_pushnil(L);
return 1;
}
static int lib_sSetInternalMusicVolume(lua_State *L)
{
UINT32 volume = (UINT32)luaL_checkinteger(L, 1);
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
{
player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
{
S_SetInternalMusicVolume(volume);
lua_pushboolean(L, true);
}
else
lua_pushnil(L);
return 1;
}
static int lib_sStopFadingMusic(lua_State *L)
{
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
{
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
{
S_StopFadingMusic();
lua_pushboolean(L, true);
}
else
lua_pushnil(L);
return 1;
}
static int lib_sFadeMusic(lua_State *L)
{
UINT32 target_volume = (UINT32)luaL_checkinteger(L, 1);
UINT32 ms;
INT32 source_volume;
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
{
player = *((player_t **)luaL_checkudata(L, 3, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
ms = (UINT32)luaL_checkinteger(L, 2);
source_volume = -1;
}
else if (!lua_isnone(L, 4) && lua_isuserdata(L, 4))
{
player = *((player_t **)luaL_checkudata(L, 4, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
source_volume = (INT32)luaL_checkinteger(L, 2);
ms = (UINT32)luaL_checkinteger(L, 3);
}
else if (luaL_optinteger(L, 3, UINT32_MAX) == UINT32_MAX)
{
ms = (UINT32)luaL_checkinteger(L, 2);
source_volume = -1;
}
else
{
source_volume = (INT32)luaL_checkinteger(L, 2);
ms = (UINT32)luaL_checkinteger(L, 3);
}
NOHUD
if (!player || P_IsLocalPlayer(player))
lua_pushboolean(L, S_FadeMusicFromVolume(target_volume, source_volume, ms));
else
lua_pushnil(L);
return 1;
}
static int lib_sFadeOutStopMusic(lua_State *L)
{
UINT32 ms = (UINT32)luaL_checkinteger(L, 1);
player_t *player = NULL;
NOHUD
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
{
player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!player || P_IsLocalPlayer(player))
{
lua_pushboolean(L, S_FadeOutStopMusic(ms));
}
else
lua_pushnil(L);
return 1;
}
#endif
static int lib_sOriginPlaying(lua_State *L) static int lib_sOriginPlaying(lua_State *L)
{ {
void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
@ -3032,26 +2646,6 @@ static luaL_Reg lib[] = {
{"S_StopSound",lib_sStopSound}, {"S_StopSound",lib_sStopSound},
{"S_ChangeMusic",lib_sChangeMusic}, {"S_ChangeMusic",lib_sChangeMusic},
{"S_SpeedMusic",lib_sSpeedMusic}, {"S_SpeedMusic",lib_sSpeedMusic},
#ifdef HAVE_LUA_MUSICPLUS
{"S_MusicType",lib_sMusicType},
{"S_MusicPlaying",lib_sMusicPlaying},
{"S_MusicPaused",lib_sMusicPaused},
{"S_MusicName",lib_sMusicName},
{"S_MusicInfo",lib_sMusicInfo},
{"S_MusicExists",lib_sMusicExists},
{"S_GetMusicLength",lib_sGetMusicLength},
{"S_SetMusicLoopPoint",lib_sSetMusicLoopPoint},
{"S_GetMusicLoopPoint",lib_sGetMusicLoopPoint},
{"S_SetMusicPosition",lib_sSetMusicPosition},
{"S_GetMusicPosition",lib_sGetMusicPosition},
{"S_PauseMusic",lib_sPauseMusic},
{"S_ResumeMusic",lib_sResumeMusic},
{"S_StopMusic",lib_sStopMusic},
{"S_SetInternalMusicVolume", lib_sSetInternalMusicVolume},
{"S_StopFadingMusic",lib_sStopFadingMusic},
{"S_FadeMusic",lib_sFadeMusic},
{"S_FadeOutStopMusic",lib_sFadeOutStopMusic},
#endif
{"S_OriginPlaying",lib_sOriginPlaying}, {"S_OriginPlaying",lib_sOriginPlaying},
{"S_IdPlaying",lib_sIdPlaying}, {"S_IdPlaying",lib_sIdPlaying},
{"S_SoundPlaying",lib_sSoundPlaying}, {"S_SoundPlaying",lib_sSoundPlaying},

View file

@ -88,9 +88,5 @@ boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8
#define LUAh_MobjMoveBlocked(mo) LUAh_MobjHook(mo, hook_MobjMoveBlocked) // Hook for P_XYMovement (when movement is blocked) #define LUAh_MobjMoveBlocked(mo) LUAh_MobjHook(mo, hook_MobjMoveBlocked) // Hook for P_XYMovement (when movement is blocked)
boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing); // Hook for P_SpawnMapThing by mobj type boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing); // Hook for P_SpawnMapThing by mobj type
boolean LUAh_FollowMobj(player_t *player, mobj_t *mo); // Hook for P_PlayerAfterThink Smiles mobj-following boolean LUAh_FollowMobj(player_t *player, mobj_t *mo); // Hook for P_PlayerAfterThink Smiles mobj-following
#ifdef HAVE_LUA_MUSICPLUS
boolean LUAh_MusicChange(const char *oldname, char *newname, UINT16 *mflags, boolean *looping,
UINT32 *position, UINT32 *prefadems, UINT32 *fadeinms); // Hook for music changes
#endif
#endif #endif

View file

@ -1193,67 +1193,4 @@ boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj)
return hooked; return hooked;
} }
#ifdef HAVE_LUA_MUSICPLUS
// Hook for music changes
boolean LUAh_MusicChange(const char *oldname, char *newname, UINT16 *mflags, boolean *looping,
UINT32 *position, UINT32 *prefadems, UINT32 *fadeinms)
{
hook_p hookp;
boolean hooked = false;
if (!gL || !(hooksAvailable[hook_MusicChange/8] & (1<<(hook_MusicChange%8))))
return false;
lua_settop(gL, 0);
for (hookp = roothook; hookp; hookp = hookp->next)
if (hookp->type == hook_MusicChange)
{
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
lua_pushstring(gL, oldname);
lua_pushstring(gL, newname);
lua_pushinteger(gL, *mflags);
lua_pushboolean(gL, *looping);
lua_pushinteger(gL, *position);
lua_pushinteger(gL, *prefadems);
lua_pushinteger(gL, *fadeinms);
if (lua_pcall(gL, 7, 6, 0)) {
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
lua_pop(gL, 1);
continue;
}
// output 1: true, false, or string musicname override
if (lua_isboolean(gL, -6) && lua_toboolean(gL, -6))
hooked = true;
else if (lua_isstring(gL, -6))
strncpy(newname, lua_tostring(gL, -6), 7);
// output 2: mflags override
if (lua_isnumber(gL, -5))
*mflags = lua_tonumber(gL, -5);
// output 3: looping override
if (lua_isboolean(gL, -4))
*looping = lua_toboolean(gL, -4);
// output 4: position override
if (lua_isboolean(gL, -3))
*position = lua_tonumber(gL, -3);
// output 5: prefadems override
if (lua_isboolean(gL, -2))
*prefadems = lua_tonumber(gL, -2);
// output 6: fadeinms override
if (lua_isboolean(gL, -1))
*fadeinms = lua_tonumber(gL, -1);
lua_pop(gL, 6);
}
lua_settop(gL, 0);
newname[6] = 0;
return hooked;
}
#endif
#endif #endif

View file

@ -1807,6 +1807,8 @@ static int mapheaderinfo_get(lua_State *L)
lua_pushinteger(L, header->levelselect); lua_pushinteger(L, header->levelselect);
else if (fastcmp(field,"bonustype")) else if (fastcmp(field,"bonustype"))
lua_pushinteger(L, header->bonustype); lua_pushinteger(L, header->bonustype);
else if (fastcmp(field,"maxbonuslives"))
lua_pushinteger(L, header->maxbonuslives);
else if (fastcmp(field,"levelflags")) else if (fastcmp(field,"levelflags"))
lua_pushinteger(L, header->levelflags); lua_pushinteger(L, header->levelflags);
else if (fastcmp(field,"menuflags")) else if (fastcmp(field,"menuflags"))

View file

@ -290,12 +290,20 @@ static int player_get(lua_State *L)
LUA_PushUserdata(L, plr->capsule, META_MOBJ); LUA_PushUserdata(L, plr->capsule, META_MOBJ);
else if (fastcmp(field,"mare")) else if (fastcmp(field,"mare"))
lua_pushinteger(L, plr->mare); lua_pushinteger(L, plr->mare);
else if (fastcmp(field,"marelap"))
lua_pushinteger(L, plr->marelap);
else if (fastcmp(field,"marebonuslap"))
lua_pushinteger(L, plr->marebonuslap);
else if (fastcmp(field,"marebegunat")) else if (fastcmp(field,"marebegunat"))
lua_pushinteger(L, plr->marebegunat); lua_pushinteger(L, plr->marebegunat);
else if (fastcmp(field,"startedtime")) else if (fastcmp(field,"startedtime"))
lua_pushinteger(L, plr->startedtime); lua_pushinteger(L, plr->startedtime);
else if (fastcmp(field,"finishedtime")) else if (fastcmp(field,"finishedtime"))
lua_pushinteger(L, plr->finishedtime); lua_pushinteger(L, plr->finishedtime);
else if (fastcmp(field,"lapbegunat"))
lua_pushinteger(L, plr->lapbegunat);
else if (fastcmp(field,"lapstartedtime"))
lua_pushinteger(L, plr->lapstartedtime);
else if (fastcmp(field,"finishedspheres")) else if (fastcmp(field,"finishedspheres"))
lua_pushinteger(L, plr->finishedspheres); lua_pushinteger(L, plr->finishedspheres);
else if (fastcmp(field,"finishedrings")) else if (fastcmp(field,"finishedrings"))
@ -304,8 +312,18 @@ static int player_get(lua_State *L)
lua_pushinteger(L, plr->marescore); lua_pushinteger(L, plr->marescore);
else if (fastcmp(field,"lastmarescore")) else if (fastcmp(field,"lastmarescore"))
lua_pushinteger(L, plr->lastmarescore); lua_pushinteger(L, plr->lastmarescore);
else if (fastcmp(field,"totalmarescore"))
lua_pushinteger(L, plr->totalmarescore);
else if (fastcmp(field,"lastmare")) else if (fastcmp(field,"lastmare"))
lua_pushinteger(L, plr->lastmare); lua_pushinteger(L, plr->lastmare);
else if (fastcmp(field,"lastmarelap"))
lua_pushinteger(L, plr->lastmarelap);
else if (fastcmp(field,"lastmarebonuslap"))
lua_pushinteger(L, plr->lastmarebonuslap);
else if (fastcmp(field,"totalmarelap"))
lua_pushinteger(L, plr->totalmarelap);
else if (fastcmp(field,"totalmarebonuslap"))
lua_pushinteger(L, plr->totalmarebonuslap);
else if (fastcmp(field,"maxlink")) else if (fastcmp(field,"maxlink"))
lua_pushinteger(L, plr->maxlink); lua_pushinteger(L, plr->maxlink);
else if (fastcmp(field,"texttimer")) else if (fastcmp(field,"texttimer"))
@ -570,12 +588,20 @@ static int player_set(lua_State *L)
} }
else if (fastcmp(field,"mare")) else if (fastcmp(field,"mare"))
plr->mare = (UINT8)luaL_checkinteger(L, 3); plr->mare = (UINT8)luaL_checkinteger(L, 3);
else if (fastcmp(field,"marelap"))
plr->marelap = (UINT8)luaL_checkinteger(L, 3);
else if (fastcmp(field,"marebonuslap"))
plr->marebonuslap = (UINT8)luaL_checkinteger(L, 3);
else if (fastcmp(field,"marebegunat")) else if (fastcmp(field,"marebegunat"))
plr->marebegunat = (tic_t)luaL_checkinteger(L, 3); plr->marebegunat = (tic_t)luaL_checkinteger(L, 3);
else if (fastcmp(field,"startedtime")) else if (fastcmp(field,"startedtime"))
plr->startedtime = (tic_t)luaL_checkinteger(L, 3); plr->startedtime = (tic_t)luaL_checkinteger(L, 3);
else if (fastcmp(field,"finishedtime")) else if (fastcmp(field,"finishedtime"))
plr->finishedtime = (tic_t)luaL_checkinteger(L, 3); plr->finishedtime = (tic_t)luaL_checkinteger(L, 3);
else if (fastcmp(field,"lapbegunat"))
plr->lapbegunat = (tic_t)luaL_checkinteger(L, 3);
else if (fastcmp(field,"lapstartedtime"))
plr->lapstartedtime = (tic_t)luaL_checkinteger(L, 3);
else if (fastcmp(field,"finishedspheres")) else if (fastcmp(field,"finishedspheres"))
plr->finishedspheres = (INT16)luaL_checkinteger(L, 3); plr->finishedspheres = (INT16)luaL_checkinteger(L, 3);
else if (fastcmp(field,"finishedrings")) else if (fastcmp(field,"finishedrings"))
@ -584,8 +610,18 @@ static int player_set(lua_State *L)
plr->marescore = (UINT32)luaL_checkinteger(L, 3); plr->marescore = (UINT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"lastmarescore")) else if (fastcmp(field,"lastmarescore"))
plr->lastmarescore = (UINT32)luaL_checkinteger(L, 3); plr->lastmarescore = (UINT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"totalmarescore"))
plr->totalmarescore = (UINT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"lastmare")) else if (fastcmp(field,"lastmare"))
plr->lastmare = (UINT8)luaL_checkinteger(L, 3); plr->lastmare = (UINT8)luaL_checkinteger(L, 3);
else if (fastcmp(field,"lastmarelap"))
plr->lastmarelap = (UINT8)luaL_checkinteger(L, 3);
else if (fastcmp(field,"lastmarebonuslap"))
plr->lastmarebonuslap = (UINT8)luaL_checkinteger(L, 3);
else if (fastcmp(field,"totalmarelap"))
plr->totalmarelap = (UINT8)luaL_checkinteger(L, 3);
else if (fastcmp(field,"totalmarebonuslap"))
plr->totalmarebonuslap = (UINT8)luaL_checkinteger(L, 3);
else if (fastcmp(field,"maxlink")) else if (fastcmp(field,"maxlink"))
plr->maxlink = (INT32)luaL_checkinteger(L, 3); plr->maxlink = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"texttimer")) else if (fastcmp(field,"texttimer"))

View file

@ -97,7 +97,4 @@ void COM_Lua_f(void);
// uncomment if you want seg_t/node_t in Lua // uncomment if you want seg_t/node_t in Lua
// #define HAVE_LUA_SEGS // #define HAVE_LUA_SEGS
// uncomment for extended music features
#define HAVE_LUA_MUSICPLUS
#endif #endif

View file

@ -879,29 +879,20 @@ void Command_Setrings_f(void)
REQUIRE_PANDORA; REQUIRE_PANDORA;
if (COM_Argc() > 1) if (COM_Argc() > 1)
{
if (!(maptol & TOL_NIGHTS))
{ {
// P_GivePlayerRings does value clamping // P_GivePlayerRings does value clamping
players[consoleplayer].rings = 0; players[consoleplayer].rings = 0;
P_GivePlayerRings(&players[consoleplayer], atoi(COM_Argv(1))); P_GivePlayerRings(&players[consoleplayer], atoi(COM_Argv(1)));
if (!G_IsSpecialStage(gamemap) || !(maptol & TOL_NIGHTS))
players[consoleplayer].totalring -= atoi(COM_Argv(1)); //undo totalring addition done in P_GivePlayerRings players[consoleplayer].totalring -= atoi(COM_Argv(1)); //undo totalring addition done in P_GivePlayerRings
G_SetGameModified(multiplayer);
} }
} else
void Command_Setspheres_f(void)
{ {
REQUIRE_INLEVEL;
REQUIRE_SINGLEPLAYER;
REQUIRE_NOULTIMATE;
REQUIRE_PANDORA;
if (COM_Argc() > 1)
{
// P_GivePlayerRings does value clamping
players[consoleplayer].spheres = 0; players[consoleplayer].spheres = 0;
P_GivePlayerSpheres(&players[consoleplayer], atoi(COM_Argv(1))); P_GivePlayerSpheres(&players[consoleplayer], atoi(COM_Argv(1)));
// no totalsphere addition to revert
}
G_SetGameModified(multiplayer); G_SetGameModified(multiplayer);
} }
@ -918,7 +909,7 @@ void Command_Setlives_f(void)
{ {
SINT8 lives = atoi(COM_Argv(1)); SINT8 lives = atoi(COM_Argv(1));
if (lives == -1) if (lives == -1)
players[consoleplayer].lives = 0x7f; // infinity! players[consoleplayer].lives = INFLIVES; // infinity!
else else
{ {
// P_GivePlayerLives does value clamping // P_GivePlayerLives does value clamping
@ -957,10 +948,12 @@ void Command_Setcontinues_f(void)
static CV_PossibleValue_t op_mapthing_t[] = {{0, "MIN"}, {4095, "MAX"}, {0, NULL}}; static CV_PossibleValue_t op_mapthing_t[] = {{0, "MIN"}, {4095, "MAX"}, {0, NULL}};
static CV_PossibleValue_t op_speed_t[] = {{1, "MIN"}, {128, "MAX"}, {0, NULL}}; static CV_PossibleValue_t op_speed_t[] = {{1, "MIN"}, {128, "MAX"}, {0, NULL}};
static CV_PossibleValue_t op_flags_t[] = {{0, "MIN"}, {15, "MAX"}, {0, NULL}}; static CV_PossibleValue_t op_flags_t[] = {{0, "MIN"}, {15, "MAX"}, {0, NULL}};
static CV_PossibleValue_t op_hoopflags_t[] = {{0, "MIN"}, {15, "MAX"}, {0, NULL}};
consvar_t cv_mapthingnum = {"op_mapthingnum", "0", CV_NOTINNET, op_mapthing_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_mapthingnum = {"op_mapthingnum", "0", CV_NOTINNET, op_mapthing_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_speed = {"op_speed", "16", CV_NOTINNET, op_speed_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_speed = {"op_speed", "16", CV_NOTINNET, op_speed_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_opflags = {"op_flags", "0", CV_NOTINNET, op_flags_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_opflags = {"op_flags", "0", CV_NOTINNET, op_flags_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_ophoopflags = {"op_hoopflags", "4", CV_NOTINNET, op_hoopflags_t, NULL, 0, NULL, NULL, 0, 0, NULL};
boolean objectplacing = false; boolean objectplacing = false;
mobjtype_t op_currentthing = 0; // For the object placement mode mobjtype_t op_currentthing = 0; // For the object placement mode
@ -1164,17 +1157,10 @@ void OP_NightsObjectplace(player_t *player)
{ {
UINT16 angle = (UINT16)(player->anotherflyangle % 360); UINT16 angle = (UINT16)(player->anotherflyangle % 360);
INT16 temp = (INT16)FixedInt(AngleFixed(player->mo->angle)); // Traditional 2D Angle INT16 temp = (INT16)FixedInt(AngleFixed(player->mo->angle)); // Traditional 2D Angle
sector_t *sec = player->mo->subsector->sector;
#ifdef ESLOPE
fixed_t fheight = sec->f_slope ? P_GetZAt(sec->f_slope, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000) : sec->floorheight;
#else
fixed_t fheight = sec->floorheight;
#endif
player->pflags |= PF_ATTACKDOWN; player->pflags |= PF_ATTACKDOWN;
mt = OP_CreateNewMapThing(player, 1705, false); mt = OP_CreateNewMapThing(player, 1713, false);
// Tilt // Tilt
mt->angle = (INT16)FixedInt(FixedDiv(angle*FRACUNIT, 360*(FRACUNIT/256))); mt->angle = (INT16)FixedInt(FixedDiv(angle*FRACUNIT, 360*(FRACUNIT/256)));
@ -1185,7 +1171,7 @@ void OP_NightsObjectplace(player_t *player)
temp += 90; temp += 90;
temp %= 360; temp %= 360;
mt->options = (UINT16)((player->mo->z - fheight)>>FRACBITS); mt->options = (mt->options & ~(UINT16)cv_opflags.value) | (UINT16)cv_ophoopflags.value;
mt->angle = (INT16)(mt->angle+(INT16)((FixedInt(FixedDiv(temp*FRACUNIT, 360*(FRACUNIT/256))))<<8)); mt->angle = (INT16)(mt->angle+(INT16)((FixedInt(FixedDiv(temp*FRACUNIT, 360*(FRACUNIT/256))))<<8));
P_SpawnHoopsAndRings(mt, false); P_SpawnHoopsAndRings(mt, false);
@ -1194,11 +1180,52 @@ void OP_NightsObjectplace(player_t *player)
// This places a bumper! // This places a bumper!
if (cmd->buttons & BT_TOSSFLAG) if (cmd->buttons & BT_TOSSFLAG)
{ {
UINT16 vertangle = (UINT16)(player->anotherflyangle % 360);
UINT16 newflags, newz;
player->pflags |= PF_ATTACKDOWN; player->pflags |= PF_ATTACKDOWN;
if (!OP_HeightOkay(player, false)) if (!OP_HeightOkay(player, false))
return; return;
mt = OP_CreateNewMapThing(player, (UINT16)mobjinfo[MT_NIGHTSBUMPER].doomednum, false); mt = OP_CreateNewMapThing(player, (UINT16)mobjinfo[MT_NIGHTSBUMPER].doomednum, false);
newz = min((mt->options >> ZSHIFT) - (mobjinfo[MT_NIGHTSBUMPER].height/4), 0);
// height offset: from P_TouchSpecialThing case MT_NIGHTSBUMPER
// clockwise
if (vertangle >= 75 && vertangle < 105) // up
newflags = 3;
else if (vertangle >= 105 && vertangle < 135) // 60 upward tilt
newflags = 2;
else if (vertangle >= 135 && vertangle < 165) // 30 upward tilt
newflags = 1;
//else if (vertangle >= 165 && vertangle < 195) // forward, see else case
// newflags = 0;
else if (vertangle >= 195 && vertangle < 225) // 30 downward tilt
newflags = 11;
else if (vertangle >= 225 && vertangle < 255) // 60 downward tilt
newflags = 10;
else if (vertangle >= 255 && vertangle < 285) // down
newflags = 9;
else if (vertangle >= 285 && vertangle < 315) // 60 downward tilt backwards
newflags = 8;
else if (vertangle >= 315 && vertangle < 345) // 30 downward tilt backwards
newflags = 7;
else if (vertangle >= 345 || vertangle < 15) // backwards
newflags = 6;
else if (vertangle >= 15 && vertangle < 45) // 30 upward tilt backwards
newflags = 5;
else if (vertangle >= 45 && vertangle < 75) // 60 upward tilt backwards
newflags = 4;
else // forward
newflags = 0;
mt->options = (newz << ZSHIFT) | newflags;
// if NiGHTS is facing backwards, orient the Thing angle forwards so that the sprite angle
// displays correctly. Backwards movement via the Thing flags is unaffected.
if (vertangle < 90 || vertangle > 270)
mt->angle = (mt->angle + 180) % 360;
P_SpawnMapThing(mt); P_SpawnMapThing(mt);
} }

View file

@ -28,7 +28,7 @@ void cht_Init(void);
void Command_ObjectPlace_f(void); void Command_ObjectPlace_f(void);
void Command_Writethings_f(void); void Command_Writethings_f(void);
extern consvar_t cv_opflags, cv_mapthingnum, cv_speed; extern consvar_t cv_opflags, cv_ophoopflags, cv_mapthingnum, cv_speed;
//extern consvar_t cv_snapto, cv_grid; //extern consvar_t cv_snapto, cv_grid;
extern boolean objectplacing; extern boolean objectplacing;
@ -51,7 +51,6 @@ void Command_Savecheckpoint_f(void);
void Command_Getallemeralds_f(void); void Command_Getallemeralds_f(void);
void Command_Resetemeralds_f(void); void Command_Resetemeralds_f(void);
void Command_Setrings_f(void); void Command_Setrings_f(void);
void Command_Setspheres_f(void);
void Command_Setlives_f(void); void Command_Setlives_f(void);
void Command_Setcontinues_f(void); void Command_Setcontinues_f(void);
void Command_Devmode_f(void); void Command_Devmode_f(void);

View file

@ -5277,7 +5277,7 @@ static void M_PandorasBox(INT32 choice)
CV_StealthSetValue(&cv_dummyrings, max(players[consoleplayer].spheres, 0)); CV_StealthSetValue(&cv_dummyrings, max(players[consoleplayer].spheres, 0));
else else
CV_StealthSetValue(&cv_dummyrings, max(players[consoleplayer].rings, 0)); CV_StealthSetValue(&cv_dummyrings, max(players[consoleplayer].rings, 0));
if (players[consoleplayer].lives == 0x7f) if (players[consoleplayer].lives == INFLIVES)
CV_StealthSetValue(&cv_dummylives, -1); CV_StealthSetValue(&cv_dummylives, -1);
else else
CV_StealthSetValue(&cv_dummylives, players[consoleplayer].lives); CV_StealthSetValue(&cv_dummylives, players[consoleplayer].lives);
@ -6334,7 +6334,7 @@ skipsign:
y += 25; y += 25;
tempx = x + 10; tempx = x + 10;
if (savegameinfo[savetodraw].lives != 0x7f if (savegameinfo[savetodraw].lives != INFLIVES
&& savegameinfo[savetodraw].lives > 9) && savegameinfo[savetodraw].lives > 9)
tempx -= 4; tempx -= 4;
@ -6361,7 +6361,7 @@ skiplife:
V_DrawScaledPatch(tempx + 9, y + 2, 0, patch); V_DrawScaledPatch(tempx + 9, y + 2, 0, patch);
tempx += 16; tempx += 16;
if (savegameinfo[savetodraw].lives == 0x7f) if (savegameinfo[savetodraw].lives == INFLIVES)
V_DrawCharacter(tempx, y + 1, '\x16', false); V_DrawCharacter(tempx, y + 1, '\x16', false);
else else
V_DrawString(tempx, y, 0, va("%d", savegameinfo[savetodraw].lives)); V_DrawString(tempx, y, 0, va("%d", savegameinfo[savetodraw].lives));
@ -9419,23 +9419,12 @@ static void M_ToggleSFX(INT32 choice)
if (sound_disabled) if (sound_disabled)
{ {
sound_disabled = false; sound_disabled = false;
I_StartupSound();
if (sound_disabled) return;
S_InitSfxChannels(cv_soundvolume.value); S_InitSfxChannels(cv_soundvolume.value);
S_StartSound(NULL, sfx_strpst); S_StartSound(NULL, sfx_strpst);
OP_SoundOptionsMenu[6].status = IT_STRING | IT_CVAR; OP_SoundOptionsMenu[6].status = IT_STRING | IT_CVAR;
//M_StartMessage(M_GetText("SFX Enabled\n"), NULL, MM_NOTHING); //M_StartMessage(M_GetText("SFX Enabled\n"), NULL, MM_NOTHING);
} }
else else
{
if (sound_disabled)
{
sound_disabled = false;
S_StartSound(NULL, sfx_strpst);
OP_SoundOptionsMenu[6].status = IT_STRING | IT_CVAR;
//M_StartMessage(M_GetText("SFX Enabled\n"), NULL, MM_NOTHING);
}
else
{ {
sound_disabled = true; sound_disabled = true;
S_StopSounds(); S_StopSounds();
@ -9443,7 +9432,6 @@ static void M_ToggleSFX(INT32 choice)
//M_StartMessage(M_GetText("SFX Disabled\n"), NULL, MM_NOTHING); //M_StartMessage(M_GetText("SFX Disabled\n"), NULL, MM_NOTHING);
} }
} }
}
static void M_ToggleDigital(INT32 choice) static void M_ToggleDigital(INT32 choice)
{ {
@ -9473,7 +9461,6 @@ static void M_ToggleDigital(INT32 choice)
{ {
digital_disabled = false; digital_disabled = false;
I_InitMusic(); I_InitMusic();
if (digital_disabled) return;
S_StopMusic(); S_StopMusic();
if (Playing()) if (Playing())
P_RestoreMusic(&players[consoleplayer]); P_RestoreMusic(&players[consoleplayer]);
@ -9541,7 +9528,6 @@ static void M_ToggleMIDI(INT32 choice)
{ {
midi_disabled = false; midi_disabled = false;
I_InitMusic(); I_InitMusic();
if (midi_disabled) return;
if (Playing()) if (Playing())
P_RestoreMusic(&players[consoleplayer]); P_RestoreMusic(&players[consoleplayer]);
else else

View file

@ -243,6 +243,7 @@ void A_BrakLobShot(mobj_t *actor);
void A_NapalmScatter(mobj_t *actor); void A_NapalmScatter(mobj_t *actor);
void A_SpawnFreshCopy(mobj_t *actor); void A_SpawnFreshCopy(mobj_t *actor);
void A_FlickySpawn(mobj_t *actor); void A_FlickySpawn(mobj_t *actor);
void A_FlickyCenter(mobj_t *actor);
void A_FlickyAim(mobj_t *actor); void A_FlickyAim(mobj_t *actor);
void A_FlickyFly(mobj_t *actor); void A_FlickyFly(mobj_t *actor);
void A_FlickySoar(mobj_t *actor); void A_FlickySoar(mobj_t *actor);
@ -10792,6 +10793,145 @@ void A_FlickySpawn(mobj_t *actor)
P_InternalFlickySpawn(actor, locvar1, ((locvar2) ? locvar2 : 8*FRACUNIT), true); P_InternalFlickySpawn(actor, locvar1, ((locvar2) ? locvar2 : 8*FRACUNIT), true);
} }
// Internal Flicky color setting
void P_InternalFlickySetColor(mobj_t *actor, UINT8 extrainfo)
{
UINT8 flickycolors[] = {
SKINCOLOR_RED,
SKINCOLOR_CYAN,
SKINCOLOR_BLUE,
SKINCOLOR_VAPOR,
SKINCOLOR_PURPLE,
SKINCOLOR_BUBBLEGUM,
SKINCOLOR_NEON,
SKINCOLOR_BLACK,
SKINCOLOR_BEIGE,
SKINCOLOR_LAVENDER,
SKINCOLOR_RUBY,
SKINCOLOR_SALMON,
SKINCOLOR_SUNSET,
SKINCOLOR_ORANGE,
SKINCOLOR_YELLOW,
};
if (extrainfo == 0)
// until we can customize flicky colors by level header, just stick to SRB2's defaults
actor->color = flickycolors[P_RandomKey(2)]; //flickycolors[P_RandomKey(sizeof(flickycolors))];
else
actor->color = flickycolors[min(extrainfo-1, 14)]; // sizeof(flickycolors)-1
}
// Function: A_FlickyCenter
//
// Description: Place flickies in-level.
//
// var1:
// Lower 16 bits = if 0, spawns random flicky based on level header. Else, spawns the designated thing type.
// Bits 17-20 = Flicky color, up to 15. Applies to fish.
// Bit 21 = Flag MF_SLIDEME (see below)
// Bit 22 = Flag MF_GRENADEBOUNCE (see below)
// Bit 23 = Flag MF_NOCLIPTHING (see below)
//
// If actor is placed from a spawnpoint (map Thing), the Thing's properties take precedence.
//
// var2 = maximum default distance away from spawn the flickies are allowed to travel. If angle != 0, then that's the radius.
//
// If MTF_EXTRA (MF_SLIDEME): is flagged, Flickies move aimlessly. Else, orbit around the target.
// If MTF_OBJECTSPECIAL (MF_GRENADEBOUNCE): Flickies stand in-place without gravity (unless they hop, then gravity is applied.)
// If MTF_AMBUSH (MF_NOCLIPTHING): is flagged, Flickies hop.
//
void A_FlickyCenter(mobj_t *actor)
{
INT32 locvar1 = var1;
INT32 locvar2 = var2;
UINT16 flickytype = (locvar1 & 0xFFFF);
UINT8 flickycolor = ((locvar1 >> 16) & 0xFF);
UINT8 flickyflags = ((locvar1 >> 20) & 0xF);
#ifdef HAVE_BLUA
if (LUA_CallAction("A_FlickyCenter", actor))
return;
#endif
if (!actor->tracer)
{
mobj_t *flicky = P_InternalFlickySpawn(actor, locvar1, 1, false);
P_SetTarget(&flicky->target, actor);
P_SetTarget(&actor->tracer, flicky);
if (actor->spawnpoint)
{
actor->flags &= ~(MF_SLIDEME|MF_GRENADEBOUNCE|MF_NOCLIPTHING);
actor->flags |= (
((actor->spawnpoint->options & MTF_EXTRA) ? MF_SLIDEME : 0)
| ((actor->spawnpoint->options & MTF_OBJECTSPECIAL) ? MF_GRENADEBOUNCE : 0)
| ((actor->spawnpoint->options & MTF_AMBUSH) ? MF_NOCLIPTHING : 0)
);
actor->extravalue1 = actor->spawnpoint->angle ? abs(actor->spawnpoint->angle) * FRACUNIT
: locvar2 ? abs(locvar2) : 384 * FRACUNIT;
actor->extravalue2 = actor->spawnpoint->extrainfo;
actor->friction = actor->spawnpoint->x*FRACUNIT;
actor->movefactor = actor->spawnpoint->y*FRACUNIT;
actor->watertop = actor->spawnpoint->z*FRACUNIT;
}
else
{
actor->flags &= ~(MF_SLIDEME|MF_GRENADEBOUNCE|MF_NOCLIPTHING);
actor->flags |= (
((flickyflags & 1) ? MF_SLIDEME : 0)
| ((flickyflags & 2) ? MF_GRENADEBOUNCE : 0)
| ((flickyflags & 4) ? MF_NOCLIPTHING : 0)
);
actor->extravalue1 = abs(locvar2);
actor->extravalue2 = flickycolor;
actor->friction = actor->x;
actor->movefactor = actor->y;
actor->watertop = actor->z;
locvar1 = flickytype;
}
if (actor->flags & MF_GRENADEBOUNCE) // in-place
actor->tracer->fuse = 0;
else if (actor->flags & MF_SLIDEME) // aimless
{
actor->tracer->fuse = 0; // less than 2*TICRATE means move aimlessly.
actor->tracer->angle = P_RandomKey(180)*ANG2;
}
else //orbit
actor->tracer->fuse = FRACUNIT;
if (locvar1 == MT_FLICKY_08)
P_InternalFlickySetColor(actor->tracer, actor->extravalue2);
actor->extravalue2 = 0;
}
if (!(actor->flags & MF_SLIDEME) && !(actor->flags & MF_GRENADEBOUNCE))
{
fixed_t originx = actor->friction;
fixed_t originy = actor->movefactor;
fixed_t originz = actor->watertop;
actor->tracer->fuse = FRACUNIT;
// Impose default home radius if flicky orbits around player
if (!actor->extravalue1)
actor->extravalue1 = locvar2 ? abs(locvar2) : 384 * FRACUNIT;
P_LookForPlayers(actor, true, false, actor->extravalue1);
if (actor->target && P_AproxDistance(actor->target->x - originx, actor->target->y - originy) < actor->extravalue1)
{
actor->extravalue2 = 1;
P_TeleportMove(actor, actor->target->x, actor->target->y, actor->target->z);
}
else if(actor->extravalue2)
{
actor->extravalue2 = 0;
P_TeleportMove(actor, originx, originy, originz);
}
}
}
// Internal Flicky bubbling function. // Internal Flicky bubbling function.
void P_InternalFlickyBubble(mobj_t *actor) void P_InternalFlickyBubble(mobj_t *actor)
{ {
@ -10834,7 +10974,10 @@ void A_FlickyAim(mobj_t *actor)
return; return;
#endif #endif
if (actor->momx == actor->momy && actor->momy == 0) if ((actor->momx == actor->momy && actor->momy == 0)
|| (actor->target && P_IsFlickyCenter(actor->target->type)
&& actor->target->extravalue1 && (actor->target->flags & MF_SLIDEME)
&& P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y) >= actor->target->extravalue1))
flickyhitwall = true; flickyhitwall = true;
P_InternalFlickyBubble(actor); P_InternalFlickyBubble(actor);
@ -10866,7 +11009,10 @@ void A_FlickyAim(mobj_t *actor)
} }
else if (flickyhitwall) else if (flickyhitwall)
{ {
actor->angle += ANGLE_180; if (actor->target && P_IsFlickyCenter(actor->target->type))
actor->angle = R_PointToAngle2(actor->target->x, actor->target->y, actor->x, actor->y) + P_RandomRange(112, 248) * ANG1;
else
actor->angle += P_RandomRange(112, 248)*ANG1;
actor->threshold = 0; actor->threshold = 0;
} }
} }
@ -10902,7 +11048,13 @@ void P_InternalFlickyFly(mobj_t *actor, fixed_t flyspeed, fixed_t targetdist, fi
if (actor->target && abs(chasez - actor->z) > targetdist) if (actor->target && abs(chasez - actor->z) > targetdist)
targetdist = P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y); targetdist = P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y);
if (actor->target
&& P_IsFlickyCenter(actor->target->type)
&& (actor->target->flags & MF_SLIDEME))
vertangle = 0;
else
vertangle = (R_PointToAngle2(0, actor->z, targetdist, chasez) >> ANGLETOFINESHIFT) & FINEMASK; vertangle = (R_PointToAngle2(0, actor->z, targetdist, chasez) >> ANGLETOFINESHIFT) & FINEMASK;
P_InstaThrust(actor, actor->angle, FixedMul(FINECOSINE(vertangle), flyspeed)); P_InstaThrust(actor, actor->angle, FixedMul(FINECOSINE(vertangle), flyspeed));
actor->momz = FixedMul(FINESINE(vertangle), flyspeed); actor->momz = FixedMul(FINESINE(vertangle), flyspeed);
} }
@ -11054,7 +11206,19 @@ void A_FlickyCheck(mobj_t *actor)
if (LUA_CallAction("A_FlickyCheck", actor)) if (LUA_CallAction("A_FlickyCheck", actor))
return; return;
#endif #endif
if (locvar2 && P_MobjFlip(actor)*actor->momz < 1) if (actor->target
&& P_IsFlickyCenter(actor->target->type)
&& (actor->target->flags & MF_GRENADEBOUNCE))
{
if (!(actor->target->flags & MF_NOCLIPTHING)) // no hopping
{
actor->momz = 0;
actor->flags |= MF_NOGRAVITY;
}
actor->flags |= MF_NOCLIP | MF_NOBLOCKMAP | MF_SCENERY;
P_SetMobjState(actor, mobjinfo[actor->type].seestate);
}
else if (locvar2 && P_MobjFlip(actor)*actor->momz < 1)
P_SetMobjState(actor, locvar2); P_SetMobjState(actor, locvar2);
else if (locvar1 && ((!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz) else if (locvar1 && ((!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz)
|| ((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz))) || ((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz)))
@ -11079,7 +11243,19 @@ void A_FlickyHeightCheck(mobj_t *actor)
if (LUA_CallAction("A_FlickyHeightCheck", actor)) if (LUA_CallAction("A_FlickyHeightCheck", actor))
return; return;
#endif #endif
if (locvar1 && actor->target && P_MobjFlip(actor)*actor->momz < 1 if (actor->target
&& P_IsFlickyCenter(actor->target->type)
&& (actor->target->flags & MF_GRENADEBOUNCE))
{
if (!(actor->target->flags & MF_NOCLIPTHING)) // no hopping
{
actor->momz = 0;
actor->flags |= MF_NOGRAVITY;
}
actor->flags |= MF_NOCLIP | MF_NOBLOCKMAP | MF_SCENERY;
P_SetMobjState(actor, mobjinfo[actor->type].seestate);
}
else 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) && ((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))) || (actor->z - actor->height < actor->floorz) || (actor->z + 2*actor->height > actor->ceilingz)))
P_SetMobjState(actor, locvar1); P_SetMobjState(actor, locvar1);
@ -11396,7 +11572,7 @@ void A_ConnectToGround(mobj_t *actor)
mobj_t *work; mobj_t *work;
fixed_t workz; fixed_t workz;
fixed_t workh; fixed_t workh;
INT8 dir; SINT8 dir;
angle_t ang; angle_t ang;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;

View file

@ -182,14 +182,14 @@ void P_DoNightsScore(player_t *player)
{ {
if (++players[i].linkcount > players[i].maxlink) if (++players[i].linkcount > players[i].maxlink)
players[i].maxlink = players[i].linkcount; players[i].maxlink = players[i].linkcount;
players[i].linktimer = 2*TICRATE; players[i].linktimer = nightslinktics;
} }
} }
else // Individual link counts else // Individual link counts
{ {
if (++player->linkcount > player->maxlink) if (++player->linkcount > player->maxlink)
player->maxlink = player->linkcount; player->maxlink = player->linkcount;
player->linktimer = 2*TICRATE; player->linktimer = nightslinktics;
} }
if (player->linkcount < 10) if (player->linkcount < 10)
@ -946,6 +946,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// Yay! The thing's in reach! Pull it in! // Yay! The thing's in reach! Pull it in!
mo2->flags |= MF_NOCLIP|MF_NOCLIPHEIGHT; mo2->flags |= MF_NOCLIP|MF_NOCLIPHEIGHT;
mo2->flags2 |= MF2_NIGHTSPULL; mo2->flags2 |= MF2_NIGHTSPULL;
// New NiGHTS attract speed dummied out because the older behavior
// is exploited as a mechanic. Uncomment to enable.
mo2->movefactor = 0; // 32*FRACUNIT; // initialize the NightsItemChase timer
P_SetTarget(&mo2->tracer, toucher); P_SetTarget(&mo2->tracer, toucher);
} }
} }
@ -1005,13 +1008,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
player->flyangle = special->threshold; player->flyangle = special->threshold;
player->speed = FixedMul(special->info->speed, special->scale); player->speed = FixedMul(special->info->speed, special->scale);
// Potentially causes axis transfer failures. P_SetTarget(&player->mo->hnext, special); // Reference bumper for position correction on next tic
// Also rarely worked properly anyway.
//P_UnsetThingPosition(player->mo);
//player->mo->x = special->x;
//player->mo->y = special->y;
//P_SetThingPosition(player->mo);
toucher->z = special->z+(special->height/4);
} }
else // More like a spring else // More like a spring
{ {
@ -1134,6 +1131,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
{ {
player->nightstime += special->info->speed; player->nightstime += special->info->speed;
player->startedtime += special->info->speed; player->startedtime += special->info->speed;
player->lapstartedtime += special->info->speed;
P_RestoreMusic(player); P_RestoreMusic(player);
} }
else else
@ -1143,6 +1141,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
{ {
players[i].nightstime += special->info->speed; players[i].nightstime += special->info->speed;
players[i].startedtime += special->info->speed; players[i].startedtime += special->info->speed;
players[i].lapstartedtime += special->info->speed;
P_RestoreMusic(&players[i]); P_RestoreMusic(&players[i]);
} }
if (special->info->deathsound != sfx_None) if (special->info->deathsound != sfx_None)
@ -1163,7 +1162,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (!G_IsSpecialStage(gamemap)) if (!G_IsSpecialStage(gamemap))
{ {
player->powers[pw_nights_linkfreeze] = (UINT16)special->info->speed; player->powers[pw_nights_linkfreeze] = (UINT16)special->info->speed;
player->linktimer = 2*TICRATE; player->linktimer = nightslinktics;
} }
else else
{ {
@ -1171,7 +1170,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (playeringame[i] && players[i].powers[pw_carry] == CR_NIGHTSMODE) if (playeringame[i] && players[i].powers[pw_carry] == CR_NIGHTSMODE)
{ {
players[i].powers[pw_nights_linkfreeze] += (UINT16)special->info->speed; players[i].powers[pw_nights_linkfreeze] += (UINT16)special->info->speed;
players[i].linktimer = 2*TICRATE; players[i].linktimer = nightslinktics;
} }
if (special->info->deathsound != sfx_None) if (special->info->deathsound != sfx_None)
S_StartSound(NULL, special->info->deathsound); S_StartSound(NULL, special->info->deathsound);
@ -2124,7 +2123,10 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
target->flags |= MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT; // Don't drop Tails 03-08-2000 target->flags |= MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT; // Don't drop Tails 03-08-2000
if (target->flags2 & MF2_NIGHTSPULL) if (target->flags2 & MF2_NIGHTSPULL)
{
P_SetTarget(&target->tracer, NULL); P_SetTarget(&target->tracer, NULL);
target->movefactor = 0; // reset NightsItemChase timer
}
// dead target is no more shootable // dead target is no more shootable
target->flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SPECIAL); target->flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SPECIAL);
@ -2183,7 +2185,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
// to make people want to actually dash towards/paraloop enemies // to make people want to actually dash towards/paraloop enemies
if (++source->player->linkcount > source->player->maxlink) if (++source->player->linkcount > source->player->maxlink)
source->player->maxlink = source->player->linkcount; source->player->maxlink = source->player->linkcount;
source->player->linktimer = 2*TICRATE; source->player->linktimer = nightslinktics;
} }
} }
else else
@ -2253,7 +2255,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
if ((target->player->lives <= 1) && (netgame || multiplayer) && (gametype == GT_COOP) && (cv_cooplives.value == 0)) if ((target->player->lives <= 1) && (netgame || multiplayer) && (gametype == GT_COOP) && (cv_cooplives.value == 0))
; ;
else if (!target->player->bot && !target->player->spectator && !G_IsSpecialStage(gamemap) && (target->player->lives != 0x7f) else if (!target->player->bot && !target->player->spectator && !G_IsSpecialStage(gamemap) && (target->player->lives != INFLIVES)
&& G_GametypeUsesLives()) && G_GametypeUsesLives())
{ {
target->player->lives -= 1; // Lose a life Tails 03-11-2000 target->player->lives -= 1; // Lose a life Tails 03-11-2000

View file

@ -311,6 +311,8 @@ void P_NewChaseDir(mobj_t *actor);
boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed_t dist); 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); mobj_t *P_InternalFlickySpawn(mobj_t *actor, mobjtype_t flickytype, fixed_t momz, boolean lookforplayers);
void P_InternalFlickySetColor(mobj_t *actor, UINT8 extrainfo);
#define P_IsFlickyCenter(type) (type > MT_FLICKY_01 && type < MT_SEED && (type - MT_FLICKY_01) % 2 ? 1 : 0)
void P_InternalFlickyBubble(mobj_t *actor); void P_InternalFlickyBubble(mobj_t *actor);
void P_InternalFlickyFly(mobj_t *actor, fixed_t flyspeed, fixed_t targetdist, fixed_t chasez); 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); void P_InternalFlickyHop(mobj_t *actor, fixed_t momz, fixed_t momh, angle_t angle);

View file

@ -1097,25 +1097,38 @@ static boolean PIT_CheckThing(mobj_t *thing)
P_SetTarget(&thing->target, tmthing); P_SetTarget(&thing->target, tmthing);
} }
// Respawn rings and items // NiGHTS lap logic
if ((tmthing->type == MT_NIGHTSDRONE || thing->type == MT_NIGHTSDRONE) if ((tmthing->type == MT_NIGHTSDRONE || thing->type == MT_NIGHTSDRONE)
&& (tmthing->player || thing->player)) && (tmthing->player || thing->player))
{ {
mobj_t *droneobj = (tmthing->type == MT_NIGHTSDRONE) ? tmthing : thing; mobj_t *droneobj = (tmthing->type == MT_NIGHTSDRONE) ? tmthing : thing;
player_t *pl = (droneobj == thing) ? tmthing->player : thing->player; player_t *pl = (droneobj == thing) ? tmthing->player : thing->player;
// Must be in bonus time, and must be NiGHTS, must wait about a second // Must be NiGHTS, must wait about a second
// must be flying in the SAME DIRECTION as the last time you came through. // must be flying in the SAME DIRECTION as the last time you came through.
// not (your direction) xor (stored direction) // not (your direction) xor (stored direction)
// In other words, you can't u-turn and respawn rings near the drone. // In other words, you can't u-turn and respawn rings near the drone.
if (pl->bonustime && (pl->powers[pw_carry] == CR_NIGHTSMODE) && (INT32)leveltime > droneobj->extravalue2 && ( if ((pl->powers[pw_carry] == CR_NIGHTSMODE) && (INT32)leveltime > droneobj->extravalue2 && (
!(pl->flyangle > 90 && pl->flyangle < 270) !(pl->flyangle > 90 && pl->flyangle < 270)
^ (droneobj->extravalue1 > 90 && droneobj->extravalue1 < 270) ^ (droneobj->extravalue1 > 90 && droneobj->extravalue1 < 270)
)) ))
{ {
// Reload all the fancy ring stuff! pl->marelap++;
pl->totalmarelap++;
pl->lapbegunat = leveltime;
pl->lapstartedtime = pl->nightstime;
if (pl->bonustime)
{
pl->marebonuslap++;
pl->totalmarebonuslap++;
// Respawn rings and items
P_ReloadRings(); P_ReloadRings();
} }
P_RunNightsLapExecutors(pl->mo);
}
droneobj->extravalue1 = pl->flyangle; droneobj->extravalue1 = pl->flyangle;
droneobj->extravalue2 = (INT32)leveltime + TICRATE; droneobj->extravalue2 = (INT32)leveltime + TICRATE;
} }

View file

@ -6102,9 +6102,11 @@ void P_SetScale(mobj_t *mobj, fixed_t newscale)
void P_Attract(mobj_t *source, mobj_t *dest, boolean nightsgrab) // Home in on your target void P_Attract(mobj_t *source, mobj_t *dest, boolean nightsgrab) // Home in on your target
{ {
fixed_t dist, ndist, speedmul; fixed_t dist, ndist, speedmul;
angle_t vangle;
fixed_t tx = dest->x; fixed_t tx = dest->x;
fixed_t ty = dest->y; fixed_t ty = dest->y;
fixed_t tz = dest->z + (dest->height/2); // Aim for center fixed_t tz = dest->z + (dest->height/2); // Aim for center
fixed_t xydist = P_AproxDistance(tx - source->x, ty - source->y);
if (!dest || dest->health <= 0 || !dest->player || !source->tracer) if (!dest || dest->health <= 0 || !dest->player || !source->tracer)
return; return;
@ -6113,11 +6115,31 @@ void P_Attract(mobj_t *source, mobj_t *dest, boolean nightsgrab) // Home in on y
source->angle = R_PointToAngle2(source->x, source->y, tx, ty); source->angle = R_PointToAngle2(source->x, source->y, tx, ty);
// change slope // change slope
dist = P_AproxDistance(P_AproxDistance(tx - source->x, ty - source->y), tz - source->z); dist = P_AproxDistance(xydist, tz - source->z);
if (dist < 1) if (dist < 1)
dist = 1; dist = 1;
if (nightsgrab && source->movefactor)
{
source->movefactor += FRACUNIT/2;
if (dist < source->movefactor)
{
source->momx = source->momy = source->momz = 0;
P_TeleportMove(source, tx, ty, tz);
}
else
{
vangle = R_PointToAngle2(source->z, 0, tz, xydist);
source->momx = FixedMul(FINESINE(vangle >> ANGLETOFINESHIFT), FixedMul(FINECOSINE(source->angle >> ANGLETOFINESHIFT), source->movefactor));
source->momy = FixedMul(FINESINE(vangle >> ANGLETOFINESHIFT), FixedMul(FINESINE(source->angle >> ANGLETOFINESHIFT), source->movefactor));
source->momz = FixedMul(FINECOSINE(vangle >> ANGLETOFINESHIFT), source->movefactor);
}
}
else
{
if (nightsgrab) if (nightsgrab)
speedmul = P_AproxDistance(dest->momx, dest->momy) + FixedMul(8*FRACUNIT, source->scale); speedmul = P_AproxDistance(dest->momx, dest->momy) + FixedMul(8*FRACUNIT, source->scale);
else else
@ -6126,6 +6148,7 @@ void P_Attract(mobj_t *source, mobj_t *dest, boolean nightsgrab) // Home in on y
source->momx = FixedMul(FixedDiv(tx - source->x, dist), speedmul); source->momx = FixedMul(FixedDiv(tx - source->x, dist), speedmul);
source->momy = FixedMul(FixedDiv(ty - source->y, dist), speedmul); source->momy = FixedMul(FixedDiv(ty - source->y, dist), speedmul);
source->momz = FixedMul(FixedDiv(tz - source->z, dist), speedmul); source->momz = FixedMul(FixedDiv(tz - source->z, dist), speedmul);
}
// Instead of just unsetting NOCLIP like an idiot, let's check the distance to our target. // Instead of just unsetting NOCLIP like an idiot, let's check the distance to our target.
ndist = P_AproxDistance(P_AproxDistance(tx - (source->x+source->momx), ndist = P_AproxDistance(P_AproxDistance(tx - (source->x+source->momx),
@ -6150,6 +6173,7 @@ static void P_NightsItemChase(mobj_t *thing)
{ {
P_SetTarget(&thing->tracer, NULL); P_SetTarget(&thing->tracer, NULL);
thing->flags2 &= ~MF2_NIGHTSPULL; thing->flags2 &= ~MF2_NIGHTSPULL;
thing->movefactor = 0;
return; return;
} }
@ -7095,6 +7119,34 @@ void P_MobjThinker(mobj_t *mobj)
S_StartSound(flame, sfx_fire); S_StartSound(flame, sfx_fire);
} }
break; break;
case MT_FLICKY_01_CENTER:
case MT_FLICKY_02_CENTER:
case MT_FLICKY_03_CENTER:
case MT_FLICKY_04_CENTER:
case MT_FLICKY_05_CENTER:
case MT_FLICKY_06_CENTER:
case MT_FLICKY_07_CENTER:
case MT_FLICKY_08_CENTER:
case MT_FLICKY_09_CENTER:
case MT_FLICKY_10_CENTER:
case MT_FLICKY_11_CENTER:
case MT_FLICKY_12_CENTER:
case MT_FLICKY_13_CENTER:
case MT_FLICKY_14_CENTER:
case MT_FLICKY_15_CENTER:
case MT_FLICKY_16_CENTER:
case MT_SECRETFLICKY_01_CENTER:
case MT_SECRETFLICKY_02_CENTER:
if (mobj->tracer && (mobj->flags & MF_NOCLIPTHING)
&& (mobj->flags & MF_GRENADEBOUNCE))
// for now: only do this bounce routine if flicky is in-place. \todo allow in all movements
{
if (!(mobj->tracer->flags2 & MF2_OBJECTFLIP) && mobj->tracer->z <= mobj->tracer->floorz)
mobj->tracer->momz = 7*FRACUNIT;
else if ((mobj->tracer->flags2 & MF2_OBJECTFLIP) && mobj->tracer->z >= mobj->tracer->ceilingz - mobj->tracer->height)
mobj->tracer->momz = -7*FRACUNIT;
}
break;
case MT_SEED: case MT_SEED:
if (P_MobjFlip(mobj)*mobj->momz < mobj->info->speed) if (P_MobjFlip(mobj)*mobj->momz < mobj->info->speed)
mobj->momz = P_MobjFlip(mobj)*mobj->info->speed; mobj->momz = P_MobjFlip(mobj)*mobj->info->speed;
@ -8751,7 +8803,8 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
nummaprings = -1; // no perfect bonus, rings are free nummaprings = -1; // no perfect bonus, rings are free
break; break;
case MT_EGGCAPSULE: case MT_EGGCAPSULE:
mobj->extravalue1 = -1; // timer for how long a player has been at the capsule mobj->extravalue1 = -1; // sphere timer for how long a player has been at the capsule
mobj->extravalue2 = -1; // tic timer for how long a player has been at the capsule
break; break;
case MT_REDTEAMRING: case MT_REDTEAMRING:
mobj->color = skincolor_redteam; mobj->color = skincolor_redteam;

View file

@ -198,15 +198,24 @@ static void P_NetArchivePlayers(void)
WRITEUINT8(save_p, players[i].drilldelay); WRITEUINT8(save_p, players[i].drilldelay);
WRITEUINT8(save_p, players[i].bonustime); WRITEUINT8(save_p, players[i].bonustime);
WRITEUINT8(save_p, players[i].mare); WRITEUINT8(save_p, players[i].mare);
WRITEUINT8(save_p, players[i].marelap);
WRITEUINT8(save_p, players[i].marebonuslap);
WRITEUINT32(save_p, players[i].marebegunat); WRITEUINT32(save_p, players[i].marebegunat);
WRITEUINT32(save_p, players[i].startedtime); WRITEUINT32(save_p, players[i].startedtime);
WRITEUINT32(save_p, players[i].finishedtime); WRITEUINT32(save_p, players[i].finishedtime);
WRITEUINT32(save_p, players[i].lapbegunat);
WRITEUINT32(save_p, players[i].lapstartedtime);
WRITEINT16(save_p, players[i].finishedspheres); WRITEINT16(save_p, players[i].finishedspheres);
WRITEINT16(save_p, players[i].finishedrings); WRITEINT16(save_p, players[i].finishedrings);
WRITEUINT32(save_p, players[i].marescore); WRITEUINT32(save_p, players[i].marescore);
WRITEUINT32(save_p, players[i].lastmarescore); WRITEUINT32(save_p, players[i].lastmarescore);
WRITEUINT32(save_p, players[i].totalmarescore);
WRITEUINT8(save_p, players[i].lastmare); WRITEUINT8(save_p, players[i].lastmare);
WRITEUINT8(save_p, players[i].lastmarelap);
WRITEUINT8(save_p, players[i].lastmarebonuslap);
WRITEUINT8(save_p, players[i].totalmarelap);
WRITEUINT8(save_p, players[i].totalmarebonuslap);
WRITEINT32(save_p, players[i].maxlink); WRITEINT32(save_p, players[i].maxlink);
WRITEUINT8(save_p, players[i].texttimer); WRITEUINT8(save_p, players[i].texttimer);
WRITEUINT8(save_p, players[i].textvar); WRITEUINT8(save_p, players[i].textvar);
@ -387,15 +396,24 @@ static void P_NetUnArchivePlayers(void)
players[i].drilldelay = READUINT8(save_p); players[i].drilldelay = READUINT8(save_p);
players[i].bonustime = (boolean)READUINT8(save_p); players[i].bonustime = (boolean)READUINT8(save_p);
players[i].mare = READUINT8(save_p); players[i].mare = READUINT8(save_p);
players[i].marelap = READUINT8(save_p);
players[i].marebonuslap = READUINT8(save_p);
players[i].marebegunat = READUINT32(save_p); players[i].marebegunat = READUINT32(save_p);
players[i].startedtime = READUINT32(save_p); players[i].startedtime = READUINT32(save_p);
players[i].finishedtime = READUINT32(save_p); players[i].finishedtime = READUINT32(save_p);
players[i].lapbegunat = READUINT32(save_p);
players[i].lapstartedtime = READUINT32(save_p);
players[i].finishedspheres = READINT16(save_p); players[i].finishedspheres = READINT16(save_p);
players[i].finishedrings = READINT16(save_p); players[i].finishedrings = READINT16(save_p);
players[i].marescore = READUINT32(save_p); players[i].marescore = READUINT32(save_p);
players[i].lastmarescore = READUINT32(save_p); players[i].lastmarescore = READUINT32(save_p);
players[i].totalmarescore = READUINT32(save_p);
players[i].lastmare = READUINT8(save_p); players[i].lastmare = READUINT8(save_p);
players[i].lastmarelap = READUINT8(save_p);
players[i].lastmarebonuslap = READUINT8(save_p);
players[i].totalmarelap = READUINT8(save_p);
players[i].totalmarebonuslap = READUINT8(save_p);
players[i].maxlink = READINT32(save_p); players[i].maxlink = READINT32(save_p);
players[i].texttimer = READUINT8(save_p); players[i].texttimer = READUINT8(save_p);
players[i].textvar = READUINT8(save_p); players[i].textvar = READUINT8(save_p);
@ -469,10 +487,14 @@ static void P_NetUnArchivePlayers(void)
#define SD_FYOFFS 0x02 #define SD_FYOFFS 0x02
#define SD_CXOFFS 0x04 #define SD_CXOFFS 0x04
#define SD_CYOFFS 0x08 #define SD_CYOFFS 0x08
#define SD_TAG 0x10 #define SD_FLOORANG 0x10
#define SD_FLOORANG 0x20 #define SD_CEILANG 0x20
#define SD_CEILANG 0x40 #define SD_TAG 0x40
#define SD_TAGLIST 0x80 #define SD_DIFF3 0x80
// diff3 flags
#define SD_TAGLIST 0x01
#define SD_MIDMAP 0x02
#define LD_FLAG 0x01 #define LD_FLAG 0x01
#define LD_SPECIAL 0x02 #define LD_SPECIAL 0x02
@ -505,7 +527,7 @@ static void P_NetArchiveWorld(void)
mapsidedef_t *msd; mapsidedef_t *msd;
maplinedef_t *mld; maplinedef_t *mld;
const sector_t *ss = sectors; const sector_t *ss = sectors;
UINT8 diff, diff2; UINT8 diff, diff2, diff3;
WRITEUINT32(save_p, ARCHIVEBLOCK_WORLD); WRITEUINT32(save_p, ARCHIVEBLOCK_WORLD);
put = save_p; put = save_p;
@ -532,7 +554,7 @@ static void P_NetArchiveWorld(void)
for (i = 0; i < numsectors; i++, ss++, ms++) for (i = 0; i < numsectors; i++, ss++, ms++)
{ {
diff = diff2 = 0; diff = diff2 = diff3 = 0;
if (ss->floorheight != SHORT(ms->floorheight)<<FRACBITS) if (ss->floorheight != SHORT(ms->floorheight)<<FRACBITS)
diff |= SD_FLOORHT; diff |= SD_FLOORHT;
if (ss->ceilingheight != SHORT(ms->ceilingheight)<<FRACBITS) if (ss->ceilingheight != SHORT(ms->ceilingheight)<<FRACBITS)
@ -566,7 +588,9 @@ static void P_NetArchiveWorld(void)
if (ss->tag != SHORT(ms->tag)) if (ss->tag != SHORT(ms->tag))
diff2 |= SD_TAG; diff2 |= SD_TAG;
if (ss->nexttag != ss->spawn_nexttag || ss->firsttag != ss->spawn_firsttag) if (ss->nexttag != ss->spawn_nexttag || ss->firsttag != ss->spawn_firsttag)
diff2 |= SD_TAGLIST; diff3 |= SD_TAGLIST;
if (ss->midmap != ss->spawn_midmap)
diff3 |= SD_MIDMAP;
// Check if any of the sector's FOFs differ from how they spawned // Check if any of the sector's FOFs differ from how they spawned
if (ss->ffloors) if (ss->ffloors)
@ -583,6 +607,9 @@ static void P_NetArchiveWorld(void)
} }
} }
if (diff3)
diff2 |= SD_DIFF3;
if (diff2) if (diff2)
diff |= SD_DIFF2; diff |= SD_DIFF2;
@ -594,6 +621,8 @@ static void P_NetArchiveWorld(void)
WRITEUINT8(put, diff); WRITEUINT8(put, diff);
if (diff & SD_DIFF2) if (diff & SD_DIFF2)
WRITEUINT8(put, diff2); WRITEUINT8(put, diff2);
if (diff2 & SD_DIFF3)
WRITEUINT8(put, diff3);
if (diff & SD_FLOORHT) if (diff & SD_FLOORHT)
WRITEFIXED(put, ss->floorheight); WRITEFIXED(put, ss->floorheight);
if (diff & SD_CEILHT) if (diff & SD_CEILHT)
@ -614,17 +643,19 @@ static void P_NetArchiveWorld(void)
WRITEFIXED(put, ss->ceiling_xoffs); WRITEFIXED(put, ss->ceiling_xoffs);
if (diff2 & SD_CYOFFS) if (diff2 & SD_CYOFFS)
WRITEFIXED(put, ss->ceiling_yoffs); WRITEFIXED(put, ss->ceiling_yoffs);
if (diff2 & SD_TAG) // save only the tag
WRITEINT16(put, ss->tag);
if (diff2 & SD_FLOORANG) if (diff2 & SD_FLOORANG)
WRITEANGLE(put, ss->floorpic_angle); WRITEANGLE(put, ss->floorpic_angle);
if (diff2 & SD_CEILANG) if (diff2 & SD_CEILANG)
WRITEANGLE(put, ss->ceilingpic_angle); WRITEANGLE(put, ss->ceilingpic_angle);
if (diff2 & SD_TAGLIST) // save both firsttag and nexttag if (diff2 & SD_TAG) // save only the tag
WRITEINT16(put, ss->tag);
if (diff3 & SD_TAGLIST) // save both firsttag and nexttag
{ // either of these could be changed even if tag isn't { // either of these could be changed even if tag isn't
WRITEINT32(put, ss->firsttag); WRITEINT32(put, ss->firsttag);
WRITEINT32(put, ss->nexttag); WRITEINT32(put, ss->nexttag);
} }
if (diff3 & SD_MIDMAP)
WRITEINT32(put, ss->midmap);
// Special case: save the stats of all modified ffloors along with their ffloor "number"s // Special case: save the stats of all modified ffloors along with their ffloor "number"s
// we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed // we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed
@ -662,7 +693,7 @@ static void P_NetArchiveWorld(void)
// do lines // do lines
for (i = 0; i < numlines; i++, mld++, li++) for (i = 0; i < numlines; i++, mld++, li++)
{ {
diff = diff2 = 0; diff = diff2 = diff3 = 0;
if (li->special != SHORT(mld->special)) if (li->special != SHORT(mld->special))
diff |= LD_SPECIAL; diff |= LD_SPECIAL;
@ -754,7 +785,7 @@ static void P_NetUnArchiveWorld(void)
line_t *li; line_t *li;
side_t *si; side_t *si;
UINT8 *get; UINT8 *get;
UINT8 diff, diff2; UINT8 diff, diff2, diff3;
if (READUINT32(save_p) != ARCHIVEBLOCK_WORLD) if (READUINT32(save_p) != ARCHIVEBLOCK_WORLD)
I_Error("Bad $$$.sav at archive block World"); I_Error("Bad $$$.sav at archive block World");
@ -776,6 +807,10 @@ static void P_NetUnArchiveWorld(void)
diff2 = READUINT8(get); diff2 = READUINT8(get);
else else
diff2 = 0; diff2 = 0;
if (diff2 & SD_DIFF3)
diff3 = READUINT8(get);
else
diff3 = 0;
if (diff & SD_FLOORHT) if (diff & SD_FLOORHT)
sectors[i].floorheight = READFIXED(get); sectors[i].floorheight = READFIXED(get);
@ -804,17 +839,19 @@ static void P_NetUnArchiveWorld(void)
sectors[i].ceiling_xoffs = READFIXED(get); sectors[i].ceiling_xoffs = READFIXED(get);
if (diff2 & SD_CYOFFS) if (diff2 & SD_CYOFFS)
sectors[i].ceiling_yoffs = READFIXED(get); sectors[i].ceiling_yoffs = READFIXED(get);
if (diff2 & SD_TAG)
sectors[i].tag = READINT16(get); // DON'T use P_ChangeSectorTag
if (diff2 & SD_TAGLIST)
{
sectors[i].firsttag = READINT32(get);
sectors[i].nexttag = READINT32(get);
}
if (diff2 & SD_FLOORANG) if (diff2 & SD_FLOORANG)
sectors[i].floorpic_angle = READANGLE(get); sectors[i].floorpic_angle = READANGLE(get);
if (diff2 & SD_CEILANG) if (diff2 & SD_CEILANG)
sectors[i].ceilingpic_angle = READANGLE(get); sectors[i].ceilingpic_angle = READANGLE(get);
if (diff2 & SD_TAG)
sectors[i].tag = READINT16(get); // DON'T use P_ChangeSectorTag
if (diff3 & SD_TAGLIST)
{
sectors[i].firsttag = READINT32(get);
sectors[i].nexttag = READINT32(get);
}
if (diff3 & SD_MIDMAP)
sectors[i].midmap = READINT32(get);
if (diff & SD_FFLOORS) if (diff & SD_FFLOORS)
{ {
@ -873,6 +910,9 @@ static void P_NetUnArchiveWorld(void)
diff2 = READUINT8(get); diff2 = READUINT8(get);
else else
diff2 = 0; diff2 = 0;
diff3 = 0;
if (diff & LD_FLAG) if (diff & LD_FLAG)
li->flags = READINT16(get); li->flags = READINT16(get);
if (diff & LD_SPECIAL) if (diff & LD_SPECIAL)

View file

@ -230,6 +230,7 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
mapheaderinfo[num]->unlockrequired = -1; mapheaderinfo[num]->unlockrequired = -1;
mapheaderinfo[num]->levelselect = 0; mapheaderinfo[num]->levelselect = 0;
mapheaderinfo[num]->bonustype = 0; mapheaderinfo[num]->bonustype = 0;
mapheaderinfo[num]->maxbonuslives = -1;
mapheaderinfo[num]->levelflags = 0; mapheaderinfo[num]->levelflags = 0;
mapheaderinfo[num]->menuflags = 0; mapheaderinfo[num]->menuflags = 0;
#if 1 // equivalent to "FlickyList = DEMO" #if 1 // equivalent to "FlickyList = DEMO"
@ -723,6 +724,7 @@ static void P_LoadRawSectors(UINT8 *data, size_t i)
ss->floorpic_angle = ss->ceilingpic_angle = 0; ss->floorpic_angle = ss->ceilingpic_angle = 0;
ss->spawn_flrpic_angle = ss->spawn_ceilpic_angle = 0; ss->spawn_flrpic_angle = ss->spawn_ceilpic_angle = 0;
ss->bottommap = ss->midmap = ss->topmap = -1; ss->bottommap = ss->midmap = ss->topmap = -1;
ss->spawn_bottommap = ss->spawn_midmap = ss->spawn_topmap = -1;
ss->gravity = NULL; ss->gravity = NULL;
ss->cullheight = NULL; ss->cullheight = NULL;
ss->verticalflip = false; ss->verticalflip = false;
@ -1474,13 +1476,14 @@ static void P_LoadRawSideDefs2(void *data)
{ {
case 63: // variable colormap via 242 linedef case 63: // variable colormap via 242 linedef
case 606: //SoM: 4/4/2000: Just colormap transfer case 606: //SoM: 4/4/2000: Just colormap transfer
case 447: // Change colormap of tagged sectors! -- Monster Iestyn 14/06/18
// SoM: R_CreateColormap will only create a colormap in software mode... // SoM: R_CreateColormap will only create a colormap in software mode...
// Perhaps we should just call it instead of doing the calculations here. // Perhaps we should just call it instead of doing the calculations here.
if (rendermode == render_soft || rendermode == render_none) if (rendermode == render_soft || rendermode == render_none)
{ {
if (msd->toptexture[0] == '#' || msd->bottomtexture[0] == '#') if (msd->toptexture[0] == '#' || msd->bottomtexture[0] == '#')
{ {
sec->midmap = R_CreateColormap(msd->toptexture, msd->midtexture, sec->midmap = sec->spawn_midmap = R_CreateColormap(msd->toptexture, msd->midtexture,
msd->bottomtexture); msd->bottomtexture);
sd->toptexture = sd->bottomtexture = 0; sd->toptexture = sd->bottomtexture = 0;
} }
@ -1510,7 +1513,7 @@ static void P_LoadRawSideDefs2(void *data)
{ {
char *col; char *col;
sec->midmap = R_CreateColormap(msd->toptexture, msd->midtexture, sec->midmap = sec->spawn_midmap = R_CreateColormap(msd->toptexture, msd->midtexture,
msd->bottomtexture); msd->bottomtexture);
sd->toptexture = sd->bottomtexture = 0; sd->toptexture = sd->bottomtexture = 0;
#define HEX2INT(x) (x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0) #define HEX2INT(x) (x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0)
@ -2386,12 +2389,16 @@ static void P_LevelInitStuff(void)
players[i].maxlink = players[i].startedtime =\ players[i].maxlink = players[i].startedtime =\
players[i].finishedtime = players[i].finishedspheres =\ players[i].finishedtime = players[i].finishedspheres =\
players[i].finishedrings = players[i].lastmare =\ players[i].finishedrings = players[i].lastmare =\
players[i].lastmarelap = players[i].lastmarebonuslap =\
players[i].totalmarelap = players[i].totalmarebonuslap =\
players[i].marebegunat = players[i].textvar =\ players[i].marebegunat = players[i].textvar =\
players[i].texttimer = players[i].linkcount =\ players[i].texttimer = players[i].linkcount =\
players[i].linktimer = players[i].flyangle =\ players[i].linktimer = players[i].flyangle =\
players[i].anotherflyangle = players[i].nightstime =\ players[i].anotherflyangle = players[i].nightstime =\
players[i].mare = players[i].realtime =\ players[i].mare = players[i].marelap =\
players[i].exiting = 0; players[i].marebonuslap = players[i].lapbegunat =\
players[i].lapstartedtime = players[i].totalmarescore =\
players[i].realtime = players[i].exiting = 0;
// i guess this could be part of the above but i feel mildly uncomfortable implicitly casting // i guess this could be part of the above but i feel mildly uncomfortable implicitly casting
players[i].gotcontinue = false; players[i].gotcontinue = false;
@ -2937,7 +2944,6 @@ boolean P_SetupLevel(boolean skipprecip)
// Important: take care of the ordering of the next functions. // Important: take care of the ordering of the next functions.
if (!loadedbm) if (!loadedbm)
P_CreateBlockMap(); // Graue 02-29-2004 P_CreateBlockMap(); // Graue 02-29-2004
R_MakeColormaps();
P_LoadLineDefs2(); P_LoadLineDefs2();
P_GroupLines(); P_GroupLines();
numdmstarts = numredctfstarts = numbluectfstarts = 0; numdmstarts = numredctfstarts = numbluectfstarts = 0;
@ -2974,7 +2980,6 @@ boolean P_SetupLevel(boolean skipprecip)
// Important: take care of the ordering of the next functions. // Important: take care of the ordering of the next functions.
if (!loadedbm) if (!loadedbm)
P_CreateBlockMap(); // Graue 02-29-2004 P_CreateBlockMap(); // Graue 02-29-2004
R_MakeColormaps();
P_LoadLineDefs2(); P_LoadLineDefs2();
P_GroupLines(); P_GroupLines();
numdmstarts = numredctfstarts = numbluectfstarts = 0; numdmstarts = numredctfstarts = numbluectfstarts = 0;

View file

@ -1375,6 +1375,67 @@ void P_ChangeSectorTag(UINT32 sector, INT16 newtag)
} }
} }
//
// P_RunNightserizeExecutors
//
void P_RunNightserizeExecutors(mobj_t *actor)
{
size_t i;
for (i = 0; i < numlines; i++)
{
if (lines[i].special == 323 || lines[i].special == 324)
P_RunTriggerLinedef(&lines[i], actor, NULL);
}
}
//
// P_RunDeNightserizeExecutors
//
void P_RunDeNightserizeExecutors(mobj_t *actor)
{
size_t i;
for (i = 0; i < numlines; i++)
{
if (lines[i].special == 325 || lines[i].special == 326)
P_RunTriggerLinedef(&lines[i], actor, NULL);
}
}
//
// P_RunNightsLapExecutors
//
void P_RunNightsLapExecutors(mobj_t *actor)
{
size_t i;
for (i = 0; i < numlines; i++)
{
if (lines[i].special == 327 || lines[i].special == 328)
P_RunTriggerLinedef(&lines[i], actor, NULL);
}
}
//
// P_RunNightsCapsuleTouchExecutors
//
void P_RunNightsCapsuleTouchExecutors(mobj_t *actor, boolean entering, boolean enoughspheres)
{
size_t i;
for (i = 0; i < numlines; i++)
{
if ((lines[i].special == 329 || lines[i].special == 330)
&& ((entering && (lines[i].flags & ML_TFERLINE))
|| (!entering && !(lines[i].flags & ML_TFERLINE)))
&& ((lines[i].flags & ML_DONTPEGTOP)
|| (enoughspheres && !(lines[i].flags & ML_BOUNCY))
|| (!enoughspheres && (lines[i].flags & ML_BOUNCY))))
P_RunTriggerLinedef(&lines[i], actor, NULL);
}
}
/** Hashes the sector tags across the sectors and linedefs. /** Hashes the sector tags across the sectors and linedefs.
* *
* \sa P_FindSectorFromTag, P_ChangeSectorTag * \sa P_FindSectorFromTag, P_ChangeSectorTag
@ -1458,6 +1519,146 @@ static void P_AddExecutorDelay(line_t *line, mobj_t *mobj, sector_t *sector)
P_AddThinker(&e->thinker); P_AddThinker(&e->thinker);
} }
/** Used by P_RunTriggerLinedef to check a NiGHTS trigger linedef's conditions
*
* \param triggerline Trigger linedef to check conditions for; should NEVER be NULL.
* \param actor Object initiating the action; should not be NULL.
* \sa P_RunTriggerLinedef
*/
static boolean P_CheckNightsTriggerLine(line_t *triggerline, mobj_t *actor)
{
INT16 specialtype = triggerline->special;
size_t i;
UINT8 inputmare = max(0, min(255, sides[triggerline->sidenum[0]].textureoffset>>FRACBITS));
UINT8 inputlap = max(0, min(255, sides[triggerline->sidenum[0]].rowoffset>>FRACBITS));
boolean ltemare = triggerline->flags & ML_NOCLIMB;
boolean gtemare = triggerline->flags & ML_BLOCKMONSTERS;
boolean ltelap = triggerline->flags & ML_EFFECT1;
boolean gtelap = triggerline->flags & ML_EFFECT2;
boolean lapfrombonustime = triggerline->flags & ML_EFFECT3;
boolean perglobalinverse = triggerline->flags & ML_DONTPEGBOTTOM;
boolean perglobal = !(triggerline->flags & ML_EFFECT4) && !perglobalinverse;
boolean donomares = triggerline->flags & ML_BOUNCY; // nightserize: run at end of level (no mares)
boolean fromnonights = triggerline->flags & ML_TFERLINE; // nightserize: from non-nights // denightserize: all players no nights
boolean fromnights = triggerline->flags & ML_DONTPEGTOP; // nightserize: from nights // denightserize: >0 players are nights
UINT8 currentmare = UINT8_MAX;
UINT8 currentlap = UINT8_MAX;
// Do early returns for Nightserize
if (specialtype >= 323 && specialtype <= 324)
{
// run only when no mares are found
if (donomares && P_FindLowestMare() != UINT8_MAX)
return false;
// run only if there is a mare present
if (!donomares && P_FindLowestMare() == UINT8_MAX)
return false;
// run only if player is nightserizing from non-nights
if (fromnonights)
{
if (!actor->player)
return false;
else if (actor->player->powers[pw_carry] == CR_NIGHTSMODE)
return false;
}
// run only if player is nightserizing from nights
else if (fromnights)
{
if (!actor->player)
return false;
else if (actor->player->powers[pw_carry] != CR_NIGHTSMODE)
return false;
}
}
// Get current mare and lap (and check early return for DeNightserize)
if (perglobal || perglobalinverse
|| (specialtype >= 325 && specialtype <= 326 && (fromnonights || fromnights)))
{
UINT8 playersarenights = 0;
for (i = 0; i < MAXPLAYERS; i++)
{
UINT8 lap;
if (!playeringame[i] || players[i].spectator)
continue;
// denightserize: run only if all players are not nights
if (specialtype >= 325 && specialtype <= 326 && fromnonights
&& players[i].powers[pw_carry] == CR_NIGHTSMODE)
return false;
// count number of nights players for denightserize return
if (specialtype >= 325 && specialtype <= 326 && fromnights
&& players[i].powers[pw_carry] == CR_NIGHTSMODE)
playersarenights++;
lap = lapfrombonustime ? players[i].marebonuslap : players[i].marelap;
// get highest mare/lap of players
if (perglobal)
{
if (players[i].mare > currentmare || currentmare == UINT8_MAX)
{
currentmare = players[i].mare;
currentlap = UINT8_MAX;
}
if (players[i].mare == currentmare
&& (lap > currentlap || currentlap == UINT8_MAX))
currentlap = lap;
}
// get lowest mare/lap of players
else if (perglobalinverse)
{
if (players[i].mare < currentmare || currentmare == UINT8_MAX)
{
currentmare = players[i].mare;
currentlap = UINT8_MAX;
}
if (players[i].mare == currentmare
&& (lap < currentlap || currentlap == UINT8_MAX))
currentlap = lap;
}
}
// denightserize: run only if >0 players are nights
if (specialtype >= 325 && specialtype <= 326 && fromnights
&& playersarenights < 1)
return false;
}
// get current mare/lap from triggering player
else if (!perglobal && !perglobalinverse)
{
if (!actor->player)
return false;
currentmare = actor->player->mare;
currentlap = lapfrombonustime ? actor->player->marebonuslap : actor->player->marelap;
}
if (lapfrombonustime && !currentlap)
return false; // special case: player->marebonuslap is 0 until passing through on bonus time. Don't trigger lines looking for inputlap 0.
// Compare current mare/lap to input mare/lap based on rules
if (!(specialtype >= 323 && specialtype <= 324 && donomares) // don't return false if donomares and we got this far
&& ((ltemare && currentmare > inputmare)
|| (gtemare && currentmare < inputmare)
|| (!ltemare && !gtemare && currentmare != inputmare)
|| (ltelap && currentlap > inputlap)
|| (gtelap && currentlap < inputlap)
|| (!ltelap && !gtelap && currentlap != inputlap))
)
return false;
return true;
}
/** Used by P_LinedefExecute to check a trigger linedef's conditions /** Used by P_LinedefExecute to check a trigger linedef's conditions
* The linedef executor specials in the trigger linedef's sector are run if all conditions are met. * The linedef executor specials in the trigger linedef's sector are run if all conditions are met.
* Return false cancels P_LinedefExecute, this happens if a condition is not met. * Return false cancels P_LinedefExecute, this happens if a condition is not met.
@ -1493,10 +1694,10 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
if (!playeringame[i] || players[i].spectator) if (!playeringame[i] || players[i].spectator)
continue; continue;
if (!players[i].mo || players[i].rings <= 0) if (!players[i].mo || ((maptol & TOL_NIGHTS) ? players[i].spheres : players[i].rings) <= 0)
continue; continue;
rings += players[i].rings; rings += (maptol & TOL_NIGHTS) ? players[i].spheres : players[i].rings;
} }
} }
else else
@ -1504,7 +1705,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
if (!(actor && actor->player)) if (!(actor && actor->player))
return false; // no player to count rings from here, sorry return false; // no player to count rings from here, sorry
rings = actor->player->rings; rings = (maptol & TOL_NIGHTS) ? actor->player->spheres : actor->player->rings;
} }
if (triggerline->flags & ML_NOCLIMB) if (triggerline->flags & ML_NOCLIMB)
@ -1668,6 +1869,18 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
return false; return false;
} }
break; break;
case 323: // nightserize - each time
case 324: // nightserize - once
case 325: // denightserize - each time
case 326: // denightserize - once
case 327: // nights lap - each time
case 328: // nights lap - once
case 329: // nights egg capsule touch - each time
case 330: // nights egg capsule touch - once
if (!P_CheckNightsTriggerLine(triggerline, actor))
return false;
break;
default: default:
break; break;
} }
@ -1796,6 +2009,10 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
|| specialtype == 318 // Unlockable trigger - Once || specialtype == 318 // Unlockable trigger - Once
|| specialtype == 320 // Unlockable - Once || specialtype == 320 // Unlockable - Once
|| specialtype == 321 || specialtype == 322 // Trigger on X calls - Continuous + Each Time || specialtype == 321 || specialtype == 322 // Trigger on X calls - Continuous + Each Time
|| specialtype == 324 // Nightserize - Once
|| specialtype == 326 // DeNightserize - Once
|| specialtype == 328 // Nights lap - Once
|| specialtype == 330 // Nights Bonus Time - Once
|| specialtype == 399) // Level Load || specialtype == 399) // Level Load
triggerline->special = 0; // Clear it out triggerline->special = 0; // Clear it out
@ -3035,6 +3252,15 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
} }
break; break;
case 447: // Change colormap of tagged sectors!
// Basically this special applies a colormap to the tagged sectors, just like 606 (the colormap linedef)
// Except it is activated by linedef executor, not level load
// This could even override existing colormaps I believe
// -- Monster Iestyn 14/06/18
for (secnum = -1; (secnum = P_FindSectorFromLineTag(line, secnum)) >= 0 ;)
sectors[secnum].midmap = line->frontsector->midmap;
break;
case 448: // Change skybox viewpoint/centerpoint case 448: // Change skybox viewpoint/centerpoint
if ((mo && mo->player && P_IsLocalPlayer(mo->player)) || (line->flags & ML_NOCLIMB)) if ((mo && mo->player && P_IsLocalPlayer(mo->player)) || (line->flags & ML_NOCLIMB))
{ {
@ -6421,6 +6647,17 @@ void P_SpawnSpecials(INT32 fromnetsave)
} }
break; break;
// NiGHTS trigger executors
case 323:
case 324:
case 325:
case 326:
case 327:
case 328:
case 329:
case 330:
break;
case 399: // Linedef execute on map load case 399: // Linedef execute on map load
// This is handled in P_RunLevelLoadExecutors. // This is handled in P_RunLevelLoadExecutors.
break; break;
@ -6534,7 +6771,7 @@ void P_SpawnSpecials(INT32 fromnetsave)
case 606: // HACK! Copy colormaps. Just plain colormaps. case 606: // HACK! Copy colormaps. Just plain colormaps.
for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
sectors[s].midmap = lines[i].frontsector->midmap; sectors[s].midmap = sectors[s].spawn_midmap = lines[i].frontsector->midmap;
break; break;
#ifdef ESLOPE // Slope copy specials. Handled here for sanity. #ifdef ESLOPE // Slope copy specials. Handled here for sanity.

View file

@ -66,6 +66,10 @@ void P_SwitchWeather(INT32 weathernum);
boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller); boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller);
void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller); void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller);
void P_ChangeSectorTag(UINT32 sector, INT16 newtag); void P_ChangeSectorTag(UINT32 sector, INT16 newtag);
void P_RunNightserizeExecutors(mobj_t *actor);
void P_RunDeNightserizeExecutors(mobj_t *actor);
void P_RunNightsLapExecutors(mobj_t *actor);
void P_RunNightsCapsuleTouchExecutors(mobj_t *actor, boolean entering, boolean enoughspheres);
ffloor_t *P_GetFFloorByID(sector_t *sec, UINT16 id); ffloor_t *P_GetFFloorByID(sector_t *sec, UINT16 id);

View file

@ -387,6 +387,8 @@ boolean P_TransferToNextMare(player_t *player)
CONS_Debug(DBG_NIGHTS, "Mare is %d\n", mare); CONS_Debug(DBG_NIGHTS, "Mare is %d\n", mare);
player->mare = mare; player->mare = mare;
player->marelap = 0;
player->marebonuslap = 0;
// scan the thinkers // scan the thinkers
// to find the closest axis point // to find the closest axis point
@ -574,6 +576,10 @@ static void P_DeNightserizePlayer(player_t *player)
player->climbing = 0; player->climbing = 0;
player->mo->fuse = 0; player->mo->fuse = 0;
player->speed = 0; player->speed = 0;
player->marelap = 0;
player->marebonuslap = 0;
player->flyangle = 0;
player->anotherflyangle = 0;
P_SetTarget(&player->mo->target, NULL); P_SetTarget(&player->mo->target, NULL);
P_SetTarget(&player->axis1, P_SetTarget(&player->axis2, NULL)); P_SetTarget(&player->axis1, P_SetTarget(&player->axis2, NULL));
@ -625,6 +631,8 @@ static void P_DeNightserizePlayer(player_t *player)
// Restore from drowning music // Restore from drowning music
P_RestoreMusic(player); P_RestoreMusic(player);
P_RunDeNightserizeExecutors(player->mo);
} }
// //
@ -633,7 +641,7 @@ static void P_DeNightserizePlayer(player_t *player)
// NiGHTS Time! // NiGHTS Time!
void P_NightserizePlayer(player_t *player, INT32 nighttime) void P_NightserizePlayer(player_t *player, INT32 nighttime)
{ {
INT32 oldmare; UINT8 oldmare, oldmarelap, oldmarebonuslap;
// Bots can't be NiGHTSerized, silly!1 :P // Bots can't be NiGHTSerized, silly!1 :P
if (player->bot) if (player->bot)
@ -648,6 +656,8 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
player->speed = 0; player->speed = 0;
player->climbing = 0; player->climbing = 0;
player->secondjump = 0; player->secondjump = 0;
player->flyangle = 0;
player->anotherflyangle = 0;
player->powers[pw_shield] = SH_NONE; player->powers[pw_shield] = SH_NONE;
player->powers[pw_super] = 0; player->powers[pw_super] = 0;
@ -662,7 +672,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
player->followitem = skins[DEFAULTNIGHTSSKIN].followitem; player->followitem = skins[DEFAULTNIGHTSSKIN].followitem;
} }
player->nightstime = player->startedtime = nighttime*TICRATE; player->nightstime = player->startedtime = player->lapstartedtime = nighttime*TICRATE;
player->bonustime = false; player->bonustime = false;
P_RestoreMusic(player); P_RestoreMusic(player);
@ -680,6 +690,8 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
} }
oldmare = player->mare; oldmare = player->mare;
oldmarelap = player->marelap;
oldmarebonuslap = player->marebonuslap;
if (!P_TransferToNextMare(player)) if (!P_TransferToNextMare(player))
{ {
@ -707,6 +719,8 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
players[i].texttimer = (3 * TICRATE) - 10; players[i].texttimer = (3 * TICRATE) - 10;
players[i].textvar = 4; // Score and grades players[i].textvar = 4; // Score and grades
players[i].lastmare = players[i].mare; players[i].lastmare = players[i].mare;
players[i].lastmarelap = players[i].marelap;
players[i].lastmarebonuslap = players[i].marebonuslap;
if (G_IsSpecialStage(gamemap)) if (G_IsSpecialStage(gamemap))
{ {
players[i].finishedspheres = (INT16)total_spheres; players[i].finishedspheres = (INT16)total_spheres;
@ -725,6 +739,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
G_AddTempNightsRecords(players[i].marescore, leveltime - player->marebegunat, players[i].mare + 1); G_AddTempNightsRecords(players[i].marescore, leveltime - player->marebegunat, players[i].mare + 1);
// transfer scores anyway // transfer scores anyway
players[i].totalmarescore += players[i].marescore;
players[i].lastmarescore = players[i].marescore; players[i].lastmarescore = players[i].marescore;
players[i].marescore = 0; players[i].marescore = 0;
@ -738,19 +753,24 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
// Spheres bonus // Spheres bonus
P_AddPlayerScore(player, (player->spheres) * 50); P_AddPlayerScore(player, (player->spheres) * 50);
player->lastmare = (UINT8)oldmare; player->lastmare = oldmare;
player->lastmarelap = oldmarelap;
player->lastmarebonuslap = oldmarebonuslap;
player->texttimer = 4*TICRATE; player->texttimer = 4*TICRATE;
player->textvar = 4; // Score and grades player->textvar = 4; // Score and grades
player->finishedspheres = (INT16)(player->spheres); player->finishedspheres = (INT16)(player->spheres);
player->finishedrings = (INT16)(player->rings);
// Add score to temp leaderboards // Add score to temp leaderboards
if (!(netgame||multiplayer) && P_IsLocalPlayer(player)) if (!(netgame||multiplayer) && P_IsLocalPlayer(player))
G_AddTempNightsRecords(player->marescore, leveltime - player->marebegunat, (UINT8)(oldmare + 1)); G_AddTempNightsRecords(player->marescore, leveltime - player->marebegunat, (UINT8)(oldmare + 1));
// Starting a new mare, transfer scores // Starting a new mare, transfer scores
player->totalmarescore += player->marescore;
player->lastmarescore = player->marescore; player->lastmarescore = player->marescore;
player->marescore = 0; player->marescore = 0;
player->marebegunat = leveltime; player->marebegunat = leveltime;
player->lapbegunat = leveltime;
player->spheres = player->rings = 0; player->spheres = player->rings = 0;
} }
@ -765,6 +785,16 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
player->texttimer = (UINT8)(110 - timeinmap); player->texttimer = (UINT8)(110 - timeinmap);
} }
// force NiGHTS to face forward or backward
if (player->mo->target)
player->mo->angle = R_PointToAngle2(player->mo->target->x, player->mo->target->y, player->mo->x, player->mo->y) // player->angle_pos, won't be set on first instance
+ ((player->mo->target->flags2 & MF2_AMBUSH) ? // if axis is invert, take the opposite right angle
(player->flyangle > 90 && player->flyangle < 270 ? ANGLE_90 : -ANGLE_90)
: (player->flyangle > 90 && player->flyangle < 270 ? -ANGLE_90 : ANGLE_90));
// Do this before setting CR_NIGHTSMODE so we can tell if player was non-NiGHTS
P_RunNightserizeExecutors(player->mo);
player->powers[pw_carry] = CR_NIGHTSMODE; player->powers[pw_carry] = CR_NIGHTSMODE;
} }
@ -927,7 +957,7 @@ void P_GivePlayerRings(player_t *player, INT32 num_rings)
player->rings = 0; player->rings = 0;
// Now extra life bonuses are handled here instead of in P_MovePlayer, since why not? // Now extra life bonuses are handled here instead of in P_MovePlayer, since why not?
if (!ultimatemode && !modeattacking && !G_IsSpecialStage(gamemap) && G_GametypeUsesLives() && player->lives != 0x7f) if (!ultimatemode && !modeattacking && !G_IsSpecialStage(gamemap) && G_GametypeUsesLives() && player->lives != INFLIVES)
{ {
INT32 gainlives = 0; INT32 gainlives = 0;
@ -986,7 +1016,7 @@ void P_GivePlayerLives(player_t *player, INT32 numlives)
if (gamestate == GS_LEVEL) if (gamestate == GS_LEVEL)
{ {
if (player->lives == 0x7f || (gametype != GT_COOP && gametype != GT_COMPETITION)) if (player->lives == INFLIVES || (gametype != GT_COOP && gametype != GT_COMPETITION))
{ {
P_GivePlayerRings(player, 100*numlives); P_GivePlayerRings(player, 100*numlives);
return; return;
@ -1247,13 +1277,13 @@ void P_RestoreMusic(player_t *player)
if (mapheaderinfo[gamemap-1]->levelflags & LF_SPEEDMUSIC) if (mapheaderinfo[gamemap-1]->levelflags & LF_SPEEDMUSIC)
{ {
S_SpeedMusic(1.4f); S_SpeedMusic(1.4f);
S_ChangeMusicAdvanced(mapmusname, mapmusflags, true, mapmusposition, 0, 0); S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
} }
else else
S_ChangeMusicInternal("_shoes", true); S_ChangeMusicInternal("_shoes", true);
} }
else else
S_ChangeMusicAdvanced(mapmusname, mapmusflags, true, mapmusposition, 0, 0); S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
} }
// //
@ -5927,6 +5957,8 @@ static void P_DoNiGHTSCapsule(player_t *player)
{ {
INT32 i; INT32 i;
player->capsule->extravalue2++; // tic counter
if (abs(player->mo->x-player->capsule->x) <= 2*FRACUNIT) if (abs(player->mo->x-player->capsule->x) <= 2*FRACUNIT)
{ {
P_UnsetThingPosition(player->mo); P_UnsetThingPosition(player->mo);
@ -5988,6 +6020,9 @@ static void P_DoNiGHTSCapsule(player_t *player)
} }
} }
if (player->capsule->extravalue2 <= 0 && player->capsule->health > 0)
P_RunNightsCapsuleTouchExecutors(player->mo, true, player->spheres >= player->capsule->health); // run capsule entrance executors
// Time to blow it up! // Time to blow it up!
if (player->mo->x == player->capsule->x if (player->mo->x == player->capsule->x
&& player->mo->y == player->capsule->y && player->mo->y == player->capsule->y
@ -6011,7 +6046,7 @@ static void P_DoNiGHTSCapsule(player_t *player)
player->capsule->flags &= ~MF_NOGRAVITY; player->capsule->flags &= ~MF_NOGRAVITY;
player->capsule->momz = 5*FRACUNIT; player->capsule->momz = 5*FRACUNIT;
player->capsule->reactiontime = 0; player->capsule->reactiontime = 0;
player->capsule->extravalue1 = -1; player->capsule->extravalue1 = player->capsule->extravalue2 = -1;
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && !player->exiting && players[i].mare == player->mare) if (playeringame[i] && !player->exiting && players[i].mare == player->mare)
@ -6080,6 +6115,7 @@ static void P_DoNiGHTSCapsule(player_t *player)
P_SetTarget(&players[i].capsule, NULL); // Remove capsule from everyone now that it is dead! P_SetTarget(&players[i].capsule, NULL); // Remove capsule from everyone now that it is dead!
S_StartScreamSound(player->mo, sfx_ngdone); S_StartScreamSound(player->mo, sfx_ngdone);
P_SwitchSpheresBonusMode(true); P_SwitchSpheresBonusMode(true);
P_RunNightsCapsuleTouchExecutors(player->mo, false, true); // run capsule exit executors, and we destroyed it
} }
} }
else else
@ -6088,7 +6124,8 @@ static void P_DoNiGHTSCapsule(player_t *player)
player->texttimer = 4*TICRATE; player->texttimer = 4*TICRATE;
player->textvar = 3; // Get more rings! player->textvar = 3; // Get more rings!
player->capsule->reactiontime = 0; player->capsule->reactiontime = 0;
player->capsule->extravalue1 = -1; player->capsule->extravalue1 = player->capsule->extravalue2 = -1;
P_RunNightsCapsuleTouchExecutors(player->mo, false, false); // run capsule exit executors, and we lacked rings
} }
} }
else else
@ -6174,7 +6211,6 @@ static void P_NiGHTSMovement(player_t *player)
// S_StartSound(NULL, sfx_timeup); // that creepy "out of time" music from NiGHTS. Dummied out, as some on the dev team thought it wasn't Sonic-y enough (Mystic, notably). Uncomment to restore. -SH // S_StartSound(NULL, sfx_timeup); // that creepy "out of time" music from NiGHTS. Dummied out, as some on the dev team thought it wasn't Sonic-y enough (Mystic, notably). Uncomment to restore. -SH
S_ChangeMusicInternal((((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)) ? "_ntime" : "_drown"), false); S_ChangeMusicInternal((((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)) ? "_ntime" : "_drown"), false);
if (player->mo->z < player->mo->floorz) if (player->mo->z < player->mo->floorz)
player->mo->z = player->mo->floorz; player->mo->z = player->mo->floorz;
@ -6642,7 +6678,18 @@ static void P_NiGHTSMovement(player_t *player)
S_StartSound(player->mo, sfx_drill1); S_StartSound(player->mo, sfx_drill1);
player->drilltimer = 32; player->drilltimer = 32;
} }
else if (--player->drilltimer <= 0) else if (player->drilltimer == 32)
{
// drill mash penalty
player->drilltimer = 31;
player->drillmeter -= TICRATE/2;
if (player->drillmeter <= 0)
player->drillmeter = TICRATE/10;
}
else if (--player->drilltimer == 11)
// give that drill mash penalty back (after 0.6 seconds)
player->drillmeter += TICRATE/2;
else if (player->drilltimer <= 0)
{ {
player->drilltimer = 10; player->drilltimer = 10;
S_StartSound(player->mo, sfx_drill2); S_StartSound(player->mo, sfx_drill2);
@ -8377,7 +8424,7 @@ boolean P_GetLives(player_t *player)
if (!(netgame || multiplayer) if (!(netgame || multiplayer)
|| (gametype != GT_COOP) || (gametype != GT_COOP)
|| (cv_cooplives.value == 1) || (cv_cooplives.value == 1)
|| (player->lives == 0x7f)) || (player->lives == INFLIVES))
return true; return true;
if ((cv_cooplives.value == 2 || cv_cooplives.value == 0) && player->lives > 0) if ((cv_cooplives.value == 2 || cv_cooplives.value == 0) && player->lives > 0)
@ -8404,7 +8451,7 @@ boolean P_GetLives(player_t *player)
{ {
if (cv_cooplives.value == 2 && (P_IsLocalPlayer(player) || P_IsLocalPlayer(&players[maxlivesplayer]))) if (cv_cooplives.value == 2 && (P_IsLocalPlayer(player) || P_IsLocalPlayer(&players[maxlivesplayer])))
S_StartSound(NULL, sfx_jshard); // placeholder S_StartSound(NULL, sfx_jshard); // placeholder
if (players[maxlivesplayer].lives != 0x7f) if (players[maxlivesplayer].lives != INFLIVES)
players[maxlivesplayer].lives--; players[maxlivesplayer].lives--;
player->lives++; player->lives++;
if (player->lives < 1) if (player->lives < 1)
@ -9763,12 +9810,18 @@ void P_PlayerThink(player_t *player)
|| mo2->type == MT_NIGHTSCHIP || mo2->type == MT_NIGHTSSTAR)) || mo2->type == MT_NIGHTSCHIP || mo2->type == MT_NIGHTSSTAR))
continue; continue;
if (mo2->flags2 & MF2_NIGHTSPULL)
continue;
if (P_AproxDistance(P_AproxDistance(mo2->x - x, mo2->y - y), mo2->z - z) > FixedMul(128*FRACUNIT, player->mo->scale)) if (P_AproxDistance(P_AproxDistance(mo2->x - x, mo2->y - y), mo2->z - z) > FixedMul(128*FRACUNIT, player->mo->scale))
continue; continue;
// Yay! The thing's in reach! Pull it in! // Yay! The thing's in reach! Pull it in!
mo2->flags |= MF_NOCLIP|MF_NOCLIPHEIGHT; mo2->flags |= MF_NOCLIP|MF_NOCLIPHEIGHT;
mo2->flags2 |= MF2_NIGHTSPULL; mo2->flags2 |= MF2_NIGHTSPULL;
// New NiGHTS attract speed dummied out because the older behavior
// is exploited as a mechanic. Uncomment to enable.
mo2->movefactor = 0; // 40*FRACUNIT; // initialize the NightsItemChase timer
P_SetTarget(&mo2->tracer, player->mo); P_SetTarget(&mo2->tracer, player->mo);
} }
} }
@ -9808,7 +9861,19 @@ void P_PlayerThink(player_t *player)
P_ResetScore(player); P_ResetScore(player);
} }
else else
{
if (player->bumpertime == TICRATE/2 && player->mo->hnext)
{
// Center player to NiGHTS bumper here because if you try to set player's position in
// P_TouchSpecialThing case MT_NIGHTSBUMPER, that position is fudged in the time
// between that routine in the previous tic
// and reaching here in the current tic
P_TeleportMove(player->mo, player->mo->hnext->x, player->mo->hnext->y
, player->mo->hnext->z + FixedMul(player->mo->hnext->height/4, player->mo->hnext->scale));
P_SetTarget(&player->mo->hnext, NULL);
}
P_MovePlayer(player); P_MovePlayer(player);
}
if (!player->mo) if (!player->mo)
return; // P_MovePlayer removed player->mo. return; // P_MovePlayer removed player->mo.
@ -9932,7 +9997,8 @@ void P_PlayerThink(player_t *player)
|| player->panim == PA_PAIN || player->panim == PA_PAIN
|| !player->mo->health || !player->mo->health
|| player->climbing || player->climbing
|| player->pflags & (PF_SPINNING|PF_SLIDING)) || player->pflags & (PF_SPINNING|PF_SLIDING)
|| player->bumpertime)
player->pflags &= ~PF_APPLYAUTOBRAKE; player->pflags &= ~PF_APPLYAUTOBRAKE;
else if (currentlyonground || player->powers[pw_tailsfly]) else if (currentlyonground || player->powers[pw_tailsfly])
player->pflags |= PF_APPLYAUTOBRAKE; player->pflags |= PF_APPLYAUTOBRAKE;

View file

@ -1313,9 +1313,6 @@ void R_ReInitColormaps(UINT16 num)
static lumpnum_t foundcolormaps[MAXCOLORMAPS]; static lumpnum_t foundcolormaps[MAXCOLORMAPS];
static char colormapFixingArray[MAXCOLORMAPS][3][9];
static size_t carrayindex;
// //
// R_ClearColormaps // R_ClearColormaps
// //
@ -1327,8 +1324,6 @@ void R_ClearColormaps(void)
num_extra_colormaps = 0; num_extra_colormaps = 0;
carrayindex = 0;
for (i = 0; i < MAXCOLORMAPS; i++) for (i = 0; i < MAXCOLORMAPS; i++)
foundcolormaps[i] = LUMPERROR; foundcolormaps[i] = LUMPERROR;
@ -1362,7 +1357,7 @@ INT32 R_ColormapNumForName(char *name)
extra_colormaps[num_extra_colormaps].fadecolor = 0x0; extra_colormaps[num_extra_colormaps].fadecolor = 0x0;
extra_colormaps[num_extra_colormaps].maskamt = 0x0; extra_colormaps[num_extra_colormaps].maskamt = 0x0;
extra_colormaps[num_extra_colormaps].fadestart = 0; extra_colormaps[num_extra_colormaps].fadestart = 0;
extra_colormaps[num_extra_colormaps].fadeend = 33; extra_colormaps[num_extra_colormaps].fadeend = 31;
extra_colormaps[num_extra_colormaps].fog = 0; extra_colormaps[num_extra_colormaps].fog = 0;
num_extra_colormaps++; num_extra_colormaps++;
@ -1385,12 +1380,12 @@ static int RoundUp(double number);
INT32 R_CreateColormap(char *p1, char *p2, char *p3) INT32 R_CreateColormap(char *p1, char *p2, char *p3)
{ {
double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb; double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb;
double r, g, b, cbrightness, maskamt = 0, othermask = 0; double maskamt = 0, othermask = 0;
int mask, fog = 0; int mask, fog = 0;
size_t mapnum = num_extra_colormaps; size_t mapnum = num_extra_colormaps;
size_t i; size_t i;
UINT32 cr, cg, cb, maskcolor, fadecolor; UINT32 cr, cg, cb, maskcolor, fadecolor;
UINT32 fadestart = 0, fadeend = 33, fadedist = 33; UINT32 fadestart = 0, fadeend = 31, fadedist = 31;
#define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0) #define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0)
if (p1[0] == '#') if (p1[0] == '#')
@ -1431,14 +1426,14 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3)
// Get parameters like fadestart, fadeend, and the fogflag // Get parameters like fadestart, fadeend, and the fogflag
fadestart = NUMFROMCHAR(p2[3]) + (NUMFROMCHAR(p2[2]) * 10); fadestart = NUMFROMCHAR(p2[3]) + (NUMFROMCHAR(p2[2]) * 10);
fadeend = NUMFROMCHAR(p2[5]) + (NUMFROMCHAR(p2[4]) * 10); fadeend = NUMFROMCHAR(p2[5]) + (NUMFROMCHAR(p2[4]) * 10);
if (fadestart > 32) if (fadestart > 30)
fadestart = 0; fadestart = 0;
if (fadeend > 33 || fadeend < 1) if (fadeend > 31 || fadeend < 1)
fadeend = 33; fadeend = 31;
fadedist = fadeend - fadestart; fadedist = fadeend - fadestart;
fog = NUMFROMCHAR(p2[1]) ? 1 : 0; fog = NUMFROMCHAR(p2[1]);
} }
#undef getnum #undef NUMFROMCHAR
if (p3[0] == '#') if (p3[0] == '#')
{ {
@ -1469,38 +1464,8 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3)
if (num_extra_colormaps == MAXCOLORMAPS) if (num_extra_colormaps == MAXCOLORMAPS)
I_Error("R_CreateColormap: Too many colormaps! the limit is %d\n", MAXCOLORMAPS); I_Error("R_CreateColormap: Too many colormaps! the limit is %d\n", MAXCOLORMAPS);
strncpy(colormapFixingArray[num_extra_colormaps][0], p1, 8);
strncpy(colormapFixingArray[num_extra_colormaps][1], p2, 8);
strncpy(colormapFixingArray[num_extra_colormaps][2], p3, 8);
num_extra_colormaps++; num_extra_colormaps++;
if (rendermode == render_soft)
{
for (i = 0; i < 256; i++)
{
r = pMasterPalette[i].s.red;
g = pMasterPalette[i].s.green;
b = pMasterPalette[i].s.blue;
cbrightness = sqrt((r*r) + (g*g) + (b*b));
map[i][0] = (cbrightness * cmaskr) + (r * othermask);
if (map[i][0] > 255.0l)
map[i][0] = 255.0l;
deltas[i][0] = (map[i][0] - cdestr) / (double)fadedist;
map[i][1] = (cbrightness * cmaskg) + (g * othermask);
if (map[i][1] > 255.0l)
map[i][1] = 255.0l;
deltas[i][1] = (map[i][1] - cdestg) / (double)fadedist;
map[i][2] = (cbrightness * cmaskb) + (b * othermask);
if (map[i][2] > 255.0l)
map[i][2] = 255.0l;
deltas[i][2] = (map[i][2] - cdestb) / (double)fadedist;
}
}
foundcolormaps[mapnum] = LUMPERROR; foundcolormaps[mapnum] = LUMPERROR;
// aligned on 8 bit for asm code // aligned on 8 bit for asm code
@ -1512,114 +1477,18 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3)
extra_colormaps[mapnum].fadeend = (UINT16)fadeend; extra_colormaps[mapnum].fadeend = (UINT16)fadeend;
extra_colormaps[mapnum].fog = fog; extra_colormaps[mapnum].fog = fog;
return (INT32)mapnum; // This code creates the colormap array used by software renderer
} if (rendermode == render_soft)
void R_MakeColormaps(void)
{ {
size_t i;
carrayindex = num_extra_colormaps;
num_extra_colormaps = 0;
for (i = 0; i < carrayindex; i++)
R_CreateColormap2(colormapFixingArray[i][0], colormapFixingArray[i][1],
colormapFixingArray[i][2]);
}
void R_CreateColormap2(char *p1, char *p2, char *p3)
{
double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb;
double r, g, b, cbrightness; double r, g, b, cbrightness;
double maskamt = 0, othermask = 0; int p;
int mask, p, fog = 0;
size_t mapnum = num_extra_colormaps;
size_t i;
char *colormap_p; char *colormap_p;
UINT32 cr, cg, cb, maskcolor, fadecolor;
UINT32 fadestart = 0, fadeend = 33, fadedist = 33;
#define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0) // Initialise the map and delta arrays
if (p1[0] == '#') // map[i] stores an RGB color (as double) for index i,
{ // which is then converted to SRB2's palette later
cr = ((HEX2INT(p1[1]) * 16) + HEX2INT(p1[2])); // deltas[i] stores a corresponding fade delta between the RGB color and the final fade color;
cmaskr = cr; // map[i]'s values are decremented by after each use
cg = ((HEX2INT(p1[3]) * 16) + HEX2INT(p1[4]));
cmaskg = cg;
cb = ((HEX2INT(p1[5]) * 16) + HEX2INT(p1[6]));
cmaskb = cb;
// Create a rough approximation of the color (a 16 bit color)
maskcolor = ((cb) >> 3) + (((cg) >> 2) << 5) + (((cr) >> 3) << 11);
if (p1[7] >= 'a' && p1[7] <= 'z')
mask = (p1[7] - 'a');
else if (p1[7] >= 'A' && p1[7] <= 'Z')
mask = (p1[7] - 'A');
else
mask = 24;
maskamt = (double)(mask/24.0l);
othermask = 1 - maskamt;
maskamt /= 0xff;
cmaskr *= maskamt;
cmaskg *= maskamt;
cmaskb *= maskamt;
}
else
{
cmaskr = cmaskg = cmaskb = 0xff;
maskamt = 0;
maskcolor = ((0xff) >> 3) + (((0xff) >> 2) << 5) + (((0xff) >> 3) << 11);
}
#define NUMFROMCHAR(c) (c >= '0' && c <= '9' ? c - '0' : 0)
if (p2[0] == '#')
{
// Get parameters like fadestart, fadeend, and the fogflag
fadestart = NUMFROMCHAR(p2[3]) + (NUMFROMCHAR(p2[2]) * 10);
fadeend = NUMFROMCHAR(p2[5]) + (NUMFROMCHAR(p2[4]) * 10);
if (fadestart > 32)
fadestart = 0;
if (fadeend > 33 || fadeend < 1)
fadeend = 33;
fadedist = fadeend - fadestart;
fog = NUMFROMCHAR(p2[1]) ? 1 : 0;
}
#undef getnum
if (p3[0] == '#')
{
cdestr = cr = ((HEX2INT(p3[1]) * 16) + HEX2INT(p3[2]));
cdestg = cg = ((HEX2INT(p3[3]) * 16) + HEX2INT(p3[4]));
cdestb = cb = ((HEX2INT(p3[5]) * 16) + HEX2INT(p3[6]));
fadecolor = (((cb) >> 3) + (((cg) >> 2) << 5) + (((cr) >> 3) << 11));
}
else
cdestr = cdestg = cdestb = fadecolor = 0;
#undef HEX2INT
for (i = 0; i < num_extra_colormaps; i++)
{
if (foundcolormaps[i] != LUMPERROR)
continue;
if (maskcolor == extra_colormaps[i].maskcolor
&& fadecolor == extra_colormaps[i].fadecolor
&& (float)maskamt == (float)extra_colormaps[i].maskamt
&& fadestart == extra_colormaps[i].fadestart
&& fadeend == extra_colormaps[i].fadeend
&& fog == extra_colormaps[i].fog)
{
return;
}
}
if (num_extra_colormaps == MAXCOLORMAPS)
I_Error("R_CreateColormap: Too many colormaps! the limit is %d\n", MAXCOLORMAPS);
num_extra_colormaps++;
if (rendermode == render_soft)
{
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
{ {
r = pMasterPalette[i].s.red; r = pMasterPalette[i].s.red;
@ -1642,25 +1511,13 @@ void R_CreateColormap2(char *p1, char *p2, char *p3)
map[i][2] = 255.0l; map[i][2] = 255.0l;
deltas[i][2] = (map[i][2] - cdestb) / (double)fadedist; deltas[i][2] = (map[i][2] - cdestb) / (double)fadedist;
} }
}
foundcolormaps[mapnum] = LUMPERROR; // Now allocate memory for the actual colormap array itself!
// aligned on 8 bit for asm code
extra_colormaps[mapnum].colormap = NULL;
extra_colormaps[mapnum].maskcolor = (UINT16)maskcolor;
extra_colormaps[mapnum].fadecolor = (UINT16)fadecolor;
extra_colormaps[mapnum].maskamt = maskamt;
extra_colormaps[mapnum].fadestart = (UINT16)fadestart;
extra_colormaps[mapnum].fadeend = (UINT16)fadeend;
extra_colormaps[mapnum].fog = fog;
#define ABS2(x) ((x) < 0 ? -(x) : (x))
if (rendermode == render_soft)
{
colormap_p = Z_MallocAlign((256 * 34) + 10, PU_LEVEL, NULL, 8); colormap_p = Z_MallocAlign((256 * 34) + 10, PU_LEVEL, NULL, 8);
extra_colormaps[mapnum].colormap = (UINT8 *)colormap_p; extra_colormaps[mapnum].colormap = (UINT8 *)colormap_p;
// Calculate the palette index for each palette index, for each light level
// (as well as the two unused colormap lines we inherited from Doom)
for (p = 0; p < 34; p++) for (p = 0; p < 34; p++)
{ {
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
@ -1672,7 +1529,7 @@ void R_CreateColormap2(char *p1, char *p2, char *p3)
if ((UINT32)p < fadestart) if ((UINT32)p < fadestart)
continue; continue;
#define ABS2(x) ((x) < 0 ? -(x) : (x))
if (ABS2(map[i][0] - cdestr) > ABS2(deltas[i][0])) if (ABS2(map[i][0] - cdestr) > ABS2(deltas[i][0]))
map[i][0] -= deltas[i][0]; map[i][0] -= deltas[i][0];
else else
@ -1687,12 +1544,12 @@ void R_CreateColormap2(char *p1, char *p2, char *p3)
map[i][2] -= deltas[i][2]; map[i][2] -= deltas[i][2];
else else
map[i][2] = cdestb; map[i][2] = cdestb;
}
}
}
#undef ABS2 #undef ABS2
}
}
}
return; return (INT32)mapnum;
} }
// Thanks to quake2 source! // Thanks to quake2 source!

View file

@ -100,8 +100,6 @@ void R_ReInitColormaps(UINT16 num);
void R_ClearColormaps(void); void R_ClearColormaps(void);
INT32 R_ColormapNumForName(char *name); INT32 R_ColormapNumForName(char *name);
INT32 R_CreateColormap(char *p1, char *p2, char *p3); INT32 R_CreateColormap(char *p1, char *p2, char *p3);
void R_CreateColormap2(char *p1, char *p2, char *p3);
void R_MakeColormaps(void);
const char *R_ColormapNameForNum(INT32 num); const char *R_ColormapNameForNum(INT32 num);
extern INT32 numtextures; extern INT32 numtextures;

View file

@ -385,6 +385,7 @@ typedef struct sector_s
// these are saved for netgames, so do not let Lua touch these! // these are saved for netgames, so do not let Lua touch these!
INT32 spawn_nexttag, spawn_firsttag; // the actual nexttag/firsttag values may differ if the sector's tag was changed INT32 spawn_nexttag, spawn_firsttag; // the actual nexttag/firsttag values may differ if the sector's tag was changed
INT32 spawn_bottommap, spawn_midmap, spawn_topmap;
// offsets sector spawned with (via linedef type 7) // offsets sector spawned with (via linedef type 7)
fixed_t spawn_flr_xoffs, spawn_flr_yoffs; fixed_t spawn_flr_xoffs, spawn_flr_yoffs;

View file

@ -1146,9 +1146,9 @@ void R_RenderPlayerView(player_t *player)
if (cv_homremoval.value && player == &players[displayplayer]) // if this is display player 1 if (cv_homremoval.value && player == &players[displayplayer]) // if this is display player 1
{ {
if (cv_homremoval.value == 1) if (cv_homremoval.value == 1)
V_DrawFill(0, 0, vid.width, vid.height, 31); // No HOM effect! V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); // No HOM effect!
else //'development' HOM removal -- makes it blindingly obvious if HOM is spotted. else //'development' HOM removal -- makes it blindingly obvious if HOM is spotted.
V_DrawFill(0, 0, vid.width, vid.height, 32+(timeinmap&15)); V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 32+(timeinmap&15));
} }
// load previous saved value of skyVisible for the player // load previous saved value of skyVisible for the player

View file

@ -37,6 +37,9 @@
// Quincunx antialiasing of flats! // Quincunx antialiasing of flats!
//#define QUINCUNX //#define QUINCUNX
// good night sweet prince
#define SHITPLANESPARENCY
//SoM: 3/23/2000: Use Boom visplane hashing. //SoM: 3/23/2000: Use Boom visplane hashing.
#define MAXVISPLANES 512 #define MAXVISPLANES 512
@ -813,7 +816,11 @@ void R_DrawSinglePlane(visplane_t *pl)
else // Opaque, but allow transparent flat pixels else // Opaque, but allow transparent flat pixels
spanfunc = splatfunc; spanfunc = splatfunc;
if (pl->extra_colormap && pl->extra_colormap->fog) #ifdef SHITPLANESPARENCY
if (spanfunc == splatfunc || (pl->extra_colormap && pl->extra_colormap->fog))
#else
if (!pl->extra_colormap || !(pl->extra_colormap->fog & 2))
#endif
light = (pl->lightlevel >> LIGHTSEGSHIFT); light = (pl->lightlevel >> LIGHTSEGSHIFT);
else else
light = LIGHTLEVELS-1; light = LIGHTLEVELS-1;
@ -867,7 +874,11 @@ void R_DrawSinglePlane(visplane_t *pl)
else // Opaque, but allow transparent flat pixels else // Opaque, but allow transparent flat pixels
spanfunc = splatfunc; spanfunc = splatfunc;
if (pl->extra_colormap && pl->extra_colormap->fog) #ifdef SHITPLANESPARENCY
if (spanfunc == splatfunc || (pl->extra_colormap && pl->extra_colormap->fog))
#else
if (!pl->extra_colormap || !(pl->extra_colormap->fog & 2))
#endif
light = (pl->lightlevel >> LIGHTSEGSHIFT); light = (pl->lightlevel >> LIGHTSEGSHIFT);
else else
light = LIGHTLEVELS-1; light = LIGHTLEVELS-1;

View file

@ -983,7 +983,8 @@ static void R_SplitSprite(vissprite_t *sprite)
newsprite->extra_colormap = sector->lightlist[i].extra_colormap; newsprite->extra_colormap = sector->lightlist[i].extra_colormap;
if (!((newsprite->cut & SC_FULLBRIGHT) && (!newsprite->extra_colormap || !newsprite->extra_colormap->fog))) if (!((newsprite->cut & SC_FULLBRIGHT)
&& (!newsprite->extra_colormap || !(newsprite->extra_colormap->fog & 1))))
{ {
lindex = FixedMul(sprite->xscale, FixedDiv(640, vid.width))>>(LIGHTSCALESHIFT); lindex = FixedMul(sprite->xscale, FixedDiv(640, vid.width))>>(LIGHTSCALESHIFT);
@ -1403,7 +1404,7 @@ static void R_ProjectSprite(mobj_t *thing)
vis->cut |= SC_FULLBRIGHT; vis->cut |= SC_FULLBRIGHT;
if (vis->cut & SC_FULLBRIGHT if (vis->cut & SC_FULLBRIGHT
&& (!vis->extra_colormap || !vis->extra_colormap->fog)) && (!vis->extra_colormap || !(vis->extra_colormap->fog & 1)))
{ {
// full bright: goggles // full bright: goggles
vis->colormap = colormaps; vis->colormap = colormaps;

View file

@ -1351,6 +1351,7 @@ const char *compat_special_music_slots[16] =
#endif #endif
static char music_name[7]; // up to 6-character name static char music_name[7]; // up to 6-character name
static void *music_data;
static UINT16 music_flags; static UINT16 music_flags;
static boolean music_looping; static boolean music_looping;
@ -1497,6 +1498,7 @@ static boolean S_LoadMusic(const char *mname)
{ {
strncpy(music_name, mname, 7); strncpy(music_name, mname, 7);
music_name[6] = 0; music_name[6] = 0;
music_data = mdata;
return true; return true;
} }
else else
@ -1506,6 +1508,12 @@ static boolean S_LoadMusic(const char *mname)
static void S_UnloadMusic(void) static void S_UnloadMusic(void)
{ {
I_UnloadSong(); I_UnloadSong();
#ifndef HAVE_SDL //SDL uses RWOPS
Z_ChangeTag(music_data, PU_CACHE);
#endif
music_data = NULL;
music_name[0] = 0; music_name[0] = 0;
music_flags = 0; music_flags = 0;
music_looping = false; music_looping = false;
@ -1543,11 +1551,11 @@ static void S_ClearQueue(void)
static void S_ChangeMusicToQueue(void) static void S_ChangeMusicToQueue(void)
{ {
S_ChangeMusicAdvanced(queue_name, queue_flags, queue_looping, queue_position, 0, queue_fadeinms); S_ChangeMusicEx(queue_name, queue_flags, queue_looping, queue_position, 0, queue_fadeinms);
S_ClearQueue(); S_ClearQueue();
} }
void S_ChangeMusicAdvanced(const char *mmusic, UINT16 mflags, boolean looping, UINT32 position, UINT32 prefadems, UINT32 fadeinms) void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 position, UINT32 prefadems, UINT32 fadeinms)
{ {
if (S_MusicDisabled()) if (S_MusicDisabled())
return; return;
@ -1617,13 +1625,7 @@ void S_StopMusic(void)
S_SpeedMusic(1.0f); S_SpeedMusic(1.0f);
I_StopSong(); I_StopSong();
I_UnloadSong(); S_UnloadMusic(); // for now, stopping also means you unload the song
#ifndef HAVE_SDL //SDL uses RWOPS
Z_ChangeTag(music_data, PU_CACHE);
#endif
music_name[0] = 0;
if (cv_closedcaptioning.value) if (cv_closedcaptioning.value)
{ {
@ -1739,5 +1741,5 @@ void S_Start(void)
if (cv_resetmusic.value) if (cv_resetmusic.value)
S_StopMusic(); S_StopMusic();
S_ChangeMusicAdvanced(mapmusname, mapmusflags, true, mapmusposition, 0, 0); S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
} }

View file

@ -176,9 +176,9 @@ UINT32 S_GetMusicPosition(void);
// note: music flags 12 bits for tracknum (gme, other formats with more than one track) // note: music flags 12 bits for tracknum (gme, other formats with more than one track)
// 13-15 aren't used yet // 13-15 aren't used yet
// and the last bit we ignore (internal game flag for resetting music on reload) // and the last bit we ignore (internal game flag for resetting music on reload)
void S_ChangeMusicAdvanced(const char *mmusic, UINT16 mflags, boolean looping, UINT32 position, UINT32 prefadems, UINT32 fadeinms); void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 position, UINT32 prefadems, UINT32 fadeinms);
#define S_ChangeMusicInternal(a,b) S_ChangeMusicAdvanced(a,0,b,0,0,0) #define S_ChangeMusicInternal(a,b) S_ChangeMusicEx(a,0,b,0,0,0)
#define S_ChangeMusic(a,b,c) S_ChangeMusicAdvanced(a,b,c,0,0,0) #define S_ChangeMusic(a,b,c) S_ChangeMusicEx(a,b,c,0,0,0)
// Stops the music. // Stops the music.
void S_StopMusic(void); void S_StopMusic(void);
@ -195,7 +195,7 @@ void S_SetInternalMusicVolume(INT32 volume);
void S_StopFadingMusic(void); void S_StopFadingMusic(void);
boolean S_FadeMusicFromVolume(UINT8 target_volume, INT16 source_volume, UINT32 ms); boolean S_FadeMusicFromVolume(UINT8 target_volume, INT16 source_volume, UINT32 ms);
#define S_FadeMusic(a, b) S_FadeMusicFromVolume(a, -1, b) #define S_FadeMusic(a, b) S_FadeMusicFromVolume(a, -1, b)
#define S_FadeInChangeMusic(a,b,c,d) S_ChangeMusicAdvanced(a,b,c,0,0,d) #define S_FadeInChangeMusic(a,b,c,d) S_ChangeMusicEx(a,b,c,0,0,d)
boolean S_FadeOutStopMusic(UINT32 ms); boolean S_FadeOutStopMusic(UINT32 ms);
// //

View file

@ -34,6 +34,12 @@
(SDL_MIXER_COMPILEDVERSION >= SDL_VERSIONNUM(X, Y, Z)) (SDL_MIXER_COMPILEDVERSION >= SDL_VERSIONNUM(X, Y, Z))
#endif #endif
// thanks alam for making the buildbots happy!
#if SDL_MIXER_VERSION_ATLEAST(2,0,2)
#define MUS_MP3_MAD MUS_MP3_MAD_UNUSED
#define MUS_MODPLUG MUS_MODPLUG_UNUSED
#endif
#ifdef HAVE_LIBGME #ifdef HAVE_LIBGME
#include "gme/gme.h" #include "gme/gme.h"
#define GME_TREBLE 5.0 #define GME_TREBLE 5.0
@ -108,7 +114,10 @@ void I_StartupSound(void)
// EE inits audio first so we're following along. // EE inits audio first so we're following along.
if (SDL_WasInit(SDL_INIT_AUDIO) == SDL_INIT_AUDIO) if (SDL_WasInit(SDL_INIT_AUDIO) == SDL_INIT_AUDIO)
CONS_Debug(DBG_BASIC, "SDL Audio already started\n"); {
CONS_Debug(DBG_DETAILED, "SDL Audio already started\n");
return;
}
else if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) else if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
{ {
CONS_Alert(CONS_ERROR, "Error initializing SDL Audio: %s\n", SDL_GetError()); CONS_Alert(CONS_ERROR, "Error initializing SDL Audio: %s\n", SDL_GetError());
@ -588,30 +597,11 @@ static void mix_gme(void *udata, Uint8 *stream, int len)
FUNCMATH void I_InitMusic(void) FUNCMATH void I_InitMusic(void)
{ {
#ifdef HAVE_LIBGME
gme = NULL;
current_track = -1;
#endif
} }
void I_ShutdownMusic(void) void I_ShutdownMusic(void)
{ {
#ifdef HAVE_LIBGME I_UnloadSong();
if (gme)
{
Mix_HookMusic(NULL, NULL);
gme_delete(gme);
gme = NULL;
}
#endif
if (!music)
return;
var_cleanup();
SDL_RemoveTimer(fading_id);
Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes);
Mix_HookMusicFinished(NULL);
Mix_FreeMusic(music);
music = NULL;
} }
/// ------------------------ /// ------------------------
@ -629,9 +619,9 @@ musictype_t I_SongType(void)
return MU_NONE; return MU_NONE;
else if (Mix_GetMusicType(music) == MUS_MID) else if (Mix_GetMusicType(music) == MUS_MID)
return MU_MID; return MU_MID;
else if (Mix_GetMusicType(music) == MUS_MOD || Mix_GetMusicType(music) == MUS_MODPLUG_UNUSED) else if (Mix_GetMusicType(music) == MUS_MOD || Mix_GetMusicType(music) == MUS_MODPLUG)
return MU_MOD; return MU_MOD;
else if (Mix_GetMusicType(music) == MUS_MP3 || Mix_GetMusicType(music) == MUS_MP3_MAD_UNUSED) else if (Mix_GetMusicType(music) == MUS_MP3 || Mix_GetMusicType(music) == MUS_MP3_MAD)
return MU_MP3; return MU_MP3;
else else
return (musictype_t)Mix_GetMusicType(music); return (musictype_t)Mix_GetMusicType(music);
@ -774,23 +764,25 @@ boolean I_SetSongPosition(UINT32 position)
#ifdef HAVE_LIBGME #ifdef HAVE_LIBGME
if (gme) if (gme)
{ {
// this is unstable, so fail silently
return true;
// this isn't required technically, but GME thread-locks for a second // this isn't required technically, but GME thread-locks for a second
// if you seek too high from the counter // if you seek too high from the counter
length = I_GetSongLength(); // length = I_GetSongLength();
if (length) // if (length)
position = get_adjusted_position(position); // position = get_adjusted_position(position);
SDL_LockAudio(); // SDL_LockAudio();
gme_err_t gme_e = gme_seek(gme, position); // gme_err_t gme_e = gme_seek(gme, position);
SDL_UnlockAudio(); // SDL_UnlockAudio();
if (gme_e != NULL) // if (gme_e != NULL)
{ // {
CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e); // CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e);
return false; // return false;
} // }
else // else
return true; // return true;
} }
else else
#endif #endif
@ -866,10 +858,32 @@ UINT32 I_GetSongPosition(void)
boolean I_LoadSong(char *data, size_t len) boolean I_LoadSong(char *data, size_t len)
{ {
I_Assert(!music); const char *key1 = "LOOP";
const char *key2 = "POINT=";
const char *key3 = "MS=";
const char *key4 = "LENGTHMS=";
const size_t key1len = strlen(key1);
const size_t key2len = strlen(key2);
const size_t key3len = strlen(key3);
const size_t key4len = strlen(key4);
// for mp3 wide chars
const char *key1w = "L\0O\0O\0P\0";
const char *key2w = "P\0O\0I\0N\0T\0\0\0\xFF\xFE";
const char *key3w = "M\0S\0\0\0\xFF\xFE";
const char *key4w = "L\0E\0N\0G\0T\0H\0M\0S\0\0\0\xFF\xFE";
const char *wterm = "\0\0";
char wval[10];
size_t wstart, wp;
char *p = data;
if (music
#ifdef HAVE_LIBGME #ifdef HAVE_LIBGME
I_Assert(!gme); || gme
#endif #endif
)
I_UnloadSong();
var_cleanup(); var_cleanup();
@ -985,25 +999,6 @@ boolean I_LoadSong(char *data, size_t len)
loop_point = 0.0f; loop_point = 0.0f;
song_length = 0.0f; song_length = 0.0f;
const char *key1 = "LOOP";
const char *key2 = "POINT=";
const char *key3 = "MS=";
const char *key4 = "LENGTHMS=";
const size_t key1len = strlen(key1);
const size_t key2len = strlen(key2);
const size_t key3len = strlen(key3);
const size_t key4len = strlen(key4);
// for mp3 wide chars
const char *key1w = "L\0O\0O\0P\0";
const char *key2w = "P\0O\0I\0N\0T\0\0\0\xFF\xFE";
const char *key3w = "M\0S\0\0\0\xFF\xFE";
const char *key4w = "L\0E\0N\0G\0T\0H\0M\0S\0\0\0\xFF\xFE";
const char *wterm = "\0\0";
char wval[10];
size_t wstart, wp;
char *p = data;
while ((UINT32)(p - data) < len) while ((UINT32)(p - data) < len)
{ {
if (!loop_point && !strncmp(p, key1, key1len)) if (!loop_point && !strncmp(p, key1, key1len))
@ -1089,11 +1084,20 @@ boolean I_LoadSong(char *data, size_t len)
void I_UnloadSong(void) void I_UnloadSong(void)
{ {
// \todo unhook looper
//var_cleanup();
//Mix_FreeMusic(music);
//music = NULL;
I_StopSong(); I_StopSong();
#ifdef HAVE_LIBGME
if (gme)
{
gme_delete(gme);
gme = NULL;
}
#endif
if (music)
{
Mix_FreeMusic(music);
music = NULL;
}
} }
boolean I_PlaySong(boolean looping) boolean I_PlaySong(boolean looping)
@ -1144,19 +1148,17 @@ void I_StopSong(void)
if (gme) if (gme)
{ {
Mix_HookMusic(NULL, NULL); Mix_HookMusic(NULL, NULL);
gme_delete(gme);
gme = NULL;
current_track = -1; current_track = -1;
return;
} }
#endif #endif
if (!music) if (music)
return; {
var_cleanup(); var_cleanup();
I_StopFadingSong();
Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes); Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes);
Mix_HookMusicFinished(NULL); Mix_HookMusicFinished(NULL);
Mix_FreeMusic(music); Mix_HaltMusic();
music = NULL; }
} }
void I_PauseSong() void I_PauseSong()

View file

@ -989,7 +989,7 @@ FUNCINLINE static ATTRINLINE void I_UpdateStream16M(Uint8 *stream, int len)
if (Snd_Mutex) SDL_UnlockMutex(Snd_Mutex); if (Snd_Mutex) SDL_UnlockMutex(Snd_Mutex);
} }
#ifdef HAVE_LIBGME #if 0 //#ifdef HAVE_LIBGME
static void I_UpdateSteamGME(Music_Emu *emu, INT16 *stream, int len, UINT8 looping) static void I_UpdateSteamGME(Music_Emu *emu, INT16 *stream, int len, UINT8 looping)
{ {
#define GME_BUFFER_LEN 44100*2048 #define GME_BUFFER_LEN 44100*2048
@ -1049,14 +1049,16 @@ static void SDLCALL I_UpdateStream(void *userdata, Uint8 *stream, int len)
else if (audio.channels == 2 && audio.format == AUDIO_S16SYS) else if (audio.channels == 2 && audio.format == AUDIO_S16SYS)
{ {
I_UpdateStream16S(stream, len); I_UpdateStream16S(stream, len);
#ifdef HAVE_LIBGME
if (userdata) // Crashes! But no matter; this build doesn't play music anyway...
{ // #ifdef HAVE_LIBGME
srb2audio_t *sa_userdata = userdata; // if (userdata)
if (!sa_userdata->gme_pause) // {
I_UpdateSteamGME(sa_userdata->gme_emu, (INT16 *)stream, len/4, sa_userdata->gme_loop); // srb2audio_t *sa_userdata = userdata;
} // if (!sa_userdata->gme_pause)
#endif // I_UpdateSteamGME(sa_userdata->gme_emu, (INT16 *)stream, len/4, sa_userdata->gme_loop);
// }
// #endif
} }
} }
@ -1313,40 +1315,11 @@ void I_StartupSound(void)
// MUSIC API. // MUSIC API.
// //
musictype_t I_SongType(void) /// ------------------------
{ // MUSIC SYSTEM
#ifdef HAVE_MIXER /// ------------------------
#ifdef HAVE_LIBGME
if (gme)
return MU_GME;
else
#endif
if (!music)
return MU_NONE;
else if (Mix_GetMusicType(music) == MUS_MID)
return MU_MID;
else if (Mix_GetMusicType(music) == MUS_MOD || Mix_GetMusicType(music) == MUS_MODPLUG_UNUSED)
return MU_MOD;
else if (Mix_GetMusicType(music) == MUS_MP3 || Mix_GetMusicType(music) == MUS_MP3_MAD_UNUSED)
return MU_MP3;
else
return (musictype_t)Mix_GetMusicType(music);
#else
return MU_NONE
#endif
}
boolean I_SongPlaying(void) #if 0 //#ifdef HAVE_LIBGME
{
return music_started;
}
boolean I_SongPaused(void)
{
return Mix_PausedMusic();
}
#ifdef HAVE_LIBGME
static void I_ShutdownGMEMusic(void) static void I_ShutdownGMEMusic(void)
{ {
Snd_LockAudio(); Snd_LockAudio();
@ -1357,235 +1330,14 @@ static void I_ShutdownGMEMusic(void)
} }
#endif #endif
#ifdef HAVE_MIXER
static boolean LoadSong(void *data, size_t lumplength, size_t selectpos)
{
FILE *midfile;
const char *tempname;
#ifdef USE_RWOPS
if (canuseRW)
{
SDL_RWops *SDLRW;
void *olddata = Smidi[selectpos]; //quick shortcut to set
Z_Free(olddata); //free old memory
Smidi[selectpos] = NULL;
if (!data)
return olddata != NULL; //was there old data?
SDLRW = SDL_RWFromConstMem(data, (int)lumplength); //new RWops from Z_zone
if (!SDLRW) //ERROR while making RWops!
{
CONS_Printf(M_GetText("Couldn't load music lump: %s\n"), SDL_GetError());
Z_Free(data);
return false;
}
music[selectpos] = Mix_LoadMUS_RW(SDLRW); // new Mix_Chuck from RWops
if (music[selectpos])
Smidi[selectpos] = data; //all done
else //ERROR while making Mix_Chuck
{
CONS_Printf(M_GetText("Couldn't load music data: %s\n"), Mix_GetError());
Z_Free(data);
SDL_RWclose(SDLRW);
Smidi[selectpos] = NULL;
}
return true;
}
#endif
tempname = va("%s/%s", MIDI_PATH, fmidi[selectpos]);
if (!data)
{
if (FIL_FileExists(tempname))
return unlink(tempname)+1;
#ifdef MIDI_PATH2
else if (FIL_FileExists(tempname = va("%s/%s", MIDI_PATH2, fmidi[selectpos])))
return unlink(tempname)+1;
#endif
else
return false;
}
midfile = fopen(tempname, "wb");
#ifdef MIDI_PATH2
if (!midfile)
{
tempname = va("%s/%s", MIDI_PATH2, fmidi[selectpos]);
midfile = fopen(tempname, "wb");
}
#endif
if (!midfile)
{
CONS_Printf(M_GetText("Couldn't open file %s to write music in\n"), tempname);
Z_Free(data);
return false;
}
if (fwrite(data, lumplength, 1, midfile) == 0)
{
CONS_Printf(M_GetText("Couldn't write music into file %s because %s\n"), tempname, strerror(ferror(midfile)));
Z_Free(data);
fclose(midfile);
return false;
}
fclose(midfile);
Z_Free(data);
music[selectpos] = Mix_LoadMUS(tempname);
if (!music[selectpos]) //ERROR while making Mix_Chuck
{
CONS_Printf(M_GetText("Couldn't load music file %s: %s\n"), tempname, Mix_GetError());
return false;
}
return true;
}
#endif
/// ------------------------
// MUSIC SYSTEM
/// ------------------------
void I_InitMusic(void) void I_InitMusic(void)
{ {
#ifdef HAVE_MIXER #if 0 //#ifdef HAVE_LIBGME
char ad[100];
SDL_version MIXcompiled;
const SDL_version *MIXlinked;
#ifdef MIXER_INIT
const int mixstart = MIX_INIT_OGG;
int mixflags;
#endif
#endif
#ifdef HAVE_LIBGME
I_AddExitFunc(I_ShutdownGMEMusic); I_AddExitFunc(I_ShutdownGMEMusic);
#endif #endif
#ifdef HAVE_MIXER
MIX_VERSION(&MIXcompiled)
MIXlinked = Mix_Linked_Version();
I_OutputMsg("Compiled for SDL_mixer version: %d.%d.%d\n",
MIXcompiled.major, MIXcompiled.minor, MIXcompiled.patch);
#ifdef MIXER_POS
if (MIXlinked->major == 1 && MIXlinked->minor == 2 && MIXlinked->patch < 7)
canlooping = SDL_FALSE;
#endif
#ifdef USE_RWOPS
if (M_CheckParm("-noRW"))
canuseRW = SDL_FALSE;
#endif
I_OutputMsg("Linked with SDL_mixer version: %d.%d.%d\n",
MIXlinked->major, MIXlinked->minor, MIXlinked->patch);
if (audio.freq < 44100 && !M_CheckParm ("-freq")) //I want atleast 44Khz
{
audio.samples = (Uint16)(audio.samples*(INT32)(44100/audio.freq));
audio.freq = 44100; //Alam: to keep it around the same XX ms
} }
if (sound_started void I_ShutdownMusic(void) { }
#ifdef HW3SOUND
&& hws_mode == HWS_DEFAULT_MODE
#endif
)
{
I_OutputMsg("Temp Shutdown of SDL Audio System");
SDL_CloseAudio();
I_OutputMsg(" Done\n");
}
CONS_Printf("%s", M_GetText("I_InitMusic:"));
#ifdef MIXER_INIT
mixflags = Mix_Init(mixstart);
if ((mixstart & MIX_INIT_FLAC) != (mixflags & MIX_INIT_FLAC))
{
CONS_Printf("%s", M_GetText(" Unable to load FLAC support\n"));
}
if ((mixstart & MIX_INIT_MOD ) != (mixflags & MIX_INIT_MOD ))
{
CONS_Printf("%s", M_GetText(" Unable to load MOD support\n"));
}
if ((mixstart & MIX_INIT_MP3 ) != (mixflags & MIX_INIT_MP3 ))
{
CONS_Printf("%s", M_GetText(" Unable to load MP3 support\n"));
}
if ((mixstart & MIX_INIT_OGG ) != (mixflags & MIX_INIT_OGG ))
{
CONS_Printf("%s", M_GetText(" Unable to load OGG support\n"));
}
#endif
if (Mix_OpenAudio(audio.freq, audio.format, audio.channels, audio.samples) < 0) //open_music(&audio)
{
CONS_Printf(M_GetText(" Unable to open music: %s\n"), Mix_GetError());
midi_disabled = digital_disabled = true;
if (sound_started
#ifdef HW3SOUND
&& hws_mode == HWS_DEFAULT_MODE
#endif
)
{
if (SDL_OpenAudio(&audio, NULL) < 0) //retry
{
CONS_Printf("%s", M_GetText(" couldn't open audio with desired format\n"));
sound_disabled = true;
sound_started = false;
}
else
{
CONS_Printf(M_GetText(" Starting with audio driver : %s\n"), SDL_AudioDriverName(ad, (int)sizeof ad));
}
}
return;
}
else
CONS_Printf(M_GetText(" Starting up with audio driver : %s with SDL_Mixer\n"), SDL_AudioDriverName(ad, (int)sizeof ad));
samplecount = audio.samples;
CV_SetValue(&cv_samplerate, audio.freq);
if (sound_started
#ifdef HW3SOUND
&& hws_mode == HWS_DEFAULT_MODE
#endif
)
I_OutputMsg(" Reconfigured SDL Audio System");
else I_OutputMsg(" Configured SDL_Mixer System");
I_OutputMsg(" with %d samples/slice at %ikhz(%dms buffer)\n", samplecount, audio.freq/1000, (INT32) ((audio.samples * 1000.0f) / audio.freq));
Mix_SetPostMix(audio.callback, audio.userdata); // after mixing music, add sound effects
Mix_Resume(-1);
CONS_Printf("%s", M_GetText("Music initialized\n"));
musicStarted = SDL_TRUE;
Msc_Mutex = SDL_CreateMutex();
#endif
}
void I_ShutdownMusic(void)
{
#ifdef HAVE_MIXER
if ((midi_disabled && digital_disabled) || !musicStarted)
return;
CONS_Printf("%s", M_GetText("I_ShutdownMusic: "));
I_UnloadSong();
I_StopSong();
Mix_CloseAudio();
#ifdef MIX_INIT
Mix_Quit();
#endif
CONS_Printf("%s", M_GetText("shut down\n"));
musicStarted = SDL_FALSE;
if (Msc_Mutex)
SDL_DestroyMutex(Msc_Mutex);
Msc_Mutex = NULL;
#endif
}
/// ------------------------ /// ------------------------
// MUSIC PROPERTIES // MUSIC PROPERTIES
@ -1649,149 +1401,64 @@ UINT32 I_GetSongPosition(void)
/// ------------------------ /// ------------------------
// MUSIC PLAYBACK // MUSIC PLAYBACK
// \todo Merge Digital and MIDI
/// ------------------------ /// ------------------------
#if 0 //#ifdef HAVE_LIBGME
static void I_StopGME(void)
{
Snd_LockAudio();
gme_seek(localdata.gme_emu, 0);
Snd_UnlockAudio();
}
static void I_PauseGME(void)
{
localdata.gme_pause = true;
}
static void I_ResumeGME(void)
{
localdata.gme_pause = false;
}
#endif
boolean I_LoadSong(char *data, size_t len) boolean I_LoadSong(char *data, size_t len)
{ {
#ifdef HAVE_MIXER
if (midi_disabled || !musicStarted)
return false;
if (!LoadSong(data, len, 0))
return false;
if (music[0])
return true;
CONS_Printf(M_GetText("Couldn't load MIDI: %s\n"), Mix_GetError());
#else
(void)len;
(void)data;
#endif
return false; return false;
} }
void I_UnloadSong(void) void I_UnloadSong(void) { }
{
#ifdef HAVE_MIXER
if (midi_disabled || !musicStarted)
return;
Mix_HaltMusic();
while (Mix_PlayingMusic())
;
if (music[handle])
Mix_FreeMusic(music[handle]);
music[handle] = NULL;
LoadSong(NULL, 0, handle);
#else
(void)handle;
#endif
}
boolean I_PlaySong(boolean looping) boolean I_PlaySong(boolean looping)
{ {
#ifdef HAVE_MIXER
if (!musicStarted || !music[handle])
return false;
#ifdef MIXER_POS
if (canlooping)
Mix_HookMusicFinished(NULL);
#endif
if (Mix_FadeInMusic(music[handle], looping ? -1 : 0, MIDIfade) == -1)
CONS_Printf(M_GetText("Couldn't play song because %s\n"), Mix_GetError());
else
{
Mix_VolumeMusic(musicvol);
return true;
}
#else
(void)looping; (void)looping;
#endif
return false; return false;
} }
void I_StopSong(void) void I_StopSong(void)
{ {
#if 0 //#ifdef HAVE_LIBGME
I_StopGME(); I_StopGME();
#ifdef HAVE_MIXER
if (digital_disabled)
return;
#ifdef MIXER_POS
if (canlooping)
Mix_HookMusicFinished(NULL);
#endif
Mix_HaltMusic();
while (Mix_PlayingMusic())
;
if (music[1])
Mix_FreeMusic(music[1]);
music[1] = NULL;
LoadSong(NULL, 0, 1);
}
static void I_PauseGME(void)
{
#ifdef HAVE_LIBGME
localdata.gme_pause = true;
#endif #endif
} }
void I_PauseSong(void) void I_PauseSong(void)
{ {
(void)handle; #if 0 //#ifdef HAVE_LIBGME
I_PauseGME(); I_PauseGME();
#ifdef HAVE_MIXER
if ((midi_disabled && digital_disabled) || !musicStarted)
return;
Mix_PauseMusic();
//I_StopSong(handle);
#endif
}
static void I_ResumeGME(void)
{
#ifdef HAVE_LIBGME
localdata.gme_pause = false;
#endif #endif
} }
void I_ResumeSong(void) void I_ResumeSong(void)
{ {
(void)handle; #if 0
I_ResumeGME(); I_ResumeGME();
#ifdef HAVE_MIXER
if ((midi_disabled && digital_disabled) || !musicStarted)
return;
Mix_VolumeMusic(musicvol);
Mix_ResumeMusic();
//I_PlaySong(handle, true);
#endif #endif
} }
void I_SetMusicVolume(UINT8 volume) void I_SetMusicVolume(UINT8 volume)
{ {
#ifdef HAVE_MIXER
if ((midi_disabled && digital_disabled) || !musicStarted)
return;
if (Msc_Mutex) SDL_LockMutex(Msc_Mutex);
musicvol = volume * 2;
if (Msc_Mutex) SDL_UnlockMutex(Msc_Mutex);
Mix_VolumeMusic(musicvol);
#else
(void)volume; (void)volume;
#endif
} }
boolean I_SetSongTrack(int track) boolean I_SetSongTrack(int track)
@ -1847,16 +1514,14 @@ boolean I_FadeInPlaySong(UINT32 ms, boolean looping)
// then move to Playback section // then move to Playback section
/// ------------------------ /// ------------------------
#ifdef HAVE_LIBGME #if 0 //#ifdef HAVE_LIBGME
static void I_CleanupGME(void *userdata) static void I_CleanupGME(void *userdata)
{ {
Z_Free(userdata); Z_Free(userdata);
} }
#endif
static boolean I_StartGMESong(const char *musicname, boolean looping) static boolean I_StartGMESong(const char *musicname, boolean looping)
{ {
#ifdef HAVE_LIBGME
char filename[9]; char filename[9];
void *data; void *data;
lumpnum_t lumpnum; lumpnum_t lumpnum;
@ -1902,199 +1567,7 @@ static boolean I_StartGMESong(const char *musicname, boolean looping)
Snd_UnlockAudio(); Snd_UnlockAudio();
return true; return true;
#else
(void)musicname;
(void)looping;
#endif
return false;
}
boolean I_StartDigSong(const char *musicname, boolean looping)
{
#ifdef HAVE_MIXER
char filename[9];
void *data;
lumpnum_t lumpnum;
size_t lumplength;
#endif
if(I_StartGMESong(musicname, looping))
return true;
#ifdef HAVE_MIXER
if (digital_disabled)
return false;
snprintf(filename, sizeof filename, "o_%s", musicname);
lumpnum = W_CheckNumForName(filename);
I_StopSong();
if (lumpnum == LUMPERROR)
{
// Alam_GBC: like in win32/win_snd.c: Graue 02-29-2004: don't worry about missing music, there might still be a MIDI
//I_OutputMsg("Music lump %s not found!\n", filename);
return false; // No music found. Oh well!
}
else
lumplength = W_LumpLength(lumpnum);
data = W_CacheLumpNum(lumpnum, PU_MUSIC);
if (Msc_Mutex) SDL_LockMutex(Msc_Mutex);
#ifdef MIXER_POS
if (canlooping && (loopingDig = looping) == SDL_TRUE && strcmp(data, "OggS") == 0)
looping = false; // Only on looping Ogg files, will we will do our own looping
// Scan the Ogg Vorbis file for the COMMENT= field for a custom
// loop point
if (!looping && loopingDig)
{
size_t scan;
const char *dataum = data;
char looplength[64];
UINT32 loopstart = 0;
UINT8 newcount = 0;
Mix_HookMusicFinished(I_FinishMusic);
for (scan = 0; scan < lumplength; scan++)
{
if (*dataum++ == 'C'){
if (*dataum++ == 'O'){
if (*dataum++ == 'M'){
if (*dataum++ == 'M'){
if (*dataum++ == 'E'){
if (*dataum++ == 'N'){
if (*dataum++ == 'T'){
if (*dataum++ == '='){
if (*dataum++ == 'L'){
if (*dataum++ == 'O'){
if (*dataum++ == 'O'){
if (*dataum++ == 'P'){
if (*dataum++ == 'P'){
if (*dataum++ == 'O'){
if (*dataum++ == 'I'){
if (*dataum++ == 'N'){
if (*dataum++ == 'T'){
if (*dataum++ == '=')
{
while (*dataum != 1 && newcount != 63)
looplength[newcount++] = *dataum++;
looplength[newcount] = '\0';
loopstart = atoi(looplength);
}
else
dataum--;}
else
dataum--;}
else
dataum--;}
else
dataum--;}
else
dataum--;}
else
dataum--;}
else
dataum--;}
else
dataum--;}
else
dataum--;}
else
dataum--;}
else
dataum--;}
else
dataum--;}
else
dataum--;}
else
dataum--;}
else
dataum--;}
else
dataum--;}
else
dataum--;}
}
if (loopstart > 0)
{
loopstartDig = (double)((44.1l+loopstart) / 44100.0l); //8 PCM chucks off and PCM to secs
//#ifdef PARANOIA
//I_OutputMsg("I_StartDigSong: setting looping point to %ul PCMs(%f seconds)\n", loopstart, loopstartDig);
//#endif
}
else
{
looping = true; // loopingDig true, but couldn't find start loop point
}
}
else
loopstartDig = 0.0l;
#else
if (looping && strcmp(data, "OggS") == 0)
I_OutputMsg("I_StartDigSong: SRB2 was not compiled with looping music support(no Mix_FadeInMusicPos)\n");
#endif
if (!LoadSong(data, lumplength, 1))
{
if (Msc_Mutex) SDL_UnlockMutex(Msc_Mutex);
return false;
}
// Note: LoadSong() frees the data. Let's make sure
// we don't try to use the data again.
data = NULL;
if (Mix_FadeInMusic(music[1], looping ? -1 : 0, Digfade) == -1)
{
if (Msc_Mutex) SDL_UnlockMutex(Msc_Mutex);
I_OutputMsg("I_StartDigSong: Couldn't play song %s because %s\n", musicname, Mix_GetError());
return false;
}
Mix_VolumeMusic(musicvol);
if (Msc_Mutex) SDL_UnlockMutex(Msc_Mutex);
return true;
#else
(void)looping;
(void)musicname;
return false;
#endif
}
static void I_StopGME(void)
{
#ifdef HAVE_LIBGME
Snd_LockAudio();
gme_seek(localdata.gme_emu, 0);
Snd_UnlockAudio();
#endif
}
#ifdef MIXER_POS
static void SDLCALL I_FinishMusic(void)
{
if (!music[1])
return;
else if (Msc_Mutex) SDL_LockMutex(Msc_Mutex);
// I_OutputMsg("I_FinishMusic: Loopping song to %g seconds\n", loopstartDig);
if (Mix_FadeInMusicPos(music[1], loopstartDig ? 0 : -1, Digfade, loopstartDig) == 0)
Mix_VolumeMusic(musicvol);
else
I_OutputMsg("I_FinishMusic: Couldn't loop song because %s\n", Mix_GetError());
if (Msc_Mutex) SDL_UnlockMutex(Msc_Mutex);
} }
#endif #endif
#endif //HAVE_SDL #endif //HAVE_SDL

View file

@ -807,7 +807,7 @@ static void ST_drawLivesArea(void)
// lives number // lives number
if (gametype == GT_RACE) if (gametype == GT_RACE)
{ {
livescount = 0x7f; livescount = INFLIVES;
notgreyedout = true; notgreyedout = true;
} }
else if ((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 3) else if ((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 3)
@ -826,9 +826,9 @@ static void ST_drawLivesArea(void)
if (players[i].lives > 1) if (players[i].lives > 1)
notgreyedout = true; notgreyedout = true;
if (players[i].lives == 0x7f) if (players[i].lives == INFLIVES)
{ {
livescount = 0x7f; livescount = INFLIVES;
break; break;
} }
else if (livescount < 99) else if (livescount < 99)
@ -837,11 +837,11 @@ static void ST_drawLivesArea(void)
} }
else else
{ {
livescount = (((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 0) ? 0x7f : stplyr->lives); livescount = (((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 0) ? INFLIVES : stplyr->lives);
notgreyedout = true; notgreyedout = true;
} }
if (livescount == 0x7f) if (livescount == INFLIVES)
V_DrawCharacter(hudinfo[HUD_LIVES].x+50, hudinfo[HUD_LIVES].y+8, V_DrawCharacter(hudinfo[HUD_LIVES].x+50, hudinfo[HUD_LIVES].y+8,
'\x16' | 0x80 | hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, false); '\x16' | 0x80 | hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, false);
else else
@ -1205,6 +1205,10 @@ static void ST_drawPowerupHUD(void)
if (stplyr->spectator || stplyr->playerstate != PST_LIVE) if (stplyr->spectator || stplyr->playerstate != PST_LIVE)
return; return;
// -------
// Shields
// -------
// Graue 06-18-2004: no V_NOSCALESTART, no SCX, no SCY, snap to right // Graue 06-18-2004: no V_NOSCALESTART, no SCX, no SCY, snap to right
if (stplyr->powers[pw_shield] & SH_NOSTACK) if (stplyr->powers[pw_shield] & SH_NOSTACK)
{ {
@ -1247,6 +1251,10 @@ static void ST_drawPowerupHUD(void)
offs -= shieldoffs[q]; offs -= shieldoffs[q];
// ---------
// CTF flags
// ---------
// YOU have a flag. Display a monitor-like icon for it. // YOU have a flag. Display a monitor-like icon for it.
if (stplyr->gotflag) if (stplyr->gotflag)
{ {
@ -1264,11 +1272,20 @@ static void ST_drawPowerupHUD(void)
offs -= flagoffs[q]; offs -= flagoffs[q];
// --------------------
// Timer-based powerups
// --------------------
#define DRAWTIMERICON(patch, timer) \
V_DrawSmallScaledPatch(offs, hudinfo[HUD_POWERUPS].y, V_PERPLAYER|hudinfo[HUD_POWERUPS].f|V_HUDTRANS, patch); \
V_DrawRightAlignedThinString(offs + 16, hudinfo[HUD_POWERUPS].y + 8, V_PERPLAYER|hudinfo[HUD_POWERUPS].f, va("%d", timer/TICRATE));
// Invincibility, both from monitor and after being hit
invulntime = stplyr->powers[pw_flashing] ? stplyr->powers[pw_flashing] : stplyr->powers[pw_invulnerability]; invulntime = stplyr->powers[pw_flashing] ? stplyr->powers[pw_flashing] : stplyr->powers[pw_invulnerability];
// Note: pw_flashing always makes the icon flicker regardless of time, unlike pw_invulnerability
if (stplyr->powers[pw_invulnerability] > 3*TICRATE || (invulntime && leveltime & 1)) if (stplyr->powers[pw_invulnerability] > 3*TICRATE || (invulntime && leveltime & 1))
{ {
V_DrawSmallScaledPatch(offs, hudinfo[HUD_POWERUPS].y, V_PERPLAYER|hudinfo[HUD_POWERUPS].f|V_HUDTRANS, invincibility); DRAWTIMERICON(invincibility, invulntime)
V_DrawRightAlignedThinString(offs + 16, hudinfo[HUD_POWERUPS].y + 8, V_PERPLAYER|hudinfo[HUD_POWERUPS].f, va("%d", invulntime/TICRATE));
} }
if (invulntime > 7) if (invulntime > 7)
@ -1281,10 +1298,10 @@ static void ST_drawPowerupHUD(void)
offs -= a; offs -= a;
} }
// Super Sneakers
if (stplyr->powers[pw_sneakers] > 3*TICRATE || (stplyr->powers[pw_sneakers] && leveltime & 1)) if (stplyr->powers[pw_sneakers] > 3*TICRATE || (stplyr->powers[pw_sneakers] && leveltime & 1))
{ {
V_DrawSmallScaledPatch(offs, hudinfo[HUD_POWERUPS].y, V_PERPLAYER|hudinfo[HUD_POWERUPS].f|V_HUDTRANS, sneakers); DRAWTIMERICON(sneakers, stplyr->powers[pw_sneakers])
V_DrawRightAlignedThinString(offs + 16, hudinfo[HUD_POWERUPS].y + 8, V_PERPLAYER|hudinfo[HUD_POWERUPS].f, va("%d", stplyr->powers[pw_sneakers]/TICRATE));
} }
if (stplyr->powers[pw_sneakers] > 7) if (stplyr->powers[pw_sneakers] > 7)
@ -1297,12 +1314,13 @@ static void ST_drawPowerupHUD(void)
offs -= a; offs -= a;
} }
// Gravity Boots
if (stplyr->powers[pw_gravityboots] > 3*TICRATE || (stplyr->powers[pw_gravityboots] && leveltime & 1)) if (stplyr->powers[pw_gravityboots] > 3*TICRATE || (stplyr->powers[pw_gravityboots] && leveltime & 1))
{ {
V_DrawSmallScaledPatch(offs, hudinfo[HUD_POWERUPS].y, V_PERPLAYER|hudinfo[HUD_POWERUPS].f|V_HUDTRANS, gravboots); DRAWTIMERICON(gravboots, stplyr->powers[pw_gravityboots])
V_DrawRightAlignedThinString(offs + 16, hudinfo[HUD_POWERUPS].y + 8, V_PERPLAYER|hudinfo[HUD_POWERUPS].f, va("%d", stplyr->powers[pw_gravityboots]/TICRATE));
} }
#undef DRAWTIMERICON
#undef ICONSEP #undef ICONSEP
} }
@ -1361,8 +1379,9 @@ static void ST_drawNightsRecords(void)
if (stplyr->texttimer < TICRATE/2) if (stplyr->texttimer < TICRATE/2)
aflag |= (9 - 9*stplyr->texttimer/(TICRATE/2)) << V_ALPHASHIFT; aflag |= (9 - 9*stplyr->texttimer/(TICRATE/2)) << V_ALPHASHIFT;
// A "Bonus Time Start" by any other name... switch (stplyr->textvar)
if (stplyr->textvar == 1) {
case 1: // A "Bonus Time Start" by any other name...
{ {
V_DrawCenteredString(BASEVIDWIDTH/2, 52, V_GREENMAP|aflag, M_GetText("GET TO THE GOAL!")); V_DrawCenteredString(BASEVIDWIDTH/2, 52, V_GREENMAP|aflag, M_GetText("GET TO THE GOAL!"));
V_DrawCenteredString(BASEVIDWIDTH/2, 60, aflag, M_GetText("SCORE MULTIPLIER START!")); V_DrawCenteredString(BASEVIDWIDTH/2, 60, aflag, M_GetText("SCORE MULTIPLIER START!"));
@ -1374,10 +1393,10 @@ static void ST_drawNightsRecords(void)
V_DrawRightAlignedString(BASEVIDWIDTH/2 + 48, 140, V_ORANGEMAP|aflag, va("%d", (stplyr->startedtime - stplyr->finishedtime)/TICRATE)); V_DrawRightAlignedString(BASEVIDWIDTH/2 + 48, 140, V_ORANGEMAP|aflag, va("%d", (stplyr->startedtime - stplyr->finishedtime)/TICRATE));
V_DrawRightAlignedString(BASEVIDWIDTH/2 + 48, 148, V_ORANGEMAP|aflag, va("%d", (stplyr->finishedtime/TICRATE) * 100)); V_DrawRightAlignedString(BASEVIDWIDTH/2 + 48, 148, V_ORANGEMAP|aflag, va("%d", (stplyr->finishedtime/TICRATE) * 100));
} }
break;
} }
case 2: // Get n Spheres
// Get n [more] Spheres case 3: // Get n more Spheres
else if (stplyr->textvar <= 3 && stplyr->textvar >= 2)
{ {
if (!stplyr->capsule) if (!stplyr->capsule)
return; return;
@ -1388,10 +1407,9 @@ static void ST_drawNightsRecords(void)
(stplyr->textvar == 3) ? M_GetText("MORE ") : "", (stplyr->textvar == 3) ? M_GetText("MORE ") : "",
(G_IsSpecialStage(gamemap)) ? "SPHERE" : "CHIP", (G_IsSpecialStage(gamemap)) ? "SPHERE" : "CHIP",
(stplyr->capsule->health > 1) ? "S" : "")); (stplyr->capsule->health > 1) ? "S" : ""));
break;
} }
case 4: // End Bonus
// End Bonus
else if (stplyr->textvar == 4)
{ {
V_DrawString(BASEVIDWIDTH/2 - 56, 140, aflag, (G_IsSpecialStage(gamemap)) ? "SPHERES:" : "CHIPS:"); V_DrawString(BASEVIDWIDTH/2 - 56, 140, aflag, (G_IsSpecialStage(gamemap)) ? "SPHERES:" : "CHIPS:");
V_DrawString(BASEVIDWIDTH/2 - 56, 148, aflag, "BONUS:"); V_DrawString(BASEVIDWIDTH/2 - 56, 148, aflag, "BONUS:");
@ -1415,6 +1433,10 @@ static void ST_drawNightsRecords(void)
V_DrawScaledPatch(BASEVIDWIDTH/2 + 60, 160, 0, V_DrawScaledPatch(BASEVIDWIDTH/2 + 60, 160, 0,
ngradeletters[P_GetGrade(stplyr->lastmarescore, gamemap, stplyr->lastmare)]); ngradeletters[P_GetGrade(stplyr->lastmarescore, gamemap, stplyr->lastmare)]);
} }
break;
}
default:
break;
} }
} }
@ -1450,20 +1472,60 @@ static skincolors_t linkColor[2][NUMLINKCOLORS] = {
{SKINCOLOR_SEAFOAM, SKINCOLOR_CYAN, SKINCOLOR_WAVE, SKINCOLOR_SAPPHIRE, SKINCOLOR_VAPOR, SKINCOLOR_BUBBLEGUM, {SKINCOLOR_SEAFOAM, SKINCOLOR_CYAN, SKINCOLOR_WAVE, SKINCOLOR_SAPPHIRE, SKINCOLOR_VAPOR, SKINCOLOR_BUBBLEGUM,
SKINCOLOR_VIOLET, SKINCOLOR_RUBY, SKINCOLOR_FLAME, SKINCOLOR_SUNSET, SKINCOLOR_SANDY, SKINCOLOR_LIME}}; SKINCOLOR_VIOLET, SKINCOLOR_RUBY, SKINCOLOR_FLAME, SKINCOLOR_SUNSET, SKINCOLOR_SANDY, SKINCOLOR_LIME}};
static void ST_drawNiGHTSLink(void)
{
static INT32 prevsel[2] = {0, 0}, prevtime[2] = {0, 0};
const UINT8 q = ((splitscreen && stplyr == &players[secondarydisplayplayer]) ? 1 : 0);
INT32 sel = ((stplyr->linkcount-1) / 5) % NUMLINKCOLORS, aflag = V_PERPLAYER, mag = ((stplyr->linkcount-1 >= 300) ? 1 : 0);
skincolors_t colornum;
fixed_t x, y, scale;
if (sel != prevsel[q])
{
prevsel[q] = sel;
prevtime[q] = 2 + mag;
}
if (stplyr->powers[pw_nights_linkfreeze] && (!(stplyr->powers[pw_nights_linkfreeze] & 2) || (stplyr->powers[pw_nights_linkfreeze] > flashingtics)))
colornum = SKINCOLOR_ICY;
else
colornum = linkColor[mag][sel];
aflag |= ((stplyr->linktimer < nightslinktics/3)
? (9 - 9*stplyr->linktimer/(nightslinktics/3)) << V_ALPHASHIFT
: 0);
y = (160+11)<<FRACBITS;
aflag |= V_SNAPTOBOTTOM;
x = (160+4)<<FRACBITS;
if (prevtime[q])
{
scale = ((32 + prevtime[q])<<FRACBITS)/32;
prevtime[q]--;
}
else
scale = FRACUNIT;
y -= (11*scale);
ST_DrawNightsOverlayNum(x-(4*scale), y, scale, aflag, (stplyr->linkcount-1), nightsnum, colornum);
V_DrawFixedPatch(x+(4*scale), y, scale, aflag, nightslink,
colornum == 0 ? colormaps : R_GetTranslationColormap(TC_DEFAULT, colornum, GTC_CACHE));
// Show remaining link time left in debug
if (cv_debug & DBG_NIGHTSBASIC)
V_DrawCenteredString(BASEVIDWIDTH/2, 180, V_SNAPTOBOTTOM, va("End in %d.%02d", stplyr->linktimer/TICRATE, G_TicsToCentiseconds(stplyr->linktimer)));
}
static void ST_drawNiGHTSHUD(void) static void ST_drawNiGHTSHUD(void)
{ {
INT32 origamount; INT32 origamount;
INT32 minlink = 1;
INT32 total_spherecount; INT32 total_spherecount;
const boolean oldspecialstage = (G_IsSpecialStage(gamemap) && !(maptol & TOL_NIGHTS)); const boolean oldspecialstage = (G_IsSpecialStage(gamemap) && !(maptol & TOL_NIGHTS));
// Cheap hack: don't display when the score is showing (it popping up for a split second when exiting a map is intentional)
if (oldspecialstage || (stplyr->texttimer && stplyr->textvar == 4))
minlink = INT32_MAX;
// When debugging, show "0 Link".
else if (cv_debug & DBG_NIGHTSBASIC)
minlink = 0;
// Drill meter // Drill meter
if ( if (
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
@ -1508,55 +1570,15 @@ static void ST_drawNiGHTSHUD(void)
}*/ }*/
// Link drawing // Link drawing
if ( if (!oldspecialstage
// Don't display when the score is showing (it popping up for a split second when exiting a map is intentional)
&& !(stplyr->texttimer && stplyr->textvar == 4)
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
LUA_HudEnabled(hud_nightslink) && && LUA_HudEnabled(hud_nightslink)
#endif #endif
stplyr->linkcount > minlink) && ((cv_debug & DBG_NIGHTSBASIC) || stplyr->linkcount > 1)) // When debugging, show "0 Link".
{ {
static INT32 prevsel[2] = {0, 0}, prevtime[2] = {0, 0}; ST_drawNiGHTSLink();
const UINT8 q = ((splitscreen && stplyr == &players[secondarydisplayplayer]) ? 1 : 0);
INT32 sel = ((stplyr->linkcount-1) / 5) % NUMLINKCOLORS, aflag = V_PERPLAYER, mag = ((stplyr->linkcount-1 >= 300) ? 1 : 0);
skincolors_t colornum;
fixed_t x, y, scale;
if (sel != prevsel[q])
{
prevsel[q] = sel;
prevtime[q] = 2 + mag;
}
if (stplyr->powers[pw_nights_linkfreeze] && (!(stplyr->powers[pw_nights_linkfreeze] & 2) || (stplyr->powers[pw_nights_linkfreeze] > flashingtics)))
colornum = SKINCOLOR_ICY;
else
colornum = linkColor[mag][sel];
aflag |= ((stplyr->linktimer < 2*TICRATE/3)
? (9 - 9*stplyr->linktimer/(2*TICRATE/3)) << V_ALPHASHIFT
: 0);
y = (160+11)<<FRACBITS;
aflag |= V_SNAPTOBOTTOM;
x = (160+4)<<FRACBITS;
if (prevtime[q])
{
scale = ((32 + prevtime[q])<<FRACBITS)/32;
prevtime[q]--;
}
else
scale = FRACUNIT;
y -= (11*scale);
ST_DrawNightsOverlayNum(x-(4*scale), y, scale, aflag, (stplyr->linkcount-1), nightsnum, colornum);
V_DrawFixedPatch(x+(4*scale), y, scale, aflag, nightslink,
colornum == 0 ? colormaps : R_GetTranslationColormap(TC_DEFAULT, colornum, GTC_CACHE));
// Show remaining link time left in debug
if (cv_debug & DBG_NIGHTSBASIC)
V_DrawCenteredString(BASEVIDWIDTH/2, 180, V_SNAPTOBOTTOM, va("End in %d.%02d", stplyr->linktimer/TICRATE, G_TicsToCentiseconds(stplyr->linktimer)));
} }
if (gametype == GT_RACE || gametype == GT_COMPETITION) if (gametype == GT_RACE || gametype == GT_COMPETITION)
@ -2448,15 +2470,26 @@ void ST_Drawer(void)
#ifdef SEENAMES #ifdef SEENAMES
if (cv_seenames.value && cv_allowseenames.value && displayplayer == consoleplayer && seenplayer && seenplayer->mo) if (cv_seenames.value && cv_allowseenames.value && displayplayer == consoleplayer && seenplayer && seenplayer->mo)
{ {
if (cv_seenames.value == 1) INT32 c = 0;
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2 + 15, V_HUDTRANSHALF, player_names[seenplayer-players]); switch (cv_seenames.value)
else if (cv_seenames.value == 2) {
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2 + 15, V_HUDTRANSHALF, case 1: // Colorless
va("%s%s", G_GametypeHasTeams() ? ((seenplayer->ctfteam == 1) ? "\x85" : "\x84") : "", player_names[seenplayer-players])); break;
else //if (cv_seenames.value == 3) case 2: // Team
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2 + 15, V_HUDTRANSHALF, if (G_GametypeHasTeams())
va("%s%s", !G_RingSlingerGametype() || (G_GametypeHasTeams() && players[consoleplayer].ctfteam == seenplayer->ctfteam) c = (seenplayer->ctfteam == 1) ? V_REDMAP : V_BLUEMAP;
? "\x83" : "\x85", player_names[seenplayer-players])); break;
case 3: // Ally/Foe
default:
// Green = Ally, Red = Foe
if (G_GametypeHasTeams())
c = (players[consoleplayer].ctfteam == seenplayer->ctfteam) ? V_GREENMAP : V_REDMAP;
else // Everyone is an ally, or everyone is a foe!
c = (G_RingSlingerGametype()) ? V_REDMAP : V_GREENMAP;
break;
}
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2 + 15, V_HUDTRANSHALF|c, player_names[seenplayer-players]);
} }
#endif #endif

View file

@ -622,7 +622,7 @@ void V_DrawFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t
if (scrn & V_FLIP) if (scrn & V_FLIP)
{ {
flip = true; flip = true;
x -= FixedMul((SHORT(patch->width) - SHORT(patch->leftoffset))<<FRACBITS, pscale); x -= FixedMul((SHORT(patch->width) - SHORT(patch->leftoffset))<<FRACBITS, pscale) + 1;
} }
else else
x -= FixedMul(SHORT(patch->leftoffset)<<FRACBITS, pscale); x -= FixedMul(SHORT(patch->leftoffset)<<FRACBITS, pscale);
@ -1236,7 +1236,7 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT) if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT)
{ // Clear the entire screen, from dest to deststop. Yes, this really works. { // Clear the entire screen, from dest to deststop. Yes, this really works.
memset(screens[0], (UINT8)(c&255), vid.width * vid.height * vid.bpp); memset(screens[0], (c&255), vid.width * vid.height * vid.bpp);
return; return;
} }
@ -1299,7 +1299,7 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
c &= 255; c &= 255;
for (;(--h >= 0) && dest < deststop; dest += vid.width) for (;(--h >= 0) && dest < deststop; dest += vid.width)
memset(dest, (UINT8)(c&255), w * vid.bpp); memset(dest, c, w * vid.bpp);
} }
// //
@ -1642,6 +1642,7 @@ void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string)
dupx = dupy = 1; dupx = dupy = 1;
scrwidth = vid.width/vid.dupx; scrwidth = vid.width/vid.dupx;
left = (scrwidth - BASEVIDWIDTH)/2; left = (scrwidth - BASEVIDWIDTH)/2;
scrwidth -= left;
} }
switch (option & V_SPACINGMASK) switch (option & V_SPACINGMASK)
@ -1701,7 +1702,7 @@ void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string)
else else
w = SHORT(hu_font[c]->width) * dupx; w = SHORT(hu_font[c]->width) * dupx;
if (cx+left > scrwidth) if (cx > scrwidth)
break; break;
if (cx+left + w < 0) //left boundary check if (cx+left + w < 0) //left boundary check
{ {
@ -1754,6 +1755,7 @@ void V_DrawSmallString(INT32 x, INT32 y, INT32 option, const char *string)
dupx = dupy = 1; dupx = dupy = 1;
scrwidth = vid.width/vid.dupx; scrwidth = vid.width/vid.dupx;
left = (scrwidth - BASEVIDWIDTH)/2; left = (scrwidth - BASEVIDWIDTH)/2;
scrwidth -= left;
} }
charflags = (option & V_CHARCOLORMASK); charflags = (option & V_CHARCOLORMASK);
@ -1813,7 +1815,8 @@ void V_DrawSmallString(INT32 x, INT32 y, INT32 option, const char *string)
} }
else else
w = SHORT(hu_font[c]->width) * dupx / 2; w = SHORT(hu_font[c]->width) * dupx / 2;
if (cx+left > scrwidth)
if (cx > scrwidth)
break; break;
if (cx+left + w < 0) //left boundary check if (cx+left + w < 0) //left boundary check
{ {
@ -1860,6 +1863,7 @@ void V_DrawThinString(INT32 x, INT32 y, INT32 option, const char *string)
dupx = dupy = 1; dupx = dupy = 1;
scrwidth = vid.width/vid.dupx; scrwidth = vid.width/vid.dupx;
left = (scrwidth - BASEVIDWIDTH)/2; left = (scrwidth - BASEVIDWIDTH)/2;
scrwidth -= left;
} }
charflags = (option & V_CHARCOLORMASK); charflags = (option & V_CHARCOLORMASK);
@ -1917,7 +1921,7 @@ void V_DrawThinString(INT32 x, INT32 y, INT32 option, const char *string)
else else
w = (SHORT(tny_font[c]->width) * dupx); w = (SHORT(tny_font[c]->width) * dupx);
if (cx+left > scrwidth) if (cx > scrwidth)
break; break;
if (cx+left + w < 0) //left boundary check if (cx+left + w < 0) //left boundary check
{ {
@ -1960,6 +1964,7 @@ void V_DrawStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string)
dupx = dupy = 1; dupx = dupy = 1;
scrwidth = vid.width/vid.dupx; scrwidth = vid.width/vid.dupx;
left = (scrwidth - BASEVIDWIDTH)/2; left = (scrwidth - BASEVIDWIDTH)/2;
scrwidth -= left;
} }
switch (option & V_SPACINGMASK) switch (option & V_SPACINGMASK)
@ -2014,9 +2019,9 @@ void V_DrawStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string)
else else
w = SHORT(hu_font[c]->width) * dupx; w = SHORT(hu_font[c]->width) * dupx;
if ((cx>>FRACBITS)+left > scrwidth) if ((cx>>FRACBITS) > scrwidth)
break; break;
if (cx+left + w < 0) //left boundary check if ((cx>>FRACBITS)+left + w < 0) //left boundary check
{ {
cx += w<<FRACBITS; cx += w<<FRACBITS;
continue; continue;
@ -2126,7 +2131,7 @@ void V_DrawCreditString(fixed_t x, fixed_t y, INT32 option, const char *string)
} }
w = SHORT(cred_font[c]->width) * dupx; w = SHORT(cred_font[c]->width) * dupx;
if ((cx>>FRACBITS) + w > scrwidth) if ((cx>>FRACBITS) > scrwidth)
break; break;
V_DrawSciencePatch(cx, cy, option, cred_font[c], FRACUNIT); V_DrawSciencePatch(cx, cy, option, cred_font[c], FRACUNIT);
@ -2178,6 +2183,7 @@ void V_DrawLevelTitle(INT32 x, INT32 y, INT32 option, const char *string)
dupx = dupy = 1; dupx = dupy = 1;
scrwidth = vid.width/vid.dupx; scrwidth = vid.width/vid.dupx;
left = (scrwidth - BASEVIDWIDTH)/2; left = (scrwidth - BASEVIDWIDTH)/2;
scrwidth -= left;
} }
for (;;ch++) for (;;ch++)
@ -2207,10 +2213,9 @@ void V_DrawLevelTitle(INT32 x, INT32 y, INT32 option, const char *string)
w = SHORT(lt_font[c]->width) * dupx; w = SHORT(lt_font[c]->width) * dupx;
if (cx+left > scrwidth) if (cx > scrwidth)
break; break;
//left boundary check if (cx+left + w < 0) //left boundary check
if (cx+left + w < 0)
{ {
cx += w; cx += w;
continue; continue;

View file

@ -471,7 +471,7 @@ void I_PlayCD(UINT8 nTrack, UINT8 bLooping)
//faB: stop MIDI music, MIDI music will restart if volume is upped later //faB: stop MIDI music, MIDI music will restart if volume is upped later
cv_digmusicvolume.value = 0; cv_digmusicvolume.value = 0;
cv_midimusicvolume.value = 0; cv_midimusicvolume.value = 0;
I_StopSong (0); I_StopSong();
//faB: I don't use the notify message, I'm trying to minimize the delay //faB: I don't use the notify message, I'm trying to minimize the delay
mciPlay.dwCallback = (DWORD)((size_t)hWndMain); mciPlay.dwCallback = (DWORD)((size_t)hWndMain);

View file

@ -475,11 +475,11 @@ musictype_t I_SongType(void)
return MU_WAV; return MU_WAV;
case FMOD_SOUND_TYPE_MOD: case FMOD_SOUND_TYPE_MOD:
return MU_MOD; return MU_MOD;
case FMOD_SOUND_TYPE_MID: case FMOD_SOUND_TYPE_MIDI:
return MU_MID; return MU_MID;
case FMOD_SOUND_TYPE_OGGVORBIS: case FMOD_SOUND_TYPE_OGGVORBIS:
return MU_OGG; return MU_OGG;
case FMOD_SOUND_TYPE_MP3: case FMOD_SOUND_TYPE_MPEG:
return MU_MP3; return MU_MP3;
case FMOD_SOUND_TYPE_FLAC: case FMOD_SOUND_TYPE_FLAC:
return MU_FLAC; return MU_FLAC;
@ -547,20 +547,13 @@ boolean I_SetSongSpeed(float speed)
boolean I_LoadSong(char *data, size_t len) boolean I_LoadSong(char *data, size_t len)
{ {
char *data;
size_t len;
FMOD_CREATESOUNDEXINFO fmt; FMOD_CREATESOUNDEXINFO fmt;
lumpnum_t lumpnum = W_CheckNumForName(va("O_%s",musicname)); FMOD_RESULT e;
FMOD_TAG tag;
unsigned int loopstart, loopend;
if (lumpnum == LUMPERROR) if (gme || music_stream)
{ I_UnloadSong();
lumpnum = W_CheckNumForName(va("D_%s",musicname));
if (lumpnum == LUMPERROR)
return false;
}
data = (char *)W_CacheLumpNum(lumpnum, PU_MUSIC);
len = W_LumpLength(lumpnum);
memset(&fmt, 0, sizeof(FMOD_CREATESOUNDEXINFO)); memset(&fmt, 0, sizeof(FMOD_CREATESOUNDEXINFO));
fmt.cbsize = sizeof(FMOD_CREATESOUNDEXINFO); fmt.cbsize = sizeof(FMOD_CREATESOUNDEXINFO);
@ -595,8 +588,6 @@ boolean I_LoadSong(char *data, size_t len)
gme_equalizer_t gmeq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0}; gme_equalizer_t gmeq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0};
Z_Free(inflatedData); // GME supposedly makes a copy for itself, so we don't need this lying around Z_Free(inflatedData); // GME supposedly makes a copy for itself, so we don't need this lying around
Z_Free(data); // We don't need this, either. Z_Free(data); // We don't need this, either.
gme_start_track(gme, 0);
current_track = 0;
gme_set_equalizer(gme,&gmeq); gme_set_equalizer(gme,&gmeq);
fmt.format = FMOD_SOUND_FORMAT_PCM16; fmt.format = FMOD_SOUND_FORMAT_PCM16;
fmt.defaultfrequency = 44100; fmt.defaultfrequency = 44100;
@ -605,10 +596,7 @@ boolean I_LoadSong(char *data, size_t len)
fmt.decodebuffersize = (44100 * 2) / 35; fmt.decodebuffersize = (44100 * 2) / 35;
fmt.pcmreadcallback = GMEReadCallback; fmt.pcmreadcallback = GMEReadCallback;
fmt.userdata = gme; fmt.userdata = gme;
FMR(FMOD_System_CreateStream(fsys, NULL, FMOD_OPENUSER | (looping ? FMOD_LOOP_NORMAL : 0), &fmt, &music_stream)); FMR(FMOD_System_CreateStream(fsys, NULL, FMOD_OPENUSER, &fmt, &music_stream));
FMR(FMOD_System_PlaySound(fsys, FMOD_CHANNEL_FREE, music_stream, false, &music_channel));
FMR(FMOD_Channel_SetVolume(music_channel, music_volume / 31.0));
FMR(FMOD_Channel_SetPriority(music_channel, 0));
return true; return true;
} }
} }
@ -675,26 +663,24 @@ boolean I_LoadSong(char *data, size_t len)
fmt.decodebuffersize = (44100 * 2) / 35; fmt.decodebuffersize = (44100 * 2) / 35;
fmt.pcmreadcallback = GMEReadCallback; fmt.pcmreadcallback = GMEReadCallback;
fmt.userdata = gme; fmt.userdata = gme;
FMR(FMOD_System_CreateStream(fsys, NULL, FMOD_OPENUSER, &fmt, &music_stream));
return true; return true;
} }
#endif #endif
fmt.length = len; fmt.length = len;
FMOD_RESULT e = FMOD_System_CreateStream(fsys, data, FMOD_OPENMEMORY_POINT|(looping ? FMOD_LOOP_NORMAL : 0), &fmt, &music_stream); e = FMOD_System_CreateStream(fsys, data, FMOD_OPENMEMORY_POINT, &fmt, &music_stream);
if (e != FMOD_OK) if (e != FMOD_OK)
{ {
if (e == FMOD_ERR_FORMAT) if (e == FMOD_ERR_FORMAT)
CONS_Alert(CONS_WARNING, "Failed to play music lump %s due to invalid format.\n", W_CheckNameForNum(lumpnum)); CONS_Alert(CONS_WARNING, "Failed to play music lump due to invalid format.\n");
else else
FMR(e); FMR(e);
return false; return false;
} }
// Try to find a loop point in streaming music formats (ogg, mp3) // Try to find a loop point in streaming music formats (ogg, mp3)
FMOD_RESULT e;
FMOD_TAG tag;
unsigned int loopstart, loopend;
// A proper LOOPPOINT is its own tag, stupid. // A proper LOOPPOINT is its own tag, stupid.
e = FMOD_Sound_GetTag(music_stream, "LOOPPOINT", 0, &tag); e = FMOD_Sound_GetTag(music_stream, "LOOPPOINT", 0, &tag);
@ -708,13 +694,6 @@ boolean I_LoadSong(char *data, size_t len)
return true; return true;
} }
// todo
// if(music type == MIDI)
// {
// FMR(FMOD_Sound_SetMode(music_stream, FMOD_LOOP_NORMAL));
// return true;
// }
// Use LOOPMS for time in miliseconds. // Use LOOPMS for time in miliseconds.
e = FMOD_Sound_GetTag(music_stream, "LOOPMS", 0, &tag); e = FMOD_Sound_GetTag(music_stream, "LOOPMS", 0, &tag);
if (e != FMOD_ERR_TAGNOTFOUND) if (e != FMOD_ERR_TAGNOTFOUND)
@ -758,11 +737,20 @@ boolean I_LoadSong(char *data, size_t len)
void I_UnloadSong(void) void I_UnloadSong(void)
{ {
UNREFERENCED_PARAMETER(handle); I_StopSong();
#ifdef HAVE_LIBGME
if (gme)
{
gme_delete(gme);
gme = NULL;
}
#endif
if (music_stream) if (music_stream)
{
FMR(FMOD_Sound_Release(music_stream)); FMR(FMOD_Sound_Release(music_stream));
music_stream = NULL; music_stream = NULL;
} }
}
boolean I_PlaySong(boolean looping) boolean I_PlaySong(boolean looping)
{ {
@ -771,7 +759,6 @@ boolean I_PlaySong(boolean looping)
{ {
gme_start_track(gme, 0); gme_start_track(gme, 0);
current_track = 0; current_track = 0;
FMR(FMOD_System_CreateStream(fsys, NULL, FMOD_OPENUSER | (looping ? FMOD_LOOP_NORMAL : 0), &fmt, &music_stream));
FMR(FMOD_System_PlaySound(fsys, FMOD_CHANNEL_FREE, music_stream, false, &music_channel)); FMR(FMOD_System_PlaySound(fsys, FMOD_CHANNEL_FREE, music_stream, false, &music_channel));
FMR(FMOD_Channel_SetVolume(music_channel, music_volume / 31.0)); FMR(FMOD_Channel_SetVolume(music_channel, music_volume / 31.0));
FMR(FMOD_Channel_SetPriority(music_channel, 0)); FMR(FMOD_Channel_SetPriority(music_channel, 0));
@ -779,6 +766,7 @@ boolean I_PlaySong(boolean looping)
} }
#endif #endif
FMR(FMOD_Sound_SetMode(music_stream, (looping ? FMOD_LOOP_NORMAL : FMOD_LOOP_OFF)));
FMR(FMOD_System_PlaySound(fsys, FMOD_CHANNEL_FREE, music_stream, false, &music_channel)); FMR(FMOD_System_PlaySound(fsys, FMOD_CHANNEL_FREE, music_stream, false, &music_channel));
if (I_SongType() != MU_MID) if (I_SongType() != MU_MID)
FMR(FMOD_Channel_SetVolume(music_channel, midi_volume / 31.0)); FMR(FMOD_Channel_SetVolume(music_channel, midi_volume / 31.0));
@ -792,33 +780,25 @@ boolean I_PlaySong(boolean looping)
void I_StopSong(void) void I_StopSong(void)
{ {
#ifdef HAVE_LIBGME if (music_channel)
if (gme) FMR_MUSIC(FMOD_Channel_Stop(music_channel));
gme_delete(gme);
gme = NULL;
#endif
current_track = -1;
I_UnloadSong();
} }
void I_PauseSong(void) void I_PauseSong(void)
{ {
UNREFERENCED_PARAMETER(handle); if (music_channel)
if (music_stream)
FMR_MUSIC(FMOD_Channel_SetPaused(music_channel, true)); FMR_MUSIC(FMOD_Channel_SetPaused(music_channel, true));
} }
void I_ResumeSong(void) void I_ResumeSong(void)
{ {
UNREFERENCED_PARAMETER(handle); if (music_channel)
if (music_stream)
FMR_MUSIC(FMOD_Channel_SetPaused(music_channel, false)); FMR_MUSIC(FMOD_Channel_SetPaused(music_channel, false));
} }
void I_SetMusicVolume(UINT8 volume) void I_SetMusicVolume(UINT8 volume)
{ {
if (!music_stream) if (!music_channel)
return; return;
// volume is 0 to 31. // volume is 0 to 31.

View file

@ -1874,7 +1874,9 @@ static void Y_AwardCoopBonuses(void)
players[i].score = MAXSCORE; players[i].score = MAXSCORE;
} }
ptlives = (!ultimatemode && !modeattacking && players[i].lives != 0x7f) ? max((players[i].score/50000) - (oldscore/50000), 0) : 0; ptlives = min(
((!ultimatemode && !modeattacking && players[i].lives != INFLIVES) ? max((players[i].score/50000) - (oldscore/50000), 0) : 0),
(mapheaderinfo[prevmap]->maxbonuslives < 0 ? INT32_MAX : mapheaderinfo[prevmap]->maxbonuslives));
if (ptlives) if (ptlives)
P_GivePlayerLives(&players[i], ptlives); P_GivePlayerLives(&players[i], ptlives);
@ -1918,7 +1920,9 @@ static void Y_AwardSpecialStageBonus(void)
players[i].score = MAXSCORE; players[i].score = MAXSCORE;
// grant extra lives right away since tally is faked // grant extra lives right away since tally is faked
ptlives = (!ultimatemode && !modeattacking && players[i].lives != 0x7f) ? max((players[i].score/50000) - (oldscore/50000), 0) : 0; ptlives = min(
((!ultimatemode && !modeattacking && players[i].lives != INFLIVES) ? max((players[i].score/50000) - (oldscore/50000), 0) : 0),
(mapheaderinfo[prevmap]->maxbonuslives < 0 ? INT32_MAX : mapheaderinfo[prevmap]->maxbonuslives));
if (ptlives) if (ptlives)
P_GivePlayerLives(&players[i], ptlives); P_GivePlayerLives(&players[i], ptlives);