mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-11-15 17:22:12 +00:00
Merge remote-tracking branch 'origin/master' into musicplus-feature-dying-fp
This commit is contained in:
commit
5f2a45befd
83 changed files with 7083 additions and 3787 deletions
|
@ -1608,7 +1608,7 @@ void CON_Drawer(void)
|
|||
if (con_curlines > 0)
|
||||
CON_DrawConsole();
|
||||
else if (gamestate == GS_LEVEL
|
||||
|| gamestate == GS_INTERMISSION || gamestate == GS_CUTSCENE
|
||||
|| gamestate == GS_INTERMISSION || gamestate == GS_ENDING || gamestate == GS_CUTSCENE
|
||||
|| gamestate == GS_CREDITS || gamestate == GS_EVALUATION)
|
||||
CON_DrawHudlines();
|
||||
}
|
||||
|
|
|
@ -4270,14 +4270,9 @@ static INT16 Consistancy(void)
|
|||
ret += P_GetRandSeed();
|
||||
|
||||
#ifdef MOBJCONSISTANCY
|
||||
if (!thinkercap.next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
DEBFILE(va("Consistancy = %u\n", ret));
|
||||
return ret;
|
||||
}
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo = (mobj_t *)th;
|
||||
|
|
|
@ -310,6 +310,12 @@ static void D_Display(void)
|
|||
wipe = true;
|
||||
break;
|
||||
|
||||
case GS_ENDING:
|
||||
F_EndingDrawer();
|
||||
HU_Erase();
|
||||
HU_Drawer();
|
||||
break;
|
||||
|
||||
case GS_CUTSCENE:
|
||||
F_CutsceneDrawer();
|
||||
HU_Erase();
|
||||
|
|
|
@ -4260,8 +4260,8 @@ static void Command_Archivetest_f(void)
|
|||
|
||||
// assign mobjnum
|
||||
i = 1;
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
if (th->function.acp1 == (actionf_p1)P_MobjThinker)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
if (th->function.acp1 != (actionf_p1)P_RemoveThinkerDelayed)
|
||||
((mobj_t *)th)->mobjnum = i++;
|
||||
|
||||
// allocate buffer
|
||||
|
|
|
@ -196,6 +196,7 @@ typedef enum
|
|||
SH_PITY = 1, // the world's most basic shield ever, given to players who suck at Match
|
||||
SH_WHIRLWIND,
|
||||
SH_ARMAGEDDON,
|
||||
SH_PINK, // PITY IN PINK!
|
||||
|
||||
// Normal shields that use flags
|
||||
SH_ATTRACT = SH_PITY|SH_PROTECTELECTRIC,
|
||||
|
|
108
src/dehacked.c
108
src/dehacked.c
|
@ -28,6 +28,7 @@
|
|||
#include "p_local.h" // for var1 and var2, and some constants
|
||||
#include "p_setup.h"
|
||||
#include "r_data.h"
|
||||
#include "r_draw.h"
|
||||
#include "r_sky.h"
|
||||
#include "fastcmp.h"
|
||||
#include "lua_script.h"
|
||||
|
@ -516,7 +517,9 @@ static void readfreeslots(MYFILE *f)
|
|||
continue;
|
||||
// Copy in the spr2 name and increment free_spr2.
|
||||
if (free_spr2 < NUMPLAYERSPRITES) {
|
||||
CONS_Printf("Sprite SPR2_%s allocated.\n",word);
|
||||
strncpy(spr2names[free_spr2],word,4);
|
||||
spr2defaults[free_spr2] = 0;
|
||||
spr2names[free_spr2++][4] = 0;
|
||||
} else
|
||||
CONS_Alert(CONS_WARNING, "Ran out of free SPR2 slots!\n");
|
||||
|
@ -1107,6 +1110,7 @@ static void readlevelheader(MYFILE *f, INT32 num)
|
|||
if (fastcmp(word2, "TITLE")) i = 1100;
|
||||
else if (fastcmp(word2, "EVALUATION")) i = 1101;
|
||||
else if (fastcmp(word2, "CREDITS")) i = 1102;
|
||||
else if (fastcmp(word2, "ENDING")) i = 1103;
|
||||
else
|
||||
// Support using the actual map name,
|
||||
// i.e., Nextlevel = AB, Nextlevel = FZ, etc.
|
||||
|
@ -4666,6 +4670,11 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
|||
|
||||
// Boss 3
|
||||
"S_EGGMOBILE3_STND",
|
||||
"S_EGGMOBILE3_LAUGH1",
|
||||
"S_EGGMOBILE3_LAUGH2",
|
||||
"S_EGGMOBILE3_LAUGH3",
|
||||
"S_EGGMOBILE3_LAUGH4",
|
||||
"S_EGGMOBILE3_LAUGH5",
|
||||
"S_EGGMOBILE3_ATK1",
|
||||
"S_EGGMOBILE3_ATK2",
|
||||
"S_EGGMOBILE3_ATK3A",
|
||||
|
@ -4674,11 +4683,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
|||
"S_EGGMOBILE3_ATK3D",
|
||||
"S_EGGMOBILE3_ATK4",
|
||||
"S_EGGMOBILE3_ATK5",
|
||||
"S_EGGMOBILE3_LAUGH1",
|
||||
"S_EGGMOBILE3_LAUGH2",
|
||||
"S_EGGMOBILE3_LAUGH3",
|
||||
"S_EGGMOBILE3_LAUGH4",
|
||||
"S_EGGMOBILE3_LAUGH5",
|
||||
"S_EGGMOBILE3_LAUGH6",
|
||||
"S_EGGMOBILE3_LAUGH7",
|
||||
"S_EGGMOBILE3_LAUGH8",
|
||||
|
@ -4731,8 +4735,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
|||
"S_FAKEMOBILE_ATK3B",
|
||||
"S_FAKEMOBILE_ATK3C",
|
||||
"S_FAKEMOBILE_ATK3D",
|
||||
"S_FAKEMOBILE_ATK4",
|
||||
"S_FAKEMOBILE_ATK5",
|
||||
"S_FAKEMOBILE_DIE1",
|
||||
"S_FAKEMOBILE_DIE2",
|
||||
|
||||
// Boss 4
|
||||
"S_EGGMOBILE4_STND",
|
||||
|
@ -4750,15 +4754,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
|||
"S_EGGMOBILE4_RATK6",
|
||||
"S_EGGMOBILE4_RAISE1",
|
||||
"S_EGGMOBILE4_RAISE2",
|
||||
"S_EGGMOBILE4_RAISE3",
|
||||
"S_EGGMOBILE4_RAISE4",
|
||||
"S_EGGMOBILE4_RAISE5",
|
||||
"S_EGGMOBILE4_RAISE6",
|
||||
"S_EGGMOBILE4_RAISE7",
|
||||
"S_EGGMOBILE4_RAISE8",
|
||||
"S_EGGMOBILE4_RAISE9",
|
||||
"S_EGGMOBILE4_RAISE10",
|
||||
"S_EGGMOBILE4_PAIN",
|
||||
"S_EGGMOBILE4_PAIN1",
|
||||
"S_EGGMOBILE4_PAIN2",
|
||||
"S_EGGMOBILE4_DIE1",
|
||||
"S_EGGMOBILE4_DIE2",
|
||||
"S_EGGMOBILE4_DIE3",
|
||||
|
@ -4776,10 +4773,21 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
|||
"S_EGGMOBILE4_FLEE1",
|
||||
"S_EGGMOBILE4_FLEE2",
|
||||
"S_EGGMOBILE4_MACE",
|
||||
"S_EGGMOBILE4_MACE_DIE1",
|
||||
"S_EGGMOBILE4_MACE_DIE2",
|
||||
"S_EGGMOBILE4_MACE_DIE3",
|
||||
|
||||
// Boss 4 jet flame
|
||||
"S_JETFLAME1",
|
||||
"S_JETFLAME2",
|
||||
"S_JETFLAME",
|
||||
|
||||
// Boss 4 Spectator Eggrobo
|
||||
"S_EGGROBO1_IDLE",
|
||||
"S_EGGROBO1_BSLAP1",
|
||||
"S_EGGROBO2_BSLAP2",
|
||||
"S_EGGROBO1_PISSED",
|
||||
|
||||
// Boss 4 Spectator Eggrobo jet flame
|
||||
"S_EGGROBOJET",
|
||||
|
||||
// Boss 5
|
||||
"S_FANG_IDLE1",
|
||||
|
@ -5132,7 +5140,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
|||
"S_METALSONIC_BADBOUNCE",
|
||||
"S_METALSONIC_SHOOT",
|
||||
"S_METALSONIC_PAIN",
|
||||
"S_METALSONIC_DEATH",
|
||||
"S_METALSONIC_DEATH1",
|
||||
"S_METALSONIC_DEATH2",
|
||||
"S_METALSONIC_DEATH3",
|
||||
"S_METALSONIC_DEATH4",
|
||||
"S_METALSONIC_FLEE1",
|
||||
"S_METALSONIC_FLEE2",
|
||||
"S_METALSONIC_FLEE3",
|
||||
|
@ -5691,7 +5702,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
|||
|
||||
"S_CEZFLOWER",
|
||||
"S_CEZPOLE",
|
||||
"S_CEZBANNER",
|
||||
"S_CEZBANNER1",
|
||||
"S_CEZBANNER2",
|
||||
"S_PINETREE",
|
||||
"S_CEZBUSH1",
|
||||
"S_CEZBUSH2",
|
||||
|
@ -5700,7 +5712,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
|||
"S_FLAMEHOLDER",
|
||||
"S_FIRETORCH",
|
||||
"S_WAVINGFLAG",
|
||||
"S_WAVINGFLAGSEG",
|
||||
"S_WAVINGFLAGSEG1",
|
||||
"S_WAVINGFLAGSEG2",
|
||||
"S_CRAWLASTATUE",
|
||||
"S_FACESTABBERSTATUE",
|
||||
"S_SUSPICIOUSFACESTABBERSTATUE_WAIT",
|
||||
|
@ -6170,6 +6183,12 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
|||
"S_PITY4",
|
||||
"S_PITY5",
|
||||
"S_PITY6",
|
||||
"S_PITY7",
|
||||
"S_PITY8",
|
||||
"S_PITY9",
|
||||
"S_PITY10",
|
||||
"S_PITY11",
|
||||
"S_PITY12",
|
||||
|
||||
"S_FIRS1",
|
||||
"S_FIRS2",
|
||||
|
@ -6654,6 +6673,12 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
|||
|
||||
"S_LOCKON1",
|
||||
"S_LOCKON2",
|
||||
"S_LOCKON3",
|
||||
"S_LOCKON4",
|
||||
"S_LOCKONINF1",
|
||||
"S_LOCKONINF2",
|
||||
"S_LOCKONINF3",
|
||||
"S_LOCKONINF4",
|
||||
|
||||
// Tag Sign
|
||||
"S_TTAG",
|
||||
|
@ -6662,6 +6687,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
|||
"S_GOTFLAG",
|
||||
|
||||
"S_CORK",
|
||||
"S_LHRT",
|
||||
|
||||
// Red Ring
|
||||
"S_RRNG1",
|
||||
|
@ -7167,6 +7193,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
|||
"S_ROCKCRUMBLEN",
|
||||
"S_ROCKCRUMBLEO",
|
||||
"S_ROCKCRUMBLEP",
|
||||
"S_BRICKDEBRIS",
|
||||
|
||||
#ifdef SEENAMES
|
||||
"S_NAMECHECK",
|
||||
|
@ -7251,11 +7278,14 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
|
|||
"MT_EGGMOBILE3",
|
||||
"MT_PROPELLER",
|
||||
"MT_FAKEMOBILE",
|
||||
"MT_SHOCK",
|
||||
|
||||
// Boss 4
|
||||
"MT_EGGMOBILE4",
|
||||
"MT_EGGMOBILE4_MACE",
|
||||
"MT_JETFLAME",
|
||||
"MT_EGGROBO1",
|
||||
"MT_EGGROBO1JET",
|
||||
|
||||
// Boss 5
|
||||
"MT_FANG",
|
||||
|
@ -7489,8 +7519,10 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
|
|||
"MT_SMALLFIREBAR", // Small Firebar
|
||||
"MT_BIGFIREBAR", // Big Firebar
|
||||
"MT_CEZFLOWER", // Flower
|
||||
"MT_CEZPOLE", // Pole
|
||||
"MT_CEZBANNER", // Banner
|
||||
"MT_CEZPOLE1", // Pole (with red banner)
|
||||
"MT_CEZPOLE2", // Pole (with blue banner)
|
||||
"MT_CEZBANNER1", // Banner (red)
|
||||
"MT_CEZBANNER2", // Banner (blue)
|
||||
"MT_PINETREE", // Pine Tree
|
||||
"MT_CEZBUSH1", // Bush 1
|
||||
"MT_CEZBUSH2", // Bush 2
|
||||
|
@ -7498,8 +7530,10 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
|
|||
"MT_CANDLEPRICKET", // Candle pricket
|
||||
"MT_FLAMEHOLDER", // Flame holder
|
||||
"MT_FIRETORCH", // Fire torch
|
||||
"MT_WAVINGFLAG", // Waving flag
|
||||
"MT_WAVINGFLAGSEG", // Waving flag segment
|
||||
"MT_WAVINGFLAG1", // Waving flag (red)
|
||||
"MT_WAVINGFLAG2", // Waving flag (blue)
|
||||
"MT_WAVINGFLAGSEG1", // Waving flag segment (red)
|
||||
"MT_WAVINGFLAGSEG2", // Waving flag segment (blue)
|
||||
"MT_CRAWLASTATUE", // Crawla statue
|
||||
"MT_FACESTABBERSTATUE", // Facestabber statue
|
||||
"MT_SUSPICIOUSFACESTABBERSTATUE", // :eggthinking:
|
||||
|
@ -7732,6 +7766,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
|
|||
"MT_DROWNNUMBERS", // Drowning Timer
|
||||
"MT_GOTEMERALD", // Chaos Emerald (intangible)
|
||||
"MT_LOCKON", // Target
|
||||
"MT_LOCKONINF", // In-level Target
|
||||
"MT_TAG", // Tag Sign
|
||||
"MT_GOTFLAG", // Got Flag sign
|
||||
|
||||
|
@ -7749,6 +7784,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
|
|||
"MT_MACHINEAMBIENCE",
|
||||
|
||||
"MT_CORK",
|
||||
"MT_LHRT",
|
||||
|
||||
// Ring Weapons
|
||||
"MT_REDRING",
|
||||
|
@ -7881,6 +7917,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
|
|||
"MT_ROCKCRUMBLE14",
|
||||
"MT_ROCKCRUMBLE15",
|
||||
"MT_ROCKCRUMBLE16",
|
||||
"MT_BRICKDEBRIS",
|
||||
|
||||
#ifdef SEENAMES
|
||||
"MT_NAMECHECK",
|
||||
|
@ -8521,6 +8558,7 @@ struct {
|
|||
{"SH_PITY",SH_PITY},
|
||||
{"SH_WHIRLWIND",SH_WHIRLWIND},
|
||||
{"SH_ARMAGEDDON",SH_ARMAGEDDON},
|
||||
{"SH_PINK",SH_PINK},
|
||||
// normal shields that use flags
|
||||
{"SH_ATTRACT",SH_ATTRACT},
|
||||
{"SH_ELEMENTAL",SH_ELEMENTAL},
|
||||
|
@ -8764,10 +8802,8 @@ struct {
|
|||
#endif
|
||||
#ifdef ESLOPE
|
||||
// Slope flags
|
||||
{"SL_NOPHYSICS",SL_NOPHYSICS}, // Don't do momentum adjustment with this slope
|
||||
{"SL_NODYNAMIC",SL_NODYNAMIC}, // Slope will never need to move during the level, so don't fuss with recalculating it
|
||||
{"SL_ANCHORVERTEX",SL_ANCHORVERTEX},// Slope is using a Slope Vertex Thing to anchor its position
|
||||
{"SL_VERTEXSLOPE",SL_VERTEXSLOPE}, // Slope is built from three Slope Vertex Things
|
||||
{"SL_NOPHYSICS",SL_NOPHYSICS},
|
||||
{"SL_DYNAMIC",SL_DYNAMIC},
|
||||
#endif
|
||||
|
||||
// Angles
|
||||
|
@ -8911,6 +8947,14 @@ struct {
|
|||
{"KR_TIMEOUT",KR_TIMEOUT},
|
||||
{"KR_BAN",KR_BAN},
|
||||
{"KR_LEAVE",KR_LEAVE},
|
||||
|
||||
// translation colormaps
|
||||
{"TC_DEFAULT",TC_DEFAULT},
|
||||
{"TC_BOSS",TC_BOSS},
|
||||
{"TC_METALSONIC",TC_METALSONIC},
|
||||
{"TC_ALLWHITE",TC_ALLWHITE},
|
||||
{"TC_RAINBOW",TC_RAINBOW},
|
||||
{"TC_BLINK",TC_BLINK},
|
||||
#endif
|
||||
|
||||
{NULL,0}
|
||||
|
@ -9458,6 +9502,7 @@ static inline int lib_freeslot(lua_State *L)
|
|||
{
|
||||
CONS_Printf("Sprite SPR2_%s allocated.\n",word);
|
||||
strncpy(spr2names[free_spr2],word,4);
|
||||
spr2defaults[free_spr2] = 0;
|
||||
spr2names[free_spr2++][4] = 0;
|
||||
} else
|
||||
CONS_Alert(CONS_WARNING, "Ran out of free SPR2 slots!\n");
|
||||
|
@ -9575,11 +9620,6 @@ static inline int lib_getenum(lua_State *L)
|
|||
lua_pushinteger(L, ((lua_Integer)1<<i));
|
||||
return 1;
|
||||
}
|
||||
if (fastcmp(p, "NETONLY"))
|
||||
{
|
||||
lua_pushinteger(L, (lua_Integer)ML_NETONLY);
|
||||
return 1;
|
||||
}
|
||||
if (mathlib) return luaL_error(L, "linedef flag '%s' could not be found.\n", word);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -130,11 +130,9 @@ typedef struct
|
|||
#define ML_EFFECT4 512
|
||||
#define ML_EFFECT5 1024
|
||||
|
||||
// New ones to disable lines for characters
|
||||
#define ML_NOSONIC 2048
|
||||
#define ML_NOTAILS 4096
|
||||
#define ML_NOKNUX 8192
|
||||
#define ML_NETONLY 14336 // all of the above
|
||||
#define ML_NETONLY 2048 // Apply effect only in netgames
|
||||
#define ML_NONET 4096 // Apply effect only in single player games
|
||||
#define ML_EFFECT6 8192
|
||||
|
||||
// Bounce off walls!
|
||||
#define ML_BOUNCY 16384
|
||||
|
|
|
@ -384,7 +384,7 @@ enum {
|
|||
LE_PINCHPHASE = -2, // A boss entered pinch phase (and, in most cases, is preparing their pinch phase attack!)
|
||||
LE_ALLBOSSESDEAD = -3, // All bosses in the map are dead (Egg capsule raise)
|
||||
LE_BOSSDEAD = -4, // A boss in the map died (Chaos mode boss tally)
|
||||
LE_BOSS4DROP = -5, // CEZ boss dropped its cage
|
||||
LE_BOSS4DROP = -5, // CEZ boss dropped its cage (also subtract the number of hitpoints it's lost)
|
||||
LE_BRAKVILEATACK = -6, // Brak's doing his LOS attack, oh noes
|
||||
LE_TURRET = 32000, // THZ turret
|
||||
LE_BRAKPLATFORM = 4200, // v2.0 Black Eggman destroys platform
|
||||
|
|
|
@ -146,6 +146,7 @@ extern UINT8 skincolor_redteam, skincolor_blueteam, skincolor_redring, skincolor
|
|||
|
||||
extern tic_t countdowntimer;
|
||||
extern boolean countdowntimeup;
|
||||
extern boolean exitfadestarted;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -233,7 +234,7 @@ extern textprompt_t *textprompts[MAX_PROMPTS];
|
|||
|
||||
// For the Custom Exit linedef.
|
||||
extern INT16 nextmapoverride;
|
||||
extern boolean skipstats;
|
||||
extern UINT8 skipstats;
|
||||
|
||||
extern UINT32 ssspheres; // Total # of spheres in a level
|
||||
|
||||
|
|
813
src/f_finale.c
813
src/f_finale.c
File diff suppressed because it is too large
Load diff
|
@ -46,6 +46,9 @@ void F_GameEvaluationDrawer(void);
|
|||
void F_StartGameEvaluation(void);
|
||||
void F_GameEvaluationTicker(void);
|
||||
|
||||
void F_EndingTicker(void);
|
||||
void F_EndingDrawer(void);
|
||||
|
||||
void F_CreditTicker(void);
|
||||
void F_CreditDrawer(void);
|
||||
|
||||
|
@ -63,6 +66,7 @@ boolean F_GetPromptHideHud(fixed_t y);
|
|||
void F_StartGameEnd(void);
|
||||
void F_StartIntro(void);
|
||||
void F_StartTitleScreen(void);
|
||||
void F_StartEnding(void);
|
||||
void F_StartCredits(void);
|
||||
|
||||
boolean F_ContinueResponder(event_t *event);
|
||||
|
@ -82,7 +86,6 @@ typedef enum
|
|||
|
||||
// Current menu parameters
|
||||
|
||||
extern UINT8 titlemapinaction;
|
||||
extern mobj_t *titlemapcameraref;
|
||||
extern char curbgname[8];
|
||||
extern SINT8 curfadevalue;
|
||||
|
@ -126,6 +129,7 @@ enum
|
|||
wipe_evaluation_toblack,
|
||||
wipe_gameend_toblack,
|
||||
wipe_intro_toblack,
|
||||
wipe_ending_toblack,
|
||||
wipe_cutscene_toblack,
|
||||
|
||||
// custom intermissions
|
||||
|
@ -142,15 +146,16 @@ enum
|
|||
wipe_evaluation_final,
|
||||
wipe_gameend_final,
|
||||
wipe_intro_final,
|
||||
wipe_ending_final,
|
||||
wipe_cutscene_final,
|
||||
|
||||
// custom intermissions
|
||||
wipe_specinter_final,
|
||||
wipe_multinter_final,
|
||||
|
||||
NUMWIPEDEFS
|
||||
NUMWIPEDEFS,
|
||||
WIPEFINALSHIFT = (wipe_level_final-wipe_level_toblack)
|
||||
};
|
||||
#define WIPEFINALSHIFT 13
|
||||
extern UINT8 wipedefs[NUMWIPEDEFS];
|
||||
|
||||
#endif
|
||||
|
|
|
@ -54,6 +54,7 @@ UINT8 wipedefs[NUMWIPEDEFS] = {
|
|||
0, // wipe_evaluation_toblack
|
||||
0, // wipe_gameend_toblack
|
||||
99, // wipe_intro_toblack (hardcoded)
|
||||
0, // wipe_ending_toblack
|
||||
99, // wipe_cutscene_toblack (hardcoded)
|
||||
|
||||
0, // wipe_specinter_toblack
|
||||
|
@ -69,6 +70,7 @@ UINT8 wipedefs[NUMWIPEDEFS] = {
|
|||
0, // wipe_evaluation_final
|
||||
0, // wipe_gameend_final
|
||||
99, // wipe_intro_final (hardcoded)
|
||||
0, // wipe_ending_final
|
||||
99, // wipe_cutscene_final (hardcoded)
|
||||
|
||||
0, // wipe_specinter_final
|
||||
|
|
55
src/g_game.c
55
src/g_game.c
|
@ -146,12 +146,13 @@ UINT8 skincolor_bluering = SKINCOLOR_CORNFLOWER;
|
|||
|
||||
tic_t countdowntimer = 0;
|
||||
boolean countdowntimeup = false;
|
||||
boolean exitfadestarted = false;
|
||||
|
||||
cutscene_t *cutscenes[128];
|
||||
textprompt_t *textprompts[MAX_PROMPTS];
|
||||
|
||||
INT16 nextmapoverride;
|
||||
boolean skipstats;
|
||||
UINT8 skipstats;
|
||||
|
||||
// Pointers to each CTF flag
|
||||
mobj_t *redflag;
|
||||
|
@ -1841,7 +1842,7 @@ boolean G_Responder(event_t *ev)
|
|||
return true;
|
||||
}
|
||||
}
|
||||
else if (gamestate == GS_CREDITS)
|
||||
else if (gamestate == GS_CREDITS || gamestate == GS_ENDING) // todo: keep ending here?
|
||||
{
|
||||
if (HU_Responder(ev))
|
||||
return true; // chat ate the event
|
||||
|
@ -2031,6 +2032,12 @@ void G_Ticker(boolean run)
|
|||
F_IntroTicker();
|
||||
break;
|
||||
|
||||
case GS_ENDING:
|
||||
if (run)
|
||||
F_EndingTicker();
|
||||
HU_Ticker();
|
||||
break;
|
||||
|
||||
case GS_CUTSCENE:
|
||||
if (run)
|
||||
F_CutsceneTicker();
|
||||
|
@ -2564,9 +2571,9 @@ void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo)
|
|||
I_Assert((oldmo != NULL) && (newmo != NULL));
|
||||
|
||||
// scan all thinkers
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
@ -2644,7 +2651,7 @@ void G_DoReborn(INT32 playernum)
|
|||
//nextmapoverride = spstage_start;
|
||||
nextmapoverride = gamemap;
|
||||
countdown2 = TICRATE;
|
||||
skipstats = true;
|
||||
skipstats = 2;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
|
@ -2848,6 +2855,10 @@ void G_ExitLevel(void)
|
|||
// Remove CEcho text on round end.
|
||||
HU_ClearCEcho();
|
||||
}
|
||||
else if (gamestate == GS_ENDING)
|
||||
{
|
||||
F_StartCredits();
|
||||
}
|
||||
else if (gamestate == GS_CREDITS)
|
||||
{
|
||||
F_StartGameEvaluation();
|
||||
|
@ -3115,7 +3126,7 @@ static void G_DoCompleted(void)
|
|||
nextmap = cm;
|
||||
}
|
||||
|
||||
if (nextmap < 0 || (nextmap >= NUMMAPS && nextmap < 1100-1) || nextmap > 1102-1)
|
||||
if (nextmap < 0 || (nextmap >= NUMMAPS && nextmap < 1100-1) || nextmap > 1103-1)
|
||||
I_Error("Followed map %d to invalid map %d\n", prevmap + 1, nextmap + 1);
|
||||
|
||||
// wrap around in race
|
||||
|
@ -3169,7 +3180,7 @@ void G_AfterIntermission(void)
|
|||
{
|
||||
HU_ClearCEcho();
|
||||
|
||||
if (mapheaderinfo[gamemap-1]->cutscenenum && !modeattacking) // Start a custom cutscene.
|
||||
if (mapheaderinfo[gamemap-1]->cutscenenum && !modeattacking && skipstats <= 1) // Start a custom cutscene.
|
||||
F_StartCustomCutscene(mapheaderinfo[gamemap-1]->cutscenenum-1, false, false);
|
||||
else
|
||||
{
|
||||
|
@ -3281,6 +3292,11 @@ void G_EndGame(void)
|
|||
// Only do evaluation and credits in coop games.
|
||||
if (gametype == GT_COOP)
|
||||
{
|
||||
if (nextmap == 1103-1) // end game with ending
|
||||
{
|
||||
F_StartEnding();
|
||||
return;
|
||||
}
|
||||
if (nextmap == 1102-1) // end game with credits
|
||||
{
|
||||
F_StartCredits();
|
||||
|
@ -3699,7 +3715,7 @@ void G_SaveGame(UINT32 slot)
|
|||
backup = va("%s",savename);
|
||||
|
||||
// save during evaluation or credits? game's over, folks!
|
||||
if (gamestate == GS_CREDITS || gamestate == GS_EVALUATION)
|
||||
if (gamestate == GS_ENDING || gamestate == GS_CREDITS || gamestate == GS_EVALUATION)
|
||||
gamecomplete = true;
|
||||
|
||||
gameaction = ga_nothing;
|
||||
|
@ -3877,7 +3893,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean
|
|||
{
|
||||
// Clear a bunch of variables
|
||||
numgameovers = tokenlist = token = sstimer = redscore = bluescore = lastmap = 0;
|
||||
countdown = countdown2 = 0;
|
||||
countdown = countdown2 = exitfadestarted = 0;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
|
@ -4365,7 +4381,7 @@ void G_WriteGhostTic(mobj_t *ghost)
|
|||
ghostext.flags = 0;
|
||||
}
|
||||
|
||||
if (ghost->player && ghost->player->followmobj)
|
||||
if (ghost->player && ghost->player->followmobj) // bloats tails runs but what can ya do
|
||||
{
|
||||
INT16 temp;
|
||||
|
||||
|
@ -4466,16 +4482,15 @@ void G_ConsGhostTic(void)
|
|||
demo_p += sizeof(angle_t); // angle, unnecessary for cons.
|
||||
|
||||
mobj = NULL;
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
mobj = (mobj_t *)th;
|
||||
if (mobj->type == (mobjtype_t)type && mobj->x == x && mobj->y == y && mobj->z == z)
|
||||
break;
|
||||
mobj = NULL; // wasn't this one, keep searching.
|
||||
}
|
||||
if (mobj && mobj->health != health) // Wasn't damaged?! This is desync! Fix it!
|
||||
if (th != &thlist[THINK_MOBJ] && mobj->health != health) // Wasn't damaged?! This is desync! Fix it!
|
||||
{
|
||||
if (demosynced)
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n"));
|
||||
|
@ -4592,6 +4607,9 @@ void G_GhostTicker(void)
|
|||
switch(g->color)
|
||||
{
|
||||
default:
|
||||
case GHC_RETURNSKIN:
|
||||
g->mo->skin = g->oldmo.skin;
|
||||
// fallthru
|
||||
case GHC_NORMAL: // Go back to skin color
|
||||
g->mo->color = g->oldmo.color;
|
||||
break;
|
||||
|
@ -4602,6 +4620,9 @@ void G_GhostTicker(void)
|
|||
case GHC_FIREFLOWER: // Fireflower
|
||||
g->mo->color = SKINCOLOR_WHITE;
|
||||
break;
|
||||
case GHC_NIGHTSSKIN: // not actually a colour
|
||||
g->mo->skin = &skins[DEFAULTNIGHTSSKIN];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (xziptic & EZT_FLIP)
|
||||
|
@ -5862,9 +5883,9 @@ void G_DoPlayMetal(void)
|
|||
metalbuffer = metal_p = W_CacheLumpNum(l, PU_STATIC);
|
||||
|
||||
// find metal sonic
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo = (mobj_t *)th;
|
||||
|
@ -5873,7 +5894,7 @@ void G_DoPlayMetal(void)
|
|||
|
||||
break;
|
||||
}
|
||||
if (!mo)
|
||||
if (th == &thlist[THINK_MOBJ])
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Failed to find bot entity.\n"));
|
||||
Z_Free(metalbuffer);
|
||||
|
|
|
@ -56,6 +56,8 @@ extern INT16 rw_maximums[NUM_WEAPONS];
|
|||
extern INT32 pausedelay;
|
||||
extern boolean pausebreakkey;
|
||||
|
||||
extern boolean promptactive;
|
||||
|
||||
// used in game menu
|
||||
extern consvar_t cv_tutorialprompt;
|
||||
extern consvar_t cv_chatwidth, cv_chatnotifications, cv_chatheight, cv_chattime, cv_consolechat, cv_chatbacktint, cv_chatspamprotection, cv_compactscoreboard;
|
||||
|
@ -140,7 +142,9 @@ typedef enum
|
|||
GHC_NORMAL = 0,
|
||||
GHC_SUPER,
|
||||
GHC_FIREFLOWER,
|
||||
GHC_INVINCIBLE
|
||||
GHC_INVINCIBLE,
|
||||
GHC_NIGHTSSKIN, // not actually a colour
|
||||
GHC_RETURNSKIN // ditto
|
||||
} ghostcolor_t;
|
||||
|
||||
// Record/playback tics
|
||||
|
|
|
@ -27,12 +27,14 @@ typedef enum
|
|||
|
||||
GS_TITLESCREEN, // title screen
|
||||
GS_TIMEATTACK, // time attack menu
|
||||
|
||||
GS_CREDITS, // credit sequence
|
||||
GS_EVALUATION, // Evaluation at the end of a game.
|
||||
GS_GAMEEND, // game end sequence
|
||||
GS_GAMEEND, // game end sequence - "did you get all those chaos emeralds?"
|
||||
|
||||
// Hardcoded fades or other fading methods
|
||||
GS_INTRO, // introduction
|
||||
GS_ENDING, // currently shared between bad and good endings
|
||||
GS_CUTSCENE, // custom cutscene
|
||||
|
||||
// Not fadable
|
||||
|
@ -50,6 +52,7 @@ typedef enum
|
|||
} gameaction_t;
|
||||
|
||||
extern gamestate_t gamestate;
|
||||
extern UINT8 titlemapinaction;
|
||||
extern UINT8 ultimatemode; // was sk_insane
|
||||
extern gameaction_t gameaction;
|
||||
|
||||
|
|
|
@ -283,7 +283,7 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
|
|||
|
||||
if (!(option & V_SCALEPATCHMASK))
|
||||
{
|
||||
// if it's meant to cover the whole screen, black out the rest
|
||||
// if it's meant to cover the whole screen, black out the rest (ONLY IF TOP LEFT ISN'T TRANSPARENT)
|
||||
// cx and cy are possibly *slightly* off from float maths
|
||||
// This is done before here compared to software because we directly alter cx and cy to centre
|
||||
if (cx >= -0.1f && cx <= 0.1f && SHORT(gpatch->width) == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && SHORT(gpatch->height) == BASEVIDHEIGHT)
|
||||
|
@ -291,8 +291,11 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
|
|||
// Need to temporarily cache the real patch to get the colour of the top left pixel
|
||||
patch_t *realpatch = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC);
|
||||
const column_t *column = (const column_t *)((const UINT8 *)(realpatch) + LONG((realpatch)->columnofs[0]));
|
||||
const UINT8 *source = (const UINT8 *)(column) + 3;
|
||||
HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0]));
|
||||
if (!column->topdelta)
|
||||
{
|
||||
const UINT8 *source = (const UINT8 *)(column) + 3;
|
||||
HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0]));
|
||||
}
|
||||
Z_Free(realpatch);
|
||||
}
|
||||
// centre screen
|
||||
|
@ -439,7 +442,7 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
|
|||
|
||||
if (!(option & V_SCALEPATCHMASK))
|
||||
{
|
||||
// if it's meant to cover the whole screen, black out the rest
|
||||
// if it's meant to cover the whole screen, black out the rest (ONLY IF TOP LEFT ISN'T TRANSPARENT)
|
||||
// cx and cy are possibly *slightly* off from float maths
|
||||
// This is done before here compared to software because we directly alter cx and cy to centre
|
||||
if (cx >= -0.1f && cx <= 0.1f && SHORT(gpatch->width) == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && SHORT(gpatch->height) == BASEVIDHEIGHT)
|
||||
|
@ -447,8 +450,11 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
|
|||
// Need to temporarily cache the real patch to get the colour of the top left pixel
|
||||
patch_t *realpatch = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC);
|
||||
const column_t *column = (const column_t *)((const UINT8 *)(realpatch) + LONG((realpatch)->columnofs[0]));
|
||||
const UINT8 *source = (const UINT8 *)(column) + 3;
|
||||
HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0]));
|
||||
if (!column->topdelta)
|
||||
{
|
||||
const UINT8 *source = (const UINT8 *)(column) + 3;
|
||||
HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0]));
|
||||
}
|
||||
Z_Free(realpatch);
|
||||
}
|
||||
// centre screen
|
||||
|
@ -683,8 +689,183 @@ void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength)
|
|||
}
|
||||
else // Do TRANSMAP** fade.
|
||||
{
|
||||
Surf.FlatColor.rgba = pLocalPalette[color].rgba;
|
||||
Surf.FlatColor.s.alpha = (UINT8)(strength*25.5f);
|
||||
Surf.FlatColor.rgba = V_GetColor(color).rgba;
|
||||
Surf.FlatColor.s.alpha = softwaretranstogl[strength];
|
||||
}
|
||||
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
|
||||
}
|
||||
|
||||
// -----------------+
|
||||
// HWR_DrawFadeFill : draw flat coloured rectangle, with transparency
|
||||
// -----------------+
|
||||
void HWR_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT16 actualcolor, UINT8 strength)
|
||||
{
|
||||
FOutVector v[4];
|
||||
FSurfaceInfo Surf;
|
||||
float fx, fy, fw, fh;
|
||||
|
||||
UINT8 perplayershuffle = 0;
|
||||
|
||||
// 3--2
|
||||
// | /|
|
||||
// |/ |
|
||||
// 0--1
|
||||
|
||||
if (splitscreen && (color & V_PERPLAYER))
|
||||
{
|
||||
fixed_t adjusty = ((color & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)/2.0f;
|
||||
h >>= 1;
|
||||
y >>= 1;
|
||||
#ifdef QUADS
|
||||
if (splitscreen > 1) // 3 or 4 players
|
||||
{
|
||||
fixed_t adjustx = ((color & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)/2.0f;
|
||||
w >>= 1;
|
||||
x >>= 1;
|
||||
if (stplyr == &players[displayplayer])
|
||||
{
|
||||
if (!(color & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 1;
|
||||
if (!(color & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
||||
perplayershuffle |= 4;
|
||||
color &= ~V_SNAPTOBOTTOM|V_SNAPTORIGHT;
|
||||
}
|
||||
else if (stplyr == &players[secondarydisplayplayer])
|
||||
{
|
||||
if (!(color & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 1;
|
||||
if (!(color & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
||||
perplayershuffle |= 8;
|
||||
x += adjustx;
|
||||
color &= ~V_SNAPTOBOTTOM|V_SNAPTOLEFT;
|
||||
}
|
||||
else if (stplyr == &players[thirddisplayplayer])
|
||||
{
|
||||
if (!(color & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 2;
|
||||
if (!(color & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
||||
perplayershuffle |= 4;
|
||||
y += adjusty;
|
||||
color &= ~V_SNAPTOTOP|V_SNAPTORIGHT;
|
||||
}
|
||||
else //if (stplyr == &players[fourthdisplayplayer])
|
||||
{
|
||||
if (!(color & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 2;
|
||||
if (!(color & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
||||
perplayershuffle |= 8;
|
||||
x += adjustx;
|
||||
y += adjusty;
|
||||
color &= ~V_SNAPTOTOP|V_SNAPTOLEFT;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
// 2 players
|
||||
{
|
||||
if (stplyr == &players[displayplayer])
|
||||
{
|
||||
if (!(color & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 1;
|
||||
color &= ~V_SNAPTOBOTTOM;
|
||||
}
|
||||
else //if (stplyr == &players[secondarydisplayplayer])
|
||||
{
|
||||
if (!(color & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 2;
|
||||
y += adjusty;
|
||||
color &= ~V_SNAPTOTOP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fx = (float)x;
|
||||
fy = (float)y;
|
||||
fw = (float)w;
|
||||
fh = (float)h;
|
||||
|
||||
if (!(color & V_NOSCALESTART))
|
||||
{
|
||||
float dupx = (float)vid.dupx, dupy = (float)vid.dupy;
|
||||
|
||||
fx *= dupx;
|
||||
fy *= dupy;
|
||||
fw *= dupx;
|
||||
fh *= dupy;
|
||||
|
||||
if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f)
|
||||
{
|
||||
if (color & V_SNAPTORIGHT)
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx));
|
||||
else if (!(color & V_SNAPTOLEFT))
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 2;
|
||||
if (perplayershuffle & 4)
|
||||
fx -= ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 4;
|
||||
else if (perplayershuffle & 8)
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 4;
|
||||
}
|
||||
if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dupy) > 1.0E-36f)
|
||||
{
|
||||
// same thing here
|
||||
if (color & V_SNAPTOBOTTOM)
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy));
|
||||
else if (!(color & V_SNAPTOTOP))
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 2;
|
||||
if (perplayershuffle & 1)
|
||||
fy -= ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 4;
|
||||
else if (perplayershuffle & 2)
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (fx >= vid.width || fy >= vid.height)
|
||||
return;
|
||||
if (fx < 0)
|
||||
{
|
||||
fw += fx;
|
||||
fx = 0;
|
||||
}
|
||||
if (fy < 0)
|
||||
{
|
||||
fh += fy;
|
||||
fy = 0;
|
||||
}
|
||||
|
||||
if (fw <= 0 || fh <= 0)
|
||||
return;
|
||||
if (fx + fw > vid.width)
|
||||
fw = (float)vid.width - fx;
|
||||
if (fy + fh > vid.height)
|
||||
fh = (float)vid.height - fy;
|
||||
|
||||
fx = -1 + fx / (vid.width / 2);
|
||||
fy = 1 - fy / (vid.height / 2);
|
||||
fw = fw / (vid.width / 2);
|
||||
fh = fh / (vid.height / 2);
|
||||
|
||||
v[0].x = v[3].x = fx;
|
||||
v[2].x = v[1].x = fx + fw;
|
||||
v[0].y = v[1].y = fy;
|
||||
v[2].y = v[3].y = fy - fh;
|
||||
|
||||
//Hurdler: do we still use this argb color? if not, we should remove it
|
||||
v[0].argb = v[1].argb = v[2].argb = v[3].argb = 0xff00ff00; //;
|
||||
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
|
||||
|
||||
v[0].sow = v[3].sow = 0.0f;
|
||||
v[2].sow = v[1].sow = 1.0f;
|
||||
v[0].tow = v[1].tow = 0.0f;
|
||||
v[2].tow = v[3].tow = 1.0f;
|
||||
|
||||
if (actualcolor & 0xFF00) // Do COLORMAP fade.
|
||||
{
|
||||
Surf.FlatColor.rgba = UINT2RGBA(0x01010160);
|
||||
Surf.FlatColor.s.alpha = (strength*8);
|
||||
}
|
||||
else // Do TRANSMAP** fade.
|
||||
{
|
||||
Surf.FlatColor.rgba = V_GetColor(actualcolor).rgba;
|
||||
Surf.FlatColor.s.alpha = softwaretranstogl[strength];
|
||||
}
|
||||
HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest);
|
||||
}
|
||||
|
@ -905,54 +1086,117 @@ void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, UINT32 color, INT32
|
|||
FSurfaceInfo Surf;
|
||||
float fx, fy, fw, fh;
|
||||
|
||||
if (w < 0 || h < 0)
|
||||
return; // consistency w/ software
|
||||
UINT8 perplayershuffle = 0;
|
||||
|
||||
// 3--2
|
||||
// | /|
|
||||
// |/ |
|
||||
// 0--1
|
||||
|
||||
if (splitscreen && (color & V_PERPLAYER))
|
||||
{
|
||||
fixed_t adjusty = ((color & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)/2.0f;
|
||||
h >>= 1;
|
||||
y >>= 1;
|
||||
#ifdef QUADS
|
||||
if (splitscreen > 1) // 3 or 4 players
|
||||
{
|
||||
fixed_t adjustx = ((color & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)/2.0f;
|
||||
w >>= 1;
|
||||
x >>= 1;
|
||||
if (stplyr == &players[displayplayer])
|
||||
{
|
||||
if (!(color & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 1;
|
||||
if (!(color & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
||||
perplayershuffle |= 4;
|
||||
color &= ~V_SNAPTOBOTTOM|V_SNAPTORIGHT;
|
||||
}
|
||||
else if (stplyr == &players[secondarydisplayplayer])
|
||||
{
|
||||
if (!(color & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 1;
|
||||
if (!(color & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
||||
perplayershuffle |= 8;
|
||||
x += adjustx;
|
||||
color &= ~V_SNAPTOBOTTOM|V_SNAPTOLEFT;
|
||||
}
|
||||
else if (stplyr == &players[thirddisplayplayer])
|
||||
{
|
||||
if (!(color & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 2;
|
||||
if (!(color & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
||||
perplayershuffle |= 4;
|
||||
y += adjusty;
|
||||
color &= ~V_SNAPTOTOP|V_SNAPTORIGHT;
|
||||
}
|
||||
else //if (stplyr == &players[fourthdisplayplayer])
|
||||
{
|
||||
if (!(color & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 2;
|
||||
if (!(color & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
||||
perplayershuffle |= 8;
|
||||
x += adjustx;
|
||||
y += adjusty;
|
||||
color &= ~V_SNAPTOTOP|V_SNAPTOLEFT;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
// 2 players
|
||||
{
|
||||
if (stplyr == &players[displayplayer])
|
||||
{
|
||||
if (!(color & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 1;
|
||||
color &= ~V_SNAPTOBOTTOM;
|
||||
}
|
||||
else //if (stplyr == &players[secondarydisplayplayer])
|
||||
{
|
||||
if (!(color & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 2;
|
||||
y += adjusty;
|
||||
color &= ~V_SNAPTOTOP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fx = (float)x;
|
||||
fy = (float)y;
|
||||
fw = (float)w;
|
||||
fh = (float)h;
|
||||
|
||||
if (!(options & V_NOSCALESTART))
|
||||
if (!(color & V_NOSCALESTART))
|
||||
{
|
||||
float dupx = (float)vid.dupx, dupy = (float)vid.dupy;
|
||||
|
||||
if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT)
|
||||
{
|
||||
RGBA_t rgbaColour = V_GetColor(color);
|
||||
FRGBAFloat clearColour;
|
||||
clearColour.red = (float)rgbaColour.s.red / 255;
|
||||
clearColour.green = (float)rgbaColour.s.green / 255;
|
||||
clearColour.blue = (float)rgbaColour.s.blue / 255;
|
||||
clearColour.alpha = 1;
|
||||
HWD.pfnClearBuffer(true, false, &clearColour);
|
||||
return;
|
||||
}
|
||||
|
||||
fx *= dupx;
|
||||
fy *= dupy;
|
||||
fw *= dupx;
|
||||
fh *= dupy;
|
||||
|
||||
if (fabsf((float)vid.width - ((float)BASEVIDWIDTH * dupx)) > 1.0E-36f)
|
||||
if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f)
|
||||
{
|
||||
if (options & V_SNAPTORIGHT)
|
||||
if (color & V_SNAPTORIGHT)
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx));
|
||||
else if (!(options & V_SNAPTOLEFT))
|
||||
else if (!(color & V_SNAPTOLEFT))
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 2;
|
||||
if (perplayershuffle & 4)
|
||||
fx -= ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 4;
|
||||
else if (perplayershuffle & 8)
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 4;
|
||||
}
|
||||
if (fabsf((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) > 1.0E-36f)
|
||||
if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dupy) > 1.0E-36f)
|
||||
{
|
||||
// same thing here
|
||||
if (options & V_SNAPTOBOTTOM)
|
||||
if (color & V_SNAPTOBOTTOM)
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy));
|
||||
else if (!(options & V_SNAPTOTOP))
|
||||
else if (!(color & V_SNAPTOTOP))
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 2;
|
||||
if (perplayershuffle & 1)
|
||||
fy -= ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 4;
|
||||
else if (perplayershuffle & 2)
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1012,9 +1256,6 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
|
|||
|
||||
UINT8 perplayershuffle = 0;
|
||||
|
||||
if (w < 0 || h < 0)
|
||||
return; // consistency w/ software
|
||||
|
||||
// 3--2
|
||||
// | /|
|
||||
// |/ |
|
||||
|
|
|
@ -202,6 +202,7 @@ light_t *t_lspr[NUMSPRITES] =
|
|||
// Boss 4 (Castle Eggman)
|
||||
&lspr[NOLIGHT], // SPR_EGGP
|
||||
&lspr[REDBALL_L], // SPR_EFIR
|
||||
&lspr[NOLIGHT], // SPR_EGR1
|
||||
|
||||
// Boss 5 (Arid Canyon)
|
||||
&lspr[NOLIGHT], //SPR_FANG // replaces EGGQ
|
||||
|
@ -487,6 +488,7 @@ light_t *t_lspr[NUMSPRITES] =
|
|||
&lspr[NOLIGHT], // SPR_GFLG
|
||||
|
||||
&lspr[NOLIGHT], // SPR_CORK
|
||||
&lspr[NOLIGHT], // SPR_LHRT
|
||||
|
||||
// Ring Weapons
|
||||
&lspr[RINGLIGHT_L], // SPR_RRNG
|
||||
|
@ -580,6 +582,9 @@ light_t *t_lspr[NUMSPRITES] =
|
|||
&lspr[NOLIGHT], // SPR_ROIO
|
||||
&lspr[NOLIGHT], // SPR_ROIP
|
||||
|
||||
// Bricks
|
||||
&lspr[NOLIGHT], // SPR_BRIC
|
||||
|
||||
// Gravity Well Objects
|
||||
&lspr[NOLIGHT], // SPR_GWLG
|
||||
&lspr[NOLIGHT], // SPR_GWLR
|
||||
|
@ -799,6 +804,14 @@ void HWR_WallLighting(FOutVector *wlVerts)
|
|||
FSurfaceInfo Surf;
|
||||
float dist_p2d, d[4], s;
|
||||
|
||||
if (!dynlights->mo[j])
|
||||
continue;
|
||||
if (P_MobjWasRemoved(dynlights->mo[j]))
|
||||
{
|
||||
P_SetTarget(&dynlights->mo[j], NULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
// check bounding box first
|
||||
if (SphereTouchBBox3D(&wlVerts[2], &wlVerts[0], &LIGHT_POS(j), DL_RADIUS(j))==false)
|
||||
continue;
|
||||
|
@ -849,8 +862,6 @@ void HWR_WallLighting(FOutVector *wlVerts)
|
|||
#ifdef DL_HIGH_QUALITY
|
||||
Surf.FlatColor.s.alpha = (UINT8)((1-dist_p2d/DL_SQRRADIUS(j))*Surf.FlatColor.s.alpha);
|
||||
#endif
|
||||
if (!dynlights->mo[j]->state)
|
||||
return;
|
||||
// next state is null so fade out with alpha
|
||||
if (dynlights->mo[j]->state->nextstate == S_NULL)
|
||||
Surf.FlatColor.s.alpha = (UINT8)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.FlatColor.s.alpha);
|
||||
|
@ -881,6 +892,14 @@ void HWR_PlaneLighting(FOutVector *clVerts, int nrClipVerts)
|
|||
FSurfaceInfo Surf;
|
||||
float dist_p2d, s;
|
||||
|
||||
if (!dynlights->mo[j])
|
||||
continue;
|
||||
if (P_MobjWasRemoved(dynlights->mo[j]))
|
||||
{
|
||||
P_SetTarget(&dynlights->mo[j], NULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
// BP: The kickass Optimization: check if light touch bounding box
|
||||
if (SphereTouchBBox3D(&p1, &p2, &dynlights->position[j], DL_RADIUS(j))==false)
|
||||
continue;
|
||||
|
@ -912,8 +931,6 @@ void HWR_PlaneLighting(FOutVector *clVerts, int nrClipVerts)
|
|||
#ifdef DL_HIGH_QUALITY
|
||||
Surf.FlatColor.s.alpha = (unsigned char)((1 - dist_p2d/DL_SQRRADIUS(j))*Surf.FlatColor.s.alpha);
|
||||
#endif
|
||||
if (!dynlights->mo[j]->state)
|
||||
return;
|
||||
// next state is null so fade out with alpha
|
||||
if ((dynlights->mo[j]->state->nextstate == S_NULL))
|
||||
Surf.FlatColor.s.alpha = (unsigned char)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.FlatColor.s.alpha);
|
||||
|
@ -1044,6 +1061,14 @@ void HWR_DrawCoronas(void)
|
|||
if (!(p_lspr->type & CORONA_SPR))
|
||||
continue;
|
||||
|
||||
if (!dynlights->mo[j])
|
||||
continue;
|
||||
if (P_MobjWasRemoved(dynlights->mo[j]))
|
||||
{
|
||||
P_SetTarget(&dynlights->mo[j], NULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
transform(&cx,&cy,&cz);
|
||||
|
||||
// more realistique corona !
|
||||
|
@ -1105,7 +1130,8 @@ void HWR_DrawCoronas(void)
|
|||
// --------------------------------------------------------------------------
|
||||
void HWR_ResetLights(void)
|
||||
{
|
||||
dynlights->nb = 0;
|
||||
while (dynlights->nb)
|
||||
P_SetTarget(&dynlights->mo[--dynlights->nb], NULL);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
@ -1136,24 +1162,25 @@ void HWR_DL_AddLight(gr_vissprite_t *spr, GLPatch_t *patch)
|
|||
return;
|
||||
#endif
|
||||
|
||||
if (dynlights->nb >= DL_MAX_LIGHT)
|
||||
return;
|
||||
|
||||
// check if sprite contain dynamic light
|
||||
p_lspr = t_lspr[spr->mobj->sprite];
|
||||
if ((p_lspr->type&DYNLIGHT_SPR)
|
||||
&& ((p_lspr->type != LIGHT_SPR) || cv_grstaticlighting.value)
|
||||
&& (dynlights->nb < DL_MAX_LIGHT)
|
||||
if (!(p_lspr->type & DYNLIGHT_SPR))
|
||||
return;
|
||||
if ((p_lspr->type != LIGHT_SPR) || cv_grstaticlighting.value)
|
||||
return;
|
||||
|
||||
&& spr->mobj->state)
|
||||
{
|
||||
LIGHT_POS(dynlights->nb).x = FIXED_TO_FLOAT(spr->mobj->x);
|
||||
LIGHT_POS(dynlights->nb).y = FIXED_TO_FLOAT(spr->mobj->z)+FIXED_TO_FLOAT(spr->mobj->height>>1)+p_lspr->light_yoffset;
|
||||
LIGHT_POS(dynlights->nb).z = FIXED_TO_FLOAT(spr->mobj->y);
|
||||
LIGHT_POS(dynlights->nb).x = FIXED_TO_FLOAT(spr->mobj->x);
|
||||
LIGHT_POS(dynlights->nb).y = FIXED_TO_FLOAT(spr->mobj->z)+FIXED_TO_FLOAT(spr->mobj->height>>1)+p_lspr->light_yoffset;
|
||||
LIGHT_POS(dynlights->nb).z = FIXED_TO_FLOAT(spr->mobj->y);
|
||||
|
||||
P_SetTarget(&dynlights->mo[dynlights->nb], spr->mobj);
|
||||
P_SetTarget(&dynlights->mo[dynlights->nb], spr->mobj);
|
||||
|
||||
dynlights->p_lspr[dynlights->nb] = p_lspr;
|
||||
dynlights->p_lspr[dynlights->nb] = p_lspr;
|
||||
|
||||
dynlights->nb++;
|
||||
}
|
||||
dynlights->nb++;
|
||||
}
|
||||
|
||||
static GLPatch_t lightmappatch;
|
||||
|
@ -1307,6 +1334,14 @@ static void HWR_CheckSubsector(size_t num, fixed_t *bbox)
|
|||
// if (CircleTouchBBox(&p1, &p2, &LIGHT_POS(lightnum), DL_RADIUS(lightnum))==false)
|
||||
// continue;
|
||||
|
||||
if (!dynlights->mo[lightnum])
|
||||
continue;
|
||||
if (P_MobjWasRemoved(dynlights->mo[lightnum]))
|
||||
{
|
||||
P_SetTarget(&dynlights->mo[lightnum], NULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
count = sub->numlines; // how many linedefs
|
||||
line = &segs[sub->firstline]; // first line seg
|
||||
while (count--)
|
||||
|
@ -1324,18 +1359,20 @@ static void HWR_CheckSubsector(size_t num, fixed_t *bbox)
|
|||
// --------------------------------------------------------------------------
|
||||
static void HWR_AddMobjLights(mobj_t *thing)
|
||||
{
|
||||
if (t_lspr[thing->sprite]->type & CORONA_SPR)
|
||||
{
|
||||
LIGHT_POS(dynlights->nb).x = FIXED_TO_FLOAT(thing->x);
|
||||
LIGHT_POS(dynlights->nb).y = FIXED_TO_FLOAT(thing->z) + t_lspr[thing->sprite]->light_yoffset;
|
||||
LIGHT_POS(dynlights->nb).z = FIXED_TO_FLOAT(thing->y);
|
||||
if (dynlights->nb >= DL_MAX_LIGHT)
|
||||
return;
|
||||
if (!(t_lspr[thing->sprite]->type & CORONA_SPR))
|
||||
return;
|
||||
|
||||
dynlights->p_lspr[dynlights->nb] = t_lspr[thing->sprite];
|
||||
LIGHT_POS(dynlights->nb).x = FIXED_TO_FLOAT(thing->x);
|
||||
LIGHT_POS(dynlights->nb).y = FIXED_TO_FLOAT(thing->z) + t_lspr[thing->sprite]->light_yoffset;
|
||||
LIGHT_POS(dynlights->nb).z = FIXED_TO_FLOAT(thing->y);
|
||||
|
||||
dynlights->nb++;
|
||||
if (dynlights->nb > DL_MAX_LIGHT)
|
||||
dynlights->nb = DL_MAX_LIGHT;
|
||||
}
|
||||
P_SetTarget(&dynlights->mo[dynlights->nb], thing);
|
||||
|
||||
dynlights->p_lspr[dynlights->nb] = t_lspr[thing->sprite];
|
||||
|
||||
dynlights->nb++;
|
||||
}
|
||||
|
||||
//Hurdler: The goal of this function is to walk through all the bsp starting
|
||||
|
@ -1361,12 +1398,9 @@ static void HWR_SearchLightsInMobjs(void)
|
|||
//mobj_t * mobj;
|
||||
|
||||
// search in the list of thinkers
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
{
|
||||
// a mobj ?
|
||||
if (th->function.acp1 == (actionf_p1)P_MobjThinker)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
if (th->function.acp1 != (actionf_p1)P_RemoveThinkerDelayed)
|
||||
HWR_AddMobjLights((mobj_t *)th);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1378,7 +1412,7 @@ void HWR_CreateStaticLightmaps(int bspnum)
|
|||
#ifdef STATICLIGHT
|
||||
CONS_Debug(DBG_RENDER, "HWR_CreateStaticLightmaps\n");
|
||||
|
||||
dynlights->nb = 0;
|
||||
HWR_ResetLights();
|
||||
|
||||
// First: Searching for lights
|
||||
// BP: if i was you, I will make it in create mobj since mobj can be create
|
||||
|
@ -1389,8 +1423,6 @@ void HWR_CreateStaticLightmaps(int bspnum)
|
|||
// Second: Build all lightmap for walls covered by lights
|
||||
validcount++; // to be sure
|
||||
HWR_ComputeLightMapsInBSPNode(bspnum, NULL);
|
||||
|
||||
dynlights->nb = 0;
|
||||
#else
|
||||
(void)bspnum;
|
||||
#endif
|
||||
|
|
|
@ -580,7 +580,7 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
|
|||
if (nrPlaneVerts < 3) //not even a triangle ?
|
||||
return;
|
||||
|
||||
if (nrPlaneVerts > UINT16_MAX) // FIXME: exceeds plVerts size
|
||||
if (nrPlaneVerts > (INT32)UINT16_MAX) // FIXME: exceeds plVerts size
|
||||
{
|
||||
CONS_Debug(DBG_RENDER, "polygon size of %d exceeds max value of %d vertices\n", nrPlaneVerts, UINT16_MAX);
|
||||
return;
|
||||
|
@ -3190,7 +3190,7 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
|
|||
if (nrPlaneVerts < 3) //not even a triangle ?
|
||||
return;
|
||||
|
||||
if (nrPlaneVerts > UINT16_MAX) // FIXME: exceeds plVerts size
|
||||
if (nrPlaneVerts > (size_t)UINT16_MAX) // FIXME: exceeds plVerts size
|
||||
{
|
||||
CONS_Debug(DBG_RENDER, "polygon size of %s exceeds max value of %d vertices\n", sizeu1(nrPlaneVerts), UINT16_MAX);
|
||||
return;
|
||||
|
@ -5660,9 +5660,9 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
vis->z2 = z2;
|
||||
|
||||
//Hurdler: 25/04/2000: now support colormap in hardware mode
|
||||
if ((vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && (leveltime & 1)) // Bosses "flash"
|
||||
if ((vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && !(vis->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash"
|
||||
{
|
||||
if (vis->mobj->type == MT_CYBRAKDEMON)
|
||||
if (vis->mobj->type == MT_CYBRAKDEMON || vis->mobj->colorized)
|
||||
vis->colormap = R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE);
|
||||
else if (vis->mobj->type == MT_METALSONIC_BATTLE)
|
||||
vis->colormap = R_GetTranslationColormap(TC_METALSONIC, 0, GTC_CACHE);
|
||||
|
@ -5672,7 +5672,9 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
else if (thing->color)
|
||||
{
|
||||
// New colormap stuff for skins Tails 06-07-2002
|
||||
if (thing->skin && thing->sprite == SPR_PLAY) // This thing is a player!
|
||||
if (thing->colorized)
|
||||
vis->colormap = R_GetTranslationColormap(TC_RAINBOW, thing->color, GTC_CACHE);
|
||||
else if (thing->skin && thing->sprite == SPR_PLAY) // This thing is a player!
|
||||
{
|
||||
size_t skinnum = (skin_t*)thing->skin-skins;
|
||||
vis->colormap = R_GetTranslationColormap((INT32)skinnum, thing->color, GTC_CACHE);
|
||||
|
|
|
@ -49,6 +49,7 @@ void HWR_CreatePlanePolygons(INT32 bspnum);
|
|||
void HWR_CreateStaticLightmaps(INT32 bspnum);
|
||||
void HWR_PrepLevelCache(size_t pnumtextures);
|
||||
void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color);
|
||||
void HWR_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT16 actualcolor, UINT8 strength);
|
||||
void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, UINT32 color, INT32 options); // Lat: separate flags from color since color needs to be an uint to work right.
|
||||
void HWR_DrawPic(INT32 x,INT32 y,lumpnum_t lumpnum);
|
||||
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
#include "../w_wad.h"
|
||||
#include "../z_zone.h"
|
||||
#include "../r_things.h"
|
||||
#include "../r_draw.h"
|
||||
#include "../p_tick.h"
|
||||
|
||||
#include "hw_main.h"
|
||||
#include "../v_video.h"
|
||||
|
@ -978,8 +980,18 @@ spritemd2found:
|
|||
fclose(f);
|
||||
}
|
||||
|
||||
static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, GLMipmap_t *grmip, skincolors_t color)
|
||||
// Define for getting accurate color brightness readings according to how the human eye sees them.
|
||||
// https://en.wikipedia.org/wiki/Relative_luminance
|
||||
// 0.2126 to red
|
||||
// 0.7152 to green
|
||||
// 0.0722 to blue
|
||||
// (See this same define in k_kart.c!)
|
||||
#define SETBRIGHTNESS(brightness,r,g,b) \
|
||||
brightness = (UINT8)(((1063*((UINT16)r)/5000) + (3576*((UINT16)g)/5000) + (361*((UINT16)b)/5000)) / 3)
|
||||
|
||||
static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, GLMipmap_t *grmip, INT32 skinnum, skincolors_t color)
|
||||
{
|
||||
UINT8 i;
|
||||
UINT16 w = gpatch->width, h = gpatch->height;
|
||||
UINT32 size = w*h;
|
||||
RGBA_t *image, *blendimage, *cur, blendcolor;
|
||||
|
@ -1005,50 +1017,112 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch,
|
|||
image = gpatch->mipmap.grInfo.data;
|
||||
blendimage = blendgpatch->mipmap.grInfo.data;
|
||||
|
||||
// Average all of the translation's colors
|
||||
if (color == SKINCOLOR_NONE || color >= MAXTRANSLATIONS)
|
||||
blendcolor = V_GetColor(0xff);
|
||||
else
|
||||
blendcolor = V_GetColor(Color_Index[color-1][4]);
|
||||
|
||||
while (size--)
|
||||
{
|
||||
if (blendimage->s.alpha == 0)
|
||||
{
|
||||
// Don't bother with blending the pixel if the alpha of the blend pixel is 0
|
||||
cur->rgba = image->rgba;
|
||||
}
|
||||
else
|
||||
{
|
||||
INT32 tempcolor;
|
||||
INT16 tempmult, tempalpha;
|
||||
tempalpha = -(abs(blendimage->s.red-127)-127)*2;
|
||||
if (tempalpha > 255)
|
||||
tempalpha = 255;
|
||||
else if (tempalpha < 0)
|
||||
tempalpha = 0;
|
||||
const UINT8 div = 6;
|
||||
const UINT8 start = 4;
|
||||
UINT32 r, g, b;
|
||||
|
||||
tempmult = (blendimage->s.red-127)*2;
|
||||
if (tempmult > 255)
|
||||
tempmult = 255;
|
||||
else if (tempmult < 0)
|
||||
tempmult = 0;
|
||||
blendcolor = V_GetColor(Color_Index[color-1][start]);
|
||||
r = (UINT32)(blendcolor.s.red*blendcolor.s.red);
|
||||
g = (UINT32)(blendcolor.s.green*blendcolor.s.green);
|
||||
b = (UINT32)(blendcolor.s.blue*blendcolor.s.blue);
|
||||
|
||||
tempcolor = (image->s.red*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.red)/255)) * blendimage->s.alpha)/255;
|
||||
cur->s.red = (UINT8)tempcolor;
|
||||
tempcolor = (image->s.green*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.green)/255)) * blendimage->s.alpha)/255;
|
||||
cur->s.green = (UINT8)tempcolor;
|
||||
tempcolor = (image->s.blue*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.blue)/255)) * blendimage->s.alpha)/255;
|
||||
cur->s.blue = (UINT8)tempcolor;
|
||||
cur->s.alpha = image->s.alpha;
|
||||
for (i = 1; i < div; i++)
|
||||
{
|
||||
RGBA_t nextcolor = V_GetColor(Color_Index[color-1][start+i]);
|
||||
r += (UINT32)(nextcolor.s.red*nextcolor.s.red);
|
||||
g += (UINT32)(nextcolor.s.green*nextcolor.s.green);
|
||||
b += (UINT32)(nextcolor.s.blue*nextcolor.s.blue);
|
||||
}
|
||||
|
||||
cur++; image++; blendimage++;
|
||||
blendcolor.s.red = (UINT8)(FixedSqrt((r/div)<<FRACBITS)>>FRACBITS);
|
||||
blendcolor.s.green = (UINT8)(FixedSqrt((g/div)<<FRACBITS)>>FRACBITS);
|
||||
blendcolor.s.blue = (UINT8)(FixedSqrt((b/div)<<FRACBITS)>>FRACBITS);
|
||||
}
|
||||
|
||||
// rainbow support, could theoretically support boss ones too
|
||||
if (skinnum == TC_RAINBOW)
|
||||
{
|
||||
while (size--)
|
||||
{
|
||||
if (image->s.alpha == 0 && blendimage->s.alpha == 0)
|
||||
{
|
||||
// Don't bother with blending the pixel if the alpha of the blend pixel is 0
|
||||
cur->rgba = image->rgba;
|
||||
}
|
||||
else
|
||||
{
|
||||
UINT32 tempcolor;
|
||||
UINT16 imagebright, blendbright, finalbright, colorbright;
|
||||
SETBRIGHTNESS(imagebright,image->s.red,image->s.green,image->s.blue);
|
||||
SETBRIGHTNESS(blendbright,blendimage->s.red,blendimage->s.green,blendimage->s.blue);
|
||||
// slightly dumb average between the blend image color and base image colour, usually one or the other will be fully opaque anyway
|
||||
finalbright = (imagebright*(255-blendimage->s.alpha))/255 + (blendbright*blendimage->s.alpha)/255;
|
||||
SETBRIGHTNESS(colorbright,blendcolor.s.red,blendcolor.s.green,blendcolor.s.blue);
|
||||
|
||||
tempcolor = (finalbright*blendcolor.s.red)/colorbright;
|
||||
tempcolor = min(255, tempcolor);
|
||||
cur->s.red = (UINT8)tempcolor;
|
||||
tempcolor = (finalbright*blendcolor.s.green)/colorbright;
|
||||
tempcolor = min(255, tempcolor);
|
||||
cur->s.green = (UINT8)tempcolor;
|
||||
tempcolor = (finalbright*blendcolor.s.blue)/colorbright;
|
||||
tempcolor = min(255, tempcolor);
|
||||
cur->s.blue = (UINT8)tempcolor;
|
||||
cur->s.alpha = image->s.alpha;
|
||||
}
|
||||
|
||||
cur++; image++; blendimage++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (size--)
|
||||
{
|
||||
if (blendimage->s.alpha == 0)
|
||||
{
|
||||
// Don't bother with blending the pixel if the alpha of the blend pixel is 0
|
||||
cur->rgba = image->rgba;
|
||||
}
|
||||
else
|
||||
{
|
||||
INT32 tempcolor;
|
||||
INT16 tempmult, tempalpha;
|
||||
tempalpha = -(abs(blendimage->s.red-127)-127)*2;
|
||||
if (tempalpha > 255)
|
||||
tempalpha = 255;
|
||||
else if (tempalpha < 0)
|
||||
tempalpha = 0;
|
||||
|
||||
tempmult = (blendimage->s.red-127)*2;
|
||||
if (tempmult > 255)
|
||||
tempmult = 255;
|
||||
else if (tempmult < 0)
|
||||
tempmult = 0;
|
||||
|
||||
tempcolor = (image->s.red*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.red)/255)) * blendimage->s.alpha)/255;
|
||||
cur->s.red = (UINT8)tempcolor;
|
||||
tempcolor = (image->s.green*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.green)/255)) * blendimage->s.alpha)/255;
|
||||
cur->s.green = (UINT8)tempcolor;
|
||||
tempcolor = (image->s.blue*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.blue)/255)) * blendimage->s.alpha)/255;
|
||||
cur->s.blue = (UINT8)tempcolor;
|
||||
cur->s.alpha = image->s.alpha;
|
||||
}
|
||||
|
||||
cur++; image++; blendimage++;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, const UINT8 *colormap, skincolors_t color)
|
||||
#undef SETBRIGHTNESS
|
||||
|
||||
static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT32 skinnum, const UINT8 *colormap, skincolors_t color)
|
||||
{
|
||||
// mostly copied from HWR_GetMappedPatch, hence the similarities and comment
|
||||
GLMipmap_t *grmip, *newmip;
|
||||
|
@ -1089,13 +1163,14 @@ static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, con
|
|||
grmip->nextcolormap = newmip;
|
||||
newmip->colormap = colormap;
|
||||
|
||||
HWR_CreateBlendedTexture(gpatch, blendgpatch, newmip, color);
|
||||
HWR_CreateBlendedTexture(gpatch, blendgpatch, newmip, skinnum, color);
|
||||
|
||||
HWD.pfnSetTexture(newmip);
|
||||
Z_ChangeTag(newmip->grInfo.data, PU_HWRCACHE_UNLOCKED);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// -----------------+
|
||||
// HWR_DrawMD2 : Draw MD2
|
||||
// : (monsters, bonuses, weapons, lights, ...)
|
||||
|
@ -1123,6 +1198,9 @@ static UINT8 P_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t *p
|
|||
if (!md2 || !skin)
|
||||
return 0;
|
||||
|
||||
if ((spr2 & ~FF_SPR2SUPER) >= free_spr2)
|
||||
return 0;
|
||||
|
||||
while (!(md2->model->spr2frames[spr2*2 + 1])
|
||||
&& spr2 != SPR2_STND
|
||||
&& ++i != 32) // recursion limiter
|
||||
|
@ -1145,7 +1223,10 @@ static UINT8 P_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t *p
|
|||
& SF_NOJUMPSPIN) ? SPR2_SPNG : SPR2_ROLL;
|
||||
break;
|
||||
case SPR2_TIRE:
|
||||
spr2 = (player && player->charability == CA_SWIM) ? SPR2_SWIM : SPR2_FLY;
|
||||
spr2 = ((player
|
||||
? player->charability
|
||||
: skin->ability)
|
||||
== CA_SWIM) ? SPR2_SWIM : SPR2_FLY;
|
||||
break;
|
||||
|
||||
// Use the handy list, that's what it's there for!
|
||||
|
@ -1157,6 +1238,9 @@ static UINT8 P_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t *p
|
|||
spr2 |= super;
|
||||
}
|
||||
|
||||
if (i >= 32) // probably an infinite loop...
|
||||
return 0;
|
||||
|
||||
return spr2;
|
||||
}
|
||||
|
||||
|
@ -1285,7 +1369,30 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
|
|||
md2->blendgrpatch && ((GLPatch_t *)md2->blendgrpatch)->mipmap.grInfo.format
|
||||
&& gpatch->width == ((GLPatch_t *)md2->blendgrpatch)->width && gpatch->height == ((GLPatch_t *)md2->blendgrpatch)->height)
|
||||
{
|
||||
HWR_GetBlendedTexture(gpatch, (GLPatch_t *)md2->blendgrpatch, spr->colormap, (skincolors_t)spr->mobj->color);
|
||||
INT32 skinnum = TC_DEFAULT;
|
||||
if ((spr->mobj->flags & (MF_ENEMY|MF_BOSS)) && (spr->mobj->flags2 & MF2_FRET) && !(spr->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash"
|
||||
{
|
||||
if (spr->mobj->type == MT_CYBRAKDEMON || spr->mobj->colorized)
|
||||
skinnum = TC_ALLWHITE;
|
||||
else if (spr->mobj->type == MT_METALSONIC_BATTLE)
|
||||
skinnum = TC_METALSONIC;
|
||||
else
|
||||
skinnum = TC_BOSS;
|
||||
}
|
||||
else if (spr->mobj->color)
|
||||
{
|
||||
if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
|
||||
{
|
||||
if (spr->mobj->colorized)
|
||||
skinnum = TC_RAINBOW;
|
||||
else
|
||||
{
|
||||
skinnum = (INT32)((skin_t*)spr->mobj->skin-skins);
|
||||
}
|
||||
}
|
||||
else skinnum = TC_DEFAULT;
|
||||
}
|
||||
HWR_GetBlendedTexture(gpatch, (GLPatch_t *)md2->blendgrpatch, skinnum, spr->colormap, (skincolors_t)spr->mobj->color);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -2138,7 +2138,7 @@ void HU_Drawer(void)
|
|||
if (!Playing()
|
||||
|| gamestate == GS_INTERMISSION || gamestate == GS_CUTSCENE
|
||||
|| gamestate == GS_CREDITS || gamestate == GS_EVALUATION
|
||||
|| gamestate == GS_GAMEEND)
|
||||
|| gamestate == GS_ENDING || gamestate == GS_GAMEEND)
|
||||
return;
|
||||
|
||||
// draw multiplayer rankings
|
||||
|
|
468
src/info.c
468
src/info.c
|
@ -90,6 +90,7 @@ char sprnames[NUMSPRITES + 1][5] =
|
|||
// Boss 4 (Castle Eggman)
|
||||
"EGGP",
|
||||
"EFIR", // Boss 4 jet flame
|
||||
"EGR1", // Boss 4 Spectator Eggrobo
|
||||
|
||||
// Boss 5 (Arid Canyon)
|
||||
"FANG", // replaces EGGQ
|
||||
|
@ -382,6 +383,7 @@ char sprnames[NUMSPRITES + 1][5] =
|
|||
"GFLG", // Got Flag sign
|
||||
|
||||
"CORK",
|
||||
"LHRT",
|
||||
|
||||
// Ring Weapons
|
||||
"RRNG", // Red Ring
|
||||
|
@ -475,6 +477,9 @@ char sprnames[NUMSPRITES + 1][5] =
|
|||
"ROIO",
|
||||
"ROIP",
|
||||
|
||||
// Bricks
|
||||
"BRIC",
|
||||
|
||||
// Gravity Well Objects
|
||||
"GWLG",
|
||||
"GWLR",
|
||||
|
@ -573,7 +578,8 @@ char spr2names[NUMPLAYERSPRITES][5] =
|
|||
"TALB",
|
||||
|
||||
"SIGN",
|
||||
"LIFE"
|
||||
"LIFE",
|
||||
"XTRA",
|
||||
};
|
||||
playersprite_t free_spr2 = SPR2_FIRSTFREESLOT;
|
||||
|
||||
|
@ -590,7 +596,7 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = {
|
|||
SPR2_DEAD, // SPR2_DRWN,
|
||||
0, // SPR2_ROLL,
|
||||
SPR2_SPNG, // SPR2_GASP,
|
||||
0, // SPR2_JUMP, (conditional)
|
||||
0, // SPR2_JUMP, (conditional, will never be referenced)
|
||||
SPR2_FALL, // SPR2_SPNG,
|
||||
SPR2_WALK, // SPR2_FALL,
|
||||
0, // SPR2_EDGE,
|
||||
|
@ -600,7 +606,7 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = {
|
|||
|
||||
SPR2_SPNG, // SPR2_FLY ,
|
||||
SPR2_FLY , // SPR2_SWIM,
|
||||
0, // SPR2_TIRE, (conditional)
|
||||
0, // SPR2_TIRE, (conditional, will never be referenced)
|
||||
|
||||
SPR2_FLY , // SPR2_GLID,
|
||||
SPR2_CLMB, // SPR2_CLNG,
|
||||
|
@ -627,7 +633,7 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = {
|
|||
SPR2_NSTN, // SPR2_NPUL,
|
||||
FF_SPR2SUPER|SPR2_ROLL, // SPR2_NATK,
|
||||
|
||||
0, // SPR2_NGT0, (should never be referenced)
|
||||
0, // SPR2_NGT0, (will never be referenced unless skin 0 lacks this)
|
||||
SPR2_NGT0, // SPR2_NGT1,
|
||||
SPR2_NGT1, // SPR2_NGT2,
|
||||
SPR2_NGT2, // SPR2_NGT3,
|
||||
|
@ -655,7 +661,7 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = {
|
|||
SPR2_NGTB, // SPR2_DRLB,
|
||||
SPR2_NGTC, // SPR2_DRLC,
|
||||
|
||||
0, // SPR2_TAL0,
|
||||
0, // SPR2_TAL0, (this will look mighty stupid but oh well)
|
||||
SPR2_TAL0, // SPR2_TAL1,
|
||||
SPR2_TAL1, // SPR2_TAL2,
|
||||
SPR2_TAL2, // SPR2_TAL3,
|
||||
|
@ -670,6 +676,7 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = {
|
|||
|
||||
0, // SPR2_SIGN,
|
||||
0, // SPR2_LIFE,
|
||||
0, // SPR2_XTRA (should never be referenced)
|
||||
};
|
||||
|
||||
// Doesn't work with g++, needs actionf_p1 (don't modify this comment)
|
||||
|
@ -742,10 +749,10 @@ state_t states[NUMSTATES] =
|
|||
{SPR_PLAY, SPR2_FIRE, 15, {NULL}, S_PLAY_STND, 0, S_PLAY_STND}, // S_PLAY_FIRE_FINISH
|
||||
|
||||
// CA_TWINSPIN
|
||||
{SPR_PLAY, SPR2_TWIN|FF_SPR2ENDSTATE, 1, {NULL}, S_PLAY_JUMP, 0, S_PLAY_TWINSPIN}, // S_PLAY_TWINSPIN
|
||||
{SPR_PLAY, SPR2_TWIN|FF_SPR2ENDSTATE, 2, {NULL}, S_PLAY_JUMP, 0, S_PLAY_TWINSPIN}, // S_PLAY_TWINSPIN
|
||||
|
||||
// CA2_MELEE
|
||||
{SPR_PLAY, SPR2_MLEE|FF_SPR2ENDSTATE, 1, {NULL}, S_PLAY_MELEE_FINISH, 0, S_PLAY_MELEE}, // S_PLAY_MELEE
|
||||
{SPR_PLAY, SPR2_MLEE|FF_SPR2ENDSTATE, 2, {NULL}, S_PLAY_MELEE_FINISH, 0, S_PLAY_MELEE}, // S_PLAY_MELEE
|
||||
{SPR_PLAY, SPR2_MLEE, 70, {NULL}, 0, 0, S_PLAY_FALL}, // S_PLAY_MELEE_FINISH
|
||||
{SPR_PLAY, SPR2_MLEL, 35, {NULL}, 0, 0, S_PLAY_WALK}, // S_PLAY_MELEE_LANDING
|
||||
|
||||
|
@ -1268,6 +1275,11 @@ state_t states[NUMSTATES] =
|
|||
|
||||
// Boss 3
|
||||
{SPR_EGGO, 0, 1, {NULL}, 0, 0, S_EGGMOBILE3_STND}, // S_EGGMOBILE3_STND
|
||||
{SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH2}, // S_EGGMOBILE3_LAUGH1
|
||||
{SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH3}, // S_EGGMOBILE3_LAUGH2
|
||||
{SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH4}, // S_EGGMOBILE3_LAUGH3
|
||||
{SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH5}, // S_EGGMOBILE3_LAUGH4
|
||||
{SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_ATK1}, // S_EGGMOBILE3_LAUGH5
|
||||
{SPR_EGGO, 1, 2, {NULL}, 0, 0, S_EGGMOBILE3_ATK2}, // S_EGGMOBILE3_ATK1
|
||||
{SPR_EGGO, 2, 2, {NULL}, 0, 0, S_EGGMOBILE3_ATK3A}, // S_EGGMOBILE3_ATK2
|
||||
{SPR_EGGO, 3, 2, {A_BossFireShot}, MT_TORPEDO, 2, S_EGGMOBILE3_ATK3B}, // S_EGGMOBILE3_ATK3A
|
||||
|
@ -1275,12 +1287,7 @@ state_t states[NUMSTATES] =
|
|||
{SPR_EGGO, 3, 2, {A_BossFireShot}, MT_TORPEDO, 3, S_EGGMOBILE3_ATK3D}, // S_EGGMOBILE3_ATK3C
|
||||
{SPR_EGGO, 3, 2, {A_BossFireShot}, MT_TORPEDO, 5, S_EGGMOBILE3_ATK4}, // S_EGGMOBILE3_ATK3D
|
||||
{SPR_EGGO, 4, 2, {NULL}, 0, 0, S_EGGMOBILE3_ATK5}, // S_EGGMOBILE3_ATK4
|
||||
{SPR_EGGO, 5, 2, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH1}, // S_EGGMOBILE3_ATK5
|
||||
{SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH2}, // S_EGGMOBILE3_LAUGH1
|
||||
{SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH3}, // S_EGGMOBILE3_LAUGH2
|
||||
{SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH4}, // S_EGGMOBILE3_LAUGH3
|
||||
{SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH5}, // S_EGGMOBILE3_LAUGH4
|
||||
{SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH6}, // S_EGGMOBILE3_LAUGH5
|
||||
{SPR_EGGO, 5, 2, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH6}, // S_EGGMOBILE3_ATK5
|
||||
{SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH7}, // S_EGGMOBILE3_LAUGH6
|
||||
{SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH8}, // S_EGGMOBILE3_LAUGH7
|
||||
{SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH9}, // S_EGGMOBILE3_LAUGH8
|
||||
|
@ -1327,14 +1334,14 @@ state_t states[NUMSTATES] =
|
|||
// Boss 3 Pinch
|
||||
{SPR_FAKE, 0, 1, {A_BossJetFume}, 1, 0, S_FAKEMOBILE}, // S_FAKEMOBILE_INIT
|
||||
{SPR_FAKE, 0, 1, {A_Boss3Path}, 0, 0, S_FAKEMOBILE}, // S_FAKEMOBILE
|
||||
{SPR_FAKE, 0, 2, {NULL}, 0, 0, S_FAKEMOBILE_ATK2}, // S_FAKEMOBILE_ATK1
|
||||
{SPR_FAKE, 0, 22, {NULL}, 0, 0, S_FAKEMOBILE_ATK2}, // S_FAKEMOBILE_ATK1
|
||||
{SPR_FAKE, 0, 2, {NULL}, 0, 0, S_FAKEMOBILE_ATK3A}, // S_FAKEMOBILE_ATK2
|
||||
{SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 2, S_FAKEMOBILE_ATK3B}, // S_FAKEMOBILE_ATK3A
|
||||
{SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 4, S_FAKEMOBILE_ATK3C}, // S_FAKEMOBILE_ATK3B
|
||||
{SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 3, S_FAKEMOBILE_ATK3D}, // S_FAKEMOBILE_ATK3C
|
||||
{SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 5, S_FAKEMOBILE_ATK4}, // S_FAKEMOBILE_ATK3D
|
||||
{SPR_FAKE, 0, 2, {NULL}, 0, 0, S_FAKEMOBILE_ATK5}, // S_FAKEMOBILE_ATK4
|
||||
{SPR_FAKE, 0, 2, {NULL}, 0, 0, S_FAKEMOBILE}, // S_FAKEMOBILE_ATK5
|
||||
{SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 5, S_FAKEMOBILE}, // S_FAKEMOBILE_ATK3D
|
||||
{SPR_FAKE, 0, 1, {NULL}, 0, 0, S_FAKEMOBILE_DIE2}, // S_FAKEMOBILE_DIE1
|
||||
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_FAKEMOBILE_DIE1}, // S_FAKEMOBILE_DIE2
|
||||
|
||||
// Boss 4
|
||||
{SPR_EGGP, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGMOBILE4_STND
|
||||
|
@ -1351,16 +1358,9 @@ state_t states[NUMSTATES] =
|
|||
{SPR_EGGP, 9,150, {A_Boss4SpeedUp}, sfx_mswing, 0, S_EGGMOBILE4_RATK6}, // S_EGGMOBILE4_RATK5
|
||||
{SPR_EGGP,10, 2, {NULL}, 0, 0, S_EGGMOBILE4_STND}, // S_EGGMOBILE4_RATK6
|
||||
{SPR_EGGP, 0, 20, {A_Boss4Raise}, sfx_doord1, 0, S_EGGMOBILE4_RAISE2}, // S_EGGMOBILE4_RAISE1
|
||||
{SPR_EGGP,13, 10, {NULL}, 0, 0, S_EGGMOBILE4_RAISE3}, // S_EGGMOBILE4_RAISE2
|
||||
{SPR_EGGP,14, 10, {NULL}, 0, 0, S_EGGMOBILE4_RAISE4}, // S_EGGMOBILE4_RAISE3
|
||||
{SPR_EGGP,13, 10, {NULL}, 0, 0, S_EGGMOBILE4_RAISE5}, // S_EGGMOBILE4_RAISE4
|
||||
{SPR_EGGP,14, 10, {NULL}, 0, 0, S_EGGMOBILE4_RAISE6}, // S_EGGMOBILE4_RAISE5
|
||||
{SPR_EGGP,13, 10, {NULL}, 0, 0, S_EGGMOBILE4_RAISE7}, // S_EGGMOBILE4_RAISE6
|
||||
{SPR_EGGP,14, 10, {NULL}, 0, 0, S_EGGMOBILE4_RAISE8}, // S_EGGMOBILE4_RAISE7
|
||||
{SPR_EGGP,13, 10, {NULL}, 0, 0, S_EGGMOBILE4_RAISE9}, // S_EGGMOBILE4_RAISE8
|
||||
{SPR_EGGP,14, 10, {NULL}, 0, 0, S_EGGMOBILE4_RAISE10},// S_EGGMOBILE4_RAISE9
|
||||
{SPR_EGGP,13, 10, {NULL}, 0, 0, S_EGGMOBILE4_STND}, // S_EGGMOBILE4_RAISE10
|
||||
{SPR_EGGP,11, 24, {A_Pain}, 0, 0, S_EGGMOBILE4_STND}, // S_EGGMOBILE4_PAIN
|
||||
{SPR_EGGP,13|FF_ANIMATE, -1, {NULL}, 1, 10, S_NULL}, // S_EGGMOBILE4_RAISE2
|
||||
{SPR_EGGP,11, 0, {A_Boss4Reverse}, sfx_alarm, sfx_s3k60, S_EGGMOBILE4_PAIN2}, // S_EGGMOBILE4_PAIN1
|
||||
{SPR_EGGP,11, 24, {A_Pain}, 0, 0, S_EGGMOBILE4_STND}, // S_EGGMOBILE4_PAIN2
|
||||
{SPR_EGGP,12, 8, {A_Fall}, 0, 0, S_EGGMOBILE4_DIE2}, // S_EGGMOBILE4_DIE1
|
||||
{SPR_EGGP,12, 8, {A_BossScream}, 0, 0, S_EGGMOBILE4_DIE3}, // S_EGGMOBILE4_DIE2
|
||||
{SPR_EGGP,12, 8, {A_BossScream}, 0, 0, S_EGGMOBILE4_DIE4}, // S_EGGMOBILE4_DIE3
|
||||
|
@ -1378,10 +1378,21 @@ state_t states[NUMSTATES] =
|
|||
{SPR_EGGP,13, 5, {NULL}, 0, 0, S_EGGMOBILE4_FLEE2}, // S_EGGMOBILE4_FLEE1
|
||||
{SPR_EGGP,14, 5, {NULL}, 0, 0, S_EGGMOBILE4_FLEE1}, // S_EGGMOBILE4_FLEE2
|
||||
{SPR_BMCE, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGMOBILE4_MACE
|
||||
{SPR_BMCE, 0, 2, {A_BossScream}, 1, MT_SONIC3KBOSSEXPLODE, S_EGGMOBILE4_MACE_DIE2}, // S_EGGMOBILE4_MACE_DIE1
|
||||
{SPR_NULL, 0, 2, {A_BossScream}, 1, MT_SONIC3KBOSSEXPLODE, S_EGGMOBILE4_MACE_DIE3}, // S_EGGMOBILE4_MACE_DIE2
|
||||
{SPR_NULL, 0, 0, {A_Repeat}, 7, S_EGGMOBILE4_MACE_DIE1, S_BOSSEXPLODE}, // S_EGGMOBILE4_MACE_DIE3
|
||||
|
||||
// Boss 4 Jet flame
|
||||
{SPR_EFIR, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_JETFLAME2}, // S_JETFLAME1
|
||||
{SPR_EFIR, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_JETFLAME1}, // S_JETFLAME2
|
||||
// Boss 4 jet flame
|
||||
{SPR_EFIR, FF_FULLBRIGHT|FF_ANIMATE, -1, {NULL}, 1, 1, S_NULL}, // S_JETFLAME
|
||||
|
||||
// Boss 4 Spectator Eggrobo
|
||||
{SPR_EGR1, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGROBO1_STND
|
||||
{SPR_EGR1, 5, 2, {NULL}, 0, 0, S_EGGROBO1_BSLAP2}, // S_EGGROBO1_BSLAP1
|
||||
{SPR_EGR1, FF_ANIMATE|6, 35, {NULL}, 1, 2, S_EGGROBO1_STND}, // S_EGGROBO1_BSLAP2
|
||||
{SPR_EGR1, FF_ANIMATE|3, -1, {NULL}, 1, 2, S_NULL}, // S_EGGROBO1_PISSED
|
||||
|
||||
// Boss 4 Spectator Eggrobo jet flame
|
||||
{SPR_EFIR, FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_NULL}, // S_EGGROBOJET
|
||||
|
||||
// Boss 5
|
||||
{SPR_FANG, 2, 16, {A_Look}, 1, 0, S_FANG_IDLE2}, // S_FANG_IDLE1
|
||||
|
@ -1746,20 +1757,23 @@ state_t states[NUMSTATES] =
|
|||
{SPR_METL, 9, 2, {NULL}, 0, 0, S_METALSONIC_RUN1}, // S_METALSONIC_RUN4
|
||||
|
||||
{SPR_METL, 4, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_FLOAT
|
||||
{SPR_METL, 12, -1, {NULL}, 0, 0, S_METALSONIC_STUN}, // S_METALSONIC_VECTOR
|
||||
{SPR_METL, 0, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_STUN
|
||||
{SPR_METL, 13, 40, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_RAISE
|
||||
{SPR_METL, 12|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_METALSONIC_STUN}, // S_METALSONIC_VECTOR
|
||||
{SPR_METL, 11, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_STUN
|
||||
{SPR_METL, 13, 20, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_RAISE
|
||||
{SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_GATHER
|
||||
{SPR_METL, 15, -1, {NULL}, 0, 0, S_METALSONIC_BOUNCE},// S_METALSONIC_DASH
|
||||
{SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BOUNCE
|
||||
{SPR_METL, 16, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BADBOUNCE
|
||||
{SPR_METL, 13, -1, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_SHOOT
|
||||
{SPR_METL, 11, 40, {A_Pain}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_PAIN
|
||||
{SPR_METL, 11, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_METALSONIC_DEATH
|
||||
{SPR_METL, 3, 4, {NULL}, 0, 0, S_METALSONIC_FLEE2}, // S_METALSONIC_FLEE1
|
||||
{SPR_METL, 4, 4, {A_BossScream}, 0, 0, S_METALSONIC_FLEE3}, // S_METALSONIC_FLEE2
|
||||
{SPR_METL, 5, 4, {NULL}, 0, 0, S_METALSONIC_FLEE4}, // S_METALSONIC_FLEE3
|
||||
{SPR_METL, 4, 4, {NULL}, 0, 0, S_METALSONIC_FLEE1}, // S_METALSONIC_FLEE4
|
||||
{SPR_METL, 13, 8, {A_Fall}, 0, 0, S_METALSONIC_DEATH2},// S_METALSONIC_DEATH1
|
||||
{SPR_METL, 13, 8, {A_BossScream}, 0, 0, S_METALSONIC_DEATH3},// S_METALSONIC_DEATH2
|
||||
{SPR_METL, 13, 0, {A_Repeat}, 11, S_METALSONIC_DEATH2, S_METALSONIC_DEATH4}, // S_METALSONIC_DEATH3
|
||||
{SPR_METL, 13, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_METALSONIC_DEATH4
|
||||
{SPR_METL, 11, 4, {NULL}, 0, 0, S_METALSONIC_FLEE2}, // S_METALSONIC_FLEE1
|
||||
{SPR_METL, 11, 4, {A_BossScream}, 0, 0, S_METALSONIC_FLEE3}, // S_METALSONIC_FLEE2
|
||||
{SPR_METL, 11, 4, {NULL}, 0, 0, S_METALSONIC_FLEE4}, // S_METALSONIC_FLEE3
|
||||
{SPR_METL, 11, 4, {NULL}, 0, 0, S_METALSONIC_FLEE1}, // S_METALSONIC_FLEE4
|
||||
|
||||
{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 0, 1, {NULL}, 0, 0, S_MSSHIELD_F2}, // S_MSSHIELD_F1
|
||||
{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 1, 1, {NULL}, 0, 0, S_MSSHIELD_F3}, // S_MSSHIELD_F2
|
||||
|
@ -1779,7 +1793,11 @@ state_t states[NUMSTATES] =
|
|||
|
||||
// Blue Sphere for special stages
|
||||
{SPR_SPHR, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_BLUESPHERE
|
||||
{SPR_SPHR, FF_FULLBRIGHT|FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 1, 4, S_NULL}, // S_BLUESPHEREBONUS
|
||||
{SPR_SPHR, FF_FULLBRIGHT
|
||||
#ifdef MANIASPHERES
|
||||
|FF_ANIMATE|FF_RANDOMANIM
|
||||
#endif
|
||||
, -1, {NULL}, 1, 4, S_NULL}, // S_BLUESPHEREBONUS
|
||||
{SPR_SPHR, 0, 20, {NULL}, 0, 0, S_NULL}, // S_BLUESPHERESPARK
|
||||
|
||||
// Bomb Sphere
|
||||
|
@ -2310,9 +2328,10 @@ state_t states[NUMSTATES] =
|
|||
{SPR_BFBR, FF_FULLBRIGHT|15, 1, {NULL}, 0, 0, S_BIGFIREBAR1}, // S_BIGFIREBAR16
|
||||
|
||||
{SPR_FWR4, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZFLOWER
|
||||
{SPR_BANR, 1, -1, {NULL}, 0, 0, S_NULL}, // S_CEZPOLE
|
||||
{SPR_BANR, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZPOLE
|
||||
|
||||
{SPR_BANR, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_CEZBANNER
|
||||
{SPR_BANR, FF_PAPERSPRITE|1, -1, {NULL}, 0, 0, S_NULL}, // S_CEZBANNER1
|
||||
{SPR_BANR, FF_PAPERSPRITE|2, -1, {NULL}, 0, 0, S_NULL}, // S_CEZBANNER2
|
||||
|
||||
{SPR_PINE, 0, -1, {NULL}, 0, 0, S_NULL}, // S_PINETREE
|
||||
{SPR_CEZB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZBUSH1
|
||||
|
@ -2326,7 +2345,8 @@ state_t states[NUMSTATES] =
|
|||
{SPR_CTRC, FF_FULLBRIGHT|FF_ANIMATE, 8*3, {A_FlameParticle}, 3, 3, S_FIRETORCH}, // S_FIRETORCH
|
||||
|
||||
{SPR_CFLG, 0, -1, {NULL}, 0, 0, S_NULL}, // S_WAVINGFLAG
|
||||
{SPR_CFLG, FF_PAPERSPRITE|1, -1, {NULL}, 0, 0, S_NULL}, // S_WAVINGFLAGSEG
|
||||
{SPR_CFLG, FF_PAPERSPRITE|1, -1, {NULL}, 0, 0, S_NULL}, // S_WAVINGFLAGSEG1
|
||||
{SPR_CFLG, FF_PAPERSPRITE|2, -1, {NULL}, 0, 0, S_NULL}, // S_WAVINGFLAGSEG2
|
||||
|
||||
{SPR_CSTA, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CRAWLASTATUE
|
||||
|
||||
|
@ -2803,12 +2823,18 @@ state_t states[NUMSTATES] =
|
|||
{SPR_ELEM, FF_FULLBRIGHT|20, 1, {NULL}, 0, 0, S_ELEMF10}, // S_ELEMF9
|
||||
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_ELEMF1 }, // S_ELEMF10
|
||||
|
||||
{SPR_PITY, FF_TRANS30 , 2, {NULL}, 0, 0, S_PITY2}, // S_PITY1
|
||||
{SPR_PITY, FF_TRANS30|1, 2, {NULL}, 0, 0, S_PITY3}, // S_PITY2
|
||||
{SPR_PITY, FF_TRANS30|2, 2, {NULL}, 0, 0, S_PITY4}, // S_PITY3
|
||||
{SPR_PITY, FF_TRANS20|3, 2, {NULL}, 0, 0, S_PITY5}, // S_PITY4
|
||||
{SPR_PITY, FF_TRANS30|4, 2, {NULL}, 0, 0, S_PITY6}, // S_PITY5
|
||||
{SPR_PITY, FF_TRANS20|5, 2, {NULL}, 0, 0, S_PITY1}, // S_PITY6
|
||||
{SPR_PITY, FF_TRANS30 , 2, {NULL}, 0, 0, S_PITY2}, // S_PITY1
|
||||
{SPR_PITY, FF_TRANS30| 1, 2, {NULL}, 0, 0, S_PITY3}, // S_PITY2
|
||||
{SPR_PITY, FF_TRANS30| 2, 2, {NULL}, 0, 0, S_PITY4}, // S_PITY3
|
||||
{SPR_PITY, FF_TRANS30| 3, 2, {NULL}, 0, 0, S_PITY5}, // S_PITY4
|
||||
{SPR_PITY, FF_TRANS30| 4, 2, {NULL}, 0, 0, S_PITY6}, // S_PITY5
|
||||
{SPR_PITY, FF_TRANS30| 5, 2, {NULL}, 0, 0, S_PITY7}, // S_PITY6
|
||||
{SPR_PITY, FF_TRANS30| 6, 2, {NULL}, 0, 0, S_PITY8}, // S_PITY7
|
||||
{SPR_PITY, FF_TRANS30| 7, 2, {NULL}, 0, 0, S_PITY9}, // S_PITY8
|
||||
{SPR_PITY, FF_TRANS30| 8, 2, {NULL}, 0, 0, S_PITY10}, // S_PITY9
|
||||
{SPR_PITY, FF_TRANS30| 9, 2, {NULL}, 0, 0, S_PITY11}, // S_PITY10
|
||||
{SPR_PITY, FF_TRANS30|10, 2, {NULL}, 0, 0, S_PITY12}, // S_PITY11
|
||||
{SPR_PITY, FF_TRANS30|11, 2, {NULL}, 0, 0, S_PITY1}, // S_PITY12
|
||||
|
||||
{SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40 , 2, {NULL}, 0, 0, S_FIRS2}, // S_FIRS1
|
||||
{SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|1, 2, {NULL}, 0, 0, S_FIRS3}, // S_FIRS2
|
||||
|
@ -2886,7 +2912,7 @@ state_t states[NUMSTATES] =
|
|||
{SPR_NULL, 0, 15*2, {NULL}, 0, 0, S_ZAPSB2 }, // S_ZAPSB11
|
||||
|
||||
// Thunder spark
|
||||
{SPR_SSPK, FF_ANIMATE, 18, {NULL}, 1, 2, S_NULL}, // S_THUNDERCOIN_SPARK
|
||||
{SPR_SSPK, FF_ANIMATE, -1, {NULL}, 1, 2, S_NULL}, // S_THUNDERCOIN_SPARK
|
||||
|
||||
// Invincibility Sparkles
|
||||
{SPR_IVSP, FF_ANIMATE, 32, {NULL}, 31, 1, S_NULL}, // S_IVSP
|
||||
|
@ -3187,8 +3213,8 @@ state_t states[NUMSTATES] =
|
|||
{SPR_SSWB, 1, 1, {NULL}, 0, 0, S_BHORIZ1}, // S_BHORIZ8
|
||||
|
||||
// Rain
|
||||
{SPR_RAIN, FF_TRANS50, -1, {NULL}, 0, 0, S_NULL}, // S_RAIN1
|
||||
{SPR_RAIN, FF_TRANS50, 1, {NULL}, 0, 0, S_RAIN1}, // S_RAINRETURN
|
||||
{SPR_RAIN, FF_FULLBRIGHT|FF_TRANS50, -1, {NULL}, 0, 0, S_NULL}, // S_RAIN1
|
||||
{SPR_RAIN, FF_FULLBRIGHT|FF_TRANS50, 1, {NULL}, 0, 0, S_RAIN1}, // S_RAINRETURN
|
||||
|
||||
// Snowflake
|
||||
{SPR_SNO1, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SNOW1
|
||||
|
@ -3298,13 +3324,21 @@ state_t states[NUMSTATES] =
|
|||
|
||||
{SPR_LCKN, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_LOCKON1
|
||||
{SPR_LCKN, 1|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_LOCKON2
|
||||
{SPR_LCKN, 2|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_LOCKON3
|
||||
{SPR_LCKN, 3|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_LOCKON4
|
||||
|
||||
{SPR_LCKN, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_LOCKONINF1
|
||||
{SPR_LCKN, 1|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_LOCKONINF2
|
||||
{SPR_LCKN, 2|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_LOCKONINF3
|
||||
{SPR_LCKN, 3|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_LOCKONINF4
|
||||
|
||||
{SPR_TTAG, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_TTAG
|
||||
|
||||
// CTF Sign
|
||||
{SPR_GFLG, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_GOTFLAG
|
||||
|
||||
{SPR_CORK, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CORK
|
||||
{SPR_CORK, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CORK
|
||||
{SPR_LHRT, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_LHRT
|
||||
|
||||
// Red Rings (thrown)
|
||||
{SPR_RRNG, FF_FULLBRIGHT, 1, {A_ThrownRing}, 0, 0, S_RRNG2}, // S_RRNG1
|
||||
|
@ -3861,6 +3895,8 @@ state_t states[NUMSTATES] =
|
|||
{SPR_ROIO, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 4, 2, S_NULL}, // S_ROCKCRUMBLEO
|
||||
{SPR_ROIP, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 4, 2, S_NULL}, // S_ROCKCRUMBLEP
|
||||
|
||||
{SPR_BRIC, FF_ANIMATE, -1, {A_DebrisRandom}, 7, 2, S_NULL}, // S_BRICKDEBRIS
|
||||
|
||||
#ifdef SEENAMES
|
||||
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK
|
||||
#endif
|
||||
|
@ -5500,7 +5536,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
MT_PROPELLER, // painchance
|
||||
sfx_dmpain, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_EGGMOBILE3_ATK1, // missilestate
|
||||
S_EGGMOBILE3_LAUGH1,// missilestate
|
||||
S_EGGMOBILE3_DIE1, // deathstate
|
||||
S_EGGMOBILE3_FLEE1, // xdeathstate
|
||||
sfx_cybdth, // deathsound
|
||||
|
@ -5555,9 +5591,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
sfx_s3k7b, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_FAKEMOBILE_ATK1, // missilestate
|
||||
S_XPLD1, // deathstate
|
||||
S_FAKEMOBILE_DIE1, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_pop, // deathsound
|
||||
sfx_mswarp, // deathsound
|
||||
8*FRACUNIT, // speed
|
||||
32*FRACUNIT, // radius
|
||||
116*FRACUNIT, // height
|
||||
|
@ -5569,6 +5605,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_SHOCK
|
||||
-1, // doomednum
|
||||
S_THUNDERCOIN_SPARK, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
0, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_SPRK1, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
10*FRACUNIT, // speed
|
||||
16*FRACUNIT, // radius
|
||||
35*FRACUNIT, // height
|
||||
0, // display offset
|
||||
DMG_ELECTRIC|(sfx_buzz2<<8), // mass
|
||||
20, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_MISSILE|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_EGGMOBILE4
|
||||
203, // doomednum
|
||||
S_EGGMOBILE4_STND, // spawnstate
|
||||
|
@ -5577,7 +5640,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
sfx_None, // seesound
|
||||
0, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_EGGMOBILE4_PAIN, // painstate
|
||||
S_EGGMOBILE4_PAIN1,// painstate
|
||||
0, // painchance
|
||||
sfx_dmpain, // painsound
|
||||
S_EGGMOBILE4_LATK1,// meleestate
|
||||
|
@ -5609,9 +5672,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_BOSSEXPLODE, // deathstate
|
||||
S_EGGMOBILE4_MACE_DIE1, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_cybdth, // deathsound
|
||||
sfx_None, // deathsound
|
||||
48*FRACUNIT, // speed
|
||||
34*FRACUNIT, // radius
|
||||
68*FRACUNIT, // height
|
||||
|
@ -5625,7 +5688,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
|
||||
{ // MT_JETFLAME
|
||||
-1, // doomednum
|
||||
S_JETFLAME1, // spawnstate
|
||||
S_JETFLAME, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
|
@ -5646,7 +5709,61 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
DMG_FIRE, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOGRAVITY|MF_PAIN|MF_FIRE, // flags
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_EGGROBO1
|
||||
1127, // doomednum
|
||||
S_EGGROBO1_STND,// spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_s3ka0, // seesound
|
||||
8, // reactiontime
|
||||
sfx_bsnipe, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_EGGROBO1_BSLAP1, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_EGGROBO1_PISSED, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_s3ka0, // deathsound
|
||||
12*FRACUNIT, // speed
|
||||
20*FRACUNIT, // radius
|
||||
72*FRACUNIT, // height
|
||||
0, // display offset
|
||||
0, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_EGGROBOJET
|
||||
-1, // doomednum
|
||||
S_EGGROBOJET, // 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
|
||||
1, // speed
|
||||
10*FRACUNIT, // radius
|
||||
28*FRACUNIT, // height
|
||||
0, // display offset
|
||||
0, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
@ -5673,7 +5790,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
0, // mass
|
||||
3, // damage
|
||||
sfx_boingf, // activesound
|
||||
MF_SPECIAL|MF_BOSS|MF_SHOOTABLE, // flags
|
||||
MF_SPECIAL|MF_BOSS|MF_SHOOTABLE|MF_GRENADEBOUNCE, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
@ -6251,13 +6368,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_METALSONIC_DASH, // seestate
|
||||
sfx_s3k54, // seesound
|
||||
0, // reactiontime
|
||||
sfx_trpowr, // attacksound
|
||||
sfx_bechrg, // attacksound
|
||||
S_METALSONIC_PAIN, // painstate
|
||||
S_METALSONIC_VECTOR,// painchance
|
||||
sfx_dmpain, // painsound
|
||||
S_METALSONIC_BADBOUNCE, // meleestate
|
||||
S_METALSONIC_SHOOT, // missilestate
|
||||
S_METALSONIC_DEATH, // deathstate
|
||||
S_METALSONIC_DEATH1,// deathstate
|
||||
S_METALSONIC_FLEE1, // xdeathstate
|
||||
sfx_s3k6e, // deathsound
|
||||
MT_ENERGYBALL, // speed
|
||||
|
@ -6289,7 +6406,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
sfx_None, // deathsound
|
||||
0, // speed
|
||||
32*FRACUNIT, // radius
|
||||
64*FRACUNIT, // height
|
||||
52*FRACUNIT, // height
|
||||
0, // display offset
|
||||
0, // mass
|
||||
0, // damage
|
||||
|
@ -7383,7 +7500,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_s3k64, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_WALLSPIKE4, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_WALLSPIKED1, // deathstate
|
||||
S_WALLSPIKED2, // xdeathstate
|
||||
|
@ -9086,7 +9203,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_MINE_BOOM1, // deathstate
|
||||
S_XPLD1, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_cybdth, // deathsound
|
||||
20*FRACUNIT, // speed
|
||||
|
@ -9113,7 +9230,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_MINE_BOOM1, // deathstate
|
||||
S_XPLD1, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_cybdth, // deathsound
|
||||
20*FRACUNIT, // speed
|
||||
|
@ -9132,7 +9249,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_ENERGYBALL1, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_s3k54, // seesound
|
||||
sfx_bexpld, // seesound
|
||||
8, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
|
@ -10909,7 +11026,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_CEZPOLE
|
||||
{ // MT_CEZPOLE1
|
||||
1117, // doomednum
|
||||
S_CEZPOLE, // spawnstate
|
||||
1000, // spawnhealth
|
||||
|
@ -10936,9 +11053,63 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_CEZBANNER
|
||||
{ // MT_CEZPOLE2
|
||||
1118, // doomednum
|
||||
S_CEZPOLE, // 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
|
||||
40*FRACUNIT, // radius
|
||||
224*FRACUNIT, // height
|
||||
0, // display offset
|
||||
100, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_CEZBANNER1
|
||||
-1, // doomednum
|
||||
S_CEZBANNER, // spawnstate
|
||||
S_CEZBANNER1, // 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
|
||||
40*FRACUNIT, // radius
|
||||
224*FRACUNIT, // height
|
||||
0, // display offset
|
||||
100, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_CEZBANNER2
|
||||
-1, // doomednum
|
||||
S_CEZBANNER2, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
|
@ -11152,8 +11323,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_WAVINGFLAG
|
||||
1118, // doomednum
|
||||
{ // MT_WAVINGFLAG1
|
||||
1128, // doomednum
|
||||
S_WAVINGFLAG, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
|
@ -11169,8 +11340,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
0, // speed
|
||||
4*FRACUNIT, // radius
|
||||
104*FRACUNIT, // height
|
||||
8*FRACUNIT, // radius
|
||||
208*FRACUNIT, // height
|
||||
0, // display offset
|
||||
100, // mass
|
||||
0, // damage
|
||||
|
@ -11179,9 +11350,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_WAVINGFLAGSEG
|
||||
-1, // doomednum
|
||||
S_WAVINGFLAGSEG, // spawnstate
|
||||
{ // MT_WAVINGFLAG2
|
||||
1129, // doomednum
|
||||
S_WAVINGFLAG, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
|
@ -11196,7 +11367,61 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
0, // speed
|
||||
4*FRACUNIT, // radius
|
||||
8*FRACUNIT, // radius
|
||||
208*FRACUNIT, // height
|
||||
0, // display offset
|
||||
100, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SOLID, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_WAVINGFLAGSEG1
|
||||
-1, // doomednum
|
||||
S_WAVINGFLAGSEG1, // 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
|
||||
8*FRACUNIT, // radius
|
||||
1, // height -- this is not a typo
|
||||
0, // display offset
|
||||
100, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_WAVINGFLAGSEG2
|
||||
-1, // doomednum
|
||||
S_WAVINGFLAGSEG2, // 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
|
||||
8*FRACUNIT, // radius
|
||||
1, // height -- this is not a typo
|
||||
0, // display offset
|
||||
100, // mass
|
||||
|
@ -16113,7 +16338,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
-24*FRACUNIT, // speed
|
||||
-72*FRACUNIT, // speed
|
||||
1*FRACUNIT, // radius
|
||||
8*FRACUNIT, // height
|
||||
0, // display offset
|
||||
|
@ -16529,6 +16754,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_LOCKONINF
|
||||
1126, // doomednum
|
||||
S_INVISIBLE, // 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
|
||||
16*FRACUNIT, // radius
|
||||
32*FRACUNIT, // height
|
||||
111, // display offset
|
||||
16, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_TAG
|
||||
-1, // doomednum
|
||||
S_TTAG, // spawnstate
|
||||
|
@ -16915,6 +17167,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_LHRT
|
||||
-1, // doomednum
|
||||
S_LHRT, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
0, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_SPRK1, // deathstate
|
||||
S_SPRK1, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
60*FRACUNIT, // speed
|
||||
16*FRACUNIT, // radius
|
||||
16*FRACUNIT, // height
|
||||
0, // display offset
|
||||
0, // mass
|
||||
1, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_MISSILE, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_REDRING
|
||||
-1, // doomednum
|
||||
S_RRNG1, // spawnstate
|
||||
|
@ -19479,7 +19758,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
0, // display offset
|
||||
100, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
sfx_wbreak, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_RUNSPAWNFUNC|MF_NOCLIPHEIGHT|MF_SCENERY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
@ -19970,6 +20249,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_BRICKDEBRIS
|
||||
-1, // doomednum
|
||||
S_BRICKDEBRIS, // spawnstate
|
||||
1, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
0, // 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
|
||||
16*FRACUNIT, // radius
|
||||
16*FRACUNIT, // height
|
||||
0, // display offset
|
||||
100, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_RUNSPAWNFUNC|MF_NOCLIPHEIGHT|MF_SCENERY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
#ifdef SEENAMES
|
||||
{ // MT_NAMECHECK
|
||||
-1, // doomednum
|
||||
|
|
93
src/info.h
93
src/info.h
|
@ -335,6 +335,7 @@ typedef enum sprite
|
|||
// Boss 4 (Castle Eggman)
|
||||
SPR_EGGP,
|
||||
SPR_EFIR, // Boss 4 jet flame
|
||||
SPR_EGR1, // Boss 4 Spectator Eggrobo
|
||||
|
||||
// Boss 5 (Arid Canyon)
|
||||
SPR_FANG, // replaces EGGQ
|
||||
|
@ -627,6 +628,7 @@ typedef enum sprite
|
|||
SPR_GFLG, // Got Flag sign
|
||||
|
||||
SPR_CORK,
|
||||
SPR_LHRT,
|
||||
|
||||
// Ring Weapons
|
||||
SPR_RRNG, // Red Ring
|
||||
|
@ -720,6 +722,9 @@ typedef enum sprite
|
|||
SPR_ROIO,
|
||||
SPR_ROIP,
|
||||
|
||||
// Bricks
|
||||
SPR_BRIC,
|
||||
|
||||
// Gravity Well Objects
|
||||
SPR_GWLG,
|
||||
SPR_GWLR,
|
||||
|
@ -829,6 +834,7 @@ typedef enum playersprite
|
|||
|
||||
SPR2_SIGN, // end sign head
|
||||
SPR2_LIFE, // life monitor icon
|
||||
SPR2_XTRA, // stuff that isn't in-game - keep this last in the list
|
||||
|
||||
SPR2_FIRSTFREESLOT,
|
||||
SPR2_LASTFREESLOT = 0x7f,
|
||||
|
@ -1421,6 +1427,11 @@ typedef enum state
|
|||
|
||||
// Boss 3
|
||||
S_EGGMOBILE3_STND,
|
||||
S_EGGMOBILE3_LAUGH1,
|
||||
S_EGGMOBILE3_LAUGH2,
|
||||
S_EGGMOBILE3_LAUGH3,
|
||||
S_EGGMOBILE3_LAUGH4,
|
||||
S_EGGMOBILE3_LAUGH5,
|
||||
S_EGGMOBILE3_ATK1,
|
||||
S_EGGMOBILE3_ATK2,
|
||||
S_EGGMOBILE3_ATK3A,
|
||||
|
@ -1429,11 +1440,6 @@ typedef enum state
|
|||
S_EGGMOBILE3_ATK3D,
|
||||
S_EGGMOBILE3_ATK4,
|
||||
S_EGGMOBILE3_ATK5,
|
||||
S_EGGMOBILE3_LAUGH1,
|
||||
S_EGGMOBILE3_LAUGH2,
|
||||
S_EGGMOBILE3_LAUGH3,
|
||||
S_EGGMOBILE3_LAUGH4,
|
||||
S_EGGMOBILE3_LAUGH5,
|
||||
S_EGGMOBILE3_LAUGH6,
|
||||
S_EGGMOBILE3_LAUGH7,
|
||||
S_EGGMOBILE3_LAUGH8,
|
||||
|
@ -1486,8 +1492,8 @@ typedef enum state
|
|||
S_FAKEMOBILE_ATK3B,
|
||||
S_FAKEMOBILE_ATK3C,
|
||||
S_FAKEMOBILE_ATK3D,
|
||||
S_FAKEMOBILE_ATK4,
|
||||
S_FAKEMOBILE_ATK5,
|
||||
S_FAKEMOBILE_DIE1,
|
||||
S_FAKEMOBILE_DIE2,
|
||||
|
||||
// Boss 4
|
||||
S_EGGMOBILE4_STND,
|
||||
|
@ -1505,15 +1511,8 @@ typedef enum state
|
|||
S_EGGMOBILE4_RATK6,
|
||||
S_EGGMOBILE4_RAISE1,
|
||||
S_EGGMOBILE4_RAISE2,
|
||||
S_EGGMOBILE4_RAISE3,
|
||||
S_EGGMOBILE4_RAISE4,
|
||||
S_EGGMOBILE4_RAISE5,
|
||||
S_EGGMOBILE4_RAISE6,
|
||||
S_EGGMOBILE4_RAISE7,
|
||||
S_EGGMOBILE4_RAISE8,
|
||||
S_EGGMOBILE4_RAISE9,
|
||||
S_EGGMOBILE4_RAISE10,
|
||||
S_EGGMOBILE4_PAIN,
|
||||
S_EGGMOBILE4_PAIN1,
|
||||
S_EGGMOBILE4_PAIN2,
|
||||
S_EGGMOBILE4_DIE1,
|
||||
S_EGGMOBILE4_DIE2,
|
||||
S_EGGMOBILE4_DIE3,
|
||||
|
@ -1531,10 +1530,21 @@ typedef enum state
|
|||
S_EGGMOBILE4_FLEE1,
|
||||
S_EGGMOBILE4_FLEE2,
|
||||
S_EGGMOBILE4_MACE,
|
||||
S_EGGMOBILE4_MACE_DIE1,
|
||||
S_EGGMOBILE4_MACE_DIE2,
|
||||
S_EGGMOBILE4_MACE_DIE3,
|
||||
|
||||
// Boss 4 jet flame
|
||||
S_JETFLAME1,
|
||||
S_JETFLAME2,
|
||||
S_JETFLAME,
|
||||
|
||||
// Boss 4 Spectator Eggrobo
|
||||
S_EGGROBO1_STND,
|
||||
S_EGGROBO1_BSLAP1,
|
||||
S_EGGROBO1_BSLAP2,
|
||||
S_EGGROBO1_PISSED,
|
||||
|
||||
// Boss 4 Spectator Eggrobo jet flame
|
||||
S_EGGROBOJET,
|
||||
|
||||
// Boss 5
|
||||
S_FANG_IDLE1,
|
||||
|
@ -1887,7 +1897,10 @@ typedef enum state
|
|||
S_METALSONIC_BADBOUNCE,
|
||||
S_METALSONIC_SHOOT,
|
||||
S_METALSONIC_PAIN,
|
||||
S_METALSONIC_DEATH,
|
||||
S_METALSONIC_DEATH1,
|
||||
S_METALSONIC_DEATH2,
|
||||
S_METALSONIC_DEATH3,
|
||||
S_METALSONIC_DEATH4,
|
||||
S_METALSONIC_FLEE1,
|
||||
S_METALSONIC_FLEE2,
|
||||
S_METALSONIC_FLEE3,
|
||||
|
@ -2446,7 +2459,8 @@ typedef enum state
|
|||
|
||||
S_CEZFLOWER,
|
||||
S_CEZPOLE,
|
||||
S_CEZBANNER,
|
||||
S_CEZBANNER1,
|
||||
S_CEZBANNER2,
|
||||
S_PINETREE,
|
||||
S_CEZBUSH1,
|
||||
S_CEZBUSH2,
|
||||
|
@ -2455,7 +2469,8 @@ typedef enum state
|
|||
S_FLAMEHOLDER,
|
||||
S_FIRETORCH,
|
||||
S_WAVINGFLAG,
|
||||
S_WAVINGFLAGSEG,
|
||||
S_WAVINGFLAGSEG1,
|
||||
S_WAVINGFLAGSEG2,
|
||||
S_CRAWLASTATUE,
|
||||
S_FACESTABBERSTATUE,
|
||||
S_SUSPICIOUSFACESTABBERSTATUE_WAIT,
|
||||
|
@ -2925,6 +2940,12 @@ typedef enum state
|
|||
S_PITY4,
|
||||
S_PITY5,
|
||||
S_PITY6,
|
||||
S_PITY7,
|
||||
S_PITY8,
|
||||
S_PITY9,
|
||||
S_PITY10,
|
||||
S_PITY11,
|
||||
S_PITY12,
|
||||
|
||||
S_FIRS1,
|
||||
S_FIRS2,
|
||||
|
@ -3409,6 +3430,12 @@ typedef enum state
|
|||
|
||||
S_LOCKON1,
|
||||
S_LOCKON2,
|
||||
S_LOCKON3,
|
||||
S_LOCKON4,
|
||||
S_LOCKONINF1,
|
||||
S_LOCKONINF2,
|
||||
S_LOCKONINF3,
|
||||
S_LOCKONINF4,
|
||||
|
||||
// Tag Sign
|
||||
S_TTAG,
|
||||
|
@ -3417,6 +3444,7 @@ typedef enum state
|
|||
S_GOTFLAG,
|
||||
|
||||
S_CORK,
|
||||
S_LHRT,
|
||||
|
||||
// Red Ring
|
||||
S_RRNG1,
|
||||
|
@ -3923,6 +3951,9 @@ typedef enum state
|
|||
S_ROCKCRUMBLEO,
|
||||
S_ROCKCRUMBLEP,
|
||||
|
||||
// Bricks
|
||||
S_BRICKDEBRIS,
|
||||
|
||||
#ifdef SEENAMES
|
||||
S_NAMECHECK,
|
||||
#endif
|
||||
|
@ -4026,11 +4057,14 @@ typedef enum mobj_type
|
|||
MT_EGGMOBILE3,
|
||||
MT_PROPELLER,
|
||||
MT_FAKEMOBILE,
|
||||
MT_SHOCK,
|
||||
|
||||
// Boss 4
|
||||
MT_EGGMOBILE4,
|
||||
MT_EGGMOBILE4_MACE,
|
||||
MT_JETFLAME,
|
||||
MT_EGGROBO1,
|
||||
MT_EGGROBO1JET,
|
||||
|
||||
// Boss 5
|
||||
MT_FANG,
|
||||
|
@ -4264,8 +4298,10 @@ typedef enum mobj_type
|
|||
MT_SMALLFIREBAR, // Small Firebar
|
||||
MT_BIGFIREBAR, // Big Firebar
|
||||
MT_CEZFLOWER, // Flower
|
||||
MT_CEZPOLE, // Pole
|
||||
MT_CEZBANNER, // Banner
|
||||
MT_CEZPOLE1, // Pole (with red banner)
|
||||
MT_CEZPOLE2, // Pole (with blue banner)
|
||||
MT_CEZBANNER1, // Banner (red)
|
||||
MT_CEZBANNER2, // Banner (blue)
|
||||
MT_PINETREE, // Pine Tree
|
||||
MT_CEZBUSH1, // Bush 1
|
||||
MT_CEZBUSH2, // Bush 2
|
||||
|
@ -4273,8 +4309,10 @@ typedef enum mobj_type
|
|||
MT_CANDLEPRICKET, // Candle pricket
|
||||
MT_FLAMEHOLDER, // Flame holder
|
||||
MT_FIRETORCH, // Fire torch
|
||||
MT_WAVINGFLAG, // Waving flag
|
||||
MT_WAVINGFLAGSEG, // Waving flag segment
|
||||
MT_WAVINGFLAG1, // Waving flag (red)
|
||||
MT_WAVINGFLAG2, // Waving flag (blue)
|
||||
MT_WAVINGFLAGSEG1, // Waving flag segment (red)
|
||||
MT_WAVINGFLAGSEG2, // Waving flag segment (blue)
|
||||
MT_CRAWLASTATUE, // Crawla statue
|
||||
MT_FACESTABBERSTATUE, // Facestabber statue
|
||||
MT_SUSPICIOUSFACESTABBERSTATUE, // :eggthinking:
|
||||
|
@ -4507,6 +4545,7 @@ typedef enum mobj_type
|
|||
MT_DROWNNUMBERS, // Drowning Timer
|
||||
MT_GOTEMERALD, // Chaos Emerald (intangible)
|
||||
MT_LOCKON, // Target
|
||||
MT_LOCKONINF, // In-level Target
|
||||
MT_TAG, // Tag Sign
|
||||
MT_GOTFLAG, // Got Flag sign
|
||||
|
||||
|
@ -4524,6 +4563,7 @@ typedef enum mobj_type
|
|||
MT_MACHINEAMBIENCE,
|
||||
|
||||
MT_CORK,
|
||||
MT_LHRT,
|
||||
|
||||
// Ring Weapons
|
||||
MT_REDRING,
|
||||
|
@ -4657,6 +4697,9 @@ typedef enum mobj_type
|
|||
MT_ROCKCRUMBLE15,
|
||||
MT_ROCKCRUMBLE16,
|
||||
|
||||
// Bricks
|
||||
MT_BRICKDEBRIS,
|
||||
|
||||
#ifdef SEENAMES
|
||||
MT_NAMECHECK,
|
||||
#endif
|
||||
|
|
|
@ -33,8 +33,6 @@
|
|||
|
||||
#define NOHUD if (hud_running)\
|
||||
return luaL_error(L, "HUD rendering code should not call this function!");
|
||||
#define INLEVEL if (gamestate != GS_LEVEL)\
|
||||
return luaL_error(L, "This function can only be used in a level!");
|
||||
|
||||
boolean luaL_checkboolean(lua_State *L, int narg) {
|
||||
luaL_checktype(L, narg, LUA_TBOOLEAN);
|
||||
|
@ -539,7 +537,8 @@ static int lib_pSpawnLockOn(lua_State *L)
|
|||
if (P_IsLocalPlayer(player)) // Only display it on your own view.
|
||||
{
|
||||
mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker
|
||||
visual->target = lockon;
|
||||
P_SetTarget(&visual->target, lockon);
|
||||
visual->flags2 |= MF2_DONTDRAW;
|
||||
P_SetMobjStateNF(visual, state);
|
||||
}
|
||||
return 0;
|
||||
|
@ -951,6 +950,21 @@ static int lib_pResetPlayer(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int lib_pPlayerCanDamage(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
|
||||
NOHUD // was hud safe but then i added a lua hook
|
||||
INLEVEL
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
if (!thing)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
lua_pushboolean(L, P_PlayerCanDamage(player, thing));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int lib_pIsObjectInGoop(lua_State *L)
|
||||
{
|
||||
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
|
||||
|
@ -1219,8 +1233,8 @@ static int lib_pHomingAttack(lua_State *L)
|
|||
INLEVEL
|
||||
if (!source || !enemy)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
P_HomingAttack(source, enemy);
|
||||
return 0;
|
||||
lua_pushboolean(L, P_HomingAttack(source, enemy));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_pSuperReady(lua_State *L)
|
||||
|
@ -2031,12 +2045,22 @@ static int lib_pStartQuake(lua_State *L)
|
|||
|
||||
static int lib_evCrumbleChain(lua_State *L)
|
||||
{
|
||||
sector_t *sec = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
|
||||
ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR));
|
||||
sector_t *sec = NULL;
|
||||
ffloor_t *rover = NULL;
|
||||
NOHUD
|
||||
INLEVEL
|
||||
if (!sec)
|
||||
return LUA_ErrInvalid(L, "sector_t");
|
||||
if (!lua_isnone(L, 2))
|
||||
{
|
||||
if (!lua_isnil(L, 1))
|
||||
{
|
||||
sec = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
|
||||
if (!sec)
|
||||
return LUA_ErrInvalid(L, "sector_t");
|
||||
}
|
||||
rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR));
|
||||
}
|
||||
else
|
||||
rover = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR));
|
||||
if (!rover)
|
||||
return LUA_ErrInvalid(L, "ffloor_t");
|
||||
EV_CrumbleChain(sec, rover);
|
||||
|
@ -2585,12 +2609,12 @@ static int lib_gSetCustomExitVars(lua_State *L)
|
|||
nextmapoverride = (INT16)luaL_checknumber(L, 1);
|
||||
lua_remove(L, 1); // remove nextmapoverride; skipstats now 1 if available
|
||||
}
|
||||
skipstats = lua_optboolean(L, 1);
|
||||
skipstats = luaL_optinteger(L, 2, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
nextmapoverride = 0;
|
||||
skipstats = false;
|
||||
skipstats = 0;
|
||||
}
|
||||
// ---
|
||||
|
||||
|
@ -2774,6 +2798,7 @@ static luaL_Reg lib[] = {
|
|||
{"P_PlayerInPain",lib_pPlayerInPain},
|
||||
{"P_DoPlayerPain",lib_pDoPlayerPain},
|
||||
{"P_ResetPlayer",lib_pResetPlayer},
|
||||
{"P_PlayerCanDamage",lib_pPlayerCanDamage},
|
||||
{"P_IsObjectInGoop",lib_pIsObjectInGoop},
|
||||
{"P_IsObjectOnGround",lib_pIsObjectOnGround},
|
||||
{"P_InSpaceSector",lib_pInSpaceSector},
|
||||
|
|
|
@ -54,10 +54,12 @@ static UINT8 lib_searchBlockmap_Objects(lua_State *L, INT32 x, INT32 y, mobj_t *
|
|||
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
|
||||
lua_pop(gL, 1);
|
||||
blockfuncerror = true;
|
||||
P_SetTarget(&bnext, NULL);
|
||||
return 0; // *shrugs*
|
||||
}
|
||||
if (!lua_isnil(gL, -1))
|
||||
{ // if nil, continue
|
||||
P_SetTarget(&bnext, NULL);
|
||||
if (lua_toboolean(gL, -1))
|
||||
return 2; // stop whole search
|
||||
else
|
||||
|
|
|
@ -28,9 +28,6 @@ return luaL_error(L, "HUD rendering code should not call this function!");
|
|||
// for functions not allowed in hooks or coroutines (supercedes above)
|
||||
#define NOHOOK if (!lua_lumploading)\
|
||||
return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
|
||||
// for functions only allowed within a level
|
||||
#define INLEVEL if (gamestate != GS_LEVEL)\
|
||||
return luaL_error(L, "This function can only be used in a level!");
|
||||
|
||||
static const char *cvname = NULL;
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ enum hook {
|
|||
hook_MobjMoveBlocked,
|
||||
hook_MapThingSpawn,
|
||||
hook_FollowMobj,
|
||||
hook_PlayerCanDamage,
|
||||
hook_PlayerQuit,
|
||||
|
||||
hook_MAX // last hook
|
||||
|
@ -87,7 +88,8 @@ boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8
|
|||
#define LUAh_ShieldSpecial(player) LUAh_PlayerHook(player, hook_ShieldSpecial) // Hook for shield abilities
|
||||
#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_FollowMobj(player_t *player, mobj_t *mo); // Hook for P_PlayerAfterThink Smiles mobj-following
|
||||
boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj); // Hook for P_PlayerAfterThink Smiles mobj-following
|
||||
UINT8 LUAh_PlayerCanDamage(player_t *player, mobj_t *mobj); // Hook for P_PlayerCanDamage
|
||||
void LUAh_PlayerQuit(player_t *plr, int reason); // Hook for player quitting
|
||||
|
||||
#endif
|
||||
|
|
1182
src/lua_hooklib.c
1182
src/lua_hooklib.c
File diff suppressed because it is too large
Load diff
|
@ -670,8 +670,8 @@ static int libd_getColormap(lua_State *L)
|
|||
else if (lua_type(L, 1) == LUA_TNUMBER) // skin number
|
||||
{
|
||||
skinnum = (INT32)luaL_checkinteger(L, 1);
|
||||
if (skinnum < TC_ALLWHITE || skinnum >= MAXSKINS)
|
||||
return luaL_error(L, "skin number %d is out of range (%d - %d)", skinnum, TC_ALLWHITE, MAXSKINS-1);
|
||||
if (skinnum < TC_BLINK || skinnum >= MAXSKINS)
|
||||
return luaL_error(L, "skin number %d is out of range (%d - %d)", skinnum, TC_BLINK, MAXSKINS-1);
|
||||
}
|
||||
else // skin name
|
||||
{
|
||||
|
|
|
@ -157,6 +157,18 @@ static int lib_setSpr2default(lua_State *L)
|
|||
playersprite_t i;
|
||||
UINT8 j = 0;
|
||||
|
||||
if (hud_running)
|
||||
return luaL_error(L, "Do not alter spr2defaults[] in HUD rendering code!");
|
||||
|
||||
// todo: maybe allow setting below first freeslot..? step 1 is toggling this, step 2 is testing to see whether it's net-safe
|
||||
#ifdef SETALLSPR2DEFAULTS
|
||||
#define FIRSTMODIFY 0
|
||||
#else
|
||||
#define FIRSTMODIFY SPR2_FIRSTFREESLOT
|
||||
if (free_spr2 == SPR2_FIRSTFREESLOT)
|
||||
return luaL_error(L, "You can only modify the spr2defaults[] entries of sprite2 freeslots, and none are currently added.");
|
||||
#endif
|
||||
|
||||
lua_remove(L, 1); // don't care about spr2defaults[] dummy userdata.
|
||||
|
||||
if (lua_isnumber(L, 1))
|
||||
|
@ -175,8 +187,9 @@ static int lib_setSpr2default(lua_State *L)
|
|||
else
|
||||
return luaL_error(L, "spr2defaults[] invalid index");
|
||||
|
||||
if (i < SPR2_FIRSTFREESLOT || i >= free_spr2)
|
||||
return luaL_error(L, "spr2defaults[] index %d out of range (%d - %d)", i, SPR2_FIRSTFREESLOT, free_spr2-1);
|
||||
if (i < FIRSTMODIFY || i >= free_spr2)
|
||||
return luaL_error(L, "spr2defaults[] index %d out of range (%d - %d)", i, FIRSTMODIFY, free_spr2-1);
|
||||
#undef FIRSTMODIFY
|
||||
|
||||
if (lua_isnumber(L, 2))
|
||||
j = lua_tonumber(L, 2);
|
||||
|
@ -189,11 +202,13 @@ static int lib_setSpr2default(lua_State *L)
|
|||
break;
|
||||
}
|
||||
if (j == free_spr2)
|
||||
return luaL_error(L, "spr2defaults[] invalid index");
|
||||
return luaL_error(L, "spr2defaults[] invalid set");
|
||||
}
|
||||
else
|
||||
return luaL_error(L, "spr2defaults[] invalid set");
|
||||
|
||||
if (j >= free_spr2)
|
||||
j = 0; // return luaL_error(L, "spr2defaults[] set %d out of range (%d - %d)", j, 0, free_spr2-1);
|
||||
if (j < 0 || j >= free_spr2)
|
||||
return luaL_error(L, "spr2defaults[] set %d out of range (%d - %d)", j, 0, free_spr2-1);
|
||||
|
||||
spr2defaults[i] = j;
|
||||
return 0;
|
||||
|
|
|
@ -292,8 +292,6 @@ enum slope_e {
|
|||
slope_normal,
|
||||
slope_zangle,
|
||||
slope_xydirection,
|
||||
slope_sourceline,
|
||||
slope_refpos,
|
||||
slope_flags
|
||||
};
|
||||
|
||||
|
@ -305,8 +303,6 @@ static const char *const slope_opt[] = {
|
|||
"normal",
|
||||
"zangle",
|
||||
"xydirection",
|
||||
"sourceline",
|
||||
"refpos",
|
||||
"flags",
|
||||
NULL};
|
||||
|
||||
|
@ -337,8 +333,7 @@ static int lib_iterateSectorThinglist(lua_State *L)
|
|||
mobj_t *state = NULL;
|
||||
mobj_t *thing = NULL;
|
||||
|
||||
if (gamestate != GS_LEVEL)
|
||||
return luaL_error(L, "This function can only be used in a level!");
|
||||
INLEVEL
|
||||
|
||||
if (lua_gettop(L) < 2)
|
||||
return luaL_error(L, "Don't call sector.thinglist() directly, use it as 'for rover in sector.thinglist do <block> end'.");
|
||||
|
@ -373,8 +368,7 @@ static int lib_iterateSectorFFloors(lua_State *L)
|
|||
ffloor_t *state = NULL;
|
||||
ffloor_t *ffloor = NULL;
|
||||
|
||||
if (gamestate != GS_LEVEL)
|
||||
return luaL_error(L, "This function can only be used in a level!");
|
||||
INLEVEL
|
||||
|
||||
if (lua_gettop(L) < 2)
|
||||
return luaL_error(L, "Don't call sector.ffloors() directly, use it as 'for rover in sector.ffloors do <block> end'.");
|
||||
|
@ -1255,8 +1249,7 @@ static int bbox_get(lua_State *L)
|
|||
static int lib_iterateSectors(lua_State *L)
|
||||
{
|
||||
size_t i = 0;
|
||||
if (gamestate != GS_LEVEL)
|
||||
return luaL_error(L, "This function can only be used in a level!");
|
||||
INLEVEL
|
||||
if (lua_gettop(L) < 2)
|
||||
return luaL_error(L, "Don't call sectors.iterate() directly, use it as 'for sector in sectors.iterate do <block> end'.");
|
||||
lua_settop(L, 2);
|
||||
|
@ -1274,8 +1267,7 @@ static int lib_iterateSectors(lua_State *L)
|
|||
static int lib_getSector(lua_State *L)
|
||||
{
|
||||
int field;
|
||||
if (gamestate != GS_LEVEL)
|
||||
return luaL_error(L, "You cannot access this outside of a level!");
|
||||
INLEVEL
|
||||
lua_settop(L, 2);
|
||||
lua_remove(L, 1); // dummy userdata table is unused.
|
||||
if (lua_isnumber(L, 1))
|
||||
|
@ -1309,8 +1301,7 @@ static int lib_numsectors(lua_State *L)
|
|||
static int lib_iterateSubsectors(lua_State *L)
|
||||
{
|
||||
size_t i = 0;
|
||||
if (gamestate != GS_LEVEL)
|
||||
return luaL_error(L, "This function can only be used in a level!");
|
||||
INLEVEL
|
||||
if (lua_gettop(L) < 2)
|
||||
return luaL_error(L, "Don't call subsectors.iterate() directly, use it as 'for subsector in subsectors.iterate do <block> end'.");
|
||||
lua_settop(L, 2);
|
||||
|
@ -1328,8 +1319,7 @@ static int lib_iterateSubsectors(lua_State *L)
|
|||
static int lib_getSubsector(lua_State *L)
|
||||
{
|
||||
int field;
|
||||
if (gamestate != GS_LEVEL)
|
||||
return luaL_error(L, "You cannot access this outside of a level!");
|
||||
INLEVEL
|
||||
lua_settop(L, 2);
|
||||
lua_remove(L, 1); // dummy userdata table is unused.
|
||||
if (lua_isnumber(L, 1))
|
||||
|
@ -1363,8 +1353,7 @@ static int lib_numsubsectors(lua_State *L)
|
|||
static int lib_iterateLines(lua_State *L)
|
||||
{
|
||||
size_t i = 0;
|
||||
if (gamestate != GS_LEVEL)
|
||||
return luaL_error(L, "This function can only be used in a level!");
|
||||
INLEVEL
|
||||
if (lua_gettop(L) < 2)
|
||||
return luaL_error(L, "Don't call lines.iterate() directly, use it as 'for line in lines.iterate do <block> end'.");
|
||||
lua_settop(L, 2);
|
||||
|
@ -1382,8 +1371,7 @@ static int lib_iterateLines(lua_State *L)
|
|||
static int lib_getLine(lua_State *L)
|
||||
{
|
||||
int field;
|
||||
if (gamestate != GS_LEVEL)
|
||||
return luaL_error(L, "You cannot access this outside of a level!");
|
||||
INLEVEL
|
||||
lua_settop(L, 2);
|
||||
lua_remove(L, 1); // dummy userdata table is unused.
|
||||
if (lua_isnumber(L, 1))
|
||||
|
@ -1417,8 +1405,7 @@ static int lib_numlines(lua_State *L)
|
|||
static int lib_iterateSides(lua_State *L)
|
||||
{
|
||||
size_t i = 0;
|
||||
if (gamestate != GS_LEVEL)
|
||||
return luaL_error(L, "This function can only be used in a level!");
|
||||
INLEVEL
|
||||
if (lua_gettop(L) < 2)
|
||||
return luaL_error(L, "Don't call sides.iterate() directly, use it as 'for side in sides.iterate do <block> end'.");
|
||||
lua_settop(L, 2);
|
||||
|
@ -1436,8 +1423,7 @@ static int lib_iterateSides(lua_State *L)
|
|||
static int lib_getSide(lua_State *L)
|
||||
{
|
||||
int field;
|
||||
if (gamestate != GS_LEVEL)
|
||||
return luaL_error(L, "You cannot access this outside of a level!");
|
||||
INLEVEL
|
||||
lua_settop(L, 2);
|
||||
lua_remove(L, 1); // dummy userdata table is unused.
|
||||
if (lua_isnumber(L, 1))
|
||||
|
@ -1471,8 +1457,7 @@ static int lib_numsides(lua_State *L)
|
|||
static int lib_iterateVertexes(lua_State *L)
|
||||
{
|
||||
size_t i = 0;
|
||||
if (gamestate != GS_LEVEL)
|
||||
return luaL_error(L, "This function can only be used in a level!");
|
||||
INLEVEL
|
||||
if (lua_gettop(L) < 2)
|
||||
return luaL_error(L, "Don't call vertexes.iterate() directly, use it as 'for vertex in vertexes.iterate do <block> end'.");
|
||||
lua_settop(L, 2);
|
||||
|
@ -1490,8 +1475,7 @@ static int lib_iterateVertexes(lua_State *L)
|
|||
static int lib_getVertex(lua_State *L)
|
||||
{
|
||||
int field;
|
||||
if (gamestate != GS_LEVEL)
|
||||
return luaL_error(L, "You cannot access this outside of a level!");
|
||||
INLEVEL
|
||||
lua_settop(L, 2);
|
||||
lua_remove(L, 1); // dummy userdata table is unused.
|
||||
if (lua_isnumber(L, 1))
|
||||
|
@ -1527,8 +1511,7 @@ static int lib_numvertexes(lua_State *L)
|
|||
static int lib_iterateSegs(lua_State *L)
|
||||
{
|
||||
size_t i = 0;
|
||||
if (gamestate != GS_LEVEL)
|
||||
return luaL_error(L, "This function can only be used in a level!");
|
||||
INLEVEL
|
||||
if (lua_gettop(L) < 2)
|
||||
return luaL_error(L, "Don't call segs.iterate() directly, use it as 'for seg in segs.iterate do <block> end'.");
|
||||
lua_settop(L, 2);
|
||||
|
@ -1546,8 +1529,7 @@ static int lib_iterateSegs(lua_State *L)
|
|||
static int lib_getSeg(lua_State *L)
|
||||
{
|
||||
int field;
|
||||
if (gamestate != GS_LEVEL)
|
||||
return luaL_error(L, "You cannot access this outside of a level!");
|
||||
INLEVEL
|
||||
lua_settop(L, 2);
|
||||
lua_remove(L, 1); // dummy userdata table is unused.
|
||||
if (lua_isnumber(L, 1))
|
||||
|
@ -1581,8 +1563,7 @@ static int lib_numsegs(lua_State *L)
|
|||
static int lib_iterateNodes(lua_State *L)
|
||||
{
|
||||
size_t i = 0;
|
||||
if (gamestate != GS_LEVEL)
|
||||
return luaL_error(L, "This function can only be used in a level!");
|
||||
INLEVEL
|
||||
if (lua_gettop(L) < 2)
|
||||
return luaL_error(L, "Don't call nodes.iterate() directly, use it as 'for node in nodes.iterate do <block> end'.");
|
||||
lua_settop(L, 2);
|
||||
|
@ -1600,8 +1581,7 @@ static int lib_iterateNodes(lua_State *L)
|
|||
static int lib_getNode(lua_State *L)
|
||||
{
|
||||
int field;
|
||||
if (gamestate != GS_LEVEL)
|
||||
return luaL_error(L, "You cannot access this outside of a level!");
|
||||
INLEVEL
|
||||
lua_settop(L, 2);
|
||||
lua_remove(L, 1); // dummy userdata table is unused.
|
||||
if (lua_isnumber(L, 1))
|
||||
|
@ -1831,12 +1811,6 @@ static int slope_get(lua_State *L)
|
|||
case slope_xydirection: // xydirection
|
||||
lua_pushangle(L, slope->xydirection);
|
||||
return 1;
|
||||
case slope_sourceline: // source linedef
|
||||
LUA_PushUserdata(L, slope->sourceline, META_LINE);
|
||||
return 1;
|
||||
case slope_refpos: // refpos
|
||||
lua_pushinteger(L, slope->refpos);
|
||||
return 1;
|
||||
case slope_flags: // flags
|
||||
lua_pushinteger(L, slope->flags);
|
||||
return 1;
|
||||
|
@ -1858,11 +1832,9 @@ static int slope_set(lua_State *L)
|
|||
switch(field) // todo: reorganize this shit
|
||||
{
|
||||
case slope_valid: // valid
|
||||
case slope_sourceline: // sourceline
|
||||
case slope_d: // d
|
||||
case slope_flags: // flags
|
||||
case slope_normal: // normal
|
||||
case slope_refpos: // refpos
|
||||
default:
|
||||
return luaL_error(L, "pslope_t field " LUA_QS " cannot be set.", slope_opt[field]);
|
||||
case slope_o: { // o
|
||||
|
|
|
@ -83,12 +83,11 @@ enum mobj_e {
|
|||
mobj_extravalue1,
|
||||
mobj_extravalue2,
|
||||
mobj_cusval,
|
||||
#ifdef ESLOPE
|
||||
mobj_cvmem,
|
||||
mobj_standingslope
|
||||
#else
|
||||
mobj_cvmem
|
||||
#ifdef ESLOPE
|
||||
mobj_standingslope,
|
||||
#endif
|
||||
mobj_colorized
|
||||
};
|
||||
|
||||
static const char *const mobj_opt[] = {
|
||||
|
@ -154,6 +153,7 @@ static const char *const mobj_opt[] = {
|
|||
#ifdef ESLOPE
|
||||
"standingslope",
|
||||
#endif
|
||||
"colorized",
|
||||
NULL};
|
||||
|
||||
#define UNIMPLEMENTED luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", mobj_opt[field])
|
||||
|
@ -274,10 +274,19 @@ static int mobj_get(lua_State *L)
|
|||
// bprev -- same deal as sprev above, but for the blockmap.
|
||||
return UNIMPLEMENTED;
|
||||
case mobj_hnext:
|
||||
if (mo->hnext && P_MobjWasRemoved(mo->hnext))
|
||||
{ // don't put invalid mobj back into Lua.
|
||||
P_SetTarget(&mo->hnext, NULL);
|
||||
return 0;
|
||||
}
|
||||
LUA_PushUserdata(L, mo->hnext, META_MOBJ);
|
||||
break;
|
||||
case mobj_hprev:
|
||||
// implimented differently from sprev and bprev because SSNTails.
|
||||
if (mo->hprev && P_MobjWasRemoved(mo->hprev))
|
||||
{ // don't put invalid mobj back into Lua.
|
||||
P_SetTarget(&mo->hprev, NULL);
|
||||
return 0;
|
||||
}
|
||||
LUA_PushUserdata(L, mo->hprev, META_MOBJ);
|
||||
break;
|
||||
case mobj_type:
|
||||
|
@ -371,6 +380,9 @@ static int mobj_get(lua_State *L)
|
|||
LUA_PushUserdata(L, mo->standingslope, META_SLOPE);
|
||||
break;
|
||||
#endif
|
||||
case mobj_colorized:
|
||||
lua_pushboolean(L, mo->colorized);
|
||||
break;
|
||||
default: // extra custom variables in Lua memory
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
|
||||
I_Assert(lua_istable(L, -1));
|
||||
|
@ -692,6 +704,9 @@ static int mobj_set(lua_State *L)
|
|||
case mobj_standingslope:
|
||||
return NOSET;
|
||||
#endif
|
||||
case mobj_colorized:
|
||||
mo->colorized = luaL_checkboolean(L, 3);
|
||||
break;
|
||||
default:
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
|
||||
I_Assert(lua_istable(L, -1));
|
||||
|
@ -789,7 +804,12 @@ static int mapthing_set(lua_State *L)
|
|||
else if(fastcmp(field,"z"))
|
||||
mt->z = (INT16)luaL_checkinteger(L, 3);
|
||||
else if(fastcmp(field,"extrainfo"))
|
||||
mt->extrainfo = (UINT8)luaL_checkinteger(L, 3);
|
||||
{
|
||||
INT32 extrainfo = luaL_checkinteger(L, 3);
|
||||
if (extrainfo & ~15)
|
||||
return luaL_error(L, "mapthing_t extrainfo set %d out of range (%d - %d)", extrainfo, 0, 15);
|
||||
mt->extrainfo = (UINT8)extrainfo;
|
||||
}
|
||||
else if(fastcmp(field,"mobj"))
|
||||
mt->mobj = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
|
||||
else
|
||||
|
@ -801,8 +821,7 @@ static int mapthing_set(lua_State *L)
|
|||
static int lib_iterateMapthings(lua_State *L)
|
||||
{
|
||||
size_t i = 0;
|
||||
if (gamestate != GS_LEVEL)
|
||||
return luaL_error(L, "This function can only be used in a level!");
|
||||
INLEVEL
|
||||
if (lua_gettop(L) < 2)
|
||||
return luaL_error(L, "Don't call mapthings.iterate() directly, use it as 'for mapthing in mapthings.iterate do <block> end'.");
|
||||
lua_settop(L, 2);
|
||||
|
@ -820,8 +839,7 @@ static int lib_iterateMapthings(lua_State *L)
|
|||
static int lib_getMapthing(lua_State *L)
|
||||
{
|
||||
int field;
|
||||
if (gamestate != GS_LEVEL)
|
||||
return luaL_error(L, "You cannot access this outside of a level!");
|
||||
INLEVEL
|
||||
lua_settop(L, 2);
|
||||
lua_remove(L, 1); // dummy userdata table is unused.
|
||||
if (lua_isnumber(L, 1))
|
||||
|
|
|
@ -25,8 +25,7 @@
|
|||
static int lib_iteratePlayers(lua_State *L)
|
||||
{
|
||||
INT32 i = -1;
|
||||
if (gamestate != GS_LEVEL)
|
||||
return luaL_error(L, "This function can only be used in a level!");
|
||||
INLEVEL
|
||||
if (lua_gettop(L) < 2)
|
||||
{
|
||||
//return luaL_error(L, "Don't call players.iterate() directly, use it as 'for player in players.iterate do <block> end'.");
|
||||
|
@ -53,8 +52,7 @@ static int lib_getPlayer(lua_State *L)
|
|||
{
|
||||
const char *field;
|
||||
// i -> players[i]
|
||||
if (gamestate != GS_LEVEL)
|
||||
return luaL_error(L, "You cannot access this outside of a level!");
|
||||
INLEVEL
|
||||
if (lua_type(L, 2) == LUA_TNUMBER)
|
||||
{
|
||||
lua_Integer i = luaL_checkinteger(L, 2);
|
||||
|
@ -476,7 +474,12 @@ static int player_set(lua_State *L)
|
|||
else if (fastcmp(field,"followitem"))
|
||||
plr->followitem = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"followmobj"))
|
||||
P_SetTarget(&plr->followmobj, *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)));
|
||||
{
|
||||
mobj_t *mo = NULL;
|
||||
if (!lua_isnil(L, 3))
|
||||
mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
|
||||
P_SetTarget(&plr->followmobj, mo);
|
||||
}
|
||||
else if (fastcmp(field,"actionspd"))
|
||||
plr->actionspd = (INT32)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"mindash"))
|
||||
|
@ -560,9 +563,19 @@ static int player_set(lua_State *L)
|
|||
else if (fastcmp(field,"old_angle_pos"))
|
||||
plr->old_angle_pos = luaL_checkangle(L, 3);
|
||||
else if (fastcmp(field,"axis1"))
|
||||
P_SetTarget(&plr->axis1, *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)));
|
||||
{
|
||||
mobj_t *mo = NULL;
|
||||
if (!lua_isnil(L, 3))
|
||||
mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
|
||||
P_SetTarget(&plr->axis1, mo);
|
||||
}
|
||||
else if (fastcmp(field,"axis2"))
|
||||
P_SetTarget(&plr->axis2, *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)));
|
||||
{
|
||||
mobj_t *mo = NULL;
|
||||
if (!lua_isnil(L, 3))
|
||||
mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
|
||||
P_SetTarget(&plr->axis2, mo);
|
||||
}
|
||||
else if (fastcmp(field,"bumpertime"))
|
||||
plr->bumpertime = (tic_t)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"flyangle"))
|
||||
|
|
|
@ -420,9 +420,9 @@ void LUA_InvalidateLevel(void)
|
|||
ffloor_t *rover = NULL;
|
||||
if (!gL)
|
||||
return;
|
||||
|
||||
for (th = thinkercap.next; th && th != &thinkercap; th = th->next)
|
||||
LUA_InvalidateUserdata(th);
|
||||
for (i = 0; i < NUM_THINKERLISTS; i++)
|
||||
for (th = thlist[i].next; th && th != &thlist[i]; th = th->next)
|
||||
LUA_InvalidateUserdata(th);
|
||||
|
||||
LUA_InvalidateMapthings();
|
||||
|
||||
|
@ -1127,13 +1127,16 @@ void LUA_Archive(void)
|
|||
ArchiveExtVars(&players[i], "player");
|
||||
}
|
||||
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
if (th->function.acp1 == (actionf_p1)P_MobjThinker)
|
||||
{
|
||||
// archive function will determine when to skip mobjs,
|
||||
// and write mobjnum in otherwise.
|
||||
ArchiveExtVars(th, "mobj");
|
||||
}
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
// archive function will determine when to skip mobjs,
|
||||
// and write mobjnum in otherwise.
|
||||
ArchiveExtVars(th, "mobj");
|
||||
}
|
||||
|
||||
WRITEUINT32(save_p, UINT32_MAX); // end of mobjs marker, replaces mobjnum.
|
||||
|
||||
LUAh_NetArchiveHook(NetArchive); // call the NetArchive hook in archive mode
|
||||
|
@ -1161,10 +1164,14 @@ void LUA_UnArchive(void)
|
|||
|
||||
do {
|
||||
mobjnum = READUINT32(save_p); // read a mobjnum
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
if (th->function.acp1 == (actionf_p1)P_MobjThinker
|
||||
&& ((mobj_t *)th)->mobjnum == mobjnum) // find matching mobj
|
||||
UnArchiveExtVars(th); // apply variables
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
if (((mobj_t *)th)->mobjnum != mobjnum) // find matching mobj
|
||||
continue;
|
||||
UnArchiveExtVars(th); // apply variables
|
||||
}
|
||||
} while(mobjnum != UINT32_MAX); // repeat until end of mobjs marker.
|
||||
|
||||
LUAh_NetArchiveHook(NetUnArchive); // call the NetArchive hook in unarchive mode
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "m_fixed.h"
|
||||
#include "doomtype.h"
|
||||
#include "d_player.h"
|
||||
#include "g_state.h"
|
||||
|
||||
#include "blua/lua.h"
|
||||
#include "blua/lualib.h"
|
||||
|
@ -97,4 +98,7 @@ void COM_Lua_f(void);
|
|||
// uncomment if you want seg_t/node_t in Lua
|
||||
// #define HAVE_LUA_SEGS
|
||||
|
||||
#define INLEVEL if (gamestate != GS_LEVEL && !titlemapinaction)\
|
||||
return luaL_error(L, "This can only be used in a level!");
|
||||
|
||||
#endif
|
||||
|
|
|
@ -27,9 +27,6 @@ enum skin {
|
|||
skin_flags,
|
||||
skin_realname,
|
||||
skin_hudname,
|
||||
skin_charsel,
|
||||
skin_face,
|
||||
skin_superface,
|
||||
skin_ability,
|
||||
skin_ability2,
|
||||
skin_thokitem,
|
||||
|
@ -66,9 +63,6 @@ static const char *const skin_opt[] = {
|
|||
"flags",
|
||||
"realname",
|
||||
"hudname",
|
||||
"charsel",
|
||||
"face",
|
||||
"superface",
|
||||
"ability",
|
||||
"ability2",
|
||||
"thokitem",
|
||||
|
@ -104,7 +98,6 @@ static int skin_get(lua_State *L)
|
|||
{
|
||||
skin_t *skin = *((skin_t **)luaL_checkudata(L, 1, META_SKIN));
|
||||
enum skin field = luaL_checkoption(L, 2, NULL, skin_opt);
|
||||
INT32 i;
|
||||
|
||||
// skins are always valid, only added, never removed
|
||||
I_Assert(skin != NULL);
|
||||
|
@ -131,24 +124,6 @@ static int skin_get(lua_State *L)
|
|||
case skin_hudname:
|
||||
lua_pushstring(L, skin->hudname);
|
||||
break;
|
||||
case skin_charsel:
|
||||
for (i = 0; i < 8; i++)
|
||||
if (!skin->charsel[i])
|
||||
break;
|
||||
lua_pushlstring(L, skin->charsel, i);
|
||||
break;
|
||||
case skin_face:
|
||||
for (i = 0; i < 8; i++)
|
||||
if (!skin->face[i])
|
||||
break;
|
||||
lua_pushlstring(L, skin->face, i);
|
||||
break;
|
||||
case skin_superface:
|
||||
for (i = 0; i < 8; i++)
|
||||
if (!skin->superface[i])
|
||||
break;
|
||||
lua_pushlstring(L, skin->superface, i);
|
||||
break;
|
||||
case skin_ability:
|
||||
lua_pushinteger(L, skin->ability);
|
||||
break;
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
#define META_ITERATIONSTATE "iteration state"
|
||||
|
||||
static const char *const iter_opt[] = {
|
||||
/*static const char *const iter_opt[] = {
|
||||
"all",
|
||||
"mobj",
|
||||
NULL};
|
||||
|
@ -26,7 +26,7 @@ static const char *const iter_opt[] = {
|
|||
static const actionf_p1 iter_funcs[] = {
|
||||
NULL,
|
||||
(actionf_p1)P_MobjThinker
|
||||
};
|
||||
};*/
|
||||
|
||||
struct iterationState {
|
||||
actionf_p1 filter;
|
||||
|
@ -56,15 +56,14 @@ static int lib_iterateThinkers(lua_State *L)
|
|||
thinker_t *th = NULL, *next = NULL;
|
||||
struct iterationState *it;
|
||||
|
||||
if (gamestate != GS_LEVEL)
|
||||
return luaL_error(L, "This function can only be used in a level!");
|
||||
INLEVEL
|
||||
|
||||
it = luaL_checkudata(L, 1, META_ITERATIONSTATE);
|
||||
|
||||
lua_settop(L, 2);
|
||||
|
||||
if (lua_isnil(L, 2))
|
||||
th = &thinkercap;
|
||||
th = &thlist[THINK_MOBJ];
|
||||
else if (lua_isuserdata(L, 2))
|
||||
{
|
||||
if (lua_islightuserdata(L, 2))
|
||||
|
@ -94,11 +93,11 @@ static int lib_iterateThinkers(lua_State *L)
|
|||
if (!next)
|
||||
return luaL_error(L, "next thinker invalidated during iteration");
|
||||
|
||||
for (; next != &thinkercap; next = next->next)
|
||||
for (; next != &thlist[THINK_MOBJ]; next = next->next)
|
||||
if (!it->filter || next->function.acp1 == it->filter)
|
||||
{
|
||||
push_thinker(next);
|
||||
if (next->next != &thinkercap)
|
||||
if (next->next != &thlist[THINK_MOBJ])
|
||||
{
|
||||
push_thinker(next->next);
|
||||
it->next = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
|
@ -112,15 +111,14 @@ static int lib_startIterate(lua_State *L)
|
|||
{
|
||||
struct iterationState *it;
|
||||
|
||||
if (gamestate != GS_LEVEL)
|
||||
return luaL_error(L, "This function can only be used in a level!");
|
||||
INLEVEL
|
||||
|
||||
lua_pushvalue(L, lua_upvalueindex(1));
|
||||
it = lua_newuserdata(L, sizeof(struct iterationState));
|
||||
luaL_getmetatable(L, META_ITERATIONSTATE);
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
it->filter = iter_funcs[luaL_checkoption(L, 1, "mobj", iter_opt)];
|
||||
it->filter = (actionf_p1)P_MobjThinker; //iter_funcs[luaL_checkoption(L, 1, "mobj", iter_opt)];
|
||||
it->next = LUA_REFNIL;
|
||||
return 2;
|
||||
}
|
||||
|
@ -138,7 +136,7 @@ int LUA_ThinkerLib(lua_State *L)
|
|||
lua_pushcfunction(L, lib_iterateThinkers);
|
||||
lua_pushcclosure(L, lib_startIterate, 1);
|
||||
lua_setfield(L, -2, "iterate");
|
||||
lua_setglobal(L, "thinkers");
|
||||
lua_setglobal(L, "mobjs");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -577,9 +577,9 @@ void Command_Teleport_f(void)
|
|||
INT32 starpostmax = 0;
|
||||
intz = starpostpath; // variable reuse - counting down for selection purposes
|
||||
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
@ -600,7 +600,7 @@ void Command_Teleport_f(void)
|
|||
break;
|
||||
}
|
||||
|
||||
if (th == &thinkercap)
|
||||
if (th == &thlist[THINK_MOBJ])
|
||||
{
|
||||
if (intz == starpostpath)
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("No starpost of position %d found (%d max).\n"), starpostnum, starpostmax);
|
||||
|
@ -1069,15 +1069,16 @@ static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean c
|
|||
thinker_t *th;
|
||||
mobj_t *mo;
|
||||
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo = (mobj_t *)th;
|
||||
// get offset from mt, which points to old mapthings, then add new location
|
||||
if (mo->spawnpoint)
|
||||
mo->spawnpoint = (mo->spawnpoint - mt) + mapthings;
|
||||
if (!mo->spawnpoint)
|
||||
continue;
|
||||
mo->spawnpoint = (mo->spawnpoint - mt) + mapthings;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -240,7 +240,7 @@ UINT8 M_UpdateUnlockablesAndExtraEmblems(void)
|
|||
if (cechoLines)
|
||||
{
|
||||
char slashed[1024] = "";
|
||||
for (i = 0; (i < 21) && (i < 24 - cechoLines); ++i)
|
||||
for (i = 0; (i < 19) && (i < 24 - cechoLines); ++i)
|
||||
slashed[i] = '\\';
|
||||
slashed[i] = 0;
|
||||
|
||||
|
|
70
src/m_menu.c
70
src/m_menu.c
|
@ -2289,23 +2289,26 @@ static boolean MIT_SetCurBackground(UINT32 menutype, INT32 level, INT32 *retval,
|
|||
(void)retval;
|
||||
(void)fromoldest;
|
||||
|
||||
if (!menutype) // if there's nothing in this level, do nothing
|
||||
return false;
|
||||
|
||||
if (menupres[menutype].bgcolor >= 0)
|
||||
{
|
||||
curbgcolor = menupres[menutype].bgcolor;
|
||||
return true;
|
||||
}
|
||||
else if (menupres[menutype].bgname[0] && (!menupres[menutype].bghide || !titlemapinaction))
|
||||
else if (menupres[menutype].bghide && titlemapinaction) // hide the background
|
||||
{
|
||||
curbghide = true;
|
||||
return true;
|
||||
}
|
||||
else if (menupres[menutype].bgname[0])
|
||||
{
|
||||
strncpy(curbgname, menupres[menutype].bgname, 8);
|
||||
curbgxspeed = menupres[menutype].titlescrollxspeed != INT32_MAX ? menupres[menutype].titlescrollxspeed : titlescrollxspeed;
|
||||
curbgyspeed = menupres[menutype].titlescrollyspeed != INT32_MAX ? menupres[menutype].titlescrollyspeed : titlescrollyspeed;
|
||||
return true;
|
||||
}
|
||||
else if (menupres[menutype].bghide && titlemapinaction) // hide the background
|
||||
{
|
||||
curbghide = true;
|
||||
return true;
|
||||
}
|
||||
else if (!level)
|
||||
{
|
||||
if (M_GetYoungestChildMenu() == MN_SP_PLAYER || !defaultname || !defaultname[0])
|
||||
|
@ -2329,6 +2332,9 @@ static boolean MIT_ChangeMusic(UINT32 menutype, INT32 level, INT32 *retval, void
|
|||
(void)retval;
|
||||
(void)fromoldest;
|
||||
|
||||
if (!menutype) // if there's nothing in this level, do nothing
|
||||
return false;
|
||||
|
||||
if (menupres[menutype].musname[0])
|
||||
{
|
||||
S_ChangeMusic(menupres[menutype].musname, menupres[menutype].mustrack, menupres[menutype].muslooping);
|
||||
|
@ -2353,6 +2359,9 @@ static boolean MIT_SetCurFadeValue(UINT32 menutype, INT32 level, INT32 *retval,
|
|||
(void)retval;
|
||||
(void)fromoldest;
|
||||
|
||||
if (!menutype) // if there's nothing in this level, do nothing
|
||||
return false;
|
||||
|
||||
if (menupres[menutype].fadestrength >= 0)
|
||||
{
|
||||
curfadevalue = (menupres[menutype].fadestrength % 32);
|
||||
|
@ -2369,6 +2378,9 @@ static boolean MIT_SetCurHideTitlePics(UINT32 menutype, INT32 level, INT32 *retv
|
|||
(void)retval;
|
||||
(void)fromoldest;
|
||||
|
||||
if (!menutype) // if there's nothing in this level, do nothing
|
||||
return false;
|
||||
|
||||
if (menupres[menutype].hidetitlepics >= 0)
|
||||
{
|
||||
curhidepics = menupres[menutype].hidetitlepics;
|
||||
|
@ -2470,7 +2482,7 @@ static void M_HandleMenuPresState(menu_t *newMenu)
|
|||
curbgcolor = -1;
|
||||
curbgxspeed = titlescrollxspeed;
|
||||
curbgyspeed = titlescrollyspeed;
|
||||
curbghide = true;
|
||||
curbghide = (gamestate != GS_TIMEATTACK); // show in time attack, hide in other menus
|
||||
|
||||
// don't do the below during the in-game menus
|
||||
if (gamestate != GS_TITLESCREEN && gamestate != GS_TIMEATTACK)
|
||||
|
@ -2799,8 +2811,8 @@ boolean M_Responder(event_t *ev)
|
|||
void (*routine)(INT32 choice); // for some casting problem
|
||||
|
||||
if (dedicated || (demoplayback && titledemo)
|
||||
|| gamestate == GS_INTRO || gamestate == GS_CUTSCENE || gamestate == GS_GAMEEND
|
||||
|| gamestate == GS_CREDITS || gamestate == GS_EVALUATION)
|
||||
|| gamestate == GS_INTRO || gamestate == GS_ENDING || gamestate == GS_CUTSCENE
|
||||
|| gamestate == GS_CREDITS || gamestate == GS_EVALUATION || gamestate == GS_GAMEEND)
|
||||
return false;
|
||||
|
||||
if (noFurtherInput)
|
||||
|
@ -2954,8 +2966,9 @@ boolean M_Responder(event_t *ev)
|
|||
return true;
|
||||
M_StartControlPanel();
|
||||
M_Options(0);
|
||||
currentMenu = &OP_SoundOptionsDef;
|
||||
itemOn = 0;
|
||||
// Uncomment the below if you want the menu to reset to the top each time like before. M_SetupNextMenu will fix it automatically.
|
||||
//OP_SoundOptionsDef.lastOn = 0;
|
||||
M_SetupNextMenu(&OP_SoundOptionsDef);
|
||||
return true;
|
||||
|
||||
case KEY_F5: // Video Mode
|
||||
|
@ -3499,6 +3512,7 @@ void M_InitCharacterTables(void)
|
|||
strcpy(description[i].picname, "");
|
||||
strcpy(description[i].skinname, "");
|
||||
description[i].prev = description[i].next = 0;
|
||||
description[i].pic = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7545,8 +7559,19 @@ static void M_SetupChoosePlayer(INT32 choice)
|
|||
if (i == char_on)
|
||||
allowed = true;
|
||||
|
||||
if (description[i].picname[0] == '\0')
|
||||
strncpy(description[i].picname, skins[skinnum].charsel, 8);
|
||||
if (!(description[i].picname[0]))
|
||||
{
|
||||
if (skins[skinnum].sprites[SPR2_XTRA].numframes >= 2)
|
||||
{
|
||||
spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA];
|
||||
spriteframe_t *sprframe = &sprdef->spriteframes[1];
|
||||
description[i].pic = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE);
|
||||
}
|
||||
else
|
||||
description[i].pic = W_CachePatchName("MISSING", PU_CACHE);
|
||||
}
|
||||
else
|
||||
description[i].pic = W_CachePatchName(description[i].picname, PU_CACHE);
|
||||
}
|
||||
// else -- Technically, character select icons without corresponding skins get bundled away behind this too. Sucks to be them.
|
||||
Z_Free(name);
|
||||
|
@ -7700,7 +7725,7 @@ static void M_DrawSetupChoosePlayerMenu(void)
|
|||
// Draw prev character if it's visible and its number isn't greater than the current one or there's more than two
|
||||
if (o < 32)
|
||||
{
|
||||
patch = W_CachePatchName(description[prev].picname, PU_CACHE);
|
||||
patch = description[prev].pic;
|
||||
if (SHORT(patch->width) >= 256)
|
||||
V_DrawCroppedPatch(8<<FRACBITS, (my + 8)<<FRACBITS, FRACUNIT/2, 0, patch, 0, SHORT(patch->height) + 2*(o-32), SHORT(patch->width), 64 - 2*o);
|
||||
else
|
||||
|
@ -7711,7 +7736,7 @@ static void M_DrawSetupChoosePlayerMenu(void)
|
|||
// Draw next character if it's visible and its number isn't less than the current one or there's more than two
|
||||
if (o < 128) // (next != i) was previously a part of this, but it's implicitly true if (prev != i) is true.
|
||||
{
|
||||
patch = W_CachePatchName(description[next].picname, PU_CACHE);
|
||||
patch = description[next].pic;
|
||||
if (SHORT(patch->width) >= 256)
|
||||
V_DrawCroppedPatch(8<<FRACBITS, (my + 168 - o)<<FRACBITS, FRACUNIT/2, 0, patch, 0, 0, SHORT(patch->width), 2*o);
|
||||
else
|
||||
|
@ -7720,7 +7745,7 @@ static void M_DrawSetupChoosePlayerMenu(void)
|
|||
}
|
||||
}
|
||||
|
||||
patch = W_CachePatchName(description[i].picname, PU_CACHE);
|
||||
patch = description[i].pic;
|
||||
if (o >= 0 && o <= 32)
|
||||
{
|
||||
if (SHORT(patch->width) >= 256)
|
||||
|
@ -8112,9 +8137,16 @@ void M_DrawTimeAttackMenu(void)
|
|||
V_DrawString(currentMenu->x, cursory, V_YELLOWMAP, currentMenu->menuitems[itemOn].text);
|
||||
|
||||
// Character face!
|
||||
if (W_CheckNumForName(skins[cv_chooseskin.value-1].charsel) != LUMPERROR)
|
||||
{
|
||||
PictureOfUrFace = W_CachePatchName(skins[cv_chooseskin.value-1].charsel, PU_CACHE);
|
||||
if (skins[cv_chooseskin.value-1].sprites[SPR2_XTRA].numframes >= 2)
|
||||
{
|
||||
spritedef_t *sprdef = &skins[cv_chooseskin.value-1].sprites[SPR2_XTRA];
|
||||
spriteframe_t *sprframe = &sprdef->spriteframes[1];
|
||||
PictureOfUrFace = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE);
|
||||
}
|
||||
else
|
||||
PictureOfUrFace = W_CachePatchName("MISSING", PU_CACHE);
|
||||
|
||||
if (PictureOfUrFace->width >= 256)
|
||||
V_DrawTinyScaledPatch(224, 120, 0, PictureOfUrFace);
|
||||
else
|
||||
|
@ -8234,6 +8266,7 @@ static void M_TimeAttack(INT32 choice)
|
|||
M_PatchSkinNameTable();
|
||||
|
||||
G_SetGamestate(GS_TIMEATTACK); // do this before M_SetupNextMenu so that menu meta state knows that we're switching
|
||||
titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please
|
||||
M_SetupNextMenu(&SP_TimeAttackDef);
|
||||
if (!M_CanShowLevelInList(cv_nextmap.value-1, -1) && levelselect.rows[0].maplist[0])
|
||||
CV_SetValue(&cv_nextmap, levelselect.rows[0].maplist[0]);
|
||||
|
@ -8415,6 +8448,7 @@ static void M_NightsAttack(INT32 choice)
|
|||
|
||||
G_SetGamestate(GS_TIMEATTACK); // do this before M_SetupNextMenu so that menu meta state knows that we're switching
|
||||
M_SetupNextMenu(&SP_NightsAttackDef);
|
||||
titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please
|
||||
if (!M_CanShowLevelInList(cv_nextmap.value-1, -1) && levelselect.rows[0].maplist[0])
|
||||
CV_SetValue(&cv_nextmap, levelselect.rows[0].maplist[0]);
|
||||
else
|
||||
|
|
|
@ -316,6 +316,7 @@ typedef struct
|
|||
char notes[441];
|
||||
char picname[8];
|
||||
char skinname[SKINNAMESIZE*2+2]; // skin&skin\0
|
||||
patch_t *pic;
|
||||
UINT8 prev;
|
||||
UINT8 next;
|
||||
} description_t;
|
||||
|
|
|
@ -409,7 +409,7 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type)
|
|||
// new door thinker
|
||||
rtn = 1;
|
||||
ceiling = Z_Calloc(sizeof (*ceiling), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&ceiling->thinker);
|
||||
P_AddThinker(THINK_MAIN, &ceiling->thinker);
|
||||
sec->ceilingdata = ceiling;
|
||||
ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling;
|
||||
ceiling->sector = sec;
|
||||
|
@ -629,7 +629,7 @@ INT32 EV_DoCrush(line_t *line, ceiling_e type)
|
|||
// new door thinker
|
||||
rtn = 1;
|
||||
ceiling = Z_Calloc(sizeof (*ceiling), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&ceiling->thinker);
|
||||
P_AddThinker(THINK_MAIN, &ceiling->thinker);
|
||||
sec->ceilingdata = ceiling;
|
||||
ceiling->thinker.function.acp1 = (actionf_p1)T_CrushCeiling;
|
||||
ceiling->sector = sec;
|
||||
|
|
311
src/p_enemy.c
311
src/p_enemy.c
|
@ -1391,7 +1391,7 @@ void A_StatueBurst(mobj_t *actor)
|
|||
return;
|
||||
|
||||
new->angle = actor->angle;
|
||||
new->target = actor->target;
|
||||
P_SetTarget(&new->target, actor->target);
|
||||
if (locvar2)
|
||||
P_SetMobjState(new, (statenum_t)locvar2);
|
||||
S_StartSound(new, new->info->attacksound);
|
||||
|
@ -2155,7 +2155,7 @@ void A_CrushclawLaunch(mobj_t *actor)
|
|||
for (i = 0; (i < CSEGS); i++)
|
||||
{
|
||||
mobj_t *newchain = P_SpawnMobjFromMobj(actor, 0, 0, 0, actor->info->raisestate);
|
||||
prevchain->target = newchain;
|
||||
P_SetTarget(&prevchain->target, newchain);
|
||||
prevchain = newchain;
|
||||
}
|
||||
actor->target->angle = R_PointToAngle2(actor->target->x, actor->target->y, crab->target->x, crab->target->y);
|
||||
|
@ -2348,7 +2348,7 @@ void A_VultureHover(mobj_t *actor)
|
|||
fixed_t targetz;
|
||||
fixed_t distdif;
|
||||
fixed_t memz = actor->z;
|
||||
INT8 i;
|
||||
SINT8 i;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_VultureHover", actor))
|
||||
|
@ -2411,6 +2411,8 @@ void A_VultureBlast(mobj_t *actor)
|
|||
{
|
||||
mobj_t *dust;
|
||||
UINT8 i;
|
||||
angle_t faa;
|
||||
fixed_t faacos, faasin;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_VultureBlast", actor))
|
||||
|
@ -2419,18 +2421,21 @@ void A_VultureBlast(mobj_t *actor)
|
|||
|
||||
S_StartSound(actor, actor->info->attacksound);
|
||||
|
||||
faa = (actor->angle >> ANGLETOFINESHIFT) & FINEMASK;
|
||||
faacos = FINECOSINE(faa);
|
||||
faasin = FINESINE(faa);
|
||||
|
||||
for (i = 0; i <= 7; i++)
|
||||
{
|
||||
angle_t fa = ((i*(angle_t)ANGLE_45) >> ANGLETOFINESHIFT) & FINEMASK;
|
||||
angle_t faa = (actor->angle >> ANGLETOFINESHIFT) & FINEMASK;
|
||||
dust = P_SpawnMobj(actor->x + 48*FixedMul(FINECOSINE(fa), -FINESINE(faa)), actor->y + 48*FixedMul(FINECOSINE(fa), FINECOSINE(faa)), actor->z + actor->height/2 + 48*FINESINE(fa), MT_PARTICLE);
|
||||
dust = P_SpawnMobj(actor->x + 48*FixedMul(FINECOSINE(fa), -faasin), actor->y + 48*FixedMul(FINECOSINE(fa), faacos), actor->z + actor->height/2 + 48*FINESINE(fa), MT_PARTICLE);
|
||||
|
||||
P_SetScale(dust, 4*FRACUNIT);
|
||||
dust->destscale = FRACUNIT;
|
||||
dust->scalespeed = 4*FRACUNIT/TICRATE;
|
||||
dust->fuse = TICRATE;
|
||||
dust->momx = FixedMul(FINECOSINE(fa), -FINESINE(faa))*3;
|
||||
dust->momy = FixedMul(FINECOSINE(fa), FINECOSINE(faa))*3;
|
||||
dust->momx = FixedMul(FINECOSINE(fa), -faasin)*3;
|
||||
dust->momy = FixedMul(FINECOSINE(fa), faacos)*3;
|
||||
dust->momz = FINESINE(fa)*6;
|
||||
}
|
||||
}
|
||||
|
@ -2858,6 +2863,7 @@ void A_BossFireShot(mobj_t *actor)
|
|||
fixed_t x, y, z;
|
||||
INT32 locvar1 = var1;
|
||||
INT32 locvar2 = var2;
|
||||
mobj_t *missile;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_BossFireShot", actor))
|
||||
|
@ -2925,7 +2931,10 @@ void A_BossFireShot(mobj_t *actor)
|
|||
break;
|
||||
}
|
||||
|
||||
P_SpawnXYZMissile(actor, actor->target, locvar1, x, y, z);
|
||||
missile = P_SpawnXYZMissile(actor, actor->target, locvar1, x, y, z);
|
||||
|
||||
if (missile && actor->tracer && (actor->tracer->flags & MF_BOSS)) // Don't harm your papa.
|
||||
P_SetTarget(&missile->target, actor->tracer);
|
||||
}
|
||||
|
||||
// Function: A_Boss7FireMissiles
|
||||
|
@ -3079,7 +3088,7 @@ void A_Boss1Laser(mobj_t *actor)
|
|||
if (z - floorz < mobjinfo[MT_EGGMOBILE_FIRE].height>>1)
|
||||
{
|
||||
point = P_SpawnMobj(x, y, floorz+1, MT_EGGMOBILE_FIRE);
|
||||
point->target = actor;
|
||||
P_SetTarget(&point->target, actor);
|
||||
point->destscale = 3*FRACUNIT;
|
||||
point->scalespeed = FRACUNIT>>2;
|
||||
point->fuse = TICRATE;
|
||||
|
@ -3154,21 +3163,35 @@ void A_FocusTarget(mobj_t *actor)
|
|||
// Description: Reverse arms direction.
|
||||
//
|
||||
// var1 = sfx to play
|
||||
// var2 = unused
|
||||
// var2 = sfx to play in pinch
|
||||
//
|
||||
void A_Boss4Reverse(mobj_t *actor)
|
||||
{
|
||||
sfxenum_t locvar1 = (sfxenum_t)var1;
|
||||
sfxenum_t locvar2 = (sfxenum_t)var2;
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_Boss4Reverse", actor))
|
||||
return;
|
||||
#endif
|
||||
S_StartSound(NULL, locvar1);
|
||||
actor->reactiontime = 0;
|
||||
if (actor->movedir == 1)
|
||||
actor->movedir = 2;
|
||||
if (actor->movedir < 3)
|
||||
{
|
||||
S_StartSound(NULL, locvar1);
|
||||
if (actor->movedir == 1)
|
||||
actor->movedir = 2;
|
||||
else
|
||||
actor->movedir = 1;
|
||||
}
|
||||
else
|
||||
actor->movedir = 1;
|
||||
{
|
||||
S_StartSound(NULL, locvar2);
|
||||
if (actor->movedir == 4)
|
||||
actor->movedir = 5;
|
||||
else
|
||||
actor->movedir = 4;
|
||||
actor->angle += ANGLE_180;
|
||||
actor->movefactor = -actor->movefactor;
|
||||
}
|
||||
}
|
||||
|
||||
// Function: A_Boss4SpeedUp
|
||||
|
@ -3465,9 +3488,11 @@ void A_1upThinker(mobj_t *actor)
|
|||
|
||||
if (closestplayer == -1 || skins[players[closestplayer].skin].sprites[SPR2_LIFE].numframes == 0)
|
||||
{ // Closest player not found (no players in game?? may be empty dedicated server!), or does not have correct sprite.
|
||||
if (actor->tracer) {
|
||||
P_RemoveMobj(actor->tracer);
|
||||
actor->tracer = NULL;
|
||||
if (actor->tracer)
|
||||
{
|
||||
mobj_t *tracer = actor->tracer;
|
||||
P_SetTarget(&actor->tracer, NULL);
|
||||
P_RemoveMobj(tracer);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -3761,9 +3786,9 @@ void A_BossDeath(mobj_t *mo)
|
|||
|
||||
// scan the remaining thinkers to see
|
||||
// if all bosses are dead
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
@ -3853,6 +3878,8 @@ bossjustdie:
|
|||
}
|
||||
default: //eggmobiles
|
||||
{
|
||||
UINT8 extrainfo = (mo->spawnpoint ? mo->spawnpoint->extrainfo : 0);
|
||||
|
||||
// Stop exploding and prepare to run.
|
||||
P_SetMobjState(mo, mo->info->xdeathstate);
|
||||
if (P_MobjWasRemoved(mo))
|
||||
|
@ -3862,9 +3889,9 @@ bossjustdie:
|
|||
|
||||
// Flee! Flee! Find a point to escape to! If none, just shoot upward!
|
||||
// scan the thinkers to find the runaway point
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
@ -3872,6 +3899,9 @@ bossjustdie:
|
|||
if (mo2->type != MT_BOSSFLYPOINT)
|
||||
continue;
|
||||
|
||||
if (mo2->spawnpoint && mo2->spawnpoint->extrainfo != extrainfo)
|
||||
continue;
|
||||
|
||||
// If this one's further then the last one, don't go for it.
|
||||
if (mo->target &&
|
||||
P_AproxDistance(P_AproxDistance(mo->x - mo2->x, mo->y - mo2->y), mo->z - mo2->z) >
|
||||
|
@ -6118,9 +6148,9 @@ void A_RingExplode(mobj_t *actor)
|
|||
|
||||
S_StartSound(actor, sfx_prloop);
|
||||
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
@ -6631,6 +6661,9 @@ void A_RecyclePowers(mobj_t *actor)
|
|||
players[recv_pl].ringweapons = weapons[send_pl];
|
||||
players[recv_pl].currentweapon = weaponheld[send_pl];
|
||||
|
||||
if (((players[recv_pl].powers[pw_shield] & SH_NOSTACK) == SH_PINK) && (players[recv_pl].revitem == MT_LHRT || players[recv_pl].spinitem == MT_LHRT || players[recv_pl].thokitem == MT_LHRT)) // Healers can't keep their buff.
|
||||
players[recv_pl].powers[pw_shield] &= SH_STACK;
|
||||
|
||||
P_SpawnShieldOrb(&players[recv_pl]);
|
||||
if (P_IsLocalPlayer(&players[recv_pl]))
|
||||
P_RestoreMusic(&players[recv_pl]);
|
||||
|
@ -7246,7 +7279,7 @@ void A_Boss2PogoTarget(mobj_t *actor)
|
|||
if (actor->info->missilestate) // spawn the pogo stick collision box
|
||||
{
|
||||
mobj_t *pogo = P_SpawnMobj(actor->x, actor->y, actor->z - mobjinfo[actor->info->missilestate].height, (mobjtype_t)actor->info->missilestate);
|
||||
pogo->target = actor;
|
||||
P_SetTarget(&pogo->target, actor);
|
||||
}
|
||||
|
||||
actor->reactiontime = 1;
|
||||
|
@ -7762,9 +7795,11 @@ void A_Boss3TakeDamage(mobj_t *actor)
|
|||
return;
|
||||
#endif
|
||||
actor->movecount = var1;
|
||||
actor->movefactor = -512*FRACUNIT;
|
||||
|
||||
/*if (actor->target && actor->target->spawnpoint)
|
||||
actor->threshold = actor->target->spawnpoint->extrainfo;*/
|
||||
|
||||
if (actor->target && actor->target->spawnpoint)
|
||||
actor->threshold = actor->target->spawnpoint->extrainfo;
|
||||
}
|
||||
|
||||
// Function: A_Boss3Path
|
||||
|
@ -7801,24 +7836,34 @@ void A_Boss3Path(mobj_t *actor)
|
|||
}
|
||||
else if (actor->threshold >= 0) // Traveling mode
|
||||
{
|
||||
thinker_t *th;
|
||||
mobj_t *mo2;
|
||||
fixed_t dist, dist2;
|
||||
fixed_t dist = 0;
|
||||
fixed_t speed;
|
||||
|
||||
P_SetTarget(&actor->target, NULL);
|
||||
|
||||
// scan the thinkers
|
||||
// to find a point that matches
|
||||
// the number
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
if (!(actor->flags2 & MF2_STRONGBOX))
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
continue;
|
||||
thinker_t *th;
|
||||
mobj_t *mo2;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint && mo2->spawnpoint->angle == actor->threshold)
|
||||
P_SetTarget(&actor->target, NULL);
|
||||
|
||||
// scan the thinkers
|
||||
// to find a point that matches
|
||||
// the number
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
if (mo2->type != MT_BOSS3WAYPOINT)
|
||||
continue;
|
||||
if (!mo2->spawnpoint)
|
||||
continue;
|
||||
if (mo2->spawnpoint->angle != actor->threshold)
|
||||
continue;
|
||||
if (mo2->spawnpoint->extrainfo != actor->cusval)
|
||||
continue;
|
||||
|
||||
P_SetTarget(&actor->target, mo2);
|
||||
break;
|
||||
}
|
||||
|
@ -7826,67 +7871,62 @@ void A_Boss3Path(mobj_t *actor)
|
|||
|
||||
if (!actor->target) // Should NEVER happen
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Error: Boss 3 Dummy was unable to find specified waypoint: %d\n", actor->threshold);
|
||||
CONS_Debug(DBG_GAMELOGIC, "Error: Boss 3 Dummy was unable to find specified waypoint: %d, %d\n", actor->threshold, actor->cusval);
|
||||
return;
|
||||
}
|
||||
|
||||
dist = P_AproxDistance(P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y), actor->target->z - actor->z);
|
||||
|
||||
if (dist < 1)
|
||||
dist = 1;
|
||||
|
||||
if (actor->tracer && ((actor->tracer->movedir)
|
||||
|| (actor->tracer->health <= actor->tracer->info->damage)))
|
||||
speed = actor->info->speed * 2;
|
||||
else
|
||||
speed = actor->info->speed;
|
||||
|
||||
actor->momx = FixedMul(FixedDiv(actor->target->x - actor->x, dist), speed);
|
||||
actor->momy = FixedMul(FixedDiv(actor->target->y - actor->y, dist), speed);
|
||||
actor->momz = FixedMul(FixedDiv(actor->target->z - actor->z, dist), speed);
|
||||
if (actor->target->x == actor->x && actor->target->y == actor->y)
|
||||
{
|
||||
dist = P_AproxDistance(P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y), actor->target->z + actor->movefactor - actor->z);
|
||||
|
||||
if (actor->momx != 0 || actor->momy != 0)
|
||||
actor->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy);
|
||||
if (dist < 1)
|
||||
dist = 1;
|
||||
|
||||
dist2 = P_AproxDistance(P_AproxDistance(actor->target->x - (actor->x + actor->momx), actor->target->y - (actor->y + actor->momy)), actor->target->z - (actor->z + actor->momz));
|
||||
actor->momx = FixedMul(FixedDiv(actor->target->x - actor->x, dist), speed);
|
||||
actor->momy = FixedMul(FixedDiv(actor->target->y - actor->y, dist), speed);
|
||||
actor->momz = FixedMul(FixedDiv(actor->target->z + actor->movefactor - actor->z, dist), speed);
|
||||
|
||||
if (dist2 < 1)
|
||||
dist2 = 1;
|
||||
if (actor->momx != 0 || actor->momy != 0)
|
||||
actor->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy);
|
||||
}
|
||||
|
||||
if ((dist >> FRACBITS) <= (dist2 >> FRACBITS))
|
||||
if (dist <= speed)
|
||||
{
|
||||
// If further away, set XYZ of mobj to waypoint location
|
||||
P_UnsetThingPosition(actor);
|
||||
actor->x = actor->target->x;
|
||||
actor->y = actor->target->y;
|
||||
actor->z = actor->target->z;
|
||||
actor->z = actor->target->z + actor->movefactor;
|
||||
actor->momx = actor->momy = actor->momz = 0;
|
||||
P_SetThingPosition(actor);
|
||||
|
||||
if (actor->threshold == 0)
|
||||
if (!actor->movefactor) // firing mode
|
||||
{
|
||||
actor->movecount |= 2;
|
||||
actor->movefactor = -512*FRACUNIT;
|
||||
actor->flags2 &= ~MF2_STRONGBOX;
|
||||
}
|
||||
else if (!(actor->flags2 & MF2_STRONGBOX)) // just spawned or going down
|
||||
{
|
||||
actor->flags2 |= MF2_STRONGBOX;
|
||||
actor->movefactor = -512*FRACUNIT;
|
||||
}
|
||||
else if (!(actor->flags2 & MF2_AMBUSH)) // just shifted tube
|
||||
{
|
||||
actor->flags2 |= MF2_AMBUSH;
|
||||
actor->movefactor = 0;
|
||||
}
|
||||
else // just hit the bottom of your tube
|
||||
{
|
||||
P_RemoveMobj(actor); // Cycle completed. Dummy removed.
|
||||
return;
|
||||
}
|
||||
|
||||
// Set to next waypoint in sequence
|
||||
if (actor->target->spawnpoint)
|
||||
{
|
||||
// From the center point, choose one of the five paths
|
||||
if (actor->target->spawnpoint->angle == 0)
|
||||
{
|
||||
P_RemoveMobj(actor); // Cycle completed. Dummy removed.
|
||||
return;
|
||||
}
|
||||
else
|
||||
actor->threshold = actor->target->spawnpoint->extrainfo;
|
||||
|
||||
// If the deaf flag is set, go into firing mode
|
||||
if (actor->target->spawnpoint->options & MTF_AMBUSH)
|
||||
actor->movecount |= 2;
|
||||
}
|
||||
else // This should never happen, as well
|
||||
CONS_Debug(DBG_GAMELOGIC, "Error: Boss 3 Dummy waypoint has no spawnpoint associated with it.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8204,9 +8244,9 @@ void A_FindTarget(mobj_t *actor)
|
|||
CONS_Debug(DBG_GAMELOGIC, "A_FindTarget called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2);
|
||||
|
||||
// scan the thinkers
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
@ -8269,9 +8309,9 @@ void A_FindTracer(mobj_t *actor)
|
|||
CONS_Debug(DBG_GAMELOGIC, "A_FindTracer called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2);
|
||||
|
||||
// scan the thinkers
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
@ -8684,8 +8724,8 @@ void A_BossJetFume(mobj_t *actor)
|
|||
{
|
||||
fixed_t jetx, jety, jetz;
|
||||
|
||||
jetx = actor->x + P_ReturnThrustX(actor, actor->angle, -FixedMul(60*FRACUNIT, actor->scale));
|
||||
jety = actor->y + P_ReturnThrustY(actor, actor->angle, -FixedMul(60*FRACUNIT, actor->scale));
|
||||
jetx = actor->x + P_ReturnThrustX(actor, actor->angle, -60*actor->scale);
|
||||
jety = actor->y + P_ReturnThrustY(actor, actor->angle, -60*actor->scale);
|
||||
if (actor->eflags & MFE_VERTICALFLIP)
|
||||
jetz = actor->z + actor->height - FixedMul(17*FRACUNIT + mobjinfo[MT_PROPELLER].height, actor->scale);
|
||||
else
|
||||
|
@ -8718,7 +8758,7 @@ void A_BossJetFume(mobj_t *actor)
|
|||
if (actor->eflags & MFE_VERTICALFLIP)
|
||||
jetz = actor->z + actor->height + FixedMul(50*FRACUNIT - mobjinfo[MT_JETFLAME].height, actor->scale);
|
||||
else
|
||||
jetz = actor->z - FixedMul(50*FRACUNIT, actor->scale);
|
||||
jetz = actor->z - 50*actor->scale;
|
||||
filler = P_SpawnMobj(actor->x, actor->y, jetz, MT_JETFLAME);
|
||||
P_SetTarget(&filler->target, actor);
|
||||
// Boss 4 already uses its tracer for other things
|
||||
|
@ -8727,6 +8767,30 @@ void A_BossJetFume(mobj_t *actor)
|
|||
if (actor->eflags & MFE_VERTICALFLIP)
|
||||
filler->flags2 |= MF2_OBJECTFLIP;
|
||||
}
|
||||
else if (locvar1 == 4) // Boss 4 Spectator Eggrobo jet flame
|
||||
{
|
||||
fixed_t jetx, jety, jetz, movefactor = 12;
|
||||
|
||||
jetz = actor->z;
|
||||
if (actor->eflags & MFE_VERTICALFLIP)
|
||||
jetz += (actor->height - FixedMul(mobjinfo[MT_EGGROBO1JET].height, actor->scale));
|
||||
|
||||
while (true)
|
||||
{
|
||||
jetx = actor->x + P_ReturnThrustX(actor, actor->angle+ANGLE_90, movefactor*actor->scale) - P_ReturnThrustX(actor, actor->angle, 19*actor->scale);
|
||||
jety = actor->y + P_ReturnThrustY(actor, actor->angle+ANGLE_90, movefactor*actor->scale) - P_ReturnThrustY(actor, actor->angle, 19*actor->scale);
|
||||
filler = P_SpawnMobj(jetx, jety, jetz, MT_EGGROBO1JET);
|
||||
filler->movefactor = movefactor;
|
||||
P_SetTarget(&filler->target, actor);
|
||||
filler->destscale = actor->scale;
|
||||
P_SetScale(filler, filler->destscale);
|
||||
if (actor->eflags & MFE_VERTICALFLIP)
|
||||
filler->flags2 |= MF2_OBJECTFLIP;
|
||||
if (movefactor <= 0)
|
||||
break;
|
||||
movefactor = -movefactor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Function: A_RandomState
|
||||
|
@ -8832,9 +8896,9 @@ void A_RemoteAction(mobj_t *actor)
|
|||
fixed_t dist1 = 0, dist2 = 0;
|
||||
|
||||
// scan the thinkers
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
@ -9098,9 +9162,9 @@ void A_SetObjectTypeState(mobj_t *actor)
|
|||
return;
|
||||
#endif
|
||||
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
@ -9736,9 +9800,9 @@ void A_CheckThingCount(mobj_t *actor)
|
|||
return;
|
||||
#endif
|
||||
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
@ -12244,6 +12308,7 @@ void A_Boss5FindWaypoint(mobj_t *actor)
|
|||
//INT32 locvar2 = var2;
|
||||
boolean avoidcenter;
|
||||
UINT32 i;
|
||||
UINT8 extrainfo = (actor->spawnpoint ? actor->spawnpoint->extrainfo : 0);
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_Boss5FindWaypoint", actor))
|
||||
return;
|
||||
|
@ -12253,16 +12318,34 @@ void A_Boss5FindWaypoint(mobj_t *actor)
|
|||
|
||||
if (locvar1 == 2) // look for the boss waypoint
|
||||
{
|
||||
for (i = 0; i < nummapthings; i++)
|
||||
thinker_t *th;
|
||||
mobj_t *mo2;
|
||||
P_SetTarget(&actor->tracer, NULL);
|
||||
// Flee! Flee! Find a point to escape to! If none, just shoot upward!
|
||||
// scan the thinkers to find the runaway point
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (!mapthings[i].mobj)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
if (mapthings[i].mobj->type != MT_BOSSFLYPOINT)
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
||||
if (mo2->type != MT_BOSSFLYPOINT)
|
||||
continue;
|
||||
P_SetTarget(&actor->tracer, mapthings[i].mobj);
|
||||
break;
|
||||
|
||||
if (mo2->spawnpoint && mo2->spawnpoint->extrainfo != extrainfo)
|
||||
continue;
|
||||
|
||||
// If this one's further then the last one, don't go for it.
|
||||
if (actor->tracer &&
|
||||
P_AproxDistance(P_AproxDistance(actor->x - mo2->x, actor->y - mo2->y), actor->z - mo2->z) >
|
||||
P_AproxDistance(P_AproxDistance(actor->x - actor->tracer->x, actor->y - actor->tracer->y), actor->z - actor->tracer->z))
|
||||
continue;
|
||||
|
||||
// Otherwise... Do!
|
||||
P_SetTarget(&actor->tracer, mo2);
|
||||
}
|
||||
if (i == nummapthings)
|
||||
if (!actor->tracer)
|
||||
return; // no boss flypoints found
|
||||
}
|
||||
else if (locvar1 == 1) // always go to ambush-marked waypoint
|
||||
|
@ -12276,11 +12359,13 @@ void A_Boss5FindWaypoint(mobj_t *actor)
|
|||
continue;
|
||||
if (mapthings[i].mobj->type != MT_FANGWAYPOINT)
|
||||
continue;
|
||||
if (mapthings[i].options & MTF_AMBUSH)
|
||||
{
|
||||
P_SetTarget(&actor->tracer, mapthings[i].mobj);
|
||||
break;
|
||||
}
|
||||
if (mapthings[i].extrainfo != extrainfo)
|
||||
continue;
|
||||
if (!(mapthings[i].options & MTF_AMBUSH))
|
||||
continue;
|
||||
|
||||
P_SetTarget(&actor->tracer, mapthings[i].mobj);
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == nummapthings)
|
||||
|
@ -12304,6 +12389,8 @@ void A_Boss5FindWaypoint(mobj_t *actor)
|
|||
continue;
|
||||
if (actor->tracer == mapthings[i].mobj) // this was your tracer last time
|
||||
continue;
|
||||
if (mapthings[i].extrainfo != extrainfo)
|
||||
continue;
|
||||
if (mapthings[i].options & MTF_AMBUSH)
|
||||
{
|
||||
if (avoidcenter)
|
||||
|
@ -12359,6 +12446,8 @@ void A_Boss5FindWaypoint(mobj_t *actor)
|
|||
continue;
|
||||
if (actor->tracer == mapthings[i].mobj) // this was your tracer last time
|
||||
continue;
|
||||
if (mapthings[i].extrainfo != extrainfo)
|
||||
continue;
|
||||
if (mapthings[i].options & MTF_AMBUSH)
|
||||
{
|
||||
if (avoidcenter)
|
||||
|
@ -13015,7 +13104,14 @@ static boolean PIT_TNTExplode(mobj_t *nearby)
|
|||
nearby->momx = FixedMul(FixedDiv(dx, dm), explodethrust);
|
||||
nearby->momy = FixedMul(FixedDiv(dy, dm), explodethrust);
|
||||
nearby->momz = FixedMul(FixedDiv(dz, dm), explodethrust);
|
||||
P_UnsetThingPosition(nearby);
|
||||
if (sector_list)
|
||||
{
|
||||
P_DelSeclist(sector_list);
|
||||
sector_list = NULL;
|
||||
}
|
||||
nearby->flags = MF_NOBLOCKMAP|MF_MISSILE;
|
||||
P_SetThingPosition(nearby);
|
||||
P_SetMobjState(nearby, nearby->info->missilestate);
|
||||
}
|
||||
}
|
||||
|
@ -13024,9 +13120,10 @@ static boolean PIT_TNTExplode(mobj_t *nearby)
|
|||
if (barrel->target == nearby)
|
||||
{
|
||||
mobj_t *tar = barrel->target; // temporarily store barrel's target
|
||||
barrel->target = NULL;
|
||||
P_SetTarget(&barrel->target, NULL);
|
||||
P_DamageMobj(nearby, barrel, NULL, 1, 0);
|
||||
barrel->target = tar;
|
||||
if (!P_MobjWasRemoved(barrel))
|
||||
P_SetTarget(&barrel->target, tar);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -13059,8 +13156,14 @@ void A_TNTExplode(mobj_t *actor)
|
|||
if (LUA_CallAction("A_TNTExplode", actor))
|
||||
return;
|
||||
#endif
|
||||
|
||||
P_UnsetThingPosition(actor);
|
||||
if (sector_list)
|
||||
{
|
||||
P_DelSeclist(sector_list);
|
||||
sector_list = NULL;
|
||||
}
|
||||
actor->flags = MF_NOCLIP|MF_NOGRAVITY|MF_NOBLOCKMAP;
|
||||
P_SetThingPosition(actor);
|
||||
actor->flags2 = MF2_EXPLOSION;
|
||||
if (actor->info->deathsound)
|
||||
S_StartSound(actor, actor->info->deathsound);
|
||||
|
@ -13522,7 +13625,7 @@ void A_SaloonDoorSpawn(mobj_t *actor)
|
|||
door->extravalue2 = 0;
|
||||
|
||||
// Origin door
|
||||
door->tracer = actor;
|
||||
P_SetTarget(&door->tracer, actor);
|
||||
|
||||
//Back
|
||||
door = P_SpawnMobj(x - c*d, y - s*d, z, MT_SALOONDOOR);
|
||||
|
@ -13535,7 +13638,7 @@ void A_SaloonDoorSpawn(mobj_t *actor)
|
|||
door->extravalue2 = 0;
|
||||
|
||||
// Origin door
|
||||
door->tracer = actor;
|
||||
P_SetTarget(&door->tracer, actor);
|
||||
}
|
||||
|
||||
// Function: A_MinecartSparkThink
|
||||
|
|
|
@ -719,6 +719,8 @@ void T_ContinuousFalling(levelspecthink_t *faller)
|
|||
}
|
||||
}
|
||||
|
||||
P_CheckSector(faller->sector, false); // you might think this is irrelevant. you would be wrong
|
||||
|
||||
faller->sector->floorspeed = faller->speed*faller->direction;
|
||||
faller->sector->ceilspeed = 42;
|
||||
faller->sector->moved = true;
|
||||
|
@ -1975,25 +1977,27 @@ void T_ThwompSector(levelspecthink_t *thwomp)
|
|||
}
|
||||
else // Not going anywhere, so look for players.
|
||||
{
|
||||
thinker_t *th;
|
||||
mobj_t *mo;
|
||||
|
||||
if (!rover || (rover->flags & FF_EXISTS))
|
||||
{
|
||||
// scan the thinkers to find players!
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
UINT8 i;
|
||||
// scan the players to find victims!
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
if (players[i].spectator)
|
||||
continue;
|
||||
if (!players[i].mo)
|
||||
continue;
|
||||
if (!players[i].mo->health)
|
||||
continue;
|
||||
if (players[i].mo->z > thwomp->sector->ceilingheight)
|
||||
continue;
|
||||
if (P_AproxDistance(thwompx - players[i].mo->x, thwompy - players[i].mo->y) > 96 * FRACUNIT)
|
||||
continue;
|
||||
|
||||
mo = (mobj_t *)th;
|
||||
if (mo->type == MT_PLAYER && mo->health && mo->player && !mo->player->spectator
|
||||
&& mo->z <= thwomp->sector->ceilingheight
|
||||
&& P_AproxDistance(thwompx - mo->x, thwompy - mo->y) <= 96*FRACUNIT)
|
||||
{
|
||||
thwomp->direction = -1;
|
||||
break;
|
||||
}
|
||||
thwomp->direction = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2701,7 +2705,7 @@ INT32 EV_DoFloor(line_t *line, floor_e floortype)
|
|||
// new floor thinker
|
||||
rtn = 1;
|
||||
dofloor = Z_Calloc(sizeof (*dofloor), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&dofloor->thinker);
|
||||
P_AddThinker(THINK_MAIN, &dofloor->thinker);
|
||||
|
||||
// make sure another floor thinker won't get started over this one
|
||||
sec->floordata = dofloor;
|
||||
|
@ -2922,7 +2926,7 @@ INT32 EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed)
|
|||
// create and initialize new elevator thinker
|
||||
rtn = 1;
|
||||
elevator = Z_Calloc(sizeof (*elevator), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&elevator->thinker);
|
||||
P_AddThinker(THINK_MAIN, &elevator->thinker);
|
||||
sec->floordata = elevator;
|
||||
sec->ceilingdata = elevator;
|
||||
elevator->thinker.function.acp1 = (actionf_p1)T_MoveElevator;
|
||||
|
@ -3027,20 +3031,40 @@ INT32 EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed)
|
|||
|
||||
void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
|
||||
{
|
||||
size_t i;
|
||||
size_t leftmostvertex = 0, rightmostvertex = 0;
|
||||
size_t topmostvertex = 0, bottommostvertex = 0;
|
||||
fixed_t leftx, rightx;
|
||||
fixed_t topy, bottomy;
|
||||
fixed_t topz, bottomz;
|
||||
fixed_t widthfactor = FRACUNIT, heightfactor = FRACUNIT;
|
||||
fixed_t a, b, c;
|
||||
mobjtype_t type = MT_ROCKCRUMBLE1;
|
||||
fixed_t spacing = (32<<FRACBITS);
|
||||
tic_t lifetime = 3*TICRATE;
|
||||
INT16 flags = 0;
|
||||
size_t i, leftmostvertex, rightmostvertex, topmostvertex, bottommostvertex;
|
||||
fixed_t leftx, rightx, topy, bottomy, topz, bottomz, widthfactor, heightfactor, a, b, c, spacing;
|
||||
mobjtype_t type;
|
||||
tic_t lifetime;
|
||||
INT16 flags;
|
||||
|
||||
#define controlsec rover->master->frontsector
|
||||
sector_t *controlsec = rover->master->frontsector;
|
||||
|
||||
if (sec == NULL)
|
||||
{
|
||||
if (controlsec->numattached)
|
||||
{
|
||||
for (i = 0; i < controlsec->numattached; i++)
|
||||
{
|
||||
sec = §ors[controlsec->attached[i]];
|
||||
if (!sec->ffloors)
|
||||
continue;
|
||||
|
||||
for (rover = sec->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
if (rover->master->frontsector == controlsec)
|
||||
EV_CrumbleChain(sec, rover);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
leftmostvertex = rightmostvertex = topmostvertex = bottommostvertex = 0;
|
||||
widthfactor = heightfactor = FRACUNIT;
|
||||
spacing = (32<<FRACBITS);
|
||||
type = MT_ROCKCRUMBLE1;
|
||||
lifetime = 3*TICRATE;
|
||||
flags = 0;
|
||||
|
||||
if (controlsec->tag != 0)
|
||||
{
|
||||
|
@ -3133,7 +3157,7 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
|
|||
// no longer exists (can't collide with again)
|
||||
rover->flags &= ~FF_EXISTS;
|
||||
rover->master->frontsector->moved = true;
|
||||
sec->moved = true;
|
||||
P_RecalcPrecipInSector(sec);
|
||||
}
|
||||
|
||||
// Used for bobbing platforms on the water
|
||||
|
@ -3149,7 +3173,7 @@ INT32 EV_BounceSector(sector_t *sec, fixed_t momz, line_t *sourceline)
|
|||
return 0;
|
||||
|
||||
bouncer = Z_Calloc(sizeof (*bouncer), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&bouncer->thinker);
|
||||
P_AddThinker(THINK_MAIN, &bouncer->thinker);
|
||||
sec->ceilingdata = bouncer;
|
||||
bouncer->thinker.function.acp1 = (actionf_p1)T_BounceCheese;
|
||||
|
||||
|
@ -3183,7 +3207,7 @@ INT32 EV_DoContinuousFall(sector_t *sec, sector_t *backsector, fixed_t spd, bool
|
|||
|
||||
// create and initialize new thinker
|
||||
faller = Z_Calloc(sizeof (*faller), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&faller->thinker);
|
||||
P_AddThinker(THINK_MAIN, &faller->thinker);
|
||||
faller->thinker.function.acp1 = (actionf_p1)T_ContinuousFalling;
|
||||
|
||||
// set up the fields
|
||||
|
@ -3232,7 +3256,7 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating,
|
|||
|
||||
// create and initialize new elevator thinker
|
||||
elevator = Z_Calloc(sizeof (*elevator), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&elevator->thinker);
|
||||
P_AddThinker(THINK_MAIN, &elevator->thinker);
|
||||
elevator->thinker.function.acp1 = (actionf_p1)T_StartCrumble;
|
||||
|
||||
// Does this crumbler return?
|
||||
|
@ -3311,7 +3335,7 @@ INT32 EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher)
|
|||
// create and initialize new elevator thinker
|
||||
|
||||
block = Z_Calloc(sizeof (*block), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&block->thinker);
|
||||
P_AddThinker(THINK_MAIN, &block->thinker);
|
||||
roversec->floordata = block;
|
||||
roversec->ceilingdata = block;
|
||||
block->thinker.function.acp1 = (actionf_p1)T_MarioBlock;
|
||||
|
|
224
src/p_inter.c
224
src/p_inter.c
|
@ -97,9 +97,9 @@ void P_ClearStarPost(INT32 postnum)
|
|||
mobj_t *mo2;
|
||||
|
||||
// scan the thinkers
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
@ -126,15 +126,17 @@ void P_ResetStarposts(void)
|
|||
thinker_t *th;
|
||||
mobj_t *post;
|
||||
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
post = (mobj_t *)th;
|
||||
|
||||
if (post->type == MT_STARPOST)
|
||||
P_SetMobjState(post, post->info->spawnstate);
|
||||
if (post->type != MT_STARPOST)
|
||||
continue;
|
||||
|
||||
P_SetMobjState(post, post->info->spawnstate);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -321,6 +323,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
// Can happen with a sliding player corpse.
|
||||
if (toucher->health <= 0)
|
||||
return;
|
||||
if (special->health <= 0)
|
||||
return;
|
||||
|
||||
if (heightcheck)
|
||||
{
|
||||
|
@ -346,9 +350,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
}
|
||||
}
|
||||
|
||||
if (special->health <= 0)
|
||||
return;
|
||||
|
||||
player = toucher->player;
|
||||
I_Assert(player != NULL); // Only players can touch stuff!
|
||||
|
||||
|
@ -453,13 +454,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
break;
|
||||
}
|
||||
|
||||
if (((player->powers[pw_carry] == CR_NIGHTSMODE) && (player->pflags & PF_DRILLING))
|
||||
|| ((player->pflags & PF_JUMPED) && (!(player->pflags & PF_NOJUMPDAMAGE) || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY)))
|
||||
|| (player->pflags & (PF_SPINNING|PF_GLIDING))
|
||||
|| (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2)
|
||||
|| ((player->charflags & SF_STOMPDAMAGE || player->pflags & PF_BOUNCING) && (P_MobjFlip(toucher)*(toucher->z - (special->z + special->height/2)) > 0) && (P_MobjFlip(toucher)*toucher->momz < 0))
|
||||
|| player->powers[pw_invulnerability] || player->powers[pw_super]
|
||||
|| elementalpierce) // Do you possess the ability to subdue the object?
|
||||
if (P_PlayerCanDamage(player, special)) // Do you possess the ability to subdue the object?
|
||||
{
|
||||
if ((P_MobjFlip(toucher)*toucher->momz < 0) && (elementalpierce != 1))
|
||||
{
|
||||
|
@ -474,18 +469,12 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
{
|
||||
toucher->momx = -toucher->momx;
|
||||
toucher->momy = -toucher->momy;
|
||||
if (player->charability == CA_FLY && player->panim == PA_ABILITY)
|
||||
toucher->momz = -toucher->momz/2;
|
||||
}
|
||||
P_DamageMobj(special, toucher, toucher, 1, 0);
|
||||
}
|
||||
else if (((toucher->z < special->z && !(toucher->eflags & MFE_VERTICALFLIP))
|
||||
|| (toucher->z + toucher->height > special->z + special->height && (toucher->eflags & MFE_VERTICALFLIP)))
|
||||
&& player->charability == CA_FLY
|
||||
&& (player->powers[pw_tailsfly]
|
||||
|| toucher->state-states == S_PLAY_FLY_TIRED)) // Tails can shred stuff with her propeller.
|
||||
{
|
||||
toucher->momz = -toucher->momz/2;
|
||||
|
||||
P_DamageMobj(special, toucher, toucher, 1, 0);
|
||||
if (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY)
|
||||
P_TwinSpinRejuvenate(player, player->thokitem);
|
||||
}
|
||||
else
|
||||
P_DamageMobj(toucher, special, special, 1, 0);
|
||||
|
@ -681,7 +670,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
P_DoMatchSuper(player);
|
||||
}
|
||||
else
|
||||
{
|
||||
emeralds |= special->info->speed;
|
||||
stagefailed = false;
|
||||
}
|
||||
|
||||
if (special->target && special->target->type == MT_EMERALDSPAWN)
|
||||
{
|
||||
|
@ -845,24 +837,24 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
// The player might have two Ideyas: toucher->tracer and toucher->tracer->hnext
|
||||
// so handle their anchorpoints accordingly.
|
||||
// scan the thinkers to find the corresponding anchorpoint
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
||||
if (mo2->type == MT_IDEYAANCHOR)
|
||||
{
|
||||
if (mo2->health == toucher->tracer->health) // do ideya numberes match?
|
||||
anchorpoint = mo2;
|
||||
else if (toucher->tracer->hnext && mo2->health == toucher->tracer->hnext->health)
|
||||
anchorpoint2 = mo2;
|
||||
if (mo2->type != MT_IDEYAANCHOR)
|
||||
continue;
|
||||
|
||||
if ((!toucher->tracer->hnext && anchorpoint)
|
||||
|| (toucher->tracer->hnext && anchorpoint && anchorpoint2))
|
||||
break;
|
||||
}
|
||||
if (mo2->health == toucher->tracer->health) // do ideya numberes match?
|
||||
anchorpoint = mo2;
|
||||
else if (toucher->tracer->hnext && mo2->health == toucher->tracer->hnext->health)
|
||||
anchorpoint2 = mo2;
|
||||
|
||||
if ((!toucher->tracer->hnext && anchorpoint)
|
||||
|| (toucher->tracer->hnext && anchorpoint && anchorpoint2))
|
||||
break;
|
||||
}
|
||||
|
||||
if (anchorpoint)
|
||||
|
@ -939,9 +931,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
count = 1;
|
||||
|
||||
// scan the remaining thinkers
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
@ -989,9 +981,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
|
||||
// Now we RE-scan all the thinkers to find close objects to pull
|
||||
// in from the paraloop. Isn't this just so efficient?
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
@ -1363,9 +1355,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
EV_DoElevator(&junk, bridgeFall, false);
|
||||
|
||||
// scan the remaining thinkers to find koopa
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
@ -1463,10 +1455,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
thinker_t *th;
|
||||
mobj_t *mo2;
|
||||
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
continue;
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
||||
|
@ -1578,6 +1570,45 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
}
|
||||
return;
|
||||
|
||||
case MT_EGGROBO1:
|
||||
if (special->state == &states[special->info->deathstate])
|
||||
return;
|
||||
if (P_PlayerInPain(player))
|
||||
return;
|
||||
|
||||
P_SetMobjState(special, special->info->meleestate);
|
||||
special->angle = special->movedir;
|
||||
special->momx = special->momy = 0;
|
||||
|
||||
// Buenos Dias Mandy
|
||||
P_SetPlayerMobjState(toucher, S_PLAY_STUN);
|
||||
player->pflags &= ~PF_APPLYAUTOBRAKE;
|
||||
player->drawangle = special->angle + ANGLE_180;
|
||||
P_InstaThrust(toucher, special->angle, FixedMul(3*special->info->speed, special->scale/2));
|
||||
toucher->z += P_MobjFlip(toucher);
|
||||
if (toucher->eflags & MFE_UNDERWATER) // unlikely.
|
||||
P_SetObjectMomZ(toucher, FixedDiv(10511*FRACUNIT,2600*FRACUNIT), false);
|
||||
else
|
||||
P_SetObjectMomZ(toucher, FixedDiv(69*FRACUNIT,10*FRACUNIT), false);
|
||||
if (P_IsLocalPlayer(player))
|
||||
{
|
||||
quake.intensity = 9*FRACUNIT;
|
||||
quake.time = TICRATE/2;
|
||||
quake.epicenter = NULL;
|
||||
}
|
||||
|
||||
#if 0 // camera redirection - deemed unnecessary
|
||||
toucher->angle = special->angle;
|
||||
if (player == &players[consoleplayer])
|
||||
localangle = toucher->angle;
|
||||
else if (player == &players[secondarydisplayplayer])
|
||||
localangle2 = toucher->angle;
|
||||
#endif
|
||||
|
||||
S_StartSound(toucher, special->info->attacksound); // home run
|
||||
|
||||
return;
|
||||
|
||||
case MT_BIGTUMBLEWEED:
|
||||
case MT_LITTLETUMBLEWEED:
|
||||
if (toucher->momx || toucher->momy)
|
||||
|
@ -1819,6 +1850,10 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour
|
|||
|
||||
deadtarget = (player->mo->health <= 0);
|
||||
|
||||
// Don't log every hazard hit if they don't want us to.
|
||||
if (!deadtarget && !cv_hazardlog.value)
|
||||
return;
|
||||
|
||||
// Target's name
|
||||
snprintf(targetname, sizeof(targetname), "%s%s%s",
|
||||
CTFTEAMCODE(player),
|
||||
|
@ -1922,7 +1957,7 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour
|
|||
switch (damagetype)
|
||||
{
|
||||
case DMG_WATER:
|
||||
str = M_GetText("%s was %s by chemical water.\n");
|
||||
str = M_GetText("%s was %s by dangerous water.\n");
|
||||
break;
|
||||
case DMG_FIRE:
|
||||
str = M_GetText("%s was %s by molten lava.\n");
|
||||
|
@ -1970,10 +2005,6 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour
|
|||
if (!str) // Should not happen! Unless we missed catching something above.
|
||||
return;
|
||||
|
||||
// Don't log every hazard hit if they don't want us to.
|
||||
if (!deadtarget && !cv_hazardlog.value)
|
||||
return;
|
||||
|
||||
if (deathonly)
|
||||
{
|
||||
if (!deadtarget)
|
||||
|
@ -2567,20 +2598,26 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
|
|||
UINT32 i = 0; // to check how many clones we've removed
|
||||
|
||||
// scan the thinkers to make sure all the old pinch dummies are gone on death
|
||||
// this can happen if the boss was hurt earlier than expected
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo = (mobj_t *)th;
|
||||
if (mo->type == (mobjtype_t)target->info->mass && mo->tracer == target)
|
||||
{
|
||||
P_RemoveMobj(mo);
|
||||
i++;
|
||||
}
|
||||
if (i == 2) // we've already removed 2 of these, let's stop now
|
||||
if (mo->type != (mobjtype_t)target->info->mass)
|
||||
continue;
|
||||
if (mo->tracer != target)
|
||||
continue;
|
||||
|
||||
P_KillMobj(mo, inflictor, source, damagetype);
|
||||
mo->destscale = mo->scale/8;
|
||||
mo->scalespeed = (mo->scale - mo->destscale)/(2*TICRATE);
|
||||
mo->momz = mo->info->speed;
|
||||
mo->angle = FixedAngle((P_RandomKey(36)*10)<<FRACBITS);
|
||||
if (++i == 2) // we've already removed 2 of these, let's stop now
|
||||
break;
|
||||
else
|
||||
S_StartSound(mo, mo->info->deathsound); // done once to prevent sound stacking
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -2895,26 +2932,47 @@ static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sou
|
|||
if (player->powers[pw_flashing] || player->powers[pw_invulnerability])
|
||||
return false;
|
||||
|
||||
// Ignore IT players shooting each other, unless friendlyfire is on.
|
||||
if ((player->pflags & PF_TAGIT && !((cv_friendlyfire.value || (damagetype & DMG_CANHURTSELF)) &&
|
||||
source && source->player && source->player->pflags & PF_TAGIT)))
|
||||
return false;
|
||||
|
||||
// Don't allow any damage before the round starts.
|
||||
if (leveltime <= hidetime * TICRATE)
|
||||
return false;
|
||||
|
||||
// Ignore IT players shooting each other, unless friendlyfire is on.
|
||||
if ((player->pflags & PF_TAGIT && !((cv_friendlyfire.value || (damagetype & DMG_CANHURTSELF)) &&
|
||||
source && source->player && source->player->pflags & PF_TAGIT)))
|
||||
{
|
||||
if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK))
|
||||
{
|
||||
if (player->revitem != MT_LHRT && player->spinitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers.
|
||||
{
|
||||
P_SwitchShield(player, SH_PINK);
|
||||
S_StartSound(target, mobjinfo[MT_PITY_ICON].seesound);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't allow players on the same team to hurt one another,
|
||||
// unless cv_friendlyfire is on.
|
||||
if (!(cv_friendlyfire.value || (damagetype & DMG_CANHURTSELF)) && (player->pflags & PF_TAGIT) == (source->player->pflags & PF_TAGIT))
|
||||
{
|
||||
if (!(inflictor->flags & MF_FIRE))
|
||||
if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK))
|
||||
{
|
||||
if (player->revitem != MT_LHRT && player->spinitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers.
|
||||
{
|
||||
P_SwitchShield(player, SH_PINK);
|
||||
S_StartSound(target, mobjinfo[MT_PITY_ICON].seesound);
|
||||
}
|
||||
}
|
||||
else if (!(inflictor->flags & MF_FIRE))
|
||||
P_GivePlayerRings(player, 1);
|
||||
if (inflictor->flags2 & MF2_BOUNCERING)
|
||||
inflictor->fuse = 0; // bounce ring disappears at -1 not 0
|
||||
return false;
|
||||
}
|
||||
|
||||
if (inflictor->type == MT_LHRT)
|
||||
return false;
|
||||
|
||||
// The tag occurs so long as you aren't shooting another tagger with friendlyfire on.
|
||||
if (source->player->pflags & PF_TAGIT && !(player->pflags & PF_TAGIT))
|
||||
{
|
||||
|
@ -2981,7 +3039,17 @@ static inline boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj
|
|||
|
||||
// In COOP/RACE, you can't hurt other players unless cv_friendlyfire is on
|
||||
if (!cv_friendlyfire.value && (G_PlatformGametype()))
|
||||
{
|
||||
if (gametype == GT_COOP && inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) // co-op only
|
||||
{
|
||||
if (player->revitem != MT_LHRT && player->spinitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers.
|
||||
{
|
||||
P_SwitchShield(player, SH_PINK);
|
||||
S_StartSound(target, mobjinfo[MT_PITY_ICON].seesound);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Tag handling
|
||||
|
@ -2995,7 +3063,15 @@ static inline boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj
|
|||
// unless cv_friendlyfire is on.
|
||||
if (!cv_friendlyfire.value && target->player->ctfteam == source->player->ctfteam)
|
||||
{
|
||||
if (!(inflictor->flags & MF_FIRE))
|
||||
if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK))
|
||||
{
|
||||
if (player->revitem != MT_LHRT && player->spinitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers.
|
||||
{
|
||||
P_SwitchShield(player, SH_PINK);
|
||||
S_StartSound(target, mobjinfo[MT_PITY_ICON].seesound);
|
||||
}
|
||||
}
|
||||
else if (!(inflictor->flags & MF_FIRE))
|
||||
P_GivePlayerRings(target->player, 1);
|
||||
if (inflictor->flags2 & MF2_BOUNCERING)
|
||||
inflictor->fuse = 0; // bounce ring disappears at -1 not 0
|
||||
|
@ -3004,6 +3080,9 @@ static inline boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj
|
|||
}
|
||||
}
|
||||
|
||||
if (inflictor->type == MT_LHRT)
|
||||
return false;
|
||||
|
||||
// Add pity.
|
||||
if (!player->powers[pw_flashing] && !player->powers[pw_invulnerability] && !player->powers[pw_super]
|
||||
&& source->player->score > player->score)
|
||||
|
@ -3576,7 +3655,7 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings)
|
|||
{
|
||||
INT32 i;
|
||||
mobj_t *mo;
|
||||
angle_t fa;
|
||||
angle_t fa, va;
|
||||
fixed_t ns;
|
||||
fixed_t z;
|
||||
boolean nightsreplace = ((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap));
|
||||
|
@ -3598,6 +3677,11 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings)
|
|||
// Spill weapons first
|
||||
P_PlayerWeaponPanelOrAmmoBurst(player);
|
||||
|
||||
if (abs(player->mo->momx) > player->mo->scale || abs(player->mo->momy) > player->mo->scale)
|
||||
va = R_PointToAngle2(player->mo->momx, player->mo->momy, 0, 0)>>ANGLETOFINESHIFT;
|
||||
else
|
||||
va = player->mo->angle>>ANGLETOFINESHIFT;
|
||||
|
||||
for (i = 0; i < num_rings; i++)
|
||||
{
|
||||
INT32 objType = mobjinfo[MT_RING].reactiontime;
|
||||
|
@ -3619,7 +3703,7 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings)
|
|||
P_SetScale(mo, player->mo->scale);
|
||||
|
||||
// Angle offset by player angle, then slightly offset by amount of rings
|
||||
fa = ((i*FINEANGLES/16) + (player->mo->angle>>ANGLETOFINESHIFT) - ((num_rings-1)*FINEANGLES/32)) & FINEMASK;
|
||||
fa = ((i*FINEANGLES/16) + va - ((num_rings-1)*FINEANGLES/32)) & FINEMASK;
|
||||
|
||||
// Make rings spill out around the player in 16 directions like SA, but spill like Sonic 2.
|
||||
// Technically a non-SA way of spilling rings. They just so happen to be a little similar.
|
||||
|
|
|
@ -76,7 +76,7 @@ fireflicker_t *P_SpawnAdjustableFireFlicker(sector_t *minsector, sector_t *maxse
|
|||
P_RemoveLighting(maxsector); // out with the old, in with the new
|
||||
flick = Z_Calloc(sizeof (*flick), PU_LEVSPEC, NULL);
|
||||
|
||||
P_AddThinker(&flick->thinker);
|
||||
P_AddThinker(THINK_MAIN, &flick->thinker);
|
||||
|
||||
flick->thinker.function.acp1 = (actionf_p1)T_FireFlicker;
|
||||
flick->sector = maxsector;
|
||||
|
@ -155,7 +155,7 @@ void P_SpawnLightningFlash(sector_t *sector)
|
|||
|
||||
flash = Z_Calloc(sizeof (*flash), PU_LEVSPEC, NULL);
|
||||
|
||||
P_AddThinker(&flash->thinker);
|
||||
P_AddThinker(THINK_MAIN, &flash->thinker);
|
||||
|
||||
flash->thinker.function.acp1 = (actionf_p1)T_LightningFlash;
|
||||
flash->sector = sector;
|
||||
|
@ -214,7 +214,7 @@ strobe_t *P_SpawnAdjustableStrobeFlash(sector_t *minsector, sector_t *maxsector,
|
|||
P_RemoveLighting(maxsector); // out with the old, in with the new
|
||||
flash = Z_Calloc(sizeof (*flash), PU_LEVSPEC, NULL);
|
||||
|
||||
P_AddThinker(&flash->thinker);
|
||||
P_AddThinker(THINK_MAIN, &flash->thinker);
|
||||
|
||||
flash->sector = maxsector;
|
||||
flash->darktime = darktime;
|
||||
|
@ -289,7 +289,7 @@ glow_t *P_SpawnAdjustableGlowingLight(sector_t *minsector, sector_t *maxsector,
|
|||
P_RemoveLighting(maxsector); // out with the old, in with the new
|
||||
g = Z_Calloc(sizeof (*g), PU_LEVSPEC, NULL);
|
||||
|
||||
P_AddThinker(&g->thinker);
|
||||
P_AddThinker(THINK_MAIN, &g->thinker);
|
||||
|
||||
g->sector = maxsector;
|
||||
g->minlight = minsector->lightlevel;
|
||||
|
@ -349,7 +349,7 @@ void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean
|
|||
ll->thinker.function.acp1 = (actionf_p1)T_LightFade;
|
||||
sector->lightingdata = ll; // set it to the lightlevel_t
|
||||
|
||||
P_AddThinker(&ll->thinker); // add thinker
|
||||
P_AddThinker(THINK_MAIN, &ll->thinker); // add thinker
|
||||
|
||||
ll->sector = sector;
|
||||
ll->sourcelevel = sector->lightlevel;
|
||||
|
|
|
@ -61,15 +61,21 @@
|
|||
#define P_GetPlayerHeight(player) FixedMul(player->height, player->mo->scale)
|
||||
#define P_GetPlayerSpinHeight(player) FixedMul(player->spinheight, player->mo->scale)
|
||||
|
||||
//
|
||||
// P_TICK
|
||||
//
|
||||
|
||||
// both the head and tail of the thinker list
|
||||
extern thinker_t thinkercap;
|
||||
typedef enum
|
||||
{
|
||||
THINK_POLYOBJ,
|
||||
THINK_MAIN,
|
||||
THINK_MOBJ,
|
||||
#ifdef ESLOPE
|
||||
THINK_DYNSLOPE,
|
||||
#endif
|
||||
THINK_PRECIP,
|
||||
NUM_THINKERLISTS
|
||||
} thinklistnum_t; /**< Thinker lists. */
|
||||
extern thinker_t thlist[];
|
||||
|
||||
void P_InitThinkers(void);
|
||||
void P_AddThinker(thinker_t *thinker);
|
||||
void P_AddThinker(const thinklistnum_t n, thinker_t *thinker);
|
||||
void P_RemoveThinker(thinker_t *thinker);
|
||||
|
||||
//
|
||||
|
@ -128,6 +134,7 @@ pflags_t P_GetJumpFlags(player_t *player);
|
|||
boolean P_PlayerInPain(player_t *player);
|
||||
void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor);
|
||||
void P_ResetPlayer(player_t *player);
|
||||
boolean P_PlayerCanDamage(player_t *player, mobj_t *thing);
|
||||
boolean P_IsLocalPlayer(player_t *player);
|
||||
|
||||
boolean P_IsObjectInGoop(mobj_t *mo);
|
||||
|
@ -135,7 +142,7 @@ boolean P_IsObjectOnGround(mobj_t *mo);
|
|||
boolean P_IsObjectOnGroundIn(mobj_t *mo, sector_t *sec);
|
||||
boolean P_InSpaceSector(mobj_t *mo);
|
||||
boolean P_InQuicksand(mobj_t *mo);
|
||||
boolean P_PlayerHitFloor(player_t *player);
|
||||
boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff);
|
||||
|
||||
void P_SetObjectMomZ(mobj_t *mo, fixed_t value, boolean relative);
|
||||
void P_RestoreMusic(player_t *player);
|
||||
|
@ -158,6 +165,7 @@ boolean P_AutoPause(void);
|
|||
void P_DoJumpShield(player_t *player);
|
||||
void P_DoBubbleBounce(player_t *player);
|
||||
void P_DoAbilityBounce(player_t *player, boolean changemomz);
|
||||
void P_TwinSpinRejuvenate(player_t *player, mobjtype_t type);
|
||||
void P_BlackOw(player_t *player);
|
||||
void P_ElementalFire(player_t *player, boolean cropcircle);
|
||||
|
||||
|
@ -174,7 +182,7 @@ void P_InstaThrustEvenIn2D(mobj_t *mo, angle_t angle, fixed_t move);
|
|||
|
||||
mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet);
|
||||
void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius);
|
||||
void P_HomingAttack(mobj_t *source, mobj_t *enemy); /// \todo doesn't belong in p_user
|
||||
boolean P_HomingAttack(mobj_t *source, mobj_t *enemy); /// \todo doesn't belong in p_user
|
||||
boolean P_SuperReady(player_t *player);
|
||||
void P_DoJump(player_t *player, boolean soundandstate);
|
||||
#if 0
|
||||
|
|
231
src/p_map.c
231
src/p_map.c
|
@ -135,6 +135,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
|
|||
fixed_t vertispeed = spring->info->mass;
|
||||
fixed_t horizspeed = spring->info->damage;
|
||||
boolean final = false;
|
||||
UINT8 strong = 0;
|
||||
|
||||
// Object was already sprung this tic
|
||||
if (object->eflags & MFE_SPRUNG)
|
||||
|
@ -148,6 +149,14 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
|
|||
if (!spring->health || !object->health)
|
||||
return false;
|
||||
|
||||
if (object->player)
|
||||
{
|
||||
if (object->player->charability == CA_TWINSPIN && object->player->panim == PA_ABILITY)
|
||||
strong = 1;
|
||||
else if (object->player->charability2 == CA2_MELEE && object->player->panim == PA_ABILITY2)
|
||||
strong = 2;
|
||||
}
|
||||
|
||||
if (spring->info->painchance == -1) // Pinball bumper mode.
|
||||
{
|
||||
// The first of the entirely different spring modes!
|
||||
|
@ -188,6 +197,9 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
|
|||
{
|
||||
fixed_t playervelocity;
|
||||
|
||||
if (strong)
|
||||
vertispeed <<= 1;
|
||||
|
||||
if (!(object->player->pflags & PF_THOKKED) && !(object->player->homing)
|
||||
&& ((playervelocity = FixedDiv(9*FixedHypot(object->player->speed, object->momz), 10<<FRACBITS)) > vertispeed))
|
||||
vertispeed = playervelocity;
|
||||
|
@ -260,11 +272,8 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (object->player
|
||||
&& ((object->player->charability == CA_TWINSPIN && object->player->panim == PA_ABILITY)
|
||||
|| (object->player->charability2 == CA2_MELEE && object->player->panim == PA_ABILITY2)))
|
||||
if (strong)
|
||||
{
|
||||
S_StartSound(object, sfx_s3k8b);
|
||||
if (horizspeed)
|
||||
horizspeed = FixedMul(horizspeed, (4*FRACUNIT)/3);
|
||||
if (vertispeed)
|
||||
|
@ -333,7 +342,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
|
|||
if (horizspeed)
|
||||
{
|
||||
object->player->drawangle = spring->angle;
|
||||
if (object->player->cmd.forwardmove == 0 && object->player->cmd.sidemove == 0)
|
||||
if (vertispeed || (object->player->cmd.forwardmove == 0 && object->player->cmd.sidemove == 0))
|
||||
{
|
||||
object->angle = spring->angle;
|
||||
|
||||
|
@ -399,6 +408,12 @@ springstate:
|
|||
P_AddPlayerScore(object->player, 10);
|
||||
spring->reactiontime--;
|
||||
}
|
||||
|
||||
if (strong)
|
||||
{
|
||||
P_TwinSpinRejuvenate(object->player, (strong == 1 ? object->player->thokitem : object->player->revitem));
|
||||
S_StartSound(object, sfx_sprong); // strong spring. sprong.
|
||||
}
|
||||
}
|
||||
|
||||
return final;
|
||||
|
@ -710,6 +725,27 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
|||
return true;
|
||||
}
|
||||
|
||||
// vectorise metal - done in a special case as at this point neither has the right flags for touching
|
||||
if (thing->type == MT_METALSONIC_BATTLE
|
||||
&& (tmthing->flags & MF_MISSILE)
|
||||
&& tmthing->target != thing
|
||||
&& thing->state == &states[thing->info->spawnstate])
|
||||
{
|
||||
blockdist = thing->radius + tmthing->radius;
|
||||
|
||||
if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist)
|
||||
return true; // didn't hit it
|
||||
|
||||
if (tmthing->z > thing->z + thing->height)
|
||||
return true; // overhead
|
||||
if (tmthing->z + tmthing->height < thing->z)
|
||||
return true; // underneath
|
||||
|
||||
thing->flags2 |= MF2_CLASSICPUSH;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_PAIN|MF_SHOOTABLE|MF_SPRING)))
|
||||
return true;
|
||||
|
||||
|
@ -1153,7 +1189,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
|||
tmthing->y = thing->y;
|
||||
P_SetThingPosition(tmthing);
|
||||
}
|
||||
else if (!(tmthing->type == MT_SHELL && thing->player)) // player collision handled in touchspecial
|
||||
else if (!(tmthing->type == MT_SHELL && thing->player)) // player collision handled in touchspecial for shell
|
||||
{
|
||||
UINT8 damagetype = tmthing->info->mass;
|
||||
if (!damagetype && tmthing->flags & MF_FIRE) // BURN!
|
||||
|
@ -1482,51 +1518,45 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
|||
}
|
||||
// Monitor?
|
||||
else if (thing->flags & MF_MONITOR
|
||||
&& !((thing->type == MT_RING_REDBOX && tmthing->player->ctfteam != 1) || (thing->type == MT_RING_BLUEBOX && tmthing->player->ctfteam != 2)))
|
||||
&& !((thing->type == MT_RING_REDBOX && tmthing->player->ctfteam != 1) || (thing->type == MT_RING_BLUEBOX && tmthing->player->ctfteam != 2))
|
||||
&& (!(thing->flags & MF_SOLID) || P_PlayerCanDamage(tmthing->player, thing)))
|
||||
{
|
||||
// 0 = none, 1 = elemental pierce, 2 = bubble bounce
|
||||
UINT8 elementalpierce = (((tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL || (tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) && (tmthing->player->pflags & PF_SHIELDABILITY)
|
||||
? (((tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) ? 1 : 2)
|
||||
: 0);
|
||||
if (!(thing->flags & MF_SOLID)
|
||||
|| tmthing->player->pflags & (PF_SPINNING|PF_GLIDING)
|
||||
|| ((tmthing->player->pflags & PF_JUMPED)
|
||||
&& (!(tmthing->player->pflags & PF_NOJUMPDAMAGE)
|
||||
|| (tmthing->player->charability == CA_TWINSPIN && tmthing->player->panim == PA_ABILITY)))
|
||||
|| (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2)
|
||||
|| ((tmthing->player->charflags & SF_STOMPDAMAGE || tmthing->player->pflags & PF_BOUNCING)
|
||||
&& (P_MobjFlip(tmthing)*(tmthing->z - (thing->z + thing->height/2)) > 0) && (P_MobjFlip(tmthing)*tmthing->momz < 0))
|
||||
|| elementalpierce)
|
||||
if (thing->z - thing->scale <= tmthing->z + tmthing->height
|
||||
&& thing->z + thing->height + thing->scale >= tmthing->z)
|
||||
{
|
||||
if (thing->z - thing->scale <= tmthing->z + tmthing->height
|
||||
&& thing->z + thing->height + thing->scale >= tmthing->z)
|
||||
player_t *player = tmthing->player;
|
||||
// 0 = none, 1 = elemental pierce, 2 = bubble bounce
|
||||
UINT8 elementalpierce = (((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL || (player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) && (player->pflags & PF_SHIELDABILITY)
|
||||
? (((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) ? 1 : 2)
|
||||
: 0);
|
||||
SINT8 flipval = P_MobjFlip(thing); // Save this value in case monitor gets removed.
|
||||
fixed_t *momz = &tmthing->momz; // tmthing gets changed by P_DamageMobj, so we need a new pointer?! X_x;;
|
||||
fixed_t *z = &tmthing->z; // aau.
|
||||
// Going down? Then bounce back up.
|
||||
if (P_DamageMobj(thing, tmthing, tmthing, 1, 0) // break the monitor
|
||||
&& (flipval*(*momz) < 0) // monitor is on the floor and you're going down, or on the ceiling and you're going up
|
||||
&& (elementalpierce != 1)) // you're not piercing through the monitor...
|
||||
{
|
||||
player_t *player = tmthing->player;
|
||||
SINT8 flipval = P_MobjFlip(thing); // Save this value in case monitor gets removed.
|
||||
fixed_t *momz = &tmthing->momz; // tmthing gets changed by P_DamageMobj, so we need a new pointer?! X_x;;
|
||||
fixed_t *z = &tmthing->z; // aau.
|
||||
// Going down? Then bounce back up.
|
||||
if (P_DamageMobj(thing, tmthing, tmthing, 1, 0) // break the monitor
|
||||
&& (flipval*(*momz) < 0) // monitor is on the floor and you're going down, or on the ceiling and you're going up
|
||||
&& (elementalpierce != 1)) // you're not piercing through the monitor...
|
||||
if (elementalpierce == 2)
|
||||
P_DoBubbleBounce(player);
|
||||
else if (!(player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2))
|
||||
{
|
||||
if (elementalpierce == 2)
|
||||
P_DoBubbleBounce(player);
|
||||
else if (!(player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2))
|
||||
*momz = -*momz; // Therefore, you should be thrust in the opposite direction, vertically.
|
||||
*momz = -*momz; // Therefore, you should be thrust in the opposite direction, vertically.
|
||||
if (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY)
|
||||
P_TwinSpinRejuvenate(player, player->thokitem);
|
||||
}
|
||||
if (!(elementalpierce == 1 && thing->flags & MF_GRENADEBOUNCE)) // prevent gold monitor clipthrough.
|
||||
{
|
||||
if (player->pflags & PF_BOUNCING)
|
||||
P_DoAbilityBounce(player, false);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
*z -= *momz; // to ensure proper collision.
|
||||
}
|
||||
|
||||
return true;
|
||||
if (!(elementalpierce == 1 && thing->flags & MF_GRENADEBOUNCE)) // prevent gold monitor clipthrough.
|
||||
{
|
||||
if (player->pflags & PF_BOUNCING)
|
||||
P_DoAbilityBounce(player, false);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
*z -= *momz; // to ensure proper collision.
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1778,7 +1808,7 @@ static boolean PIT_CheckLine(line_t *ld)
|
|||
{
|
||||
tmceilingz = opentop;
|
||||
ceilingline = ld;
|
||||
tmceilingrover = NULL;
|
||||
tmceilingrover = openceilingrover;
|
||||
#ifdef ESLOPE
|
||||
tmceilingslope = opentopslope;
|
||||
#endif
|
||||
|
@ -1787,7 +1817,7 @@ static boolean PIT_CheckLine(line_t *ld)
|
|||
if (openbottom > tmfloorz)
|
||||
{
|
||||
tmfloorz = openbottom;
|
||||
tmfloorrover = NULL;
|
||||
tmfloorrover = openfloorrover;
|
||||
#ifdef ESLOPE
|
||||
tmfloorslope = openbottomslope;
|
||||
#endif
|
||||
|
@ -2059,6 +2089,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
|
|||
#ifdef ESLOPE
|
||||
tmfloorslope = NULL;
|
||||
#endif
|
||||
tmfloorrover = NULL;
|
||||
}
|
||||
|
||||
if (polybottom < tmceilingz && abs(delta1) >= abs(delta2)) {
|
||||
|
@ -2066,6 +2097,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
|
|||
#ifdef ESLOPE
|
||||
tmceilingslope = NULL;
|
||||
#endif
|
||||
tmceilingrover = NULL;
|
||||
}
|
||||
}
|
||||
plink = (polymaplink_t *)(plink->link.next);
|
||||
|
@ -2790,7 +2822,7 @@ boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y)
|
|||
static boolean P_ThingHeightClip(mobj_t *thing)
|
||||
{
|
||||
boolean floormoved;
|
||||
fixed_t oldfloorz = thing->floorz;
|
||||
fixed_t oldfloorz = thing->floorz, oldz = thing->z;
|
||||
ffloor_t *oldfloorrover = thing->floorrover;
|
||||
ffloor_t *oldceilingrover = thing->ceilingrover;
|
||||
boolean onfloor = P_IsObjectOnGround(thing);//(thing->z <= thing->floorz);
|
||||
|
@ -2849,6 +2881,12 @@ static boolean P_ThingHeightClip(mobj_t *thing)
|
|||
thing->z = thing->ceilingz - thing->height;
|
||||
}
|
||||
|
||||
if (thing->z != oldz)
|
||||
{
|
||||
if (thing->player)
|
||||
P_PlayerHitFloor(thing->player, false);
|
||||
}
|
||||
|
||||
// debug: be sure it falls to the floor
|
||||
thing->eflags &= ~MFE_ONGROUND;
|
||||
|
||||
|
@ -4003,7 +4041,7 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush)
|
|||
thinker_t *think;
|
||||
elevator_t *crumbler;
|
||||
|
||||
for (think = thinkercap.next; think != &thinkercap; think = think->next)
|
||||
for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next)
|
||||
{
|
||||
if (think->function.acp1 != (actionf_p1)T_StartCrumble)
|
||||
continue;
|
||||
|
@ -4049,6 +4087,7 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush)
|
|||
boolean P_CheckSector(sector_t *sector, boolean crunch)
|
||||
{
|
||||
msecnode_t *n;
|
||||
size_t i;
|
||||
|
||||
nofit = false;
|
||||
crushchange = crunch;
|
||||
|
@ -4063,9 +4102,57 @@ boolean P_CheckSector(sector_t *sector, boolean crunch)
|
|||
|
||||
|
||||
// First, let's see if anything will keep it from crushing.
|
||||
|
||||
// Sal: This stupid function chain is required to fix polyobjects not being able to crush.
|
||||
// Monster Iestyn: don't use P_CheckSector actually just look for objects in the blockmap instead
|
||||
validcount++;
|
||||
|
||||
for (i = 0; i < sector->linecount; i++)
|
||||
{
|
||||
if (sector->lines[i]->polyobj)
|
||||
{
|
||||
polyobj_t *po = sector->lines[i]->polyobj;
|
||||
if (po->validcount == validcount)
|
||||
continue; // skip if already checked
|
||||
if (!(po->flags & POF_SOLID))
|
||||
continue;
|
||||
if (po->lines[0]->backsector == sector) // Make sure you're currently checking the control sector
|
||||
{
|
||||
INT32 x, y;
|
||||
po->validcount = validcount;
|
||||
|
||||
for (y = po->blockbox[BOXBOTTOM]; y <= po->blockbox[BOXTOP]; ++y)
|
||||
{
|
||||
for (x = po->blockbox[BOXLEFT]; x <= po->blockbox[BOXRIGHT]; ++x)
|
||||
{
|
||||
mobj_t *mo;
|
||||
|
||||
if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight)
|
||||
continue;
|
||||
|
||||
mo = blocklinks[y * bmapwidth + x];
|
||||
|
||||
for (; mo; mo = mo->bnext)
|
||||
{
|
||||
// Monster Iestyn: do we need to check if a mobj has already been checked? ...probably not I suspect
|
||||
|
||||
if (!P_MobjTouchingPolyobj(po, mo))
|
||||
continue;
|
||||
|
||||
if (!PIT_ChangeSector(mo, false))
|
||||
{
|
||||
nofit = true;
|
||||
return nofit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sector->numattached)
|
||||
{
|
||||
size_t i;
|
||||
sector_t *sec;
|
||||
for (i = 0; i < sector->numattached; i++)
|
||||
{
|
||||
|
@ -4125,9 +4212,53 @@ boolean P_CheckSector(sector_t *sector, boolean crunch)
|
|||
} while (n); // repeat from scratch until all things left are marked valid
|
||||
|
||||
// Nothing blocked us, so lets crush for real!
|
||||
|
||||
// Sal: This stupid function chain is required to fix polyobjects not being able to crush.
|
||||
// Monster Iestyn: don't use P_CheckSector actually just look for objects in the blockmap instead
|
||||
validcount++;
|
||||
|
||||
for (i = 0; i < sector->linecount; i++)
|
||||
{
|
||||
if (sector->lines[i]->polyobj)
|
||||
{
|
||||
polyobj_t *po = sector->lines[i]->polyobj;
|
||||
if (po->validcount == validcount)
|
||||
continue; // skip if already checked
|
||||
if (!(po->flags & POF_SOLID))
|
||||
continue;
|
||||
if (po->lines[0]->backsector == sector) // Make sure you're currently checking the control sector
|
||||
{
|
||||
INT32 x, y;
|
||||
po->validcount = validcount;
|
||||
|
||||
for (y = po->blockbox[BOXBOTTOM]; y <= po->blockbox[BOXTOP]; ++y)
|
||||
{
|
||||
for (x = po->blockbox[BOXLEFT]; x <= po->blockbox[BOXRIGHT]; ++x)
|
||||
{
|
||||
mobj_t *mo;
|
||||
|
||||
if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight)
|
||||
continue;
|
||||
|
||||
mo = blocklinks[y * bmapwidth + x];
|
||||
|
||||
for (; mo; mo = mo->bnext)
|
||||
{
|
||||
// Monster Iestyn: do we need to check if a mobj has already been checked? ...probably not I suspect
|
||||
|
||||
if (!P_MobjTouchingPolyobj(po, mo))
|
||||
continue;
|
||||
|
||||
PIT_ChangeSector(mo, true);
|
||||
return nofit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sector->numattached)
|
||||
{
|
||||
size_t i;
|
||||
sector_t *sec;
|
||||
for (i = 0; i < sector->numattached; i++)
|
||||
{
|
||||
|
|
|
@ -311,6 +311,7 @@ fixed_t opentop, openbottom, openrange, lowfloor, highceiling;
|
|||
#ifdef ESLOPE
|
||||
pslope_t *opentopslope, *openbottomslope;
|
||||
#endif
|
||||
ffloor_t *openfloorrover, *openceilingrover;
|
||||
|
||||
// P_CameraLineOpening
|
||||
// P_LineOpening, but for camera
|
||||
|
@ -517,6 +518,8 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
|
|||
I_Assert(front != NULL);
|
||||
I_Assert(back != NULL);
|
||||
|
||||
openfloorrover = openceilingrover = NULL;
|
||||
|
||||
{ // Set open and high/low values here
|
||||
fixed_t frontheight, backheight;
|
||||
|
||||
|
@ -641,6 +644,8 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
|
|||
pslope_t *ceilingslope = opentopslope;
|
||||
pslope_t *floorslope = openbottomslope;
|
||||
#endif
|
||||
ffloor_t *floorrover = NULL;
|
||||
ffloor_t *ceilingrover = NULL;
|
||||
|
||||
// Check for frontsector's fake floors
|
||||
for (rover = front->ffloors; rover; rover = rover->next)
|
||||
|
@ -668,6 +673,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
|
|||
#ifdef ESLOPE
|
||||
ceilingslope = *rover->b_slope;
|
||||
#endif
|
||||
ceilingrover = rover;
|
||||
}
|
||||
else if (bottomheight < highestceiling)
|
||||
highestceiling = bottomheight;
|
||||
|
@ -680,6 +686,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
|
|||
#ifdef ESLOPE
|
||||
floorslope = *rover->t_slope;
|
||||
#endif
|
||||
floorrover = rover;
|
||||
}
|
||||
else if (topheight > lowestfloor)
|
||||
lowestfloor = topheight;
|
||||
|
@ -712,6 +719,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
|
|||
#ifdef ESLOPE
|
||||
ceilingslope = *rover->b_slope;
|
||||
#endif
|
||||
ceilingrover = rover;
|
||||
}
|
||||
else if (bottomheight < highestceiling)
|
||||
highestceiling = bottomheight;
|
||||
|
@ -724,6 +732,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
|
|||
#ifdef ESLOPE
|
||||
floorslope = *rover->t_slope;
|
||||
#endif
|
||||
floorrover = rover;
|
||||
}
|
||||
else if (topheight > lowestfloor)
|
||||
lowestfloor = topheight;
|
||||
|
@ -743,6 +752,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
|
|||
#ifdef ESLOPE
|
||||
ceilingslope = NULL;
|
||||
#endif
|
||||
ceilingrover = NULL;
|
||||
}
|
||||
else if (polysec->floorheight < highestceiling && delta1 >= delta2)
|
||||
highestceiling = polysec->floorheight;
|
||||
|
@ -752,6 +762,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
|
|||
#ifdef ESLOPE
|
||||
floorslope = NULL;
|
||||
#endif
|
||||
floorrover = NULL;
|
||||
}
|
||||
else if (polysec->ceilingheight > lowestfloor && delta1 < delta2)
|
||||
lowestfloor = polysec->ceilingheight;
|
||||
|
@ -765,6 +776,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
|
|||
#ifdef ESLOPE
|
||||
openbottomslope = floorslope;
|
||||
#endif
|
||||
openfloorrover = floorrover;
|
||||
}
|
||||
|
||||
if (lowestceiling < opentop) {
|
||||
|
@ -772,6 +784,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
|
|||
#ifdef ESLOPE
|
||||
opentopslope = ceilingslope;
|
||||
#endif
|
||||
openceilingrover = ceilingrover;
|
||||
}
|
||||
|
||||
if (lowestfloor > lowfloor)
|
||||
|
@ -1093,7 +1106,10 @@ boolean P_BlockThingsIterator(INT32 x, INT32 y, boolean (*func)(mobj_t *))
|
|||
{
|
||||
P_SetTarget(&bnext, mobj->bnext); // We want to note our reference to bnext here incase it is MF_NOTHINK and gets removed!
|
||||
if (!func(mobj))
|
||||
{
|
||||
P_SetTarget(&bnext, NULL);
|
||||
return false;
|
||||
}
|
||||
if (P_MobjWasRemoved(tmthing) // func just popped our tmthing, cannot continue.
|
||||
|| (bnext && P_MobjWasRemoved(bnext))) // func just broke blockmap chain, cannot continue.
|
||||
{
|
||||
|
|
|
@ -58,6 +58,7 @@ extern fixed_t opentop, openbottom, openrange, lowfloor, highceiling;
|
|||
#ifdef ESLOPE
|
||||
extern pslope_t *opentopslope, *openbottomslope;
|
||||
#endif
|
||||
extern ffloor_t *openfloorrover, *openceilingrover;
|
||||
|
||||
void P_LineOpening(line_t *plinedef, mobj_t *mobj);
|
||||
|
||||
|
|
1569
src/p_mobj.c
1569
src/p_mobj.c
File diff suppressed because it is too large
Load diff
|
@ -371,6 +371,8 @@ typedef struct mobj_s
|
|||
struct pslope_s *standingslope; // The slope that the object is standing on (shouldn't need synced in savegames, right?)
|
||||
#endif
|
||||
|
||||
boolean colorized; // Whether the mobj uses the rainbow colormap
|
||||
|
||||
// WARNING: New fields must be added separately to savegame and Lua.
|
||||
} mobj_t;
|
||||
|
||||
|
@ -468,4 +470,5 @@ extern INT32 numhuntemeralds;
|
|||
extern boolean runemeraldmanager;
|
||||
extern UINT16 emeraldspawndelay;
|
||||
extern INT32 numstarposts;
|
||||
extern UINT16 bossdisabled;
|
||||
#endif
|
||||
|
|
345
src/p_polyobj.c
345
src/p_polyobj.c
|
@ -146,16 +146,6 @@ FUNCINLINE static ATTRINLINE void Polyobj_vecSub2(vertex_t *dst, vertex_t *v1, v
|
|||
dst->y = v1->y - v2->y;
|
||||
}
|
||||
|
||||
// Add the polyobject's thinker to the thinker list
|
||||
// Unlike P_AddThinker, this adds it to the front of the list instead of the back, so that carrying physics can work right. -Red
|
||||
FUNCINLINE static ATTRINLINE void PolyObj_AddThinker(thinker_t *th)
|
||||
{
|
||||
thinkercap.next->prev = th;
|
||||
th->next = thinkercap.next;
|
||||
th->prev = &thinkercap;
|
||||
thinkercap.next = th;
|
||||
}
|
||||
|
||||
//
|
||||
// P_PointInsidePolyobj
|
||||
//
|
||||
|
@ -1505,6 +1495,7 @@ void Polyobj_InitLevel(void)
|
|||
mqueue_t anchorqueue;
|
||||
mobjqitem_t *qitem;
|
||||
INT32 i, numAnchors = 0;
|
||||
mobj_t *mo;
|
||||
|
||||
M_QueueInit(&spawnqueue);
|
||||
M_QueueInit(&anchorqueue);
|
||||
|
@ -1518,31 +1509,31 @@ void Polyobj_InitLevel(void)
|
|||
|
||||
// run down the thinker list, count the number of spawn points, and save
|
||||
// the mobj_t pointers on a queue for use below.
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 == (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo = (mobj_t *)th;
|
||||
|
||||
if (mo->info->doomednum == POLYOBJ_SPAWN_DOOMEDNUM ||
|
||||
mo->info->doomednum == POLYOBJ_SPAWNCRUSH_DOOMEDNUM)
|
||||
{
|
||||
mobj_t *mo = (mobj_t *)th;
|
||||
++numPolyObjects;
|
||||
|
||||
if (mo->info->doomednum == POLYOBJ_SPAWN_DOOMEDNUM ||
|
||||
mo->info->doomednum == POLYOBJ_SPAWNCRUSH_DOOMEDNUM)
|
||||
{
|
||||
++numPolyObjects;
|
||||
qitem = malloc(sizeof(mobjqitem_t));
|
||||
memset(qitem, 0, sizeof(mobjqitem_t));
|
||||
qitem->mo = mo;
|
||||
M_QueueInsert(&(qitem->mqitem), &spawnqueue);
|
||||
}
|
||||
else if (mo->info->doomednum == POLYOBJ_ANCHOR_DOOMEDNUM)
|
||||
{
|
||||
++numAnchors;
|
||||
|
||||
qitem = malloc(sizeof(mobjqitem_t));
|
||||
memset(qitem, 0, sizeof(mobjqitem_t));
|
||||
qitem->mo = mo;
|
||||
M_QueueInsert(&(qitem->mqitem), &spawnqueue);
|
||||
}
|
||||
else if (mo->info->doomednum == POLYOBJ_ANCHOR_DOOMEDNUM)
|
||||
{
|
||||
++numAnchors;
|
||||
|
||||
qitem = malloc(sizeof(mobjqitem_t));
|
||||
memset(qitem, 0, sizeof(mobjqitem_t));
|
||||
qitem->mo = mo;
|
||||
M_QueueInsert(&(qitem->mqitem), &anchorqueue);
|
||||
}
|
||||
qitem = malloc(sizeof(mobjqitem_t));
|
||||
memset(qitem, 0, sizeof(mobjqitem_t));
|
||||
qitem->mo = mo;
|
||||
M_QueueInsert(&(qitem->mqitem), &anchorqueue);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1657,7 +1648,7 @@ void T_PolyObjRotate(polyrotate_t *th)
|
|||
#else
|
||||
{
|
||||
CONS_Debug(DBG_POLYOBJ, "T_PolyObjRotate: thinker with invalid id %d removed.\n", th->polyObjNum);
|
||||
P_RemoveThinkerDelayed(&th->thinker);
|
||||
P_RemoveThinker(&th->thinker);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
@ -1742,7 +1733,7 @@ void T_PolyObjMove(polymove_t *th)
|
|||
#else
|
||||
{
|
||||
CONS_Debug(DBG_POLYOBJ, "T_PolyObjMove: thinker with invalid id %d removed.\n", th->polyObjNum);
|
||||
P_RemoveThinkerDelayed(&th->thinker);
|
||||
P_RemoveThinker(&th->thinker);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
@ -1815,7 +1806,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
|
|||
#else
|
||||
{
|
||||
CONS_Debug(DBG_POLYOBJ, "T_PolyObjWaypoint: thinker with invalid id %d removed.", th->polyObjNum);
|
||||
P_RemoveThinkerDelayed(&th->thinker);
|
||||
P_RemoveThinker(&th->thinker);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
@ -1826,9 +1817,9 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
|
|||
|
||||
// Find out target first.
|
||||
// We redo this each tic to make savegame compatibility easier.
|
||||
for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next)
|
||||
for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
|
||||
{
|
||||
if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
|
||||
if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)wp;
|
||||
|
@ -1882,7 +1873,8 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
|
|||
po->lines[0]->backsector->floorheight = target->z - amtz;
|
||||
po->lines[0]->backsector->ceilingheight = target->z + amtz;
|
||||
// Sal: Remember to check your sectors!
|
||||
P_CheckSector(po->lines[0]->frontsector, (boolean)(po->damage));
|
||||
// Monster Iestyn: we only need to bother with the back sector, now that P_CheckSector automatically checks the blockmap
|
||||
// updating objects in the front one too just added teleporting to ground bugs
|
||||
P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage));
|
||||
// Apply action to mirroring polyobjects as well
|
||||
start = 0;
|
||||
|
@ -1896,7 +1888,8 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
|
|||
po->lines[0]->backsector->floorheight += diffz; // move up/down by same amount as the parent did
|
||||
po->lines[0]->backsector->ceilingheight += diffz;
|
||||
// Sal: Remember to check your sectors!
|
||||
P_CheckSector(po->lines[0]->frontsector, (boolean)(po->damage));
|
||||
// Monster Iestyn: we only need to bother with the back sector, now that P_CheckSector automatically checks the blockmap
|
||||
// updating objects in the front one too just added teleporting to ground bugs
|
||||
P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage));
|
||||
}
|
||||
|
||||
|
@ -1907,9 +1900,9 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
|
|||
CONS_Debug(DBG_POLYOBJ, "Looking for next waypoint...\n");
|
||||
|
||||
// Find next waypoint
|
||||
for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next)
|
||||
for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
|
||||
{
|
||||
if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
|
||||
if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)wp;
|
||||
|
@ -1917,8 +1910,85 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
|
|||
if (mo2->type != MT_TUBEWAYPOINT)
|
||||
continue;
|
||||
|
||||
if (mo2->threshold == th->sequence)
|
||||
if (mo2->threshold != th->sequence)
|
||||
continue;
|
||||
|
||||
if (th->direction == -1)
|
||||
{
|
||||
if (mo2->health == target->health - 1)
|
||||
{
|
||||
waypoint = mo2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mo2->health == target->health + 1)
|
||||
{
|
||||
waypoint = mo2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!waypoint && th->wrap) // If specified, wrap waypoints
|
||||
{
|
||||
if (!th->continuous)
|
||||
{
|
||||
th->wrap = 0;
|
||||
th->stophere = true;
|
||||
}
|
||||
|
||||
for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
|
||||
{
|
||||
if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)wp;
|
||||
|
||||
if (mo2->type != MT_TUBEWAYPOINT)
|
||||
continue;
|
||||
|
||||
if (mo2->threshold != th->sequence)
|
||||
continue;
|
||||
|
||||
if (th->direction == -1)
|
||||
{
|
||||
if (waypoint == NULL)
|
||||
waypoint = mo2;
|
||||
else if (mo2->health > waypoint->health)
|
||||
waypoint = mo2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mo2->health == 0)
|
||||
{
|
||||
waypoint = mo2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!waypoint && th->comeback) // Come back to the start
|
||||
{
|
||||
th->direction = -th->direction;
|
||||
|
||||
if (!th->continuous)
|
||||
th->comeback = false;
|
||||
|
||||
for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
|
||||
{
|
||||
if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)wp;
|
||||
|
||||
if (mo2->type != MT_TUBEWAYPOINT)
|
||||
continue;
|
||||
|
||||
if (mo2->threshold != th->sequence)
|
||||
continue;
|
||||
|
||||
if (th->direction == -1)
|
||||
{
|
||||
if (mo2->health == target->health - 1)
|
||||
|
@ -1937,83 +2007,6 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!waypoint && th->wrap) // If specified, wrap waypoints
|
||||
{
|
||||
if (!th->continuous)
|
||||
{
|
||||
th->wrap = 0;
|
||||
th->stophere = true;
|
||||
}
|
||||
|
||||
for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next)
|
||||
{
|
||||
if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)wp;
|
||||
|
||||
if (mo2->type != MT_TUBEWAYPOINT)
|
||||
continue;
|
||||
|
||||
if (mo2->threshold == th->sequence)
|
||||
{
|
||||
if (th->direction == -1)
|
||||
{
|
||||
if (waypoint == NULL)
|
||||
waypoint = mo2;
|
||||
else if (mo2->health > waypoint->health)
|
||||
waypoint = mo2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mo2->health == 0)
|
||||
{
|
||||
waypoint = mo2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!waypoint && th->comeback) // Come back to the start
|
||||
{
|
||||
th->direction = -th->direction;
|
||||
|
||||
if (!th->continuous)
|
||||
th->comeback = false;
|
||||
|
||||
for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next)
|
||||
{
|
||||
if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)wp;
|
||||
|
||||
if (mo2->type != MT_TUBEWAYPOINT)
|
||||
continue;
|
||||
|
||||
if (mo2->threshold == th->sequence)
|
||||
{
|
||||
if (th->direction == -1)
|
||||
{
|
||||
if (mo2->health == target->health - 1)
|
||||
{
|
||||
waypoint = mo2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mo2->health == target->health + 1)
|
||||
{
|
||||
waypoint = mo2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (waypoint)
|
||||
|
@ -2059,8 +2052,9 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
|
|||
po->lines[0]->backsector->floorheight += momz;
|
||||
po->lines[0]->backsector->ceilingheight += momz;
|
||||
// Sal: Remember to check your sectors!
|
||||
P_CheckSector(po->lines[0]->frontsector, (boolean)(po->damage)); // frontsector is NEEDED for crushing
|
||||
P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage)); // backsector may not be necessary, but just in case
|
||||
// Monster Iestyn: we only need to bother with the back sector, now that P_CheckSector automatically checks the blockmap
|
||||
// updating objects in the front one too just added teleporting to ground bugs
|
||||
P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage));
|
||||
|
||||
// Apply action to mirroring polyobjects as well
|
||||
start = 0;
|
||||
|
@ -2074,7 +2068,8 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
|
|||
po->lines[0]->backsector->floorheight += momz;
|
||||
po->lines[0]->backsector->ceilingheight += momz;
|
||||
// Sal: Remember to check your sectors!
|
||||
P_CheckSector(po->lines[0]->frontsector, (boolean)(po->damage));
|
||||
// Monster Iestyn: we only need to bother with the back sector, now that P_CheckSector automatically checks the blockmap
|
||||
// updating objects in the front one too just added teleporting to ground bugs
|
||||
P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage));
|
||||
}
|
||||
}
|
||||
|
@ -2089,7 +2084,7 @@ void T_PolyDoorSlide(polyslidedoor_t *th)
|
|||
#else
|
||||
{
|
||||
CONS_Debug(DBG_POLYOBJ, "T_PolyDoorSlide: thinker with invalid id %d removed.\n", th->polyObjNum);
|
||||
P_RemoveThinkerDelayed(&th->thinker);
|
||||
P_RemoveThinker(&th->thinker);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
@ -2194,7 +2189,7 @@ void T_PolyDoorSwing(polyswingdoor_t *th)
|
|||
#else
|
||||
{
|
||||
CONS_Debug(DBG_POLYOBJ, "T_PolyDoorSwing: thinker with invalid id %d removed.\n", th->polyObjNum);
|
||||
P_RemoveThinkerDelayed(&th->thinker);
|
||||
P_RemoveThinker(&th->thinker);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
@ -2293,7 +2288,7 @@ void T_PolyObjDisplace(polydisplace_t *th)
|
|||
#else
|
||||
{
|
||||
CONS_Debug(DBG_POLYOBJ, "T_PolyObjDisplace: thinker with invalid id %d removed.\n", th->polyObjNum);
|
||||
P_RemoveThinkerDelayed(&th->thinker);
|
||||
P_RemoveThinker(&th->thinker);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
@ -2333,7 +2328,7 @@ void T_PolyObjRotDisplace(polyrotdisplace_t *th)
|
|||
#else
|
||||
{
|
||||
CONS_Debug(DBG_POLYOBJ, "T_PolyObjRotDisplace: thinker with invalid id %d removed.\n", th->polyObjNum);
|
||||
P_RemoveThinkerDelayed(&th->thinker);
|
||||
P_RemoveThinker(&th->thinker);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
@ -2390,7 +2385,7 @@ INT32 EV_DoPolyObjRotate(polyrotdata_t *prdata)
|
|||
// create a new thinker
|
||||
th = Z_Malloc(sizeof(polyrotate_t), PU_LEVSPEC, NULL);
|
||||
th->thinker.function.acp1 = (actionf_p1)T_PolyObjRotate;
|
||||
PolyObj_AddThinker(&th->thinker);
|
||||
P_AddThinker(THINK_POLYOBJ, &th->thinker);
|
||||
po->thinker = &th->thinker;
|
||||
|
||||
// set fields
|
||||
|
@ -2455,7 +2450,7 @@ INT32 EV_DoPolyObjMove(polymovedata_t *pmdata)
|
|||
// create a new thinker
|
||||
th = Z_Malloc(sizeof(polymove_t), PU_LEVSPEC, NULL);
|
||||
th->thinker.function.acp1 = (actionf_p1)T_PolyObjMove;
|
||||
PolyObj_AddThinker(&th->thinker);
|
||||
P_AddThinker(THINK_POLYOBJ, &th->thinker);
|
||||
po->thinker = &th->thinker;
|
||||
|
||||
// set fields
|
||||
|
@ -2516,7 +2511,7 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
|
|||
// create a new thinker
|
||||
th = Z_Malloc(sizeof(polywaypoint_t), PU_LEVSPEC, NULL);
|
||||
th->thinker.function.acp1 = (actionf_p1)T_PolyObjWaypoint;
|
||||
PolyObj_AddThinker(&th->thinker);
|
||||
P_AddThinker(THINK_POLYOBJ, &th->thinker);
|
||||
po->thinker = &th->thinker;
|
||||
|
||||
// set fields
|
||||
|
@ -2534,9 +2529,9 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
|
|||
th->stophere = false;
|
||||
|
||||
// Find the first waypoint we need to use
|
||||
for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next)
|
||||
for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
|
||||
{
|
||||
if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
|
||||
if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)wp;
|
||||
|
@ -2544,31 +2539,31 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
|
|||
if (mo2->type != MT_TUBEWAYPOINT)
|
||||
continue;
|
||||
|
||||
if (mo2->threshold == th->sequence)
|
||||
if (mo2->threshold != th->sequence)
|
||||
continue;
|
||||
|
||||
if (th->direction == -1) // highest waypoint #
|
||||
{
|
||||
if (th->direction == -1) // highest waypoint #
|
||||
if (mo2->health == 0)
|
||||
last = mo2;
|
||||
else
|
||||
{
|
||||
if (mo2->health == 0)
|
||||
last = mo2;
|
||||
else
|
||||
{
|
||||
if (first == NULL)
|
||||
first = mo2;
|
||||
else if (mo2->health > first->health)
|
||||
first = mo2;
|
||||
}
|
||||
}
|
||||
else // waypoint 0
|
||||
{
|
||||
if (mo2->health == 0)
|
||||
if (first == NULL)
|
||||
first = mo2;
|
||||
else
|
||||
{
|
||||
if (last == NULL)
|
||||
last = mo2;
|
||||
else if (mo2->health > last->health)
|
||||
last = mo2;
|
||||
}
|
||||
else if (mo2->health > first->health)
|
||||
first = mo2;
|
||||
}
|
||||
}
|
||||
else // waypoint 0
|
||||
{
|
||||
if (mo2->health == 0)
|
||||
first = mo2;
|
||||
else
|
||||
{
|
||||
if (last == NULL)
|
||||
last = mo2;
|
||||
else if (mo2->health > last->health)
|
||||
last = mo2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2605,9 +2600,9 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
|
|||
|
||||
// Find the actual target movement waypoint
|
||||
target = first;
|
||||
/*for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next)
|
||||
/*for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
|
||||
{
|
||||
if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
|
||||
if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)wp;
|
||||
|
@ -2615,23 +2610,23 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
|
|||
if (mo2->type != MT_TUBEWAYPOINT)
|
||||
continue;
|
||||
|
||||
if (mo2->threshold == th->sequence)
|
||||
if (mo2->threshold != th->sequence)
|
||||
continue;
|
||||
|
||||
if (th->direction == -1) // highest waypoint #
|
||||
{
|
||||
if (th->direction == -1) // highest waypoint #
|
||||
if (mo2->health == first->health - 1)
|
||||
{
|
||||
if (mo2->health == first->health - 1)
|
||||
{
|
||||
target = mo2;
|
||||
break;
|
||||
}
|
||||
target = mo2;
|
||||
break;
|
||||
}
|
||||
else // waypoint 0
|
||||
}
|
||||
else // waypoint 0
|
||||
{
|
||||
if (mo2->health == first->health + 1)
|
||||
{
|
||||
if (mo2->health == first->health + 1)
|
||||
{
|
||||
target = mo2;
|
||||
break;
|
||||
}
|
||||
target = mo2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
@ -2662,7 +2657,7 @@ static void Polyobj_doSlideDoor(polyobj_t *po, polydoordata_t *doordata)
|
|||
// allocate and add a new slide door thinker
|
||||
th = Z_Malloc(sizeof(polyslidedoor_t), PU_LEVSPEC, NULL);
|
||||
th->thinker.function.acp1 = (actionf_p1)T_PolyDoorSlide;
|
||||
PolyObj_AddThinker(&th->thinker);
|
||||
P_AddThinker(THINK_POLYOBJ, &th->thinker);
|
||||
|
||||
// point the polyobject to this thinker
|
||||
po->thinker = &th->thinker;
|
||||
|
@ -2710,7 +2705,7 @@ static void Polyobj_doSwingDoor(polyobj_t *po, polydoordata_t *doordata)
|
|||
// allocate and add a new swing door thinker
|
||||
th = Z_Malloc(sizeof(polyswingdoor_t), PU_LEVSPEC, NULL);
|
||||
th->thinker.function.acp1 = (actionf_p1)T_PolyDoorSwing;
|
||||
PolyObj_AddThinker(&th->thinker);
|
||||
P_AddThinker(THINK_POLYOBJ, &th->thinker);
|
||||
|
||||
// point the polyobject to this thinker
|
||||
po->thinker = &th->thinker;
|
||||
|
@ -2792,7 +2787,7 @@ INT32 EV_DoPolyObjDisplace(polydisplacedata_t *prdata)
|
|||
// create a new thinker
|
||||
th = Z_Malloc(sizeof(polydisplace_t), PU_LEVSPEC, NULL);
|
||||
th->thinker.function.acp1 = (actionf_p1)T_PolyObjDisplace;
|
||||
PolyObj_AddThinker(&th->thinker);
|
||||
P_AddThinker(THINK_POLYOBJ, &th->thinker);
|
||||
po->thinker = &th->thinker;
|
||||
|
||||
// set fields
|
||||
|
@ -2838,7 +2833,7 @@ INT32 EV_DoPolyObjRotDisplace(polyrotdisplacedata_t *prdata)
|
|||
// create a new thinker
|
||||
th = Z_Malloc(sizeof(polyrotdisplace_t), PU_LEVSPEC, NULL);
|
||||
th->thinker.function.acp1 = (actionf_p1)T_PolyObjRotDisplace;
|
||||
PolyObj_AddThinker(&th->thinker);
|
||||
P_AddThinker(THINK_POLYOBJ, &th->thinker);
|
||||
po->thinker = &th->thinker;
|
||||
|
||||
// set fields
|
||||
|
@ -2875,7 +2870,7 @@ void T_PolyObjFlag(polymove_t *th)
|
|||
#else
|
||||
{
|
||||
CONS_Debug(DBG_POLYOBJ, "T_PolyObjFlag: thinker with invalid id %d removed.\n", th->polyObjNum);
|
||||
P_RemoveThinkerDelayed(&th->thinker);
|
||||
P_RemoveThinker(&th->thinker);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
@ -2939,7 +2934,7 @@ INT32 EV_DoPolyObjFlag(line_t *pfdata)
|
|||
// create a new thinker
|
||||
th = Z_Malloc(sizeof(polymove_t), PU_LEVSPEC, NULL);
|
||||
th->thinker.function.acp1 = (actionf_p1)T_PolyObjFlag;
|
||||
PolyObj_AddThinker(&th->thinker);
|
||||
P_AddThinker(THINK_POLYOBJ, &th->thinker);
|
||||
po->thinker = &th->thinker;
|
||||
|
||||
// set fields
|
||||
|
@ -2978,7 +2973,7 @@ void T_PolyObjFade(polyfade_t *th)
|
|||
#else
|
||||
{
|
||||
CONS_Debug(DBG_POLYOBJ, "T_PolyObjFade: thinker with invalid id %d removed.\n", th->polyObjNum);
|
||||
P_RemoveThinkerDelayed(&th->thinker);
|
||||
P_RemoveThinker(&th->thinker);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
@ -3089,7 +3084,7 @@ INT32 EV_DoPolyObjFade(polyfadedata_t *pfdata)
|
|||
// create a new thinker
|
||||
th = Z_Malloc(sizeof(polyfade_t), PU_LEVSPEC, NULL);
|
||||
th->thinker.function.acp1 = (actionf_p1)T_PolyObjFade;
|
||||
PolyObj_AddThinker(&th->thinker);
|
||||
P_AddThinker(THINK_POLYOBJ, &th->thinker);
|
||||
po->thinker = &th->thinker;
|
||||
|
||||
// set fields
|
||||
|
|
1162
src/p_saveg.c
1162
src/p_saveg.c
File diff suppressed because it is too large
Load diff
|
@ -102,6 +102,7 @@ line_t *lines;
|
|||
side_t *sides;
|
||||
mapthing_t *mapthings;
|
||||
INT32 numstarposts;
|
||||
UINT16 bossdisabled;
|
||||
boolean levelloading;
|
||||
UINT8 levelfadecol;
|
||||
|
||||
|
@ -815,9 +816,9 @@ void P_ReloadRings(void)
|
|||
mapthing_t *mt = mapthings;
|
||||
|
||||
// scan the thinkers to find rings/spheres/hoops to unset
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo = (mobj_t *)th;
|
||||
|
@ -859,12 +860,7 @@ void P_ReloadRings(void)
|
|||
mt->z = (INT16)(R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS)
|
||||
->sector->floorheight>>FRACBITS);
|
||||
|
||||
P_SpawnHoopsAndRings(mt,
|
||||
#ifdef MANIASPHERES
|
||||
true);
|
||||
#else
|
||||
!G_IsSpecialStage(gamemap)); // prevent flashing spheres in special stages
|
||||
#endif
|
||||
P_SpawnHoopsAndRings(mt, true);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < numHoops; i++)
|
||||
|
@ -878,15 +874,10 @@ void P_SwitchSpheresBonusMode(boolean bonustime)
|
|||
mobj_t *mo;
|
||||
thinker_t *th;
|
||||
|
||||
#ifndef MANIASPHERES
|
||||
if (G_IsSpecialStage(gamemap)) // prevent flashing spheres in special stages
|
||||
return;
|
||||
#endif
|
||||
|
||||
// scan the thinkers to find spheres to switch
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo = (mobj_t *)th;
|
||||
|
@ -1288,6 +1279,9 @@ static void P_LoadLineDefs2(void)
|
|||
// Compile linedef 'text' from both sidedefs 'text' for appropriate specials.
|
||||
switch(ld->special)
|
||||
{
|
||||
case 331: // Trigger linedef executor: Skin - Continuous
|
||||
case 332: // Trigger linedef executor: Skin - Each time
|
||||
case 333: // Trigger linedef executor: Skin - Once
|
||||
case 443: // Calls a named Lua function
|
||||
if (sides[ld->sidenum[0]].text)
|
||||
{
|
||||
|
@ -1498,6 +1492,9 @@ static void P_LoadRawSideDefs2(void *data)
|
|||
break;
|
||||
}
|
||||
|
||||
case 331: // Trigger linedef executor: Skin - Continuous
|
||||
case 332: // Trigger linedef executor: Skin - Each time
|
||||
case 333: // Trigger linedef executor: Skin - Once
|
||||
case 443: // Calls a named Lua function
|
||||
case 459: // Control text prompt (named tag)
|
||||
{
|
||||
|
@ -2209,7 +2206,7 @@ static void P_LevelInitStuff(void)
|
|||
ssspheres = timeinmap = 0;
|
||||
|
||||
// special stage
|
||||
stagefailed = false;
|
||||
stagefailed = true; // assume failed unless proven otherwise - P_GiveEmerald or emerald touchspecial
|
||||
// Reset temporary record data
|
||||
memset(&ntemprecords, 0, sizeof(nightsdata_t));
|
||||
|
||||
|
@ -2228,7 +2225,7 @@ static void P_LevelInitStuff(void)
|
|||
}
|
||||
}
|
||||
|
||||
countdown = countdown2 = 0;
|
||||
countdown = countdown2 = exitfadestarted = 0;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
|
@ -2284,7 +2281,6 @@ static void P_LevelInitStuff(void)
|
|||
void P_LoadThingsOnly(void)
|
||||
{
|
||||
// Search through all the thinkers.
|
||||
mobj_t *mo;
|
||||
thinker_t *think;
|
||||
INT32 i, viewid = -1, centerid = -1; // for skyboxes
|
||||
|
||||
|
@ -2299,15 +2295,11 @@ void P_LoadThingsOnly(void)
|
|||
}
|
||||
|
||||
|
||||
for (think = thinkercap.next; think != &thinkercap; think = think->next)
|
||||
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
|
||||
{
|
||||
if (think->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
continue; // not a mobj thinker
|
||||
|
||||
mo = (mobj_t *)think;
|
||||
|
||||
if (mo)
|
||||
P_RemoveMobj(mo);
|
||||
if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
P_RemoveMobj((mobj_t *)think);
|
||||
}
|
||||
|
||||
P_LevelInitStuff();
|
||||
|
@ -2880,7 +2872,10 @@ boolean P_SetupLevel(boolean skipprecip)
|
|||
|
||||
// reset the player starts
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
playerstarts[i] = NULL;
|
||||
playerstarts[i] = bluectfstarts[i] = redctfstarts[i] = NULL;
|
||||
|
||||
for (i = 0; i < MAX_DM_STARTS; i++)
|
||||
deathmatchstarts[i] = NULL;
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
skyboxmo[i] = NULL;
|
||||
|
@ -2916,7 +2911,10 @@ boolean P_SetupLevel(boolean skipprecip)
|
|||
|
||||
// reset the player starts
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
playerstarts[i] = NULL;
|
||||
playerstarts[i] = bluectfstarts[i] = redctfstarts[i] = NULL;
|
||||
|
||||
for (i = 0; i < MAX_DM_STARTS; i++)
|
||||
deathmatchstarts[i] = NULL;
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
skyboxmo[i] = NULL;
|
||||
|
@ -2934,7 +2932,7 @@ boolean P_SetupLevel(boolean skipprecip)
|
|||
P_InitSpecials();
|
||||
|
||||
#ifdef ESLOPE
|
||||
P_ResetDynamicSlopes();
|
||||
P_ResetDynamicSlopes(fromnetsave);
|
||||
#endif
|
||||
|
||||
P_LoadThings(loademblems);
|
||||
|
@ -3132,7 +3130,7 @@ boolean P_SetupLevel(boolean skipprecip)
|
|||
R_PrecacheLevel();
|
||||
|
||||
nextmapoverride = 0;
|
||||
skipstats = false;
|
||||
skipstats = 0;
|
||||
|
||||
if (!(netgame || multiplayer) && (!modifiedgame || savemoddata))
|
||||
mapvisited[gamemap-1] |= MV_VISITED;
|
||||
|
@ -3443,13 +3441,13 @@ boolean P_AddWadFile(const char *wadfilename)
|
|||
ST_UnloadGraphics();
|
||||
HU_LoadGraphics();
|
||||
ST_LoadGraphics();
|
||||
ST_ReloadSkinFaceGraphics();
|
||||
|
||||
//
|
||||
// look for skins
|
||||
//
|
||||
R_AddSkins(wadnum); // faB: wadfile index in wadfiles[]
|
||||
R_PatchSkins(wadnum); // toast: PATCH PATCH
|
||||
ST_ReloadSkinFaceGraphics();
|
||||
|
||||
//
|
||||
// search for maps
|
||||
|
|
626
src/p_slopes.c
626
src/p_slopes.c
|
@ -25,68 +25,66 @@
|
|||
|
||||
#ifdef ESLOPE
|
||||
|
||||
static pslope_t *slopelist = NULL;
|
||||
static UINT16 slopecount = 0;
|
||||
pslope_t *slopelist = NULL;
|
||||
UINT16 slopecount = 0;
|
||||
|
||||
// Calculate line normal
|
||||
void P_CalculateSlopeNormal(pslope_t *slope) {
|
||||
slope->normal.z = FINECOSINE(slope->zangle>>ANGLETOFINESHIFT);
|
||||
slope->normal.x = -FixedMul(FINESINE(slope->zangle>>ANGLETOFINESHIFT), slope->d.x);
|
||||
slope->normal.y = -FixedMul(FINESINE(slope->zangle>>ANGLETOFINESHIFT), slope->d.y);
|
||||
slope->normal.x = FixedMul(FINESINE(slope->zangle>>ANGLETOFINESHIFT), slope->d.x);
|
||||
slope->normal.y = FixedMul(FINESINE(slope->zangle>>ANGLETOFINESHIFT), slope->d.y);
|
||||
}
|
||||
|
||||
// With a vertex slope that has its vertices set, configure relevant slope info
|
||||
static void P_ReconfigureVertexSlope(pslope_t *slope)
|
||||
/// Setup slope via 3 vertexes.
|
||||
static void ReconfigureViaVertexes (pslope_t *slope, const vector3_t v1, const vector3_t v2, const vector3_t v3)
|
||||
{
|
||||
vector3_t vec1, vec2;
|
||||
|
||||
// Set slope normal
|
||||
vec1.x = (slope->vertices[1]->x - slope->vertices[0]->x) << FRACBITS;
|
||||
vec1.y = (slope->vertices[1]->y - slope->vertices[0]->y) << FRACBITS;
|
||||
vec1.z = (slope->vertices[1]->z - slope->vertices[0]->z) << FRACBITS;
|
||||
// Set origin.
|
||||
FV3_Copy(&slope->o, &v1);
|
||||
|
||||
vec2.x = (slope->vertices[2]->x - slope->vertices[0]->x) << FRACBITS;
|
||||
vec2.y = (slope->vertices[2]->y - slope->vertices[0]->y) << FRACBITS;
|
||||
vec2.z = (slope->vertices[2]->z - slope->vertices[0]->z) << FRACBITS;
|
||||
// Get slope's normal.
|
||||
FV3_SubEx(&v2, &v1, &vec1);
|
||||
FV3_SubEx(&v3, &v1, &vec2);
|
||||
|
||||
// ugggggggh fixed-point maaaaaaath
|
||||
slope->extent = max(
|
||||
max(max(abs(vec1.x), abs(vec1.y)), abs(vec1.z)),
|
||||
max(max(abs(vec2.x), abs(vec2.y)), abs(vec2.z))
|
||||
) >> (FRACBITS+5);
|
||||
vec1.x /= slope->extent;
|
||||
vec1.y /= slope->extent;
|
||||
vec1.z /= slope->extent;
|
||||
vec2.x /= slope->extent;
|
||||
vec2.y /= slope->extent;
|
||||
vec2.z /= slope->extent;
|
||||
// Set some defaults for a non-sloped "slope"
|
||||
if (vec1.z == 0 && vec2.z == 0)
|
||||
{
|
||||
/// \todo Fix fully flat cases.
|
||||
|
||||
FV3_Cross(&vec1, &vec2, &slope->normal);
|
||||
|
||||
slope->extent = R_PointToDist2(0, 0, R_PointToDist2(0, 0, slope->normal.x, slope->normal.y), slope->normal.z);
|
||||
if (slope->normal.z < 0)
|
||||
slope->extent = -slope->extent;
|
||||
|
||||
slope->normal.x = FixedDiv(slope->normal.x, slope->extent);
|
||||
slope->normal.y = FixedDiv(slope->normal.y, slope->extent);
|
||||
slope->normal.z = FixedDiv(slope->normal.z, slope->extent);
|
||||
|
||||
// Set origin
|
||||
slope->o.x = slope->vertices[0]->x << FRACBITS;
|
||||
slope->o.y = slope->vertices[0]->y << FRACBITS;
|
||||
slope->o.z = slope->vertices[0]->z << FRACBITS;
|
||||
|
||||
if (slope->normal.x == 0 && slope->normal.y == 0) { // Set some defaults for a non-sloped "slope"
|
||||
slope->zangle = slope->xydirection = 0;
|
||||
slope->zdelta = slope->d.x = slope->d.y = 0;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
/// \note Using fixed point for vectorial products easily leads to overflows so we work around by downscaling them.
|
||||
fixed_t m = max(
|
||||
max(max(abs(vec1.x), abs(vec1.y)), abs(vec1.z)),
|
||||
max(max(abs(vec2.x), abs(vec2.y)), abs(vec2.z))
|
||||
) >> 5; // shifting right by 5 is good enough.
|
||||
|
||||
FV3_Cross(
|
||||
FV3_Divide(&vec1, m),
|
||||
FV3_Divide(&vec2, m),
|
||||
&slope->normal
|
||||
);
|
||||
|
||||
// NOTE: FV3_Magnitude() doesn't work properly in some cases, and chaining FixedHypot() seems to give worse results.
|
||||
m = R_PointToDist2(0, 0, R_PointToDist2(0, 0, slope->normal.x, slope->normal.y), slope->normal.z);
|
||||
|
||||
// Invert normal if it's facing down.
|
||||
if (slope->normal.z < 0)
|
||||
m = -m;
|
||||
|
||||
FV3_Divide(&slope->normal, m);
|
||||
|
||||
// Get direction vector
|
||||
slope->extent = R_PointToDist2(0, 0, slope->normal.x, slope->normal.y);
|
||||
slope->d.x = -FixedDiv(slope->normal.x, slope->extent);
|
||||
slope->d.y = -FixedDiv(slope->normal.y, slope->extent);
|
||||
m = FixedHypot(slope->normal.x, slope->normal.y);
|
||||
slope->d.x = -FixedDiv(slope->normal.x, m);
|
||||
slope->d.y = -FixedDiv(slope->normal.y, m);
|
||||
|
||||
// Z delta
|
||||
slope->zdelta = FixedDiv(slope->extent, slope->normal.z);
|
||||
slope->zdelta = FixedDiv(m, slope->normal.z);
|
||||
|
||||
// Get angles
|
||||
slope->xydirection = R_PointToAngle2(0, 0, slope->d.x, slope->d.y)+ANGLE_180;
|
||||
|
@ -94,88 +92,95 @@ static void P_ReconfigureVertexSlope(pslope_t *slope)
|
|||
}
|
||||
}
|
||||
|
||||
// Recalculate dynamic slopes
|
||||
void P_RunDynamicSlopes(void) {
|
||||
pslope_t *slope;
|
||||
/// Recalculate dynamic slopes.
|
||||
void T_DynamicSlopeLine (dynplanethink_t* th)
|
||||
{
|
||||
pslope_t* slope = th->slope;
|
||||
line_t* srcline = th->sourceline;
|
||||
|
||||
for (slope = slopelist; slope; slope = slope->next) {
|
||||
fixed_t zdelta;
|
||||
fixed_t zdelta;
|
||||
|
||||
if (slope->flags & SL_NODYNAMIC)
|
||||
continue;
|
||||
switch(th->type) {
|
||||
case DP_FRONTFLOOR:
|
||||
zdelta = srcline->backsector->floorheight - srcline->frontsector->floorheight;
|
||||
slope->o.z = srcline->frontsector->floorheight;
|
||||
break;
|
||||
|
||||
switch(slope->refpos) {
|
||||
case 1: // front floor
|
||||
zdelta = slope->sourceline->backsector->floorheight - slope->sourceline->frontsector->floorheight;
|
||||
slope->o.z = slope->sourceline->frontsector->floorheight;
|
||||
break;
|
||||
case 2: // front ceiling
|
||||
zdelta = slope->sourceline->backsector->ceilingheight - slope->sourceline->frontsector->ceilingheight;
|
||||
slope->o.z = slope->sourceline->frontsector->ceilingheight;
|
||||
break;
|
||||
case 3: // back floor
|
||||
zdelta = slope->sourceline->frontsector->floorheight - slope->sourceline->backsector->floorheight;
|
||||
slope->o.z = slope->sourceline->backsector->floorheight;
|
||||
break;
|
||||
case 4: // back ceiling
|
||||
zdelta = slope->sourceline->frontsector->ceilingheight - slope->sourceline->backsector->ceilingheight;
|
||||
slope->o.z = slope->sourceline->backsector->ceilingheight;
|
||||
break;
|
||||
case 5: // vertices
|
||||
{
|
||||
mapthing_t *mt;
|
||||
size_t i;
|
||||
INT32 l;
|
||||
line_t *line;
|
||||
case DP_FRONTCEIL:
|
||||
zdelta = srcline->backsector->ceilingheight - srcline->frontsector->ceilingheight;
|
||||
slope->o.z = srcline->frontsector->ceilingheight;
|
||||
break;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
mt = slope->vertices[i];
|
||||
l = P_FindSpecialLineFromTag(799, mt->angle, -1);
|
||||
if (l != -1) {
|
||||
line = &lines[l];
|
||||
mt->z = line->frontsector->floorheight >> FRACBITS;
|
||||
}
|
||||
}
|
||||
case DP_BACKFLOOR:
|
||||
zdelta = srcline->frontsector->floorheight - srcline->backsector->floorheight;
|
||||
slope->o.z = srcline->backsector->floorheight;
|
||||
break;
|
||||
|
||||
P_ReconfigureVertexSlope(slope);
|
||||
}
|
||||
continue; // TODO
|
||||
case DP_BACKCEIL:
|
||||
zdelta = srcline->frontsector->ceilingheight - srcline->backsector->ceilingheight;
|
||||
slope->o.z = srcline->backsector->ceilingheight;
|
||||
break;
|
||||
|
||||
default:
|
||||
I_Error("P_RunDynamicSlopes: slope has invalid type!");
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (slope->zdelta != FixedDiv(zdelta, slope->extent)) {
|
||||
slope->zdelta = FixedDiv(zdelta, slope->extent);
|
||||
slope->zangle = R_PointToAngle2(0, 0, slope->extent, -zdelta);
|
||||
P_CalculateSlopeNormal(slope);
|
||||
}
|
||||
if (slope->zdelta != FixedDiv(zdelta, th->extent)) {
|
||||
slope->zdelta = FixedDiv(zdelta, th->extent);
|
||||
slope->zangle = R_PointToAngle2(0, 0, th->extent, -zdelta);
|
||||
P_CalculateSlopeNormal(slope);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// P_MakeSlope
|
||||
//
|
||||
// Alocates and fill the contents of a slope structure.
|
||||
//
|
||||
static pslope_t *P_MakeSlope(const vector3_t *o, const vector2_t *d,
|
||||
const fixed_t zdelta, UINT8 flags)
|
||||
/// Mapthing-defined
|
||||
void T_DynamicSlopeVert (dynplanethink_t* th)
|
||||
{
|
||||
pslope_t *ret = Z_Malloc(sizeof(pslope_t), PU_LEVEL, NULL);
|
||||
memset(ret, 0, sizeof(*ret));
|
||||
pslope_t* slope = th->slope;
|
||||
|
||||
ret->o.x = o->x;
|
||||
ret->o.y = o->y;
|
||||
ret->o.z = o->z;
|
||||
size_t i;
|
||||
INT32 l;
|
||||
|
||||
ret->d.x = d->x;
|
||||
ret->d.y = d->y;
|
||||
for (i = 0; i < 3; i++) {
|
||||
l = P_FindSpecialLineFromTag(799, th->tags[i], -1);
|
||||
if (l != -1) {
|
||||
th->vex[i].z = lines[l].frontsector->floorheight;
|
||||
}
|
||||
else
|
||||
th->vex[i].z = 0;
|
||||
}
|
||||
|
||||
ret->zdelta = zdelta;
|
||||
ReconfigureViaVertexes(slope, th->vex[0], th->vex[1], th->vex[2]);
|
||||
}
|
||||
|
||||
static inline void P_AddDynSlopeThinker (pslope_t* slope, dynplanetype_t type, line_t* sourceline, fixed_t extent, const INT16 tags[3], const vector3_t vx[3])
|
||||
{
|
||||
dynplanethink_t* th = Z_Calloc(sizeof (*th), PU_LEVSPEC, NULL);
|
||||
switch (type)
|
||||
{
|
||||
case DP_VERTEX:
|
||||
th->thinker.function.acp1 = (actionf_p1)T_DynamicSlopeVert;
|
||||
memcpy(th->tags, tags, sizeof(th->tags));
|
||||
memcpy(th->vex, vx, sizeof(th->vex));
|
||||
break;
|
||||
default:
|
||||
th->thinker.function.acp1 = (actionf_p1)T_DynamicSlopeLine;
|
||||
th->sourceline = sourceline;
|
||||
th->extent = extent;
|
||||
}
|
||||
|
||||
th->slope = slope;
|
||||
th->type = type;
|
||||
|
||||
P_AddThinker(THINK_DYNSLOPE, &th->thinker);
|
||||
}
|
||||
|
||||
|
||||
/// Create a new slope and add it to the slope list.
|
||||
static inline pslope_t* Slope_Add (const UINT8 flags)
|
||||
{
|
||||
pslope_t *ret = Z_Calloc(sizeof(pslope_t), PU_LEVEL, NULL);
|
||||
ret->flags = flags;
|
||||
|
||||
// Add to the slope list
|
||||
ret->next = slopelist;
|
||||
slopelist = ret;
|
||||
|
||||
|
@ -185,13 +190,24 @@ static pslope_t *P_MakeSlope(const vector3_t *o, const vector2_t *d,
|
|||
return ret;
|
||||
}
|
||||
|
||||
//
|
||||
// P_GetExtent
|
||||
//
|
||||
// Returns the distance to the first line within the sector that
|
||||
// is intersected by a line parallel to the plane normal with the point (ox, oy)
|
||||
//
|
||||
static fixed_t P_GetExtent(sector_t *sector, line_t *line)
|
||||
/// Alocates and fill the contents of a slope structure.
|
||||
static pslope_t *MakeViaVectors(const vector3_t *o, const vector2_t *d,
|
||||
const fixed_t zdelta, UINT8 flags)
|
||||
{
|
||||
pslope_t *ret = Slope_Add(flags);
|
||||
|
||||
FV3_Copy(&ret->o, o);
|
||||
FV2_Copy(&ret->d, d);
|
||||
|
||||
ret->zdelta = zdelta;
|
||||
|
||||
ret->flags = flags;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// Get furthest perpendicular distance from all vertexes in a sector for a given line.
|
||||
static fixed_t GetExtent(sector_t *sector, line_t *line)
|
||||
{
|
||||
// ZDoom code reference: v3float_t = vertex_t
|
||||
fixed_t fardist = -FRACUNIT;
|
||||
|
@ -224,14 +240,8 @@ static fixed_t P_GetExtent(sector_t *sector, line_t *line)
|
|||
return fardist;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// P_SpawnSlope_Line
|
||||
//
|
||||
// Creates one or more slopes based on the given line type and front/back
|
||||
// sectors.
|
||||
//
|
||||
void P_SpawnSlope_Line(int linenum)
|
||||
/// Creates one or more slopes based on the given line type and front/back sectors.
|
||||
static void line_SpawnViaLine(const int linenum, const boolean spawnthinker)
|
||||
{
|
||||
// With dynamic slopes, it's fine to just leave this function as normal,
|
||||
// because checking to see if a slope had changed will waste more memory than
|
||||
|
@ -249,12 +259,10 @@ void P_SpawnSlope_Line(int linenum)
|
|||
boolean backceil = (special == 711 || special == 712 || special == 703);
|
||||
|
||||
UINT8 flags = 0; // Slope flags
|
||||
if (line->flags & ML_NOSONIC)
|
||||
if (line->flags & ML_NETONLY)
|
||||
flags |= SL_NOPHYSICS;
|
||||
if (!(line->flags & ML_NOTAILS))
|
||||
flags |= SL_NODYNAMIC;
|
||||
if (line->flags & ML_NOKNUX)
|
||||
flags |= SL_ANCHORVERTEX;
|
||||
if (line->flags & ML_NONET)
|
||||
flags |= SL_DYNAMIC;
|
||||
|
||||
if(!frontfloor && !backfloor && !frontceil && !backceil)
|
||||
{
|
||||
|
@ -274,6 +282,7 @@ void P_SpawnSlope_Line(int linenum)
|
|||
ny = -FixedDiv(line->dx, len);
|
||||
}
|
||||
|
||||
// Set origin to line's center.
|
||||
origin.x = line->v1->x + (line->v2->x - line->v1->x)/2;
|
||||
origin.y = line->v1->y + (line->v2->y - line->v1->y)/2;
|
||||
|
||||
|
@ -286,7 +295,7 @@ void P_SpawnSlope_Line(int linenum)
|
|||
direction.x = nx;
|
||||
direction.y = ny;
|
||||
|
||||
extent = P_GetExtent(line->frontsector, line);
|
||||
extent = GetExtent(line->frontsector, line);
|
||||
|
||||
if(extent < 0)
|
||||
{
|
||||
|
@ -304,104 +313,43 @@ void P_SpawnSlope_Line(int linenum)
|
|||
|
||||
if(frontfloor)
|
||||
{
|
||||
fixed_t highest, lowest;
|
||||
size_t l;
|
||||
point.z = line->frontsector->floorheight; // Startz
|
||||
dz = FixedDiv(origin.z - point.z, extent); // Destinationz
|
||||
|
||||
// In P_SpawnSlopeLine the origin is the centerpoint of the sourcelinedef
|
||||
|
||||
fslope = line->frontsector->f_slope =
|
||||
P_MakeSlope(&point, &direction, dz, flags);
|
||||
|
||||
// Set up some shit
|
||||
fslope->extent = extent;
|
||||
fslope->refpos = 1;
|
||||
MakeViaVectors(&point, &direction, dz, flags);
|
||||
|
||||
// Now remember that f_slope IS a vector
|
||||
// fslope->o = origin 3D point 1 of the vector
|
||||
// fslope->d = destination 3D point 2 of the vector
|
||||
// fslope->normal is a 3D line perpendicular to the 3D vector
|
||||
|
||||
// Sync the linedata of the line that started this slope
|
||||
// TODO: Anything special for control sector based slopes later?
|
||||
fslope->sourceline = line;
|
||||
|
||||
// To find the real highz/lowz of a slope, you need to check all the vertexes
|
||||
// in the slope's sector with P_GetZAt to get the REAL lowz & highz
|
||||
// Although these slopes are set by floorheights the ANGLE is what a slope is,
|
||||
// so technically any slope can extend on forever (they are just bound by sectors)
|
||||
// *You can use sourceline as a reference to see if two slopes really are the same
|
||||
|
||||
// Default points for high and low
|
||||
highest = point.z > origin.z ? point.z : origin.z;
|
||||
lowest = point.z < origin.z ? point.z : origin.z;
|
||||
|
||||
// Now check to see what the REAL high and low points of the slope inside the sector
|
||||
// TODO: Is this really needed outside of FOFs? -Red
|
||||
|
||||
for (l = 0; l < line->frontsector->linecount; l++)
|
||||
{
|
||||
fixed_t height = P_GetZAt(line->frontsector->f_slope, line->frontsector->lines[l]->v1->x, line->frontsector->lines[l]->v1->y);
|
||||
|
||||
if (height > highest)
|
||||
highest = height;
|
||||
|
||||
if (height < lowest)
|
||||
lowest = height;
|
||||
}
|
||||
|
||||
// Sets extra clipping data for the frontsector's slope
|
||||
fslope->highz = highest;
|
||||
fslope->lowz = lowest;
|
||||
|
||||
fslope->zangle = R_PointToAngle2(0, origin.z, extent, point.z);
|
||||
fslope->xydirection = R_PointToAngle2(origin.x, origin.y, point.x, point.y);
|
||||
|
||||
P_CalculateSlopeNormal(fslope);
|
||||
|
||||
if (spawnthinker && (flags & SL_DYNAMIC))
|
||||
P_AddDynSlopeThinker(fslope, DP_FRONTFLOOR, line, extent, NULL, NULL);
|
||||
}
|
||||
if(frontceil)
|
||||
{
|
||||
fixed_t highest, lowest;
|
||||
size_t l;
|
||||
origin.z = line->backsector->ceilingheight;
|
||||
point.z = line->frontsector->ceilingheight;
|
||||
dz = FixedDiv(origin.z - point.z, extent);
|
||||
|
||||
cslope = line->frontsector->c_slope =
|
||||
P_MakeSlope(&point, &direction, dz, flags);
|
||||
|
||||
// Set up some shit
|
||||
cslope->extent = extent;
|
||||
cslope->refpos = 2;
|
||||
|
||||
// Sync the linedata of the line that started this slope
|
||||
// TODO: Anything special for control sector based slopes later?
|
||||
cslope->sourceline = line;
|
||||
|
||||
// Remember the way the slope is formed
|
||||
highest = point.z > origin.z ? point.z : origin.z;
|
||||
lowest = point.z < origin.z ? point.z : origin.z;
|
||||
|
||||
for (l = 0; l < line->frontsector->linecount; l++)
|
||||
{
|
||||
fixed_t height = P_GetZAt(line->frontsector->c_slope, line->frontsector->lines[l]->v1->x, line->frontsector->lines[l]->v1->y);
|
||||
|
||||
if (height > highest)
|
||||
highest = height;
|
||||
|
||||
if (height < lowest)
|
||||
lowest = height;
|
||||
}
|
||||
|
||||
// This line special sets extra clipping data for the frontsector's slope
|
||||
cslope->highz = highest;
|
||||
cslope->lowz = lowest;
|
||||
MakeViaVectors(&point, &direction, dz, flags);
|
||||
|
||||
cslope->zangle = R_PointToAngle2(0, origin.z, extent, point.z);
|
||||
cslope->xydirection = R_PointToAngle2(origin.x, origin.y, point.x, point.y);
|
||||
|
||||
P_CalculateSlopeNormal(cslope);
|
||||
|
||||
if (spawnthinker && (flags & SL_DYNAMIC))
|
||||
P_AddDynSlopeThinker(cslope, DP_FRONTCEIL, line, extent, NULL, NULL);
|
||||
}
|
||||
}
|
||||
if(backfloor || backceil)
|
||||
|
@ -413,7 +361,7 @@ void P_SpawnSlope_Line(int linenum)
|
|||
direction.x = -nx;
|
||||
direction.y = -ny;
|
||||
|
||||
extent = P_GetExtent(line->backsector, line);
|
||||
extent = GetExtent(line->backsector, line);
|
||||
|
||||
if(extent < 0)
|
||||
{
|
||||
|
@ -429,88 +377,36 @@ void P_SpawnSlope_Line(int linenum)
|
|||
|
||||
if(backfloor)
|
||||
{
|
||||
fixed_t highest, lowest;
|
||||
size_t l;
|
||||
point.z = line->backsector->floorheight;
|
||||
dz = FixedDiv(origin.z - point.z, extent);
|
||||
|
||||
fslope = line->backsector->f_slope =
|
||||
P_MakeSlope(&point, &direction, dz, flags);
|
||||
|
||||
// Set up some shit
|
||||
fslope->extent = extent;
|
||||
fslope->refpos = 3;
|
||||
|
||||
// Sync the linedata of the line that started this slope
|
||||
// TODO: Anything special for control sector based slopes later?
|
||||
fslope->sourceline = line;
|
||||
|
||||
// Remember the way the slope is formed
|
||||
highest = point.z > origin.z ? point.z : origin.z;
|
||||
lowest = point.z < origin.z ? point.z : origin.z;
|
||||
|
||||
for (l = 0; l < line->backsector->linecount; l++)
|
||||
{
|
||||
fixed_t height = P_GetZAt(line->backsector->f_slope, line->backsector->lines[l]->v1->x, line->backsector->lines[l]->v1->y);
|
||||
|
||||
if (height > highest)
|
||||
highest = height;
|
||||
|
||||
if (height < lowest)
|
||||
lowest = height;
|
||||
}
|
||||
|
||||
// This line special sets extra clipping data for the frontsector's slope
|
||||
fslope->highz = highest;
|
||||
fslope->lowz = lowest;
|
||||
MakeViaVectors(&point, &direction, dz, flags);
|
||||
|
||||
fslope->zangle = R_PointToAngle2(0, origin.z, extent, point.z);
|
||||
fslope->xydirection = R_PointToAngle2(origin.x, origin.y, point.x, point.y);
|
||||
|
||||
P_CalculateSlopeNormal(fslope);
|
||||
|
||||
if (spawnthinker && (flags & SL_DYNAMIC))
|
||||
P_AddDynSlopeThinker(fslope, DP_BACKFLOOR, line, extent, NULL, NULL);
|
||||
}
|
||||
if(backceil)
|
||||
{
|
||||
fixed_t highest, lowest;
|
||||
size_t l;
|
||||
origin.z = line->frontsector->ceilingheight;
|
||||
point.z = line->backsector->ceilingheight;
|
||||
dz = FixedDiv(origin.z - point.z, extent);
|
||||
|
||||
cslope = line->backsector->c_slope =
|
||||
P_MakeSlope(&point, &direction, dz, flags);
|
||||
|
||||
// Set up some shit
|
||||
cslope->extent = extent;
|
||||
cslope->refpos = 4;
|
||||
|
||||
// Sync the linedata of the line that started this slope
|
||||
// TODO: Anything special for control sector based slopes later?
|
||||
cslope->sourceline = line;
|
||||
|
||||
// Remember the way the slope is formed
|
||||
highest = point.z > origin.z ? point.z : origin.z;
|
||||
lowest = point.z < origin.z ? point.z : origin.z;
|
||||
|
||||
for (l = 0; l < line->backsector->linecount; l++)
|
||||
{
|
||||
fixed_t height = P_GetZAt(line->backsector->c_slope, line->backsector->lines[l]->v1->x, line->backsector->lines[l]->v1->y);
|
||||
|
||||
if (height > highest)
|
||||
highest = height;
|
||||
|
||||
if (height < lowest)
|
||||
lowest = height;
|
||||
}
|
||||
|
||||
// This line special sets extra clipping data for the backsector's slope
|
||||
cslope->highz = highest;
|
||||
cslope->lowz = lowest;
|
||||
MakeViaVectors(&point, &direction, dz, flags);
|
||||
|
||||
cslope->zangle = R_PointToAngle2(0, origin.z, extent, point.z);
|
||||
cslope->xydirection = R_PointToAngle2(origin.x, origin.y, point.x, point.y);
|
||||
|
||||
P_CalculateSlopeNormal(cslope);
|
||||
|
||||
if (spawnthinker && (flags & SL_DYNAMIC))
|
||||
P_AddDynSlopeThinker(cslope, DP_BACKCEIL, line, extent, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -518,63 +414,99 @@ void P_SpawnSlope_Line(int linenum)
|
|||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// P_NewVertexSlope
|
||||
//
|
||||
// Creates a new slope from three vertices with the specified IDs
|
||||
//
|
||||
static pslope_t *P_NewVertexSlope(INT16 tag1, INT16 tag2, INT16 tag3, UINT8 flags)
|
||||
/// Creates a new slope from three mapthings with the specified IDs
|
||||
static pslope_t *MakeViaMapthings(INT16 tag1, INT16 tag2, INT16 tag3, UINT8 flags, const boolean spawnthinker)
|
||||
{
|
||||
size_t i;
|
||||
mapthing_t *mt = mapthings;
|
||||
mapthing_t* mt = mapthings;
|
||||
mapthing_t* vertices[3] = {0};
|
||||
INT16 tags[3] = {tag1, tag2, tag3};
|
||||
|
||||
pslope_t *ret = Z_Malloc(sizeof(pslope_t), PU_LEVEL, NULL);
|
||||
memset(ret, 0, sizeof(*ret));
|
||||
|
||||
// Start by setting flags
|
||||
ret->flags = flags;
|
||||
|
||||
// Now set up the vertex list
|
||||
ret->vertices = Z_Malloc(3*sizeof(mapthing_t), PU_LEVEL, NULL);
|
||||
memset(ret->vertices, 0, 3*sizeof(mapthing_t));
|
||||
vector3_t vx[3];
|
||||
pslope_t* ret = Slope_Add(flags);
|
||||
|
||||
// And... look for the vertices in question.
|
||||
for (i = 0; i < nummapthings; i++, mt++) {
|
||||
if (mt->type != 750) // Haha, I'm hijacking the old Chaos Spawn thingtype for something!
|
||||
continue;
|
||||
|
||||
if (!ret->vertices[0] && mt->angle == tag1)
|
||||
ret->vertices[0] = mt;
|
||||
else if (!ret->vertices[1] && mt->angle == tag2)
|
||||
ret->vertices[1] = mt;
|
||||
else if (!ret->vertices[2] && mt->angle == tag3)
|
||||
ret->vertices[2] = mt;
|
||||
if (!vertices[0] && mt->angle == tag1)
|
||||
vertices[0] = mt;
|
||||
else if (!vertices[1] && mt->angle == tag2)
|
||||
vertices[1] = mt;
|
||||
else if (!vertices[2] && mt->angle == tag3)
|
||||
vertices[2] = mt;
|
||||
}
|
||||
|
||||
// Now set heights for each vertex, because they haven't been set yet
|
||||
for (i = 0; i < 3; i++) {
|
||||
mt = ret->vertices[i];
|
||||
mt = vertices[i];
|
||||
if (!mt) // If a vertex wasn't found, it's game over. There's nothing you can do to recover (except maybe try and kill the slope instead - TODO?)
|
||||
I_Error("P_NewVertexSlope: Slope vertex %s (for linedef tag %d) not found!", sizeu1(i), tag1);
|
||||
I_Error("MakeViaMapthings: Slope vertex %s (for linedef tag %d) not found!", sizeu1(i), tag1);
|
||||
vx[i].x = mt->x << FRACBITS;
|
||||
vx[i].y = mt->y << FRACBITS;
|
||||
if (mt->extrainfo)
|
||||
mt->z = mt->options;
|
||||
vx[i].z = mt->options << FRACBITS;
|
||||
else
|
||||
mt->z = (R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS)->sector->floorheight >> FRACBITS) + (mt->options >> ZSHIFT);
|
||||
vx[i].z = (R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS)->sector->floorheight) + ((mt->options >> ZSHIFT) << FRACBITS);
|
||||
}
|
||||
|
||||
P_ReconfigureVertexSlope(ret);
|
||||
ret->refpos = 5;
|
||||
ReconfigureViaVertexes(ret, vx[0], vx[1], vx[2]);
|
||||
|
||||
// Add to the slope list
|
||||
ret->next = slopelist;
|
||||
slopelist = ret;
|
||||
|
||||
slopecount++;
|
||||
ret->id = slopecount;
|
||||
if (spawnthinker && (flags & SL_DYNAMIC))
|
||||
P_AddDynSlopeThinker(ret, DP_VERTEX, NULL, 0, tags, vx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// Create vertex based slopes.
|
||||
static void line_SpawnViaVertexes(const int linenum, const boolean spawnthinker)
|
||||
{
|
||||
line_t *line = lines + linenum;
|
||||
side_t *side;
|
||||
pslope_t **slopetoset;
|
||||
UINT16 tag1, tag2, tag3;
|
||||
|
||||
UINT8 flags = 0;
|
||||
if (line->flags & ML_NETONLY)
|
||||
flags |= SL_NOPHYSICS;
|
||||
if (line->flags & ML_NONET)
|
||||
flags |= SL_DYNAMIC;
|
||||
|
||||
switch(line->special)
|
||||
{
|
||||
case 704:
|
||||
slopetoset = &line->frontsector->f_slope;
|
||||
side = &sides[line->sidenum[0]];
|
||||
break;
|
||||
case 705:
|
||||
slopetoset = &line->frontsector->c_slope;
|
||||
side = &sides[line->sidenum[0]];
|
||||
break;
|
||||
case 714:
|
||||
slopetoset = &line->backsector->f_slope;
|
||||
side = &sides[line->sidenum[1]];
|
||||
break;
|
||||
case 715:
|
||||
slopetoset = &line->backsector->c_slope;
|
||||
side = &sides[line->sidenum[1]];
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (line->flags & ML_EFFECT6)
|
||||
{
|
||||
tag1 = line->tag;
|
||||
tag2 = side->textureoffset >> FRACBITS;
|
||||
tag3 = side->rowoffset >> FRACBITS;
|
||||
}
|
||||
else
|
||||
tag1 = tag2 = tag3 = line->tag;
|
||||
|
||||
*slopetoset = MakeViaMapthings(tag1, tag2, tag3, flags, spawnthinker);
|
||||
|
||||
side->sector->hasslope = true;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
|
@ -620,56 +552,20 @@ pslope_t *P_SlopeById(UINT16 id)
|
|||
return ret;
|
||||
}
|
||||
|
||||
// Reset the dynamic slopes pointer, and read all of the fancy schmancy slopes
|
||||
void P_ResetDynamicSlopes(void) {
|
||||
/// Reset slopes and read them from special lines.
|
||||
void P_ResetDynamicSlopes(const UINT32 fromsave) {
|
||||
size_t i;
|
||||
#ifdef ESLOPE_TYPESHIM // Rewrite old specials to new ones, and give a console warning
|
||||
boolean warned = false;
|
||||
#endif
|
||||
|
||||
boolean spawnthinkers = !(boolean)fromsave;
|
||||
|
||||
slopelist = NULL;
|
||||
slopecount = 0;
|
||||
|
||||
// We'll handle copy slopes later, after all the tag lists have been made.
|
||||
// Yes, this means copied slopes won't affect things' spawning heights. Too bad for you.
|
||||
/// Generates line special-defined slopes.
|
||||
for (i = 0; i < numlines; i++)
|
||||
{
|
||||
switch (lines[i].special)
|
||||
{
|
||||
#ifdef ESLOPE_TYPESHIM // Rewrite old specials to new ones, and give a console warning
|
||||
#define WARNME if (!warned) {warned = true; CONS_Alert(CONS_WARNING, "This level uses old slope specials.\nA conversion will be needed before 2.2's release.\n");}
|
||||
case 386:
|
||||
case 387:
|
||||
case 388:
|
||||
lines[i].special += 700-386;
|
||||
WARNME
|
||||
P_SpawnSlope_Line(i);
|
||||
break;
|
||||
|
||||
case 389:
|
||||
case 390:
|
||||
case 391:
|
||||
case 392:
|
||||
lines[i].special += 710-389;
|
||||
WARNME
|
||||
P_SpawnSlope_Line(i);
|
||||
break;
|
||||
|
||||
case 393:
|
||||
lines[i].special = 703;
|
||||
WARNME
|
||||
P_SpawnSlope_Line(i);
|
||||
break;
|
||||
|
||||
case 394:
|
||||
case 395:
|
||||
case 396:
|
||||
lines[i].special += 720-394;
|
||||
WARNME
|
||||
break;
|
||||
|
||||
#endif
|
||||
|
||||
case 700:
|
||||
case 701:
|
||||
case 702:
|
||||
|
@ -678,63 +574,35 @@ void P_ResetDynamicSlopes(void) {
|
|||
case 711:
|
||||
case 712:
|
||||
case 713:
|
||||
P_SpawnSlope_Line(i);
|
||||
line_SpawnViaLine(i, spawnthinkers);
|
||||
break;
|
||||
|
||||
case 704:
|
||||
case 705:
|
||||
case 714:
|
||||
case 715:
|
||||
{
|
||||
pslope_t **slopetoset;
|
||||
size_t which = lines[i].special;
|
||||
|
||||
UINT8 flags = SL_VERTEXSLOPE;
|
||||
if (lines[i].flags & ML_NOSONIC)
|
||||
flags |= SL_NOPHYSICS;
|
||||
if (!(lines[i].flags & ML_NOTAILS))
|
||||
flags |= SL_NODYNAMIC;
|
||||
|
||||
if (which == 704)
|
||||
{
|
||||
slopetoset = &lines[i].frontsector->f_slope;
|
||||
which = 0;
|
||||
}
|
||||
else if (which == 705)
|
||||
{
|
||||
slopetoset = &lines[i].frontsector->c_slope;
|
||||
which = 0;
|
||||
}
|
||||
else if (which == 714)
|
||||
{
|
||||
slopetoset = &lines[i].backsector->f_slope;
|
||||
which = 1;
|
||||
}
|
||||
else // 715
|
||||
{
|
||||
slopetoset = &lines[i].backsector->c_slope;
|
||||
which = 1;
|
||||
}
|
||||
|
||||
if (lines[i].flags & ML_NOKNUX)
|
||||
*slopetoset = P_NewVertexSlope(lines[i].tag, sides[lines[i].sidenum[which]].textureoffset >> FRACBITS,
|
||||
sides[lines[i].sidenum[which]].rowoffset >> FRACBITS, flags);
|
||||
else
|
||||
*slopetoset = P_NewVertexSlope(lines[i].tag, lines[i].tag, lines[i].tag, flags);
|
||||
|
||||
sides[lines[i].sidenum[which]].sector->hasslope = true;
|
||||
}
|
||||
line_SpawnViaVertexes(i, spawnthinkers);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// Copies slopes from tagged sectors via line specials.
|
||||
/// \note Doesn't actually copy, but instead they share the same pointers.
|
||||
for (i = 0; i < numlines; i++)
|
||||
switch (lines[i].special)
|
||||
{
|
||||
case 720:
|
||||
case 721:
|
||||
case 722:
|
||||
P_CopySectorSlope(&lines[i]);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// ============================================================================
|
||||
//
|
||||
// Various utilities related to slopes
|
||||
|
|
|
@ -13,14 +13,17 @@
|
|||
#ifndef P_SLOPES_H__
|
||||
#define P_SLOPES_H__
|
||||
|
||||
#include "m_fixed.h" // Vectors
|
||||
|
||||
#ifdef ESLOPE
|
||||
|
||||
extern pslope_t *slopelist;
|
||||
extern UINT16 slopecount;
|
||||
|
||||
void P_LinkSlopeThinkers (void);
|
||||
|
||||
void P_CalculateSlopeNormal(pslope_t *slope);
|
||||
void P_ResetDynamicSlopes(void);
|
||||
void P_RunDynamicSlopes(void);
|
||||
// P_SpawnSlope_Line
|
||||
// Creates one or more slopes based on the given line type and front/back
|
||||
// sectors.
|
||||
void P_SpawnSlope_Line(int linenum);
|
||||
void P_ResetDynamicSlopes(const UINT32 fromsave);
|
||||
|
||||
//
|
||||
// P_CopySectorSlope
|
||||
|
@ -42,7 +45,34 @@ fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope);
|
|||
void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope);
|
||||
void P_ButteredSlope(mobj_t *mo);
|
||||
|
||||
#endif
|
||||
|
||||
// EOF
|
||||
/// Dynamic plane type enum for the thinker. Will have a different functionality depending on this.
|
||||
typedef enum {
|
||||
DP_FRONTFLOOR,
|
||||
DP_FRONTCEIL,
|
||||
DP_BACKFLOOR,
|
||||
DP_BACKCEIL,
|
||||
DP_VERTEX
|
||||
} dynplanetype_t;
|
||||
|
||||
/// Permit slopes to be dynamically altered through a thinker.
|
||||
typedef struct
|
||||
{
|
||||
thinker_t thinker;
|
||||
|
||||
pslope_t* slope;
|
||||
dynplanetype_t type;
|
||||
|
||||
// Used by line slopes.
|
||||
line_t* sourceline;
|
||||
fixed_t extent;
|
||||
|
||||
// Used by mapthing vertex slopes.
|
||||
INT16 tags[3];
|
||||
vector3_t vex[3];
|
||||
} dynplanethink_t;
|
||||
|
||||
void T_DynamicSlopeLine (dynplanethink_t* th);
|
||||
void T_DynamicSlopeVert (dynplanethink_t* th);
|
||||
#endif // #ifdef ESLOPE
|
||||
#endif // #ifndef P_SLOPES_H__
|
||||
|
|
423
src/p_spec.c
423
src/p_spec.c
|
@ -36,6 +36,7 @@
|
|||
#include "m_cond.h" //unlock triggers
|
||||
#include "lua_hook.h" // LUAh_LinedefExecute
|
||||
#include "f_finale.h" // control text prompt
|
||||
#include "r_things.h" // skins
|
||||
|
||||
#ifdef HW3SOUND
|
||||
#include "hardware/hw3sound.h"
|
||||
|
@ -98,7 +99,6 @@ typedef struct
|
|||
thinker_t **thinkers;
|
||||
} thinkerlist_t;
|
||||
|
||||
static void P_SearchForDisableLinedefs(void);
|
||||
static void P_SpawnScrollers(void);
|
||||
static void P_SpawnFriction(void);
|
||||
static void P_SpawnPushers(void);
|
||||
|
@ -1644,7 +1644,7 @@ static void P_AddExecutorDelay(line_t *line, mobj_t *mobj, sector_t *sector)
|
|||
e->sector = sector;
|
||||
e->timer = (line->backsector->ceilingheight>>FRACBITS)+(line->backsector->floorheight>>FRACBITS);
|
||||
P_SetTarget(&e->caller, mobj); // Use P_SetTarget to make sure the mobj doesn't get freed while we're delaying.
|
||||
P_AddThinker(&e->thinker);
|
||||
P_AddThinker(THINK_MAIN, &e->thinker);
|
||||
}
|
||||
|
||||
/** Used by P_RunTriggerLinedef to check a NiGHTS trigger linedef's conditions
|
||||
|
@ -2008,7 +2008,12 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
|
|||
if (!P_CheckNightsTriggerLine(triggerline, actor))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case 331: // continuous
|
||||
case 332: // each time
|
||||
case 333: // once
|
||||
if (!(actor && actor->player && ((stricmp(triggerline->text, skins[actor->player->skin].name) == 0) ^ ((triggerline->flags & ML_NOCLIMB) == ML_NOCLIMB))))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -2141,6 +2146,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
|
|||
|| specialtype == 326 // DeNightserize - Once
|
||||
|| specialtype == 328 // Nights lap - Once
|
||||
|| specialtype == 330 // Nights Bonus Time - Once
|
||||
|| specialtype == 333 // Skin - Once
|
||||
|| specialtype == 399) // Level Load
|
||||
triggerline->special = 0; // Clear it out
|
||||
|
||||
|
@ -2181,7 +2187,8 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller)
|
|||
|| lines[masterline].special == 306 // Character ability - Each time
|
||||
|| lines[masterline].special == 310 // CTF Red team - Each time
|
||||
|| lines[masterline].special == 312 // CTF Blue team - Each time
|
||||
|| lines[masterline].special == 322) // Trigger on X calls - Each Time
|
||||
|| lines[masterline].special == 322 // Trigger on X calls - Each Time
|
||||
|| lines[masterline].special == 332)// Skin - Each time
|
||||
continue;
|
||||
|
||||
if (lines[masterline].special < 300
|
||||
|
@ -2253,7 +2260,7 @@ void P_SwitchWeather(INT32 weathernum)
|
|||
thinker_t *think;
|
||||
precipmobj_t *precipmobj;
|
||||
|
||||
for (think = thinkercap.next; think != &thinkercap; think = think->next)
|
||||
for (think = thlist[THINK_PRECIP].next; think != &thlist[THINK_PRECIP]; think = think->next)
|
||||
{
|
||||
if (think->function.acp1 != (actionf_p1)P_NullPrecipThinker)
|
||||
continue; // not a precipmobj thinker
|
||||
|
@ -2269,7 +2276,7 @@ void P_SwitchWeather(INT32 weathernum)
|
|||
precipmobj_t *precipmobj;
|
||||
state_t *st;
|
||||
|
||||
for (think = thinkercap.next; think != &thinkercap; think = think->next)
|
||||
for (think = thlist[THINK_PRECIP].next; think != &thlist[THINK_PRECIP]; think = think->next)
|
||||
{
|
||||
if (think->function.acp1 != (actionf_p1)P_NullPrecipThinker)
|
||||
continue; // not a precipmobj thinker
|
||||
|
@ -3144,7 +3151,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
|
|||
scroll_t *scroller;
|
||||
thinker_t *th;
|
||||
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)T_Scroll)
|
||||
continue;
|
||||
|
@ -3382,7 +3389,10 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
|
|||
|
||||
// if flags changed, reset sector's light list
|
||||
if (rover->flags != oldflags)
|
||||
{
|
||||
sec->moved = true;
|
||||
P_RecalcPrecipInSector(sec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3544,6 +3554,29 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
|
|||
}
|
||||
break;
|
||||
|
||||
case 449: // Enable bosses with parameter
|
||||
{
|
||||
INT32 bossid = sides[line->sidenum[0]].textureoffset>>FRACBITS;
|
||||
if (bossid & ~15) // if any bits other than first 16 are set
|
||||
{
|
||||
CONS_Alert(CONS_WARNING,
|
||||
M_GetText("Boss enable linedef (tag %d) has an invalid texture x offset.\nConsider changing it or removing it entirely.\n"),
|
||||
line->tag);
|
||||
break;
|
||||
}
|
||||
if (line->flags & ML_NOCLIMB)
|
||||
{
|
||||
bossdisabled |= (1<<bossid);
|
||||
CONS_Debug(DBG_GAMELOGIC, "Line type 449 Executor: bossid disabled = %d", bossid);
|
||||
}
|
||||
else
|
||||
{
|
||||
bossdisabled &= ~(1<<bossid);
|
||||
CONS_Debug(DBG_GAMELOGIC, "Line type 449 Executor: bossid enabled = %d", bossid);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 450: // Execute Linedef Executor - for recursion
|
||||
P_LinedefExecute(line->tag, mo, NULL);
|
||||
break;
|
||||
|
@ -3908,6 +3941,18 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
|
|||
}
|
||||
break;
|
||||
|
||||
case 460: // Award rings
|
||||
{
|
||||
INT16 rings = (sides[line->sidenum[0]].textureoffset>>FRACBITS);
|
||||
INT32 delay = (sides[line->sidenum[0]].rowoffset>>FRACBITS);
|
||||
if (mo && mo->player)
|
||||
{
|
||||
if (delay <= 0 || !(leveltime % delay))
|
||||
P_GivePlayerRings(mo->player, rings);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef POLYOBJECTS
|
||||
case 480: // Polyobj_DoorSlide
|
||||
case 481: // Polyobj_DoorSwing
|
||||
|
@ -3980,10 +4025,10 @@ void P_SetupSignExit(player_t *player)
|
|||
|
||||
// didn't find any signposts in the exit sector.
|
||||
// spin all signposts in the level then.
|
||||
for (think = thinkercap.next; think != &thinkercap; think = think->next)
|
||||
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
|
||||
{
|
||||
if (think->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
continue; // not a mobj thinker
|
||||
if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
thing = (mobj_t *)think;
|
||||
if (thing->type != MT_SIGN)
|
||||
|
@ -4010,23 +4055,18 @@ boolean P_IsFlagAtBase(mobjtype_t flag)
|
|||
{
|
||||
thinker_t *think;
|
||||
mobj_t *mo;
|
||||
INT32 specialnum = 0;
|
||||
INT32 specialnum = (flag == MT_REDFLAG) ? 3 : 4;
|
||||
|
||||
for (think = thinkercap.next; think != &thinkercap; think = think->next)
|
||||
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
|
||||
{
|
||||
if (think->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
continue; // not a mobj thinker
|
||||
if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo = (mobj_t *)think;
|
||||
|
||||
if (mo->type != flag)
|
||||
continue;
|
||||
|
||||
if (mo->type == MT_REDFLAG)
|
||||
specialnum = 3;
|
||||
else if (mo->type == MT_BLUEFLAG)
|
||||
specialnum = 4;
|
||||
|
||||
if (GETSECSPECIAL(mo->subsector->sector->special, 4) == specialnum)
|
||||
return true;
|
||||
else if (mo->subsector->sector->ffloors) // Check the 3D floors
|
||||
|
@ -4041,9 +4081,11 @@ boolean P_IsFlagAtBase(mobjtype_t flag)
|
|||
if (GETSECSPECIAL(rover->master->frontsector->special, 4) != specialnum)
|
||||
continue;
|
||||
|
||||
if (mo->z <= P_GetSpecialTopZ(mo, sectors + rover->secnum, mo->subsector->sector)
|
||||
&& mo->z >= P_GetSpecialBottomZ(mo, sectors + rover->secnum, mo->subsector->sector))
|
||||
return true;
|
||||
if (!(mo->z <= P_GetSpecialTopZ(mo, sectors + rover->secnum, mo->subsector->sector)
|
||||
&& mo->z >= P_GetSpecialBottomZ(mo, sectors + rover->secnum, mo->subsector->sector)))
|
||||
continue;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4445,14 +4487,14 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers
|
|||
|
||||
// Find the center of the Eggtrap and release all the pretty animals!
|
||||
// The chimps are my friends.. heeheeheheehehee..... - LouisJM
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
if (mo2->type == MT_EGGTRAP)
|
||||
P_KillMobj(mo2, NULL, player->mo, 0);
|
||||
if (mo2->type != MT_EGGTRAP)
|
||||
continue;
|
||||
P_KillMobj(mo2, NULL, player->mo, 0);
|
||||
}
|
||||
|
||||
// clear the special so you can't push the button twice.
|
||||
|
@ -4594,7 +4636,10 @@ DoneSection2:
|
|||
if (player->bot)
|
||||
break;
|
||||
if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap) && player->nightstime > 6)
|
||||
{
|
||||
player->nightstime = 6; // Just let P_Ticker take care of the rest.
|
||||
return;
|
||||
}
|
||||
|
||||
// Exit (for FOF exits; others are handled in P_PlayerThink in p_user.c)
|
||||
{
|
||||
|
@ -4617,7 +4662,7 @@ DoneSection2:
|
|||
nextmapoverride = (INT16)(lines[lineindex].frontsector->floorheight>>FRACBITS);
|
||||
|
||||
if (lines[lineindex].flags & ML_NOCLIMB)
|
||||
skipstats = true;
|
||||
skipstats = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -4751,19 +4796,22 @@ DoneSection2:
|
|||
|
||||
// scan the thinkers
|
||||
// to find the first waypoint
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
||||
if (mo2->type == MT_TUBEWAYPOINT && mo2->threshold == sequence
|
||||
&& mo2->health == 0)
|
||||
{
|
||||
waypoint = mo2;
|
||||
break;
|
||||
}
|
||||
if (mo2->type != MT_TUBEWAYPOINT)
|
||||
continue;
|
||||
if (mo2->threshold != sequence)
|
||||
continue;
|
||||
if (mo2->health != 0)
|
||||
continue;
|
||||
|
||||
waypoint = mo2;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!waypoint)
|
||||
|
@ -4830,20 +4878,22 @@ DoneSection2:
|
|||
|
||||
// scan the thinkers
|
||||
// to find the last waypoint
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
||||
if (mo2->type == MT_TUBEWAYPOINT && mo2->threshold == sequence)
|
||||
{
|
||||
if (!waypoint)
|
||||
waypoint = mo2;
|
||||
else if (mo2->health > waypoint->health)
|
||||
waypoint = mo2;
|
||||
}
|
||||
if (mo2->type != MT_TUBEWAYPOINT)
|
||||
continue;
|
||||
if (mo2->threshold != sequence)
|
||||
continue;
|
||||
|
||||
if (!waypoint)
|
||||
waypoint = mo2;
|
||||
else if (mo2->health > waypoint->health)
|
||||
waypoint = mo2;
|
||||
}
|
||||
|
||||
if (!waypoint)
|
||||
|
@ -4982,9 +5032,9 @@ DoneSection2:
|
|||
|
||||
// scan the thinkers
|
||||
// to find the first waypoint
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
@ -5020,9 +5070,9 @@ DoneSection2:
|
|||
}
|
||||
|
||||
// Find waypoint before this one (waypointlow)
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
@ -5047,9 +5097,9 @@ DoneSection2:
|
|||
}
|
||||
|
||||
// Find waypoint after this one (waypointhigh)
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
@ -5566,11 +5616,6 @@ void P_UpdateSpecials(void)
|
|||
// POINT LIMIT
|
||||
P_CheckPointLimit();
|
||||
|
||||
#ifdef ESLOPE
|
||||
// Dynamic slopeness
|
||||
P_RunDynamicSlopes();
|
||||
#endif
|
||||
|
||||
// ANIMATE TEXTURES
|
||||
for (anim = anims; anim < lastanim; anim++)
|
||||
{
|
||||
|
@ -5640,26 +5685,26 @@ ffloor_t *P_GetFFloorByID(sector_t *sec, UINT16 id)
|
|||
/** Adds a newly formed 3Dfloor structure to a sector's ffloors list.
|
||||
*
|
||||
* \param sec Target sector.
|
||||
* \param ffloor Newly formed 3Dfloor structure.
|
||||
* \param fflr Newly formed 3Dfloor structure.
|
||||
* \sa P_AddFakeFloor
|
||||
*/
|
||||
static inline void P_AddFFloorToList(sector_t *sec, ffloor_t *ffloor)
|
||||
static inline void P_AddFFloorToList(sector_t *sec, ffloor_t *fflr)
|
||||
{
|
||||
ffloor_t *rover;
|
||||
|
||||
if (!sec->ffloors)
|
||||
{
|
||||
sec->ffloors = ffloor;
|
||||
ffloor->next = 0;
|
||||
ffloor->prev = 0;
|
||||
sec->ffloors = fflr;
|
||||
fflr->next = 0;
|
||||
fflr->prev = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
for (rover = sec->ffloors; rover->next; rover = rover->next);
|
||||
|
||||
rover->next = ffloor;
|
||||
ffloor->prev = rover;
|
||||
ffloor->next = 0;
|
||||
rover->next = fflr;
|
||||
fflr->prev = rover;
|
||||
fflr->next = 0;
|
||||
}
|
||||
|
||||
/** Adds a 3Dfloor.
|
||||
|
@ -5674,7 +5719,7 @@ static inline void P_AddFFloorToList(sector_t *sec, ffloor_t *ffloor)
|
|||
*/
|
||||
static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, ffloortype_e flags, thinkerlist_t *secthinkers)
|
||||
{
|
||||
ffloor_t *ffloor;
|
||||
ffloor_t *fflr;
|
||||
thinker_t *th;
|
||||
friction_t *f;
|
||||
pusher_t *p;
|
||||
|
@ -5684,8 +5729,8 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f
|
|||
|
||||
if (sec == sec2)
|
||||
return NULL; //Don't need a fake floor on a control sector.
|
||||
if ((ffloor = (P_GetFFloorBySec(sec, sec2))))
|
||||
return ffloor; // If this ffloor already exists, return it
|
||||
if ((fflr = (P_GetFFloorBySec(sec, sec2))))
|
||||
return fflr; // If this ffloor already exists, return it
|
||||
|
||||
if (sec2->ceilingheight < sec2->floorheight)
|
||||
{
|
||||
|
@ -5724,27 +5769,27 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f
|
|||
}
|
||||
|
||||
// Add the floor
|
||||
ffloor = Z_Calloc(sizeof (*ffloor), PU_LEVEL, NULL);
|
||||
ffloor->secnum = sec2 - sectors;
|
||||
ffloor->target = sec;
|
||||
ffloor->bottomheight = &sec2->floorheight;
|
||||
ffloor->bottompic = &sec2->floorpic;
|
||||
ffloor->bottomxoffs = &sec2->floor_xoffs;
|
||||
ffloor->bottomyoffs = &sec2->floor_yoffs;
|
||||
ffloor->bottomangle = &sec2->floorpic_angle;
|
||||
fflr = Z_Calloc(sizeof (*fflr), PU_LEVEL, NULL);
|
||||
fflr->secnum = sec2 - sectors;
|
||||
fflr->target = sec;
|
||||
fflr->bottomheight = &sec2->floorheight;
|
||||
fflr->bottompic = &sec2->floorpic;
|
||||
fflr->bottomxoffs = &sec2->floor_xoffs;
|
||||
fflr->bottomyoffs = &sec2->floor_yoffs;
|
||||
fflr->bottomangle = &sec2->floorpic_angle;
|
||||
|
||||
// Add the ceiling
|
||||
ffloor->topheight = &sec2->ceilingheight;
|
||||
ffloor->toppic = &sec2->ceilingpic;
|
||||
ffloor->toplightlevel = &sec2->lightlevel;
|
||||
ffloor->topxoffs = &sec2->ceiling_xoffs;
|
||||
ffloor->topyoffs = &sec2->ceiling_yoffs;
|
||||
ffloor->topangle = &sec2->ceilingpic_angle;
|
||||
fflr->topheight = &sec2->ceilingheight;
|
||||
fflr->toppic = &sec2->ceilingpic;
|
||||
fflr->toplightlevel = &sec2->lightlevel;
|
||||
fflr->topxoffs = &sec2->ceiling_xoffs;
|
||||
fflr->topyoffs = &sec2->ceiling_yoffs;
|
||||
fflr->topangle = &sec2->ceilingpic_angle;
|
||||
|
||||
#ifdef ESLOPE
|
||||
// Add slopes
|
||||
ffloor->t_slope = &sec2->c_slope;
|
||||
ffloor->b_slope = &sec2->f_slope;
|
||||
fflr->t_slope = &sec2->c_slope;
|
||||
fflr->b_slope = &sec2->f_slope;
|
||||
// mark the target sector as having slopes, if the FOF has any of its own
|
||||
// (this fixes FOF slopes glitching initially at level load in software mode)
|
||||
if (sec2->hasslope)
|
||||
|
@ -5757,10 +5802,10 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f
|
|||
if ((flags & FF_SOLID) && (master->flags & ML_EFFECT2)) // Block all BUT player
|
||||
flags &= ~FF_BLOCKPLAYER;
|
||||
|
||||
ffloor->spawnflags = ffloor->flags = flags;
|
||||
ffloor->master = master;
|
||||
ffloor->norender = INFTICS;
|
||||
ffloor->fadingdata = NULL;
|
||||
fflr->spawnflags = fflr->flags = flags;
|
||||
fflr->master = master;
|
||||
fflr->norender = INFTICS;
|
||||
fflr->fadingdata = NULL;
|
||||
|
||||
// Scan the thinkers to check for special conditions applying to this FOF.
|
||||
// If we have thinkers sorted by sector, just check the relevant ones;
|
||||
|
@ -5770,7 +5815,7 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f
|
|||
|
||||
// Just initialise both of these to placate the compiler.
|
||||
i = 0;
|
||||
th = thinkercap.next;
|
||||
th = thlist[THINK_MAIN].next;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
|
@ -5780,7 +5825,7 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f
|
|||
th = secthinkers[sec2num].thinkers[i];
|
||||
else break;
|
||||
}
|
||||
else if (th == &thinkercap)
|
||||
else if (th == &thlist[THINK_MAIN])
|
||||
break;
|
||||
|
||||
// Should this FOF have spikeness?
|
||||
|
@ -5816,14 +5861,14 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f
|
|||
if (flags & FF_TRANSLUCENT)
|
||||
{
|
||||
if (sides[master->sidenum[0]].toptexture > 0)
|
||||
ffloor->alpha = sides[master->sidenum[0]].toptexture; // for future reference, "#0" is 1, and "#255" is 256. Be warned
|
||||
fflr->alpha = sides[master->sidenum[0]].toptexture; // for future reference, "#0" is 1, and "#255" is 256. Be warned
|
||||
else
|
||||
ffloor->alpha = 0x80;
|
||||
fflr->alpha = 0x80;
|
||||
}
|
||||
else
|
||||
ffloor->alpha = 0xff;
|
||||
fflr->alpha = 0xff;
|
||||
|
||||
ffloor->spawnalpha = ffloor->alpha; // save for netgames
|
||||
fflr->spawnalpha = fflr->alpha; // save for netgames
|
||||
|
||||
if (flags & FF_QUICKSAND)
|
||||
CheckForQuicksand = true;
|
||||
|
@ -5847,9 +5892,9 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f
|
|||
CheckForFloatBob = true;
|
||||
}
|
||||
|
||||
P_AddFFloorToList(sec, ffloor);
|
||||
P_AddFFloorToList(sec, fflr);
|
||||
|
||||
return ffloor;
|
||||
return fflr;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -5870,7 +5915,7 @@ static void P_AddSpikeThinker(sector_t *sec, INT32 referrer)
|
|||
|
||||
// create and initialize new thinker
|
||||
spikes = Z_Calloc(sizeof (*spikes), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&spikes->thinker);
|
||||
P_AddThinker(THINK_MAIN, &spikes->thinker);
|
||||
|
||||
spikes->thinker.function.acp1 = (actionf_p1)T_SpikeSector;
|
||||
|
||||
|
@ -5892,7 +5937,7 @@ static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline)
|
|||
|
||||
// create and initialize new thinker
|
||||
floater = Z_Calloc(sizeof (*floater), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&floater->thinker);
|
||||
P_AddThinker(THINK_MAIN, &floater->thinker);
|
||||
|
||||
floater->thinker.function.acp1 = (actionf_p1)T_FloatSector;
|
||||
|
||||
|
@ -5916,7 +5961,7 @@ static inline void P_AddBridgeThinker(line_t *sourceline, sector_t *sec)
|
|||
|
||||
// create an initialize new thinker
|
||||
bridge = Z_Calloc(sizeof (*bridge), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&bridge->thinker);
|
||||
P_AddThinker(THINK_MAIN, &bridge->thinker);
|
||||
|
||||
bridge->thinker.function.acp1 = (actionf_p1)T_BridgeThinker;
|
||||
|
||||
|
@ -5952,7 +5997,7 @@ static void P_AddPlaneDisplaceThinker(INT32 type, fixed_t speed, INT32 control,
|
|||
|
||||
// create and initialize new displacement thinker
|
||||
displace = Z_Calloc(sizeof (*displace), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&displace->thinker);
|
||||
P_AddThinker(THINK_MAIN, &displace->thinker);
|
||||
|
||||
displace->thinker.function.acp1 = (actionf_p1)T_PlaneDisplace;
|
||||
displace->affectee = affectee;
|
||||
|
@ -5979,7 +6024,7 @@ static void P_AddBlockThinker(sector_t *sec, line_t *sourceline)
|
|||
|
||||
// create and initialize new elevator thinker
|
||||
block = Z_Calloc(sizeof (*block), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&block->thinker);
|
||||
P_AddThinker(THINK_MAIN, &block->thinker);
|
||||
|
||||
block->thinker.function.acp1 = (actionf_p1)T_MarioBlockChecker;
|
||||
block->sourceline = sourceline;
|
||||
|
@ -6008,7 +6053,7 @@ static void P_AddRaiseThinker(sector_t *sec, line_t *sourceline)
|
|||
levelspecthink_t *raise;
|
||||
|
||||
raise = Z_Calloc(sizeof (*raise), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&raise->thinker);
|
||||
P_AddThinker(THINK_MAIN, &raise->thinker);
|
||||
|
||||
raise->thinker.function.acp1 = (actionf_p1)T_RaiseSector;
|
||||
|
||||
|
@ -6047,7 +6092,7 @@ static void P_AddOldAirbob(sector_t *sec, line_t *sourceline, boolean noadjust)
|
|||
levelspecthink_t *airbob;
|
||||
|
||||
airbob = Z_Calloc(sizeof (*airbob), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&airbob->thinker);
|
||||
P_AddThinker(THINK_MAIN, &airbob->thinker);
|
||||
|
||||
airbob->thinker.function.acp1 = (actionf_p1)T_RaiseSector;
|
||||
|
||||
|
@ -6108,7 +6153,7 @@ static inline void P_AddThwompThinker(sector_t *sec, sector_t *actionsector, lin
|
|||
|
||||
// create and initialize new elevator thinker
|
||||
thwomp = Z_Calloc(sizeof (*thwomp), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&thwomp->thinker);
|
||||
P_AddThinker(THINK_MAIN, &thwomp->thinker);
|
||||
|
||||
thwomp->thinker.function.acp1 = (actionf_p1)T_ThwompSector;
|
||||
|
||||
|
@ -6144,7 +6189,7 @@ static inline void P_AddNoEnemiesThinker(sector_t *sec, line_t *sourceline)
|
|||
|
||||
// create and initialize new thinker
|
||||
nobaddies = Z_Calloc(sizeof (*nobaddies), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&nobaddies->thinker);
|
||||
P_AddThinker(THINK_MAIN, &nobaddies->thinker);
|
||||
|
||||
nobaddies->thinker.function.acp1 = (actionf_p1)T_NoEnemiesSector;
|
||||
|
||||
|
@ -6160,13 +6205,13 @@ static inline void P_AddNoEnemiesThinker(sector_t *sec, line_t *sourceline)
|
|||
* \sa P_SpawnSpecials, T_EachTimeThinker
|
||||
* \author SSNTails <http://www.ssntails.org>
|
||||
*/
|
||||
static inline void P_AddEachTimeThinker(sector_t *sec, line_t *sourceline)
|
||||
static void P_AddEachTimeThinker(sector_t *sec, line_t *sourceline)
|
||||
{
|
||||
levelspecthink_t *eachtime;
|
||||
|
||||
// create and initialize new thinker
|
||||
eachtime = Z_Calloc(sizeof (*eachtime), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&eachtime->thinker);
|
||||
P_AddThinker(THINK_MAIN, &eachtime->thinker);
|
||||
|
||||
eachtime->thinker.function.acp1 = (actionf_p1)T_EachTimeThinker;
|
||||
|
||||
|
@ -6188,7 +6233,7 @@ static inline void P_AddCameraScanner(sector_t *sourcesec, sector_t *actionsecto
|
|||
|
||||
// create and initialize new elevator thinker
|
||||
elevator = Z_Calloc(sizeof (*elevator), PU_LEVSPEC, NULL);
|
||||
P_AddThinker(&elevator->thinker);
|
||||
P_AddThinker(THINK_MAIN, &elevator->thinker);
|
||||
|
||||
elevator->thinker.function.acp1 = (actionf_p1)T_CameraScanner;
|
||||
elevator->type = elevateBounce;
|
||||
|
@ -6212,30 +6257,30 @@ void T_LaserFlash(laserthink_t *flash)
|
|||
msecnode_t *node;
|
||||
mobj_t *thing;
|
||||
sector_t *sourcesec;
|
||||
ffloor_t *ffloor = flash->ffloor;
|
||||
ffloor_t *fflr = flash->ffloor;
|
||||
sector_t *sector = flash->sector;
|
||||
fixed_t top, bottom;
|
||||
|
||||
if (!ffloor || !(ffloor->flags & FF_EXISTS))
|
||||
if (!fflr || !(fflr->flags & FF_EXISTS))
|
||||
return;
|
||||
|
||||
if (leveltime & 2)
|
||||
//ffloor->flags |= FF_RENDERALL;
|
||||
ffloor->alpha = 0xB0;
|
||||
//fflr->flags |= FF_RENDERALL;
|
||||
fflr->alpha = 0xB0;
|
||||
else
|
||||
//ffloor->flags &= ~FF_RENDERALL;
|
||||
ffloor->alpha = 0x90;
|
||||
//fflr->flags &= ~FF_RENDERALL;
|
||||
fflr->alpha = 0x90;
|
||||
|
||||
sourcesec = ffloor->master->frontsector; // Less to type!
|
||||
sourcesec = fflr->master->frontsector; // Less to type!
|
||||
|
||||
#ifdef ESLOPE
|
||||
top = (*ffloor->t_slope) ? P_GetZAt(*ffloor->t_slope, sector->soundorg.x, sector->soundorg.y)
|
||||
: *ffloor->topheight;
|
||||
bottom = (*ffloor->b_slope) ? P_GetZAt(*ffloor->b_slope, sector->soundorg.x, sector->soundorg.y)
|
||||
: *ffloor->bottomheight;
|
||||
top = (*fflr->t_slope) ? P_GetZAt(*fflr->t_slope, sector->soundorg.x, sector->soundorg.y)
|
||||
: *fflr->topheight;
|
||||
bottom = (*fflr->b_slope) ? P_GetZAt(*fflr->b_slope, sector->soundorg.x, sector->soundorg.y)
|
||||
: *fflr->bottomheight;
|
||||
sector->soundorg.z = (top + bottom)/2;
|
||||
#else
|
||||
sector->soundorg.z = (*ffloor->topheight + *ffloor->bottomheight)/2;
|
||||
sector->soundorg.z = (*fflr->topheight + *fflr->bottomheight)/2;
|
||||
#endif
|
||||
S_StartSound(§or->soundorg, sfx_laser);
|
||||
|
||||
|
@ -6244,7 +6289,7 @@ void T_LaserFlash(laserthink_t *flash)
|
|||
{
|
||||
thing = node->m_thing;
|
||||
|
||||
if ((ffloor->master->flags & ML_EFFECT1)
|
||||
if ((fflr->master->flags & ML_EFFECT1)
|
||||
&& thing->flags & MF_BOSS)
|
||||
continue; // Don't hurt bosses
|
||||
|
||||
|
@ -6268,7 +6313,7 @@ void T_LaserFlash(laserthink_t *flash)
|
|||
|
||||
/** Adds a laser thinker to a 3Dfloor.
|
||||
*
|
||||
* \param ffloor 3Dfloor to turn into a laser block.
|
||||
* \param fflr 3Dfloor to turn into a laser block.
|
||||
* \param sector Target sector.
|
||||
* \param secthkiners Lists of thinkers sorted by sector. May be NULL.
|
||||
* \sa T_LaserFlash
|
||||
|
@ -6277,17 +6322,17 @@ void T_LaserFlash(laserthink_t *flash)
|
|||
static inline void EV_AddLaserThinker(sector_t *sec, sector_t *sec2, line_t *line, thinkerlist_t *secthinkers)
|
||||
{
|
||||
laserthink_t *flash;
|
||||
ffloor_t *ffloor = P_AddFakeFloor(sec, sec2, line, laserflags, secthinkers);
|
||||
ffloor_t *fflr = P_AddFakeFloor(sec, sec2, line, laserflags, secthinkers);
|
||||
|
||||
if (!ffloor)
|
||||
if (!fflr)
|
||||
return;
|
||||
|
||||
flash = Z_Calloc(sizeof (*flash), PU_LEVSPEC, NULL);
|
||||
|
||||
P_AddThinker(&flash->thinker);
|
||||
P_AddThinker(THINK_MAIN, &flash->thinker);
|
||||
|
||||
flash->thinker.function.acp1 = (actionf_p1)T_LaserFlash;
|
||||
flash->ffloor = ffloor;
|
||||
flash->ffloor = fflr;
|
||||
flash->sector = sec; // For finding mobjs
|
||||
flash->sec = sec2;
|
||||
flash->sourceline = line;
|
||||
|
@ -6351,7 +6396,7 @@ void P_InitSpecials(void)
|
|||
|
||||
static void P_ApplyFlatAlignment(line_t *master, sector_t *sector, angle_t flatangle, fixed_t xoffs, fixed_t yoffs)
|
||||
{
|
||||
if (!(master->flags & ML_NOSONIC)) // Modify floor flat alignment unless NOSONIC flag is set
|
||||
if (!(master->flags & ML_NETONLY)) // Modify floor flat alignment unless ML_NETONLY flag is set
|
||||
{
|
||||
sector->spawn_flrpic_angle = sector->floorpic_angle = flatangle;
|
||||
sector->floor_xoffs += xoffs;
|
||||
|
@ -6361,7 +6406,7 @@ static void P_ApplyFlatAlignment(line_t *master, sector_t *sector, angle_t flata
|
|||
sector->spawn_flr_yoffs = sector->floor_yoffs;
|
||||
}
|
||||
|
||||
if (!(master->flags & ML_NOTAILS)) // Modify ceiling flat alignment unless NOTAILS flag is set
|
||||
if (!(master->flags & ML_NONET)) // Modify ceiling flat alignment unless ML_NONET flag is set
|
||||
{
|
||||
sector->spawn_ceilpic_angle = sector->ceilingpic_angle = flatangle;
|
||||
sector->ceiling_xoffs += xoffs;
|
||||
|
@ -6394,6 +6439,9 @@ void P_SpawnSpecials(INT32 fromnetsave)
|
|||
// but currently isn't.
|
||||
(void)fromnetsave;
|
||||
|
||||
// yep, we do this here - "bossdisabled" is considered an apparatus of specials.
|
||||
bossdisabled = 0;
|
||||
|
||||
// Init special SECTORs.
|
||||
sector = sectors;
|
||||
for (i = 0; i < numsectors; i++, sector++)
|
||||
|
@ -6442,8 +6490,6 @@ void P_SpawnSpecials(INT32 fromnetsave)
|
|||
}
|
||||
}
|
||||
|
||||
P_SearchForDisableLinedefs(); // Disable linedefs are now allowed to disable *any* line
|
||||
|
||||
P_SpawnScrollers(); // Add generalized scrollers
|
||||
P_SpawnFriction(); // Friction model using linedefs
|
||||
P_SpawnPushers(); // Pusher model using linedefs
|
||||
|
@ -6453,7 +6499,7 @@ void P_SpawnSpecials(INT32 fromnetsave)
|
|||
secthinkers = Z_Calloc(numsectors * sizeof(thinkerlist_t), PU_STATIC, NULL);
|
||||
|
||||
// Firstly, find out how many there are in each sector
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 == (actionf_p1)T_SpikeSector)
|
||||
secthinkers[((levelspecthink_t *)th)->sector - sectors].count++;
|
||||
|
@ -6473,7 +6519,7 @@ void P_SpawnSpecials(INT32 fromnetsave)
|
|||
}
|
||||
|
||||
// Finally, populate the lists.
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next)
|
||||
{
|
||||
size_t secnum = (size_t)-1;
|
||||
|
||||
|
@ -6492,28 +6538,22 @@ void P_SpawnSpecials(INT32 fromnetsave)
|
|||
// Init line EFFECTs
|
||||
for (i = 0; i < numlines; i++)
|
||||
{
|
||||
if (lines[i].special != 7) // This is a hack. I can at least hope nobody wants to prevent flat alignment with arbitrary skin setups...
|
||||
if (lines[i].special != 7) // This is a hack. I can at least hope nobody wants to prevent flat alignment in netgames...
|
||||
{
|
||||
// set line specials to 0 here too, same reason as above
|
||||
if (netgame || multiplayer)
|
||||
{
|
||||
// future: nonet flag?
|
||||
}
|
||||
else if ((lines[i].flags & ML_NETONLY) == ML_NETONLY)
|
||||
{
|
||||
lines[i].special = 0;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((players[consoleplayer].charability == CA_THOK && (lines[i].flags & ML_NOSONIC))
|
||||
|| (players[consoleplayer].charability == CA_FLY && (lines[i].flags & ML_NOTAILS))
|
||||
|| (players[consoleplayer].charability == CA_GLIDEANDCLIMB && (lines[i].flags & ML_NOKNUX)))
|
||||
if (lines[i].flags & ML_NONET)
|
||||
{
|
||||
lines[i].special = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (lines[i].flags & ML_NETONLY)
|
||||
{
|
||||
lines[i].special = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
switch (lines[i].special)
|
||||
|
@ -6552,20 +6592,14 @@ void P_SpawnSpecials(INT32 fromnetsave)
|
|||
P_AddCameraScanner(§ors[sec], §ors[s], R_PointToAngle2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y));
|
||||
break;
|
||||
|
||||
#ifdef PARANOIA
|
||||
case 6: // Disable tags if level not cleared
|
||||
I_Error("Failed to catch a disable linedef");
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 7: // Flat alignment - redone by toast
|
||||
if ((lines[i].flags & (ML_NOSONIC|ML_NOTAILS)) != (ML_NOSONIC|ML_NOTAILS)) // If you can do something...
|
||||
if ((lines[i].flags & (ML_NETONLY|ML_NONET)) != (ML_NETONLY|ML_NONET)) // If you can do something...
|
||||
{
|
||||
angle_t flatangle = InvAngle(R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y));
|
||||
fixed_t xoffs;
|
||||
fixed_t yoffs;
|
||||
|
||||
if (lines[i].flags & ML_NOKNUX) // Set offset through x and y texture offsets if NOKNUX flag is set
|
||||
if (lines[i].flags & ML_EFFECT6) // Set offset through x and y texture offsets if ML_EFFECT6 flag is set
|
||||
{
|
||||
xoffs = sides[lines[i].sidenum[0]].textureoffset;
|
||||
yoffs = sides[lines[i].sidenum[0]].rowoffset;
|
||||
|
@ -7204,6 +7238,7 @@ void P_SpawnSpecials(INT32 fromnetsave)
|
|||
case 301:
|
||||
case 310:
|
||||
case 312:
|
||||
case 332:
|
||||
sec = sides[*lines[i].sidenum].sector - sectors;
|
||||
P_AddEachTimeThinker(§ors[sec], &lines[i]);
|
||||
break;
|
||||
|
@ -7252,6 +7287,11 @@ void P_SpawnSpecials(INT32 fromnetsave)
|
|||
case 330:
|
||||
break;
|
||||
|
||||
// Skin trigger executors
|
||||
case 331:
|
||||
case 333:
|
||||
break;
|
||||
|
||||
case 399: // Linedef execute on map load
|
||||
// This is handled in P_RunLevelLoadExecutors.
|
||||
break;
|
||||
|
@ -7290,6 +7330,24 @@ void P_SpawnSpecials(INT32 fromnetsave)
|
|||
case 431:
|
||||
break;
|
||||
|
||||
case 449: // Enable bosses with parameter
|
||||
{
|
||||
INT32 bossid = sides[*lines[i].sidenum].textureoffset>>FRACBITS;
|
||||
if (bossid & ~15) // if any bits other than first 16 are set
|
||||
{
|
||||
CONS_Alert(CONS_WARNING,
|
||||
M_GetText("Boss enable linedef (tag %d) has an invalid texture x offset.\nConsider changing it or removing it entirely.\n"),
|
||||
lines[i].tag);
|
||||
break;
|
||||
}
|
||||
if (!(lines[i].flags & ML_NOCLIMB))
|
||||
{
|
||||
bossdisabled |= (1<<bossid); // gotta disable in the first place to enable
|
||||
CONS_Debug(DBG_GAMELOGIC, "Line type 449 spawn effect: bossid disabled = %d", bossid);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// 500 is used for a scroller
|
||||
// 501 is used for a scroller
|
||||
// 502 is used for a scroller
|
||||
|
@ -7368,14 +7426,6 @@ void P_SpawnSpecials(INT32 fromnetsave)
|
|||
sectors[s].extra_colormap = sectors[s].spawn_extra_colormap = sides[lines[i].sidenum[0]].colormap_data;
|
||||
break;
|
||||
|
||||
#ifdef ESLOPE // Slope copy specials. Handled here for sanity.
|
||||
case 720:
|
||||
case 721:
|
||||
case 722:
|
||||
P_CopySectorSlope(&lines[i]);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -7735,7 +7785,7 @@ static void Add_Scroller(INT32 type, fixed_t dx, fixed_t dy, INT32 control, INT3
|
|||
if ((s->control = control) != -1)
|
||||
s->last_height = sectors[control].floorheight + sectors[control].ceilingheight;
|
||||
s->affectee = affectee;
|
||||
P_AddThinker(&s->thinker);
|
||||
P_AddThinker(THINK_MAIN, &s->thinker);
|
||||
}
|
||||
|
||||
/** Initializes the scrollers.
|
||||
|
@ -7869,7 +7919,7 @@ static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t o
|
|||
d->exists = true;
|
||||
d->timer = 1;
|
||||
|
||||
P_AddThinker(&d->thinker);
|
||||
P_AddThinker(THINK_MAIN, &d->thinker);
|
||||
}
|
||||
|
||||
/** Makes a FOF appear/disappear
|
||||
|
@ -7916,6 +7966,7 @@ void T_Disappear(disappear_t *d)
|
|||
}
|
||||
}
|
||||
sectors[s].moved = true;
|
||||
P_RecalcPrecipInSector(§ors[s]);
|
||||
}
|
||||
|
||||
if (d->exists)
|
||||
|
@ -8264,7 +8315,7 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor
|
|||
d->ffloornum = (UINT32)ffloornum;
|
||||
|
||||
d->alpha = d->sourcevalue = rover->alpha;
|
||||
d->destvalue = max(1, min(256, relative ? rover->alpha + destvalue : destvalue)); // ffloor->alpha is 1-256
|
||||
d->destvalue = max(1, min(256, relative ? rover->alpha + destvalue : destvalue)); // rover->alpha is 1-256
|
||||
|
||||
if (ticbased)
|
||||
{
|
||||
|
@ -8358,7 +8409,7 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor
|
|||
FixedFloor(FixedDiv(abs(d->destvalue - d->alpha), d->speed))/FRACUNIT);
|
||||
}
|
||||
|
||||
P_AddThinker(&d->thinker);
|
||||
P_AddThinker(THINK_MAIN, &d->thinker);
|
||||
}
|
||||
|
||||
/** Makes a FOF fade
|
||||
|
@ -8428,7 +8479,7 @@ static void Add_ColormapFader(sector_t *sector, extracolormap_t *source_exc, ext
|
|||
}
|
||||
|
||||
sector->fadecolormapdata = d;
|
||||
P_AddThinker(&d->thinker); // add thinker
|
||||
P_AddThinker(THINK_MAIN, &d->thinker);
|
||||
}
|
||||
|
||||
void T_FadeColormap(fadecolormap_t *d)
|
||||
|
@ -8547,7 +8598,7 @@ static void Add_Friction(INT32 friction, INT32 movefactor, INT32 affectee, INT32
|
|||
else
|
||||
f->roverfriction = false;
|
||||
|
||||
P_AddThinker(&f->thinker);
|
||||
P_AddThinker(THINK_MAIN, &f->thinker);
|
||||
}
|
||||
|
||||
/** Applies friction to all things in a sector.
|
||||
|
@ -8713,7 +8764,7 @@ static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t *
|
|||
p->z = p->source->z;
|
||||
}
|
||||
p->affectee = affectee;
|
||||
P_AddThinker(&p->thinker);
|
||||
P_AddThinker(THINK_MAIN, &p->thinker);
|
||||
}
|
||||
|
||||
|
||||
|
@ -9214,40 +9265,4 @@ static void P_SpawnPushers(void)
|
|||
Add_Pusher(p_downwind, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void P_SearchForDisableLinedefs(void)
|
||||
{
|
||||
size_t i;
|
||||
INT32 j;
|
||||
|
||||
// Look for disable linedefs
|
||||
for (i = 0; i < numlines; i++)
|
||||
{
|
||||
if (lines[i].special == 6)
|
||||
{
|
||||
// Remove special
|
||||
// Do *not* remove tag. That would mess with the tag lists
|
||||
// that P_InitTagLists literally just created!
|
||||
lines[i].special = 0;
|
||||
|
||||
// Ability flags can disable disable linedefs now, lol
|
||||
if (netgame || multiplayer)
|
||||
{
|
||||
// future: nonet flag?
|
||||
}
|
||||
else if ((lines[i].flags & ML_NETONLY) == ML_NETONLY)
|
||||
continue; // Net-only never triggers in single player
|
||||
else if (players[consoleplayer].charability == CA_THOK && (lines[i].flags & ML_NOSONIC))
|
||||
continue;
|
||||
else if (players[consoleplayer].charability == CA_FLY && (lines[i].flags & ML_NOTAILS))
|
||||
continue;
|
||||
else if (players[consoleplayer].charability == CA_GLIDEANDCLIMB && (lines[i].flags & ML_NOKNUX))
|
||||
continue;
|
||||
|
||||
// Disable any linedef specials with our tag.
|
||||
for (j = -1; (j = P_FindLineFromLineTag(&lines[i], j)) >= 0;)
|
||||
lines[j].special = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
104
src/p_tick.c
104
src/p_tick.c
|
@ -35,8 +35,8 @@ tic_t leveltime;
|
|||
// but the first element must be thinker_t.
|
||||
//
|
||||
|
||||
// Both the head and tail of the thinker list.
|
||||
thinker_t thinkercap;
|
||||
// The entries will behave like both the head and tail of the lists.
|
||||
thinker_t thlist[NUM_THINKERLISTS];
|
||||
|
||||
void Command_Numthinkers_f(void)
|
||||
{
|
||||
|
@ -44,6 +44,9 @@ void Command_Numthinkers_f(void)
|
|||
INT32 count = 0;
|
||||
actionf_p1 action;
|
||||
thinker_t *think;
|
||||
thinklistnum_t start = 0;
|
||||
thinklistnum_t end = NUM_THINKERLISTS - 1;
|
||||
thinklistnum_t i;
|
||||
|
||||
if (gamestate != GS_LEVEL)
|
||||
{
|
||||
|
@ -70,6 +73,7 @@ void Command_Numthinkers_f(void)
|
|||
switch (num)
|
||||
{
|
||||
case 1:
|
||||
start = end = THINK_MOBJ;
|
||||
action = (actionf_p1)P_MobjThinker;
|
||||
CONS_Printf(M_GetText("Number of %s: "), "P_MobjThinker");
|
||||
break;
|
||||
|
@ -82,14 +86,17 @@ void Command_Numthinkers_f(void)
|
|||
CONS_Printf(M_GetText("Number of %s: "), "P_SnowThinker");
|
||||
break;*/
|
||||
case 2:
|
||||
start = end = THINK_PRECIP;
|
||||
action = (actionf_p1)P_NullPrecipThinker;
|
||||
CONS_Printf(M_GetText("Number of %s: "), "P_NullPrecipThinker");
|
||||
break;
|
||||
case 3:
|
||||
start = end = THINK_MAIN;
|
||||
action = (actionf_p1)T_Friction;
|
||||
CONS_Printf(M_GetText("Number of %s: "), "T_Friction");
|
||||
break;
|
||||
case 4:
|
||||
start = end = THINK_MAIN;
|
||||
action = (actionf_p1)T_Pusher;
|
||||
CONS_Printf(M_GetText("Number of %s: "), "T_Pusher");
|
||||
break;
|
||||
|
@ -102,12 +109,15 @@ void Command_Numthinkers_f(void)
|
|||
return;
|
||||
}
|
||||
|
||||
for (think = thinkercap.next; think != &thinkercap; think = think->next)
|
||||
for (i = start; i <= end; i++)
|
||||
{
|
||||
if (think->function.acp1 != action)
|
||||
continue;
|
||||
for (think = thlist[i].next; think != &thlist[i]; think = think->next)
|
||||
{
|
||||
if (think->function.acp1 != action)
|
||||
continue;
|
||||
|
||||
count++;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
CONS_Printf("%d\n", count);
|
||||
|
@ -139,9 +149,9 @@ void Command_CountMobjs_f(void)
|
|||
|
||||
count = 0;
|
||||
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
if (((mobj_t *)th)->type == i)
|
||||
|
@ -159,9 +169,9 @@ void Command_CountMobjs_f(void)
|
|||
{
|
||||
count = 0;
|
||||
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
if (((mobj_t *)th)->type == i)
|
||||
|
@ -178,19 +188,22 @@ void Command_CountMobjs_f(void)
|
|||
//
|
||||
void P_InitThinkers(void)
|
||||
{
|
||||
thinkercap.prev = thinkercap.next = &thinkercap;
|
||||
UINT8 i;
|
||||
for (i = 0; i < NUM_THINKERLISTS; i++)
|
||||
thlist[i].prev = thlist[i].next = &thlist[i];
|
||||
}
|
||||
|
||||
//
|
||||
// P_AddThinker
|
||||
// Adds a new thinker at the end of the list.
|
||||
//
|
||||
void P_AddThinker(thinker_t *thinker)
|
||||
void P_AddThinker(const thinklistnum_t n, thinker_t *thinker)
|
||||
{
|
||||
thinkercap.prev->next = thinker;
|
||||
thinker->next = &thinkercap;
|
||||
thinker->prev = thinkercap.prev;
|
||||
thinkercap.prev = thinker;
|
||||
#ifdef PARANOIA
|
||||
I_Assert(n >= 0 && n < NUM_THINKERLISTS);
|
||||
#endif
|
||||
|
||||
thlist[n].prev->next = thinker;
|
||||
thinker->next = &thlist[n];
|
||||
thinker->prev = thlist[n].prev;
|
||||
thlist[n].prev = thinker;
|
||||
|
||||
thinker->references = 0; // killough 11/98: init reference counter to 0
|
||||
}
|
||||
|
@ -213,22 +226,33 @@ static thinker_t *currentthinker;
|
|||
// remove it, and set currentthinker to one node preceeding it, so
|
||||
// that the next step in P_RunThinkers() will get its successor.
|
||||
//
|
||||
void P_RemoveThinkerDelayed(void *pthinker)
|
||||
void P_RemoveThinkerDelayed(thinker_t *thinker)
|
||||
{
|
||||
thinker_t *thinker = pthinker;
|
||||
if (!thinker->references)
|
||||
thinker_t *next;
|
||||
#ifdef PARANOIA
|
||||
#define BEENAROUNDBIT (0x40000000) // has to be sufficiently high that it's unlikely to happen in regular gameplay. If you change this, pay attention to the bit pattern of INT32_MIN.
|
||||
if (thinker->references & ~BEENAROUNDBIT)
|
||||
{
|
||||
{
|
||||
/* Remove from main thinker list */
|
||||
thinker_t *next = thinker->next;
|
||||
/* Note that currentthinker is guaranteed to point to us,
|
||||
* and since we're freeing our memory, we had better change that. So
|
||||
* point it to thinker->prev, so the iterator will correctly move on to
|
||||
* thinker->prev->next = thinker->next */
|
||||
(next->prev = currentthinker = thinker->prev)->next = next;
|
||||
}
|
||||
Z_Free(thinker);
|
||||
if (thinker->references & BEENAROUNDBIT) // Usually gets cleared up in one frame; what's going on here, then?
|
||||
CONS_Printf("Number of potentially faulty references: %d\n", (thinker->references & ~BEENAROUNDBIT));
|
||||
thinker->references |= BEENAROUNDBIT;
|
||||
return;
|
||||
}
|
||||
#undef BEENAROUNDBIT
|
||||
#else
|
||||
if (thinker->references)
|
||||
return;
|
||||
#endif
|
||||
|
||||
/* Remove from main thinker list */
|
||||
next = thinker->next;
|
||||
/* Note that currentthinker is guaranteed to point to us,
|
||||
* and since we're freeing our memory, we had better change that. So
|
||||
* point it to thinker->prev, so the iterator will correctly move on to
|
||||
* thinker->prev->next = thinker->next */
|
||||
(next->prev = currentthinker = thinker->prev)->next = next;
|
||||
|
||||
Z_Free(thinker);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -248,7 +272,7 @@ void P_RemoveThinker(thinker_t *thinker)
|
|||
#ifdef HAVE_BLUA
|
||||
LUA_InvalidateUserdata(thinker);
|
||||
#endif
|
||||
thinker->function.acp1 = P_RemoveThinkerDelayed;
|
||||
thinker->function.acp1 = (actionf_p1)P_RemoveThinkerDelayed;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -296,11 +320,18 @@ if ((*mop = targ) != NULL) // Set new target and if non-NULL, increase its count
|
|||
//
|
||||
static inline void P_RunThinkers(void)
|
||||
{
|
||||
for (currentthinker = thinkercap.next; currentthinker != &thinkercap; currentthinker = currentthinker->next)
|
||||
size_t i;
|
||||
for (i = 0; i < NUM_THINKERLISTS; i++)
|
||||
{
|
||||
if (currentthinker->function.acp1)
|
||||
for (currentthinker = thlist[i].next; currentthinker != &thlist[i]; currentthinker = currentthinker->next)
|
||||
{
|
||||
#ifdef PARANOIA
|
||||
I_Assert(currentthinker->function.acp1 != NULL)
|
||||
#endif
|
||||
currentthinker->function.acp1(currentthinker);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -487,10 +518,7 @@ static inline void P_DoSpecialStageStuff(void)
|
|||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sstimer = 0;
|
||||
stagefailed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ void Command_CountMobjs_f(void);
|
|||
void P_Ticker(boolean run);
|
||||
void P_PreTicker(INT32 frames);
|
||||
void P_DoTeamscrambling(void);
|
||||
void P_RemoveThinkerDelayed(void *pthinker); //killed
|
||||
void P_RemoveThinkerDelayed(thinker_t *thinker); //killed
|
||||
mobj_t *P_SetTarget(mobj_t **mo, mobj_t *target); // killough 11/98
|
||||
|
||||
#endif
|
||||
|
|
810
src/p_user.c
810
src/p_user.c
File diff suppressed because it is too large
Load diff
81
src/r_data.c
81
src/r_data.c
|
@ -578,16 +578,7 @@ void R_LoadTextures(void)
|
|||
// but the alternative is to spend a ton of time checking and re-checking all previous entries just to skip any potentially patched textures.
|
||||
for (w = 0, numtextures = 0; w < numwadfiles; w++)
|
||||
{
|
||||
if (wadfiles[w]->type == RET_PK3)
|
||||
{
|
||||
texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0);
|
||||
texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart);
|
||||
}
|
||||
else
|
||||
{
|
||||
texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0) + 1;
|
||||
texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0);
|
||||
}
|
||||
// Count the textures from TEXTURES lumps
|
||||
|
||||
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0);
|
||||
while (texturesLumpPos != INT16_MAX)
|
||||
|
@ -596,18 +587,43 @@ void R_LoadTextures(void)
|
|||
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, texturesLumpPos + 1);
|
||||
}
|
||||
|
||||
// Add all the textures between TX_START and TX_END
|
||||
if (texstart != INT16_MAX && texend != INT16_MAX)
|
||||
// Count single-patch textures
|
||||
|
||||
if (wadfiles[w]->type == RET_PK3)
|
||||
{
|
||||
texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0);
|
||||
texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart);
|
||||
}
|
||||
else
|
||||
{
|
||||
texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0);
|
||||
texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0);
|
||||
}
|
||||
|
||||
if (texstart == INT16_MAX || texend == INT16_MAX)
|
||||
continue;
|
||||
|
||||
texstart++; // Do not count the first marker
|
||||
|
||||
// PK3s have subfolders, so we can't just make a simple sum
|
||||
if (wadfiles[w]->type == RET_PK3)
|
||||
{
|
||||
for (j = texstart; j < texend; j++)
|
||||
{
|
||||
if (!W_IsLumpFolder((UINT16)w, j)) // Check if lump is a folder; if not, then count it
|
||||
numtextures++;
|
||||
}
|
||||
}
|
||||
else // Add all the textures between TX_START and TX_END
|
||||
{
|
||||
numtextures += (UINT32)(texend - texstart);
|
||||
}
|
||||
|
||||
// If no textures found by this point, bomb out
|
||||
if (!numtextures && w == (numwadfiles - 1))
|
||||
{
|
||||
I_Error("No textures detected in any WADs!\n");
|
||||
}
|
||||
}
|
||||
|
||||
// If no textures found by this point, bomb out
|
||||
if (!numtextures)
|
||||
I_Error("No textures detected in any WADs!\n");
|
||||
|
||||
// Allocate memory and initialize to 0 for all the textures we are initialising.
|
||||
// There are actually 5 buffers allocated in one for convenience.
|
||||
textures = Z_Calloc((numtextures * sizeof(void *)) * 5, PU_STATIC, NULL);
|
||||
|
@ -642,7 +658,7 @@ void R_LoadTextures(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0) + 1;
|
||||
texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0);
|
||||
texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0);
|
||||
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0);
|
||||
if (texturesLumpPos != INT16_MAX)
|
||||
|
@ -652,9 +668,16 @@ void R_LoadTextures(void)
|
|||
if (texstart == INT16_MAX || texend == INT16_MAX)
|
||||
continue;
|
||||
|
||||
texstart++; // Do not count the first marker
|
||||
|
||||
// Work through each lump between the markers in the WAD.
|
||||
for (j = 0; j < (texend - texstart); i++, j++)
|
||||
for (j = 0; j < (texend - texstart); j++)
|
||||
{
|
||||
if (wadfiles[w]->type == RET_PK3)
|
||||
{
|
||||
if (W_IsLumpFolder((UINT16)w, texstart + j)) // Check if lump is a folder
|
||||
continue; // If it is then SKIP IT
|
||||
}
|
||||
patchlump = W_CacheLumpNumPwad((UINT16)w, texstart + j, PU_CACHE);
|
||||
|
||||
//CONS_Printf("\n\"%s\" is a single patch, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),patchlump->width, patchlump->height);
|
||||
|
@ -684,6 +707,7 @@ void R_LoadTextures(void)
|
|||
|
||||
texturewidthmask[i] = k - 1;
|
||||
textureheight[i] = texture->height << FRACBITS;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1293,14 +1317,23 @@ void R_ReInitColormaps(UINT16 num)
|
|||
{
|
||||
char colormap[9] = "COLORMAP";
|
||||
lumpnum_t lump;
|
||||
const lumpnum_t basecolormaplump = W_GetNumForName(colormap);
|
||||
if (num > 0 && num <= 10000)
|
||||
snprintf(colormap, 8, "CLM%04u", num-1);
|
||||
|
||||
// Load in the light tables, now 64k aligned for smokie...
|
||||
lump = W_GetNumForName(colormap);
|
||||
if (lump == LUMPERROR)
|
||||
lump = W_GetNumForName("COLORMAP");
|
||||
W_ReadLump(lump, colormaps);
|
||||
lump = basecolormaplump;
|
||||
else
|
||||
{
|
||||
if (W_LumpLength(lump) != W_LumpLength(basecolormaplump))
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "%s lump size does not match COLORMAP, results may be unexpected.\n", colormap);
|
||||
}
|
||||
}
|
||||
|
||||
W_ReadLumpHeader(lump, colormaps, W_LumpLength(basecolormaplump), 0U);
|
||||
|
||||
// Init Boom colormaps.
|
||||
R_ClearColormaps();
|
||||
|
@ -2242,8 +2275,8 @@ void R_PrecacheLevel(void)
|
|||
spritepresent = calloc(numsprites, sizeof (*spritepresent));
|
||||
if (spritepresent == NULL) I_Error("%s: Out of memory looking up sprites", "R_PrecacheLevel");
|
||||
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
if (th->function.acp1 == (actionf_p1)P_MobjThinker)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
if (th->function.acp1 != (actionf_p1)P_RemoveThinkerDelayed)
|
||||
spritepresent[((mobj_t *)th)->sprite] = 1;
|
||||
|
||||
spritememory = 0;
|
||||
|
|
39
src/r_defs.h
39
src/r_defs.h
|
@ -237,46 +237,27 @@ typedef struct linechain_s
|
|||
// Slopes
|
||||
#ifdef ESLOPE
|
||||
typedef enum {
|
||||
SL_NOPHYSICS = 1, // Don't do momentum adjustment with this slope
|
||||
SL_NODYNAMIC = 1<<1, // Slope will never need to move during the level, so don't fuss with recalculating it
|
||||
SL_ANCHORVERTEX = 1<<2, // Slope is using a Slope Vertex Thing to anchor its position
|
||||
SL_VERTEXSLOPE = 1<<3, // Slope is built from three Slope Vertex Things
|
||||
SL_NOPHYSICS = 1, /// This plane will have no physics applied besides the positioning.
|
||||
SL_DYNAMIC = 1<<1, /// This plane slope will be assigned a thinker to make it dynamic.
|
||||
} slopeflags_t;
|
||||
|
||||
typedef struct pslope_s
|
||||
{
|
||||
UINT16 id; // The number of the slope, mostly used for netgame syncing purposes
|
||||
struct pslope_s *next; // Make a linked list of dynamic slopes, for easy reference later
|
||||
|
||||
// --- Information used in clipping/projection ---
|
||||
// Origin vector for the plane
|
||||
vector3_t o;
|
||||
// The plane's definition.
|
||||
vector3_t o; /// Plane origin.
|
||||
vector3_t normal; /// Plane normal.
|
||||
|
||||
// 2-Dimentional vector (x, y) normalized. Used to determine distance from
|
||||
// the origin in 2d mapspace. (Basically a thrust of FRACUNIT in xydirection angle)
|
||||
vector2_t d;
|
||||
|
||||
// The rate at which z changes based on distance from the origin plane.
|
||||
fixed_t zdelta;
|
||||
|
||||
// The normal of the slope; will always point upward, and thus be inverted on ceilings. I think it's only needed for physics? -Red
|
||||
vector3_t normal;
|
||||
|
||||
// For comparing when a slope should be rendered
|
||||
fixed_t lowz;
|
||||
fixed_t highz;
|
||||
vector2_t d; /// Precomputed normalized projection of the normal over XY.
|
||||
fixed_t zdelta; /// Precomputed Z unit increase per XY unit.
|
||||
|
||||
// This values only check and must be updated if the slope itself is modified
|
||||
angle_t zangle; // Angle of the plane going up from the ground (not mesured in degrees)
|
||||
angle_t xydirection; // The direction the slope is facing (north, west, south, etc.)
|
||||
|
||||
struct line_s *sourceline; // The line that generated the slope
|
||||
fixed_t extent; // Distance value used for recalculating zdelta
|
||||
UINT8 refpos; // 1=front floor 2=front ceiling 3=back floor 4=back ceiling (used for dynamic sloping)
|
||||
angle_t zangle; /// Precomputed angle of the plane going up from the ground (not measured in degrees).
|
||||
angle_t xydirection;/// Precomputed angle of the normal's projection on the XY plane.
|
||||
|
||||
UINT8 flags; // Slope options
|
||||
mapthing_t **vertices; // List should be three long for slopes made by vertex things, or one long for slopes using one vertex thing to anchor
|
||||
|
||||
struct pslope_s *next; // Make a linked list of dynamic slopes, for easy reference later
|
||||
} pslope_t;
|
||||
#endif
|
||||
|
||||
|
|
84
src/r_draw.c
84
src/r_draw.c
|
@ -126,10 +126,12 @@ UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask;
|
|||
#define BOSS_TT_CACHE_INDEX (MAXSKINS + 1)
|
||||
#define METALSONIC_TT_CACHE_INDEX (MAXSKINS + 2)
|
||||
#define ALLWHITE_TT_CACHE_INDEX (MAXSKINS + 3)
|
||||
#define RAINBOW_TT_CACHE_INDEX (MAXSKINS + 4)
|
||||
#define BLINK_TT_CACHE_INDEX (MAXSKINS + 5)
|
||||
#define DEFAULT_STARTTRANSCOLOR 96
|
||||
#define NUM_PALETTE_ENTRIES 256
|
||||
|
||||
static UINT8** translationtablecache[MAXSKINS + 4] = {NULL};
|
||||
static UINT8** translationtablecache[MAXSKINS + 6] = {NULL};
|
||||
|
||||
const UINT8 Color_Index[MAXTRANSLATIONS-1][16] = {
|
||||
// {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, // SKINCOLOR_NONE
|
||||
|
@ -457,17 +459,82 @@ void R_InitTranslationTables(void)
|
|||
|
||||
\return void
|
||||
*/
|
||||
|
||||
// Define for getting accurate color brightness readings according to how the human eye sees them.
|
||||
// https://en.wikipedia.org/wiki/Relative_luminance
|
||||
// 0.2126 to red
|
||||
// 0.7152 to green
|
||||
// 0.0722 to blue
|
||||
// (See this same define in hw_md2.c!)
|
||||
#define SETBRIGHTNESS(brightness,r,g,b) \
|
||||
brightness = (UINT8)(((1063*((UINT16)r)/5000) + (3576*((UINT16)g)/5000) + (361*((UINT16)b)/5000)) / 3)
|
||||
|
||||
/** \brief Generates the rainbow colourmaps that are used when a player has the invincibility power... stolen from kart, with permission
|
||||
|
||||
\param dest_colormap colormap to populate
|
||||
\param skincolor translation color
|
||||
*/
|
||||
static void R_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor)
|
||||
{
|
||||
INT32 i;
|
||||
RGBA_t color;
|
||||
UINT8 brightness;
|
||||
INT32 j;
|
||||
UINT8 colorbrightnesses[16];
|
||||
UINT16 brightdif;
|
||||
INT32 temp;
|
||||
|
||||
// first generate the brightness of all the colours of that skincolour
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
color = V_GetColor(Color_Index[skincolor-1][i]);
|
||||
SETBRIGHTNESS(colorbrightnesses[i], color.s.red, color.s.green, color.s.blue);
|
||||
}
|
||||
|
||||
// next, for every colour in the palette, choose the transcolor that has the closest brightness
|
||||
for (i = 0; i < NUM_PALETTE_ENTRIES; i++)
|
||||
{
|
||||
if (i == 0 || i == 31) // pure black and pure white don't change
|
||||
{
|
||||
dest_colormap[i] = (UINT8)i;
|
||||
continue;
|
||||
}
|
||||
color = V_GetColor(i);
|
||||
SETBRIGHTNESS(brightness, color.s.red, color.s.green, color.s.blue);
|
||||
brightdif = 256;
|
||||
for (j = 0; j < 16; j++)
|
||||
{
|
||||
temp = abs((INT16)brightness - (INT16)colorbrightnesses[j]);
|
||||
if (temp < brightdif)
|
||||
{
|
||||
brightdif = (UINT16)temp;
|
||||
dest_colormap[i] = Color_Index[skincolor-1][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef SETBRIGHTNESS
|
||||
|
||||
static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, UINT8 color)
|
||||
{
|
||||
INT32 i, starttranscolor, skinramplength;
|
||||
|
||||
// Handle a couple of simple special cases
|
||||
if (skinnum == TC_BOSS || skinnum == TC_ALLWHITE || skinnum == TC_METALSONIC || color == SKINCOLOR_NONE)
|
||||
if (skinnum == TC_BOSS
|
||||
|| skinnum == TC_ALLWHITE
|
||||
|| skinnum == TC_METALSONIC
|
||||
|| skinnum == TC_BLINK
|
||||
|| color == SKINCOLOR_NONE)
|
||||
{
|
||||
for (i = 0; i < NUM_PALETTE_ENTRIES; i++)
|
||||
if (skinnum == TC_ALLWHITE)
|
||||
memset(dest_colormap, 0, NUM_PALETTE_ENTRIES * sizeof(UINT8));
|
||||
else if (skinnum == TC_BLINK && color != SKINCOLOR_NONE)
|
||||
memset(dest_colormap, Color_Index[color-1][3], NUM_PALETTE_ENTRIES * sizeof(UINT8));
|
||||
else
|
||||
{
|
||||
if (skinnum == TC_ALLWHITE) dest_colormap[i] = 0;
|
||||
else dest_colormap[i] = (UINT8)i;
|
||||
for (i = 0; i < NUM_PALETTE_ENTRIES; i++)
|
||||
dest_colormap[i] = (UINT8)i;
|
||||
}
|
||||
|
||||
// White!
|
||||
|
@ -478,6 +545,11 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U
|
|||
|
||||
return;
|
||||
}
|
||||
else if (skinnum == TC_RAINBOW)
|
||||
{
|
||||
R_RainbowColormap(dest_colormap, color);
|
||||
return;
|
||||
}
|
||||
|
||||
if (color >= MAXTRANSLATIONS)
|
||||
I_Error("Invalid skin color #%hu.", (UINT16)color);
|
||||
|
@ -522,6 +594,8 @@ UINT8* R_GetTranslationColormap(INT32 skinnum, skincolors_t color, UINT8 flags)
|
|||
else if (skinnum == TC_BOSS) skintableindex = BOSS_TT_CACHE_INDEX;
|
||||
else if (skinnum == TC_METALSONIC) skintableindex = METALSONIC_TT_CACHE_INDEX;
|
||||
else if (skinnum == TC_ALLWHITE) skintableindex = ALLWHITE_TT_CACHE_INDEX;
|
||||
else if (skinnum == TC_RAINBOW) skintableindex = RAINBOW_TT_CACHE_INDEX;
|
||||
else if (skinnum == TC_BLINK) skintableindex = BLINK_TT_CACHE_INDEX;
|
||||
else skintableindex = skinnum;
|
||||
|
||||
if (flags & GTC_CACHE)
|
||||
|
|
|
@ -105,6 +105,8 @@ extern lumpnum_t viewborderlump[8];
|
|||
#define TC_BOSS -2
|
||||
#define TC_METALSONIC -3 // For Metal Sonic battle
|
||||
#define TC_ALLWHITE -4 // For Cy-Brak-demon
|
||||
#define TC_RAINBOW -5 // For single colour
|
||||
#define TC_BLINK -6 // For item blinking, according to kart
|
||||
|
||||
// Initialize color translation tables, for player rendering etc.
|
||||
void R_InitTranslationTables(void);
|
||||
|
|
|
@ -486,7 +486,11 @@ void R_InitSprites(void)
|
|||
// it can be is do before loading config for skin cvar possible value
|
||||
R_InitSkins();
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
{
|
||||
R_AddSkins((UINT16)i);
|
||||
R_PatchSkins((UINT16)i);
|
||||
}
|
||||
ST_ReloadSkinFaceGraphics();
|
||||
|
||||
//
|
||||
// check if all sprites have frames
|
||||
|
@ -719,11 +723,11 @@ static void R_DrawVisSprite(vissprite_t *vis)
|
|||
|
||||
colfunc = basecolfunc; // hack: this isn't resetting properly somewhere.
|
||||
dc_colormap = vis->colormap;
|
||||
if (!(vis->cut & SC_PRECIP) && (vis->mobj->flags & (MF_ENEMY|MF_BOSS)) && (vis->mobj->flags2 & MF2_FRET) && (leveltime & 1)) // Bosses "flash"
|
||||
if (!(vis->cut & SC_PRECIP) && (vis->mobj->flags & (MF_ENEMY|MF_BOSS)) && (vis->mobj->flags2 & MF2_FRET) && !(vis->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash"
|
||||
{
|
||||
// translate certain pixels to white
|
||||
colfunc = transcolfunc;
|
||||
if (vis->mobj->type == MT_CYBRAKDEMON)
|
||||
if (vis->mobj->type == MT_CYBRAKDEMON || vis->mobj->colorized)
|
||||
dc_translation = R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE);
|
||||
else if (vis->mobj->type == MT_METALSONIC_BATTLE)
|
||||
dc_translation = R_GetTranslationColormap(TC_METALSONIC, 0, GTC_CACHE);
|
||||
|
@ -734,7 +738,9 @@ static void R_DrawVisSprite(vissprite_t *vis)
|
|||
{
|
||||
colfunc = transtransfunc;
|
||||
dc_transmap = vis->transmap;
|
||||
if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // MT_GHOST LOOKS LIKE A PLAYER SO USE THE PLAYER TRANSLATION TABLES. >_>
|
||||
if (!(vis->cut & SC_PRECIP) && vis->mobj->colorized)
|
||||
dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE);
|
||||
else if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // MT_GHOST LOOKS LIKE A PLAYER SO USE THE PLAYER TRANSLATION TABLES. >_>
|
||||
{
|
||||
size_t skinnum = (skin_t*)vis->mobj->skin-skins;
|
||||
dc_translation = R_GetTranslationColormap((INT32)skinnum, vis->mobj->color, GTC_CACHE);
|
||||
|
@ -753,7 +759,9 @@ static void R_DrawVisSprite(vissprite_t *vis)
|
|||
colfunc = transcolfunc;
|
||||
|
||||
// New colormap stuff for skins Tails 06-07-2002
|
||||
if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // This thing is a player!
|
||||
if (!(vis->cut & SC_PRECIP) && vis->mobj->colorized)
|
||||
dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE);
|
||||
else if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // This thing is a player!
|
||||
{
|
||||
size_t skinnum = (skin_t*)vis->mobj->skin-skins;
|
||||
dc_translation = R_GetTranslationColormap((INT32)skinnum, vis->mobj->color, GTC_CACHE);
|
||||
|
@ -2442,8 +2450,10 @@ static void R_DrawMaskedList (drawnode_t* head)
|
|||
|
||||
void R_DrawMasked(maskcount_t* masks, UINT8 nummasks)
|
||||
{
|
||||
drawnode_t heads[nummasks]; /**< Drawnode lists; as many as number of views/portals. */
|
||||
INT8 i;
|
||||
drawnode_t *heads; /**< Drawnode lists; as many as number of views/portals. */
|
||||
SINT8 i;
|
||||
|
||||
heads = calloc(nummasks, sizeof(drawnode_t));
|
||||
|
||||
for (i = 0; i < nummasks; i++)
|
||||
{
|
||||
|
@ -2470,6 +2480,8 @@ void R_DrawMasked(maskcount_t* masks, UINT8 nummasks)
|
|||
R_DrawMaskedList(&heads[nummasks - 1]);
|
||||
R_ClearDrawNodes(&heads[nummasks - 1]);
|
||||
}
|
||||
|
||||
free(heads);
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
|
@ -2499,6 +2511,9 @@ UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player)
|
|||
if (!skin)
|
||||
return 0;
|
||||
|
||||
if ((spr2 & ~FF_SPR2SUPER) >= free_spr2)
|
||||
return 0;
|
||||
|
||||
while (!(skin->sprites[spr2].numframes)
|
||||
&& spr2 != SPR2_STND
|
||||
&& ++i < 32) // recursion limiter
|
||||
|
@ -2521,8 +2536,10 @@ UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player)
|
|||
& SF_NOJUMPSPIN) ? SPR2_SPNG : SPR2_ROLL;
|
||||
break;
|
||||
case SPR2_TIRE:
|
||||
spr2 = (player && player->charability == CA_SWIM) ? SPR2_SWIM : SPR2_FLY;
|
||||
break;
|
||||
spr2 = ((player
|
||||
? player->charability
|
||||
: skin->ability)
|
||||
== CA_SWIM) ? SPR2_SWIM : SPR2_FLY;
|
||||
|
||||
// Use the handy list, that's what it's there for!
|
||||
default:
|
||||
|
@ -2533,6 +2550,9 @@ UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player)
|
|||
spr2 |= super;
|
||||
}
|
||||
|
||||
if (i >= 32) // probably an infinite loop...
|
||||
return 0;
|
||||
|
||||
return spr2;
|
||||
}
|
||||
|
||||
|
@ -2552,9 +2572,6 @@ static void Sk_SetDefaultValue(skin_t *skin)
|
|||
|
||||
strcpy(skin->realname, "Someone");
|
||||
strcpy(skin->hudname, "???");
|
||||
strncpy(skin->charsel, "CHRSONIC", 9);
|
||||
strncpy(skin->face, "MISSING", 8);
|
||||
strncpy(skin->superface, "MISSING", 8);
|
||||
|
||||
skin->starttranscolor = 96;
|
||||
skin->prefcolor = SKINCOLOR_GREEN;
|
||||
|
@ -2700,6 +2717,9 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
|
|||
player->revitem = skin->revitem < 0 ? (mobjtype_t)mobjinfo[MT_PLAYER].raisestate : (UINT32)skin->revitem;
|
||||
player->followitem = skin->followitem;
|
||||
|
||||
if (((player->powers[pw_shield] & SH_NOSTACK) == SH_PINK) && (player->revitem == MT_LHRT || player->spinitem == MT_LHRT || player->thokitem == MT_LHRT)) // Healers can't keep their buff.
|
||||
player->powers[pw_shield] &= SH_STACK;
|
||||
|
||||
player->actionspd = skin->actionspd;
|
||||
player->mindash = skin->mindash;
|
||||
player->maxdash = skin->maxdash;
|
||||
|
@ -2981,7 +3001,7 @@ void R_AddSkins(UINT16 wadnum)
|
|||
char *value;
|
||||
size_t size;
|
||||
skin_t *skin;
|
||||
boolean hudname, realname, superface;
|
||||
boolean hudname, realname;
|
||||
|
||||
//
|
||||
// search for all skin markers in pwad
|
||||
|
@ -3011,7 +3031,7 @@ void R_AddSkins(UINT16 wadnum)
|
|||
skin = &skins[numskins];
|
||||
Sk_SetDefaultValue(skin);
|
||||
skin->wadnum = wadnum;
|
||||
hudname = realname = superface = false;
|
||||
hudname = realname = false;
|
||||
// parse
|
||||
stoken = strtok (buf2, "\r\n= ");
|
||||
while (stoken)
|
||||
|
@ -3087,24 +3107,6 @@ void R_AddSkins(UINT16 wadnum)
|
|||
if (!realname)
|
||||
STRBUFCPY(skin->realname, skin->hudname);
|
||||
}
|
||||
else if (!stricmp(stoken, "charsel"))
|
||||
{
|
||||
strupr(value);
|
||||
strncpy(skin->charsel, value, sizeof skin->charsel);
|
||||
}
|
||||
else if (!stricmp(stoken, "face"))
|
||||
{
|
||||
strupr(value);
|
||||
strncpy(skin->face, value, sizeof skin->face);
|
||||
if (!superface)
|
||||
strncpy(skin->superface, value, sizeof skin->superface);
|
||||
}
|
||||
else if (!stricmp(stoken, "superface"))
|
||||
{
|
||||
superface = true;
|
||||
strupr(value);
|
||||
strncpy(skin->superface, value, sizeof skin->superface);
|
||||
}
|
||||
else if (!stricmp(stoken, "availability"))
|
||||
{
|
||||
skin->availability = atoi(value);
|
||||
|
@ -3123,6 +3125,7 @@ next_token:
|
|||
|
||||
// Add sprites
|
||||
R_LoadSkinSprites(wadnum, &lump, &lastlump, skin);
|
||||
//ST_LoadFaceGraphics(numskins); -- nah let's do this elsewhere
|
||||
|
||||
R_FlushTranslationColormapCache();
|
||||
|
||||
|
@ -3133,9 +3136,6 @@ next_token:
|
|||
skin_cons_t[numskins].strvalue = skin->name;
|
||||
#endif
|
||||
|
||||
// add face graphics
|
||||
ST_LoadFaceGraphics(skin->face, skin->superface, numskins);
|
||||
|
||||
#ifdef HWRENDER
|
||||
if (rendermode == render_opengl)
|
||||
HWR_AddPlayerMD2(numskins);
|
||||
|
@ -3258,6 +3258,9 @@ next_token:
|
|||
|
||||
// Patch sprites
|
||||
R_LoadSkinSprites(wadnum, &lump, &lastlump, skin);
|
||||
//ST_LoadFaceGraphics(skinnum); -- nah let's do this elsewhere
|
||||
|
||||
R_FlushTranslationColormapCache();
|
||||
|
||||
if (!skin->availability) // Safe to print...
|
||||
CONS_Printf(M_GetText("Patched skin '%s'\n"), skin->name);
|
||||
|
|
|
@ -88,7 +88,6 @@ typedef struct
|
|||
|
||||
char realname[SKINNAMESIZE+1]; // Display name for level completion.
|
||||
char hudname[SKINNAMESIZE+1]; // HUD name to display (officially exactly 5 characters long)
|
||||
char charsel[9], face[9], superface[9]; // Arbitrarily named patch lumps
|
||||
|
||||
UINT8 ability; // ability definition
|
||||
UINT8 ability2; // secondary ability definition
|
||||
|
|
|
@ -519,6 +519,7 @@ void S_StartCaption(sfxenum_t sfx_id, INT32 cnum, UINT16 lifespan)
|
|||
void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
|
||||
{
|
||||
INT32 sep, pitch, priority, cnum;
|
||||
const sfxenum_t actual_id = sfx_id;
|
||||
sfxinfo_t *sfx;
|
||||
|
||||
const mobj_t *origin = (const mobj_t *)origin_p;
|
||||
|
@ -657,7 +658,7 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
|
|||
#endif
|
||||
|
||||
// Handle closed caption input.
|
||||
S_StartCaption(sfx_id, cnum, MAXCAPTIONTICS);
|
||||
S_StartCaption(actual_id, cnum, MAXCAPTIONTICS);
|
||||
|
||||
// Assigns the handle to one of the channels in the
|
||||
// mix/output buffer.
|
||||
|
@ -710,7 +711,7 @@ dontplay:
|
|||
#endif
|
||||
|
||||
// Handle closed caption input.
|
||||
S_StartCaption(sfx_id, cnum, MAXCAPTIONTICS);
|
||||
S_StartCaption(actual_id, cnum, MAXCAPTIONTICS);
|
||||
|
||||
// Assigns the handle to one of the channels in the
|
||||
// mix/output buffer.
|
||||
|
@ -1683,7 +1684,17 @@ void S_StopMusic(void)
|
|||
if (cv_closedcaptioning.value)
|
||||
{
|
||||
if (closedcaptions[0].s-S_sfx == sfx_None)
|
||||
closedcaptions[0].t = CAPTIONFADETICS;
|
||||
{
|
||||
if (gamestate != wipegamestate)
|
||||
{
|
||||
closedcaptions[0].c = NULL;
|
||||
closedcaptions[0].s = NULL;
|
||||
closedcaptions[0].t = 0;
|
||||
closedcaptions[0].b = 0;
|
||||
}
|
||||
else
|
||||
closedcaptions[0].t = CAPTIONFADETICS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1989,8 +2000,10 @@ void GameMIDIMusic_OnChange(void)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENMPT
|
||||
void ModFilter_OnChange(void)
|
||||
{
|
||||
if (openmpt_mhandle)
|
||||
openmpt_module_set_render_param(openmpt_mhandle, OPENMPT_MODULE_RENDER_INTERPOLATIONFILTER_LENGTH, cv_modfilter.value);
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -438,7 +438,9 @@ void SCR_ClosedCaptions(void)
|
|||
|
||||
if (gamestate == GS_LEVEL)
|
||||
{
|
||||
if (splitscreen)
|
||||
if (promptactive)
|
||||
basey -= 28;
|
||||
else if (splitscreen)
|
||||
basey -= 8;
|
||||
else if ((modeattacking == ATTACKING_NIGHTS)
|
||||
|| (!(maptol & TOL_NIGHTS)
|
||||
|
|
|
@ -277,6 +277,7 @@
|
|||
<ClInclude Include="..\r_local.h" />
|
||||
<ClInclude Include="..\r_main.h" />
|
||||
<ClInclude Include="..\r_plane.h" />
|
||||
<ClInclude Include="..\r_portal.h" />
|
||||
<ClInclude Include="..\r_segs.h" />
|
||||
<ClInclude Include="..\r_sky.h" />
|
||||
<ClInclude Include="..\r_splats.h" />
|
||||
|
@ -430,6 +431,7 @@
|
|||
</ClCompile>
|
||||
<ClCompile Include="..\r_main.c" />
|
||||
<ClCompile Include="..\r_plane.c" />
|
||||
<ClCompile Include="..\r_portal.c" />
|
||||
<ClCompile Include="..\r_segs.c" />
|
||||
<ClCompile Include="..\r_sky.c" />
|
||||
<ClCompile Include="..\r_splats.c" />
|
||||
|
|
|
@ -453,6 +453,9 @@
|
|||
<ClInclude Include="..\hardware\hw_clip.h">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\r_portal.h">
|
||||
<Filter>R_Rend</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="..\tmap.nas">
|
||||
|
@ -894,6 +897,10 @@
|
|||
<ClCompile Include="..\hardware\hw_clip.c">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\apng.c" />
|
||||
<ClCompile Include="..\r_portal.c">
|
||||
<Filter>R_Rend</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="Srb2SDL.ico">
|
||||
|
|
|
@ -108,14 +108,16 @@ static UINT16 current_track;
|
|||
#endif
|
||||
|
||||
#ifdef HAVE_OPENMPT
|
||||
int mod_err = OPENMPT_ERROR_OK;
|
||||
static int mod_err = OPENMPT_ERROR_OK;
|
||||
static const char *mod_err_str;
|
||||
static UINT16 current_subsong;
|
||||
static size_t probesize;
|
||||
static int result;
|
||||
#endif
|
||||
|
||||
static void var_cleanup(void)
|
||||
{
|
||||
loop_point = song_length = 0.0f;
|
||||
song_length = loop_point = 0.0f;
|
||||
music_bytes = fading_source = fading_target =\
|
||||
fading_timer = fading_duration = 0;
|
||||
|
||||
|
@ -388,7 +390,7 @@ void *I_GetSfx(sfxinfo_t *sfx)
|
|||
gme_track_info(emu, &info, 0);
|
||||
|
||||
len = (info->play_length * 441 / 10) << 2;
|
||||
mem = malloc(len);
|
||||
mem = Z_Malloc(len, PU_SOUND, 0);
|
||||
gme_play(emu, len >> 1, mem);
|
||||
gme_free_info(info);
|
||||
gme_delete(emu);
|
||||
|
@ -461,7 +463,7 @@ void *I_GetSfx(sfxinfo_t *sfx)
|
|||
gme_track_info(emu, &info, 0);
|
||||
|
||||
len = (info->play_length * 441 / 10) << 2;
|
||||
mem = malloc(len);
|
||||
mem = Z_Malloc(len, PU_SOUND, 0);
|
||||
gme_play(emu, len >> 1, mem);
|
||||
gme_free_info(info);
|
||||
gme_delete(emu);
|
||||
|
@ -1112,6 +1114,36 @@ boolean I_LoadSong(char *data, size_t len)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENMPT
|
||||
/*
|
||||
If the size of the data to be checked is bigger than the recommended size (> 2048)
|
||||
Let's just set the probe size to the recommended size
|
||||
Otherwise let's give it the full data size
|
||||
*/
|
||||
|
||||
if (len > openmpt_probe_file_header_get_recommended_size())
|
||||
probesize = openmpt_probe_file_header_get_recommended_size();
|
||||
else
|
||||
probesize = len;
|
||||
|
||||
result = openmpt_probe_file_header(OPENMPT_PROBE_FILE_HEADER_FLAGS_DEFAULT, data, probesize, len, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
if (result == OPENMPT_PROBE_FILE_HEADER_RESULT_SUCCESS) // We only cared if it succeeded, continue on if not.
|
||||
{
|
||||
openmpt_mhandle = openmpt_module_create_from_memory2(data, len, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (!openmpt_mhandle) // Failed to create module handle? Show error and return!
|
||||
{
|
||||
mod_err = openmpt_module_error_get_last(openmpt_mhandle);
|
||||
mod_err_str = openmpt_error_string(mod_err);
|
||||
CONS_Alert(CONS_ERROR, "openmpt_module_create_from_memory2: %s\n", mod_err_str);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true; // All good and we're ready for music playback!
|
||||
}
|
||||
#endif
|
||||
|
||||
// Let's see if Mixer is able to load this.
|
||||
rw = SDL_RWFromMem(data, len);
|
||||
if (rw != NULL)
|
||||
{
|
||||
|
@ -1123,40 +1155,6 @@ boolean I_LoadSong(char *data, size_t len)
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENMPT
|
||||
switch(Mix_GetMusicType(music))
|
||||
{
|
||||
case MUS_MODPLUG:
|
||||
case MUS_MOD:
|
||||
openmpt_mhandle = openmpt_module_create_from_memory2(data, len, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (!openmpt_mhandle)
|
||||
{
|
||||
mod_err = openmpt_module_error_get_last(openmpt_mhandle);
|
||||
mod_err_str = openmpt_error_string(mod_err);
|
||||
CONS_Alert(CONS_ERROR, "openmpt_module_create_from_memory2: %s\n", mod_err_str);
|
||||
Mix_FreeMusic(music);
|
||||
music = NULL;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Mix_FreeMusic(music);
|
||||
music = NULL;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case MUS_WAV:
|
||||
case MUS_MID:
|
||||
case MUS_OGG:
|
||||
case MUS_MP3:
|
||||
case MUS_FLAC:
|
||||
Mix_HookMusic(NULL, NULL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Find the OGG loop point.
|
||||
loop_point = 0.0f;
|
||||
song_length = 0.0f;
|
||||
|
|
12
src/sounds.c
12
src/sounds.c
|
@ -137,7 +137,7 @@ sfxinfo_t S_sfx[NUMSFX] =
|
|||
|
||||
// Game objects, etc
|
||||
{"appear", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Appearing platform"},
|
||||
{"bkpoof", false, 70, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Armageddon explosion"},
|
||||
{"bkpoof", false, 70, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Armageddon pow"},
|
||||
{"bnce1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bounce"}, // Boing!
|
||||
{"bnce2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Scatter"}, // Boing!
|
||||
{"cannon", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Powerful shot"},
|
||||
|
@ -197,6 +197,8 @@ sfxinfo_t S_sfx[NUMSFX] =
|
|||
{"corkh", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Cork hit"},
|
||||
{"bowl", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bowling"},
|
||||
{"chuchu", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Train horn"},
|
||||
{"bsnipe", false, 200, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Home-run smash"},
|
||||
{"sprong", false, 112, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Power spring"},
|
||||
|
||||
// Menu, interface
|
||||
{"chchng", false, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Score"},
|
||||
|
@ -303,7 +305,7 @@ sfxinfo_t S_sfx[NUMSFX] =
|
|||
{"s3k3e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flame Shield"},
|
||||
{"s3k3f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bubble Shield"},
|
||||
{"s3k40", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Attraction blast"},
|
||||
{"s3k41", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Lightning Shield"},
|
||||
{"s3k41", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Thunder Shield"},
|
||||
{"s3k42", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Twinspin"},
|
||||
{"s3k43", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flame burst"},
|
||||
{"s3k44", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bubble bounce"},
|
||||
|
@ -334,7 +336,7 @@ sfxinfo_t S_sfx[NUMSFX] =
|
|||
{"s3k5d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Heavy hit"},
|
||||
{"s3k5e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Firing laser"},
|
||||
{"s3k5f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Crusher stomp"},
|
||||
{"s3k60", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flying away"},
|
||||
{"s3k60", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Accelerating"},
|
||||
{"s3k61", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Drilling"},
|
||||
{"s3k62", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Jump"},
|
||||
{"s3k63", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Starpost"},
|
||||
|
@ -430,8 +432,8 @@ sfxinfo_t S_sfx[NUMSFX] =
|
|||
{"s3kbcl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // long version of previous
|
||||
{"s3kbds", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flying fortress"},
|
||||
{"s3kbdl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flying fortress"}, // ditto
|
||||
{"s3kbes", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flying away"},
|
||||
{"s3kbel", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flying away"}, // ditto
|
||||
{"s3kbes", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flying"},
|
||||
{"s3kbel", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flying"}, // ditto
|
||||
{"s3kbfs", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Turbine"},
|
||||
{"s3kbfl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Turbine"}, // ditto
|
||||
{"s3kc0s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Turbine"},
|
||||
|
|
|
@ -263,6 +263,8 @@ typedef enum
|
|||
sfx_corkh,
|
||||
sfx_bowl,
|
||||
sfx_chuchu,
|
||||
sfx_bsnipe,
|
||||
sfx_sprong,
|
||||
|
||||
// Menu, interface
|
||||
sfx_chchng,
|
||||
|
|
111
src/st_stuff.c
111
src/st_stuff.c
|
@ -95,6 +95,7 @@ static patch_t *ringshield;
|
|||
static patch_t *watershield;
|
||||
static patch_t *bombshield;
|
||||
static patch_t *pityshield;
|
||||
static patch_t *pinkshield;
|
||||
static patch_t *flameshield;
|
||||
static patch_t *bubbleshield;
|
||||
static patch_t *thundershield;
|
||||
|
@ -109,6 +110,7 @@ static patch_t *orngstat;
|
|||
static patch_t *redstat;
|
||||
static patch_t *yelstat;
|
||||
static patch_t *nbracket;
|
||||
static patch_t *nring;
|
||||
static patch_t *nhud[12];
|
||||
static patch_t *nsshud;
|
||||
static patch_t *nbon[12];
|
||||
|
@ -225,7 +227,7 @@ void ST_doPaletteStuff(void)
|
|||
|
||||
void ST_UnloadGraphics(void)
|
||||
{
|
||||
Z_FreeTags(PU_HUDGFX, PU_HUDGFX);
|
||||
Z_FreeTag(PU_HUDGFX);
|
||||
}
|
||||
|
||||
void ST_LoadGraphics(void)
|
||||
|
@ -285,6 +287,7 @@ void ST_LoadGraphics(void)
|
|||
watershield = W_CachePatchName("TVELICON", PU_HUDGFX);
|
||||
bombshield = W_CachePatchName("TVARICON", PU_HUDGFX);
|
||||
pityshield = W_CachePatchName("TVPIICON", PU_HUDGFX);
|
||||
pinkshield = W_CachePatchName("TVPPICON", PU_HUDGFX);
|
||||
flameshield = W_CachePatchName("TVFLICON", PU_HUDGFX);
|
||||
bubbleshield = W_CachePatchName("TVBBICON", PU_HUDGFX);
|
||||
thundershield = W_CachePatchName("TVZPICON", PU_HUDGFX);
|
||||
|
@ -309,6 +312,7 @@ void ST_LoadGraphics(void)
|
|||
redstat = W_CachePatchName("REDSTAT", PU_HUDGFX);
|
||||
yelstat = W_CachePatchName("YELSTAT", PU_HUDGFX);
|
||||
nbracket = W_CachePatchName("NBRACKET", PU_HUDGFX);
|
||||
nring = W_CachePatchName("NRNG1", PU_HUDGFX);
|
||||
for (i = 0; i < 12; ++i)
|
||||
{
|
||||
nhud[i] = W_CachePatchName(va("NHUD%d", i+1), PU_HUDGFX);
|
||||
|
@ -339,10 +343,24 @@ void ST_LoadGraphics(void)
|
|||
}
|
||||
|
||||
// made separate so that skins code can reload custom face graphics
|
||||
void ST_LoadFaceGraphics(char *facestr, char *superstr, INT32 skinnum)
|
||||
void ST_LoadFaceGraphics(INT32 skinnum)
|
||||
{
|
||||
faceprefix[skinnum] = W_CachePatchName(facestr, PU_HUDGFX);
|
||||
superprefix[skinnum] = W_CachePatchName(superstr, PU_HUDGFX);
|
||||
if (skins[skinnum].sprites[SPR2_XTRA].numframes)
|
||||
{
|
||||
spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA];
|
||||
spriteframe_t *sprframe = &sprdef->spriteframes[0];
|
||||
faceprefix[skinnum] = W_CachePatchNum(sprframe->lumppat[0], PU_HUDGFX);
|
||||
if (skins[skinnum].sprites[(SPR2_XTRA|FF_SPR2SUPER)].numframes)
|
||||
{
|
||||
sprdef = &skins[skinnum].sprites[SPR2_XTRA|FF_SPR2SUPER];
|
||||
sprframe = &sprdef->spriteframes[0];
|
||||
superprefix[skinnum] = W_CachePatchNum(sprframe->lumppat[0], PU_HUDGFX);
|
||||
}
|
||||
else
|
||||
superprefix[skinnum] = faceprefix[skinnum]; // not manually freed, okay to set to same pointer
|
||||
}
|
||||
else
|
||||
faceprefix[skinnum] = superprefix[skinnum] = W_CachePatchName("MISSING", PU_HUDGFX); // ditto
|
||||
facefreed[skinnum] = false;
|
||||
}
|
||||
|
||||
|
@ -351,7 +369,7 @@ void ST_ReloadSkinFaceGraphics(void)
|
|||
INT32 i;
|
||||
|
||||
for (i = 0; i < numskins; i++)
|
||||
ST_LoadFaceGraphics(skins[i].face, skins[i].superface, i);
|
||||
ST_LoadFaceGraphics(i);
|
||||
}
|
||||
|
||||
static inline void ST_InitData(void)
|
||||
|
@ -1250,6 +1268,7 @@ static void ST_drawPowerupHUD(void)
|
|||
case SH_ARMAGEDDON: p = bombshield; break;
|
||||
case SH_ATTRACT: p = ringshield; break;
|
||||
case SH_PITY: p = pityshield; break;
|
||||
case SH_PINK: p = pinkshield; break;
|
||||
case SH_FLAMEAURA: p = flameshield; break;
|
||||
case SH_BUBBLEWRAP: p = bubbleshield; break;
|
||||
case SH_THUNDERCOIN: p = thundershield; break;
|
||||
|
@ -1542,7 +1561,7 @@ static void ST_drawNiGHTSLink(void)
|
|||
static void ST_drawNiGHTSHUD(void)
|
||||
{
|
||||
INT32 origamount;
|
||||
INT32 total_spherecount;
|
||||
INT32 total_spherecount, total_ringcount;
|
||||
const boolean oldspecialstage = (G_IsSpecialStage(gamemap) && !(maptol & TOL_NIGHTS));
|
||||
|
||||
// Drill meter
|
||||
|
@ -1614,33 +1633,28 @@ static void ST_drawNiGHTSHUD(void)
|
|||
#endif
|
||||
ST_DrawTopLeftOverlayPatch(16, 8, nbracket);
|
||||
if (G_IsSpecialStage(gamemap))
|
||||
#ifdef MANIASPHERES
|
||||
ST_DrawTopLeftOverlayPatch(24, 16, (
|
||||
(stplyr->bonustime && (leveltime & 4)) ? nssbon : nsshud));
|
||||
#else
|
||||
ST_DrawTopLeftOverlayPatch(24, 16, (nsshud));
|
||||
#endif
|
||||
(stplyr->bonustime && (leveltime & 4) && (states[S_BLUESPHEREBONUS].frame & FF_ANIMATE)) ? nssbon : nsshud));
|
||||
else
|
||||
ST_DrawTopLeftOverlayPatch(24, 16, *(((stplyr->bonustime) ? nbon : nhud)+((leveltime/2)%12)));
|
||||
|
||||
if (G_IsSpecialStage(gamemap))
|
||||
{
|
||||
INT32 i;
|
||||
total_spherecount = 0;
|
||||
total_spherecount = total_ringcount = 0;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
if (playeringame[i] /*&& players[i].powers[pw_carry] == CR_NIGHTSMODE*/ && players[i].spheres)
|
||||
total_spherecount += players[i].spheres;
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
total_spherecount += players[i].spheres;
|
||||
total_ringcount += players[i].rings;
|
||||
}
|
||||
}
|
||||
else
|
||||
total_spherecount = stplyr->spheres;
|
||||
|
||||
/*if (oldspecialstage)
|
||||
{
|
||||
if (total_spherecount < ssspheres)
|
||||
total_spherecount = ssspheres - total_spherecount;
|
||||
else
|
||||
total_spherecount = 0;
|
||||
}*/
|
||||
total_spherecount = stplyr->spheres;
|
||||
total_ringcount = stplyr->spheres;
|
||||
}
|
||||
|
||||
if (stplyr->capsule)
|
||||
{
|
||||
|
@ -1728,6 +1742,27 @@ static void ST_drawNiGHTSHUD(void)
|
|||
else
|
||||
ST_DrawTopLeftOverlayPatch(40, 8 + 5, narrow[8]);
|
||||
|
||||
if (oldspecialstage)
|
||||
{
|
||||
// invert for s3k style junk
|
||||
total_spherecount = ssspheres - total_spherecount;
|
||||
if (total_spherecount < 0)
|
||||
total_spherecount = 0;
|
||||
|
||||
if (nummaprings > 0) // don't count down if there ISN'T a valid maximum number of rings, like sonic 3
|
||||
{
|
||||
total_ringcount = nummaprings - total_ringcount;
|
||||
if (total_ringcount < 0)
|
||||
total_ringcount = 0;
|
||||
}
|
||||
|
||||
// now rings! you know, for that perfect bonus.
|
||||
V_DrawScaledPatch(272, 8, V_PERPLAYER|V_SNAPTOTOP|V_SNAPTORIGHT|V_HUDTRANS, nbracket);
|
||||
V_DrawScaledPatch(280, 16+1, V_PERPLAYER|V_SNAPTOTOP|V_SNAPTORIGHT|V_HUDTRANS, nring);
|
||||
V_DrawScaledPatch(280, 8+5, V_FLIP|V_PERPLAYER|V_SNAPTOTOP|V_SNAPTORIGHT|V_HUDTRANS, narrow[8]);
|
||||
V_DrawTallNum(272, 8 + 11, V_PERPLAYER|V_SNAPTOTOP|V_SNAPTORIGHT|V_HUDTRANS, total_ringcount);
|
||||
}
|
||||
|
||||
if (total_spherecount >= 100)
|
||||
V_DrawTallNum((total_spherecount >= 1000) ? 76 : 72, 8 + 11, V_PERPLAYER|V_SNAPTOTOP|V_SNAPTOLEFT|V_HUDTRANS, total_spherecount);
|
||||
else
|
||||
|
@ -2303,31 +2338,33 @@ static void ST_doItemFinderIconsAndSound(void)
|
|||
return;
|
||||
|
||||
// Scan thinkers to find emblem mobj with these ids
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
||||
if (mo2->type == MT_EMBLEM)
|
||||
if (mo2->type != MT_EMBLEM)
|
||||
continue;
|
||||
|
||||
if (!(mo2->flags & MF_SPECIAL))
|
||||
continue;
|
||||
|
||||
for (i = 0; i < stemblems; ++i)
|
||||
{
|
||||
if (!(mo2->flags & MF_SPECIAL))
|
||||
continue;
|
||||
|
||||
for (i = 0; i < stemblems; ++i)
|
||||
if (mo2->health == emblems[i] + 1)
|
||||
{
|
||||
if (mo2->health == emblems[i]+1)
|
||||
{
|
||||
soffset = (i * 20) - ((stemblems-1) * 10);
|
||||
soffset = (i * 20) - ((stemblems - 1) * 10);
|
||||
|
||||
newinterval = ST_drawEmeraldHuntIcon(mo2, itemhoming, soffset);
|
||||
if (newinterval && (!interval || newinterval < interval))
|
||||
interval = newinterval;
|
||||
newinterval = ST_drawEmeraldHuntIcon(mo2, itemhoming, soffset);
|
||||
if (newinterval && (!interval || newinterval < interval))
|
||||
interval = newinterval;
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!(P_AutoPause() || paused) && interval > 0 && leveltime && leveltime % interval == 0)
|
||||
|
|
|
@ -42,7 +42,7 @@ void ST_UnloadGraphics(void);
|
|||
void ST_LoadGraphics(void);
|
||||
|
||||
// face load graphics, called when skin changes
|
||||
void ST_LoadFaceGraphics(char *facestr, char *superstr, INT32 playernum);
|
||||
void ST_LoadFaceGraphics(INT32 playernum);
|
||||
void ST_ReloadSkinFaceGraphics(void);
|
||||
|
||||
void ST_doPaletteStuff(void);
|
||||
|
|
341
src/v_video.c
341
src/v_video.c
|
@ -309,12 +309,14 @@ static boolean InitCube(void)
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifdef BACKWARDSCOMPATCORRECTION
|
||||
/*
|
||||
So it turns out that the way gamma was implemented previously, the default
|
||||
colour profile of the game was messed up. Since this bad decision has been
|
||||
around for a long time, and the intent is to keep the base game looking the
|
||||
same, I'm not gonna be the one to remove this base modification.
|
||||
toast 20/04/17
|
||||
... welp yes i am (27/07/19, see the ifdef around it)
|
||||
*/
|
||||
const UINT8 correctiontable[256] =
|
||||
{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,
|
||||
|
@ -333,6 +335,7 @@ const UINT8 correctiontable[256] =
|
|||
208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
|
||||
224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
|
||||
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255};
|
||||
#endif
|
||||
|
||||
// keep a copy of the palette so that we can get the RGB value for a color index at any time.
|
||||
static void LoadPalette(const char *lumpname)
|
||||
|
@ -351,12 +354,18 @@ static void LoadPalette(const char *lumpname)
|
|||
pal = W_CacheLumpNum(lumpnum, PU_CACHE);
|
||||
for (i = 0; i < palsize; i++)
|
||||
{
|
||||
#ifdef BACKWARDSCOMPATCORRECTION
|
||||
pMasterPalette[i].s.red = pLocalPalette[i].s.red = correctiontable[*pal++];
|
||||
pMasterPalette[i].s.green = pLocalPalette[i].s.green = correctiontable[*pal++];
|
||||
pMasterPalette[i].s.blue = pLocalPalette[i].s.blue = correctiontable[*pal++];
|
||||
#else
|
||||
pMasterPalette[i].s.red = pLocalPalette[i].s.red = *pal++;
|
||||
pMasterPalette[i].s.green = pLocalPalette[i].s.green = *pal++;
|
||||
pMasterPalette[i].s.blue = pLocalPalette[i].s.blue = *pal++;
|
||||
#endif
|
||||
pMasterPalette[i].s.alpha = pLocalPalette[i].s.alpha = 0xFF;
|
||||
|
||||
// lerp of colour cubing!
|
||||
// lerp of colour cubing! if you want, make it smoother yourself
|
||||
if (cube)
|
||||
{
|
||||
float working[4][3];
|
||||
|
@ -732,12 +741,15 @@ void V_DrawFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t
|
|||
// Center it if necessary
|
||||
if (!(scrn & V_SCALEPATCHMASK))
|
||||
{
|
||||
// if it's meant to cover the whole screen, black out the rest
|
||||
// if it's meant to cover the whole screen, black out the rest (ONLY IF TOP LEFT ISN'T TRANSPARENT)
|
||||
if (x == 0 && SHORT(patch->width) == BASEVIDWIDTH && y == 0 && SHORT(patch->height) == BASEVIDHEIGHT)
|
||||
{
|
||||
column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[0]));
|
||||
source = (const UINT8 *)(column) + 3;
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0]));
|
||||
if (!column->topdelta)
|
||||
{
|
||||
source = (const UINT8 *)(column) + 3;
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, source[0]);
|
||||
}
|
||||
}
|
||||
|
||||
if (vid.width != BASEVIDWIDTH * dupx)
|
||||
|
@ -984,12 +996,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_
|
|||
if (!(scrn & V_SCALEPATCHMASK))
|
||||
{
|
||||
// if it's meant to cover the whole screen, black out the rest
|
||||
if (x == 0 && SHORT(patch->width) == BASEVIDWIDTH && y == 0 && SHORT(patch->height) == BASEVIDHEIGHT)
|
||||
{
|
||||
column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[0]));
|
||||
source = (const UINT8 *)(column) + 3;
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0]));
|
||||
}
|
||||
// no the patch is cropped do not do this ever
|
||||
|
||||
if (vid.width != BASEVIDWIDTH * dupx)
|
||||
{
|
||||
|
@ -1349,13 +1356,16 @@ static UINT32 V_GetHWConsBackColor(void)
|
|||
|
||||
|
||||
// THANK YOU MPC!!!
|
||||
// and thanks toaster for cleaning it up.
|
||||
|
||||
void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
|
||||
{
|
||||
UINT8 *dest;
|
||||
INT32 u, v;
|
||||
const UINT8 *deststop;
|
||||
INT32 u;
|
||||
UINT8 *fadetable;
|
||||
UINT32 alphalevel = 0;
|
||||
UINT8 perplayershuffle = 0;
|
||||
|
||||
if (rendermode == render_none)
|
||||
return;
|
||||
|
@ -1369,16 +1379,91 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
|
|||
}
|
||||
#endif
|
||||
|
||||
if ((alphalevel = ((c & V_ALPHAMASK) >> V_ALPHASHIFT)))
|
||||
{
|
||||
if (alphalevel == 13)
|
||||
alphalevel = hudminusalpha[cv_translucenthud.value];
|
||||
else if (alphalevel == 14)
|
||||
alphalevel = 10 - cv_translucenthud.value;
|
||||
else if (alphalevel == 15)
|
||||
alphalevel = hudplusalpha[cv_translucenthud.value];
|
||||
|
||||
if (alphalevel >= 10)
|
||||
return; // invis
|
||||
}
|
||||
|
||||
if (splitscreen && (c & V_PERPLAYER))
|
||||
{
|
||||
fixed_t adjusty = ((c & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)>>1;
|
||||
h >>= 1;
|
||||
y >>= 1;
|
||||
#ifdef QUADS
|
||||
if (splitscreen > 1) // 3 or 4 players
|
||||
{
|
||||
fixed_t adjustx = ((c & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)>>1;
|
||||
w >>= 1;
|
||||
x >>= 1;
|
||||
if (stplyr == &players[displayplayer])
|
||||
{
|
||||
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 1;
|
||||
if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
||||
perplayershuffle |= 4;
|
||||
c &= ~V_SNAPTOBOTTOM|V_SNAPTORIGHT;
|
||||
}
|
||||
else if (stplyr == &players[secondarydisplayplayer])
|
||||
{
|
||||
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 1;
|
||||
if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
||||
perplayershuffle |= 8;
|
||||
x += adjustx;
|
||||
c &= ~V_SNAPTOBOTTOM|V_SNAPTOLEFT;
|
||||
}
|
||||
else if (stplyr == &players[thirddisplayplayer])
|
||||
{
|
||||
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 2;
|
||||
if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
||||
perplayershuffle |= 4;
|
||||
y += adjusty;
|
||||
c &= ~V_SNAPTOTOP|V_SNAPTORIGHT;
|
||||
}
|
||||
else //if (stplyr == &players[fourthdisplayplayer])
|
||||
{
|
||||
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 2;
|
||||
if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
||||
perplayershuffle |= 8;
|
||||
x += adjustx;
|
||||
y += adjusty;
|
||||
c &= ~V_SNAPTOTOP|V_SNAPTOLEFT;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
// 2 players
|
||||
{
|
||||
if (stplyr == &players[displayplayer])
|
||||
{
|
||||
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 1;
|
||||
c &= ~V_SNAPTOBOTTOM;
|
||||
}
|
||||
else //if (stplyr == &players[secondarydisplayplayer])
|
||||
{
|
||||
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 2;
|
||||
y += adjusty;
|
||||
c &= ~V_SNAPTOTOP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(c & V_NOSCALESTART))
|
||||
{
|
||||
INT32 dupx = vid.dupx, dupy = vid.dupy;
|
||||
|
||||
if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT)
|
||||
{ // Clear the entire screen, from dest to deststop. Yes, this really works.
|
||||
memset(screens[0], (UINT8)(c&255), vid.width * vid.height * vid.bpp);
|
||||
return;
|
||||
}
|
||||
|
||||
x *= dupx;
|
||||
y *= dupy;
|
||||
w *= dupx;
|
||||
|
@ -1393,6 +1478,10 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
|
|||
x += (vid.width - (BASEVIDWIDTH * dupx));
|
||||
else if (!(c & V_SNAPTOLEFT))
|
||||
x += (vid.width - (BASEVIDWIDTH * dupx)) / 2;
|
||||
if (perplayershuffle & 4)
|
||||
x -= (vid.width - (BASEVIDWIDTH * dupx)) / 4;
|
||||
else if (perplayershuffle & 8)
|
||||
x += (vid.width - (BASEVIDWIDTH * dupx)) / 4;
|
||||
}
|
||||
if (vid.height != BASEVIDHEIGHT * dupy)
|
||||
{
|
||||
|
@ -1401,6 +1490,10 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
|
|||
y += (vid.height - (BASEVIDHEIGHT * dupy));
|
||||
else if (!(c & V_SNAPTOTOP))
|
||||
y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2;
|
||||
if (perplayershuffle & 1)
|
||||
y -= (vid.height - (BASEVIDHEIGHT * dupy)) / 4;
|
||||
else if (perplayershuffle & 2)
|
||||
y += (vid.height - (BASEVIDHEIGHT * dupy)) / 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1423,34 +1516,206 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
|
|||
h = vid.height-y;
|
||||
|
||||
dest = screens[0] + y*vid.width + x;
|
||||
|
||||
if ((alphalevel = ((c & V_ALPHAMASK) >> V_ALPHASHIFT)))
|
||||
{
|
||||
if (alphalevel == 13)
|
||||
alphalevel = hudminusalpha[cv_translucenthud.value];
|
||||
else if (alphalevel == 14)
|
||||
alphalevel = 10 - cv_translucenthud.value;
|
||||
else if (alphalevel == 15)
|
||||
alphalevel = hudplusalpha[cv_translucenthud.value];
|
||||
|
||||
if (alphalevel >= 10)
|
||||
return; // invis
|
||||
}
|
||||
deststop = screens[0] + vid.rowbytes * vid.height;
|
||||
|
||||
c &= 255;
|
||||
|
||||
// Jimita (12-04-2018)
|
||||
w = min(w, vid.width);
|
||||
h = min(h, vid.height);
|
||||
fadetable = ((UINT8 *)transtables + ((alphalevel-1)<<FF_TRANSSHIFT) + (c*256));
|
||||
for (v = 0; v < h; v++, dest += vid.width)
|
||||
for (u = 0; u < w; u++)
|
||||
if (alphalevel)
|
||||
{
|
||||
fadetable = ((UINT8 *)transtables + ((alphalevel-1)<<FF_TRANSSHIFT) + (c*256));
|
||||
for (;(--h >= 0) && dest < deststop; dest += vid.width)
|
||||
{
|
||||
if (!alphalevel)
|
||||
dest[u] = consolebgmap[dest[u]];
|
||||
else
|
||||
u = 0;
|
||||
while (u < w)
|
||||
{
|
||||
dest[u] = fadetable[consolebgmap[dest[u]]];
|
||||
u++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (;(--h >= 0) && dest < deststop; dest += vid.width)
|
||||
{
|
||||
u = 0;
|
||||
while (u < w)
|
||||
{
|
||||
dest[u] = consolebgmap[dest[u]];
|
||||
u++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// If color is 0x00 to 0xFF, draw transtable (strength range 0-9).
|
||||
// Else, use COLORMAP lump (strength range 0-31).
|
||||
// c is not color, it is for flags only. transparency flags will be ignored.
|
||||
// IF YOU ARE NOT CAREFUL, THIS CAN AND WILL CRASH!
|
||||
// I have kept the safety checks for strength out of this function;
|
||||
// I don't trust Lua users with it, so it doesn't matter.
|
||||
//
|
||||
void V_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c, UINT16 color, UINT8 strength)
|
||||
{
|
||||
UINT8 *dest;
|
||||
const UINT8 *deststop;
|
||||
INT32 u;
|
||||
UINT8 *fadetable;
|
||||
UINT8 perplayershuffle = 0;
|
||||
|
||||
if (rendermode == render_none)
|
||||
return;
|
||||
|
||||
#ifdef HWRENDER
|
||||
if (rendermode != render_soft && rendermode != render_none)
|
||||
{
|
||||
// ughhhhh please can someone else do this? thanks ~toast 25/7/19 in 38 degrees centigrade w/o AC
|
||||
HWR_DrawFadeFill(x, y, w, h, c, color, strength); // toast two days later - left above comment in 'cause it's funny
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (splitscreen && (c & V_PERPLAYER))
|
||||
{
|
||||
fixed_t adjusty = ((c & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)>>1;
|
||||
h >>= 1;
|
||||
y >>= 1;
|
||||
#ifdef QUADS
|
||||
if (splitscreen > 1) // 3 or 4 players
|
||||
{
|
||||
fixed_t adjustx = ((c & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)>>1;
|
||||
w >>= 1;
|
||||
x >>= 1;
|
||||
if (stplyr == &players[displayplayer])
|
||||
{
|
||||
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 1;
|
||||
if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
||||
perplayershuffle |= 4;
|
||||
c &= ~V_SNAPTOBOTTOM|V_SNAPTORIGHT;
|
||||
}
|
||||
else if (stplyr == &players[secondarydisplayplayer])
|
||||
{
|
||||
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 1;
|
||||
if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
||||
perplayershuffle |= 8;
|
||||
x += adjustx;
|
||||
c &= ~V_SNAPTOBOTTOM|V_SNAPTOLEFT;
|
||||
}
|
||||
else if (stplyr == &players[thirddisplayplayer])
|
||||
{
|
||||
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 2;
|
||||
if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
||||
perplayershuffle |= 4;
|
||||
y += adjusty;
|
||||
c &= ~V_SNAPTOTOP|V_SNAPTORIGHT;
|
||||
}
|
||||
else //if (stplyr == &players[fourthdisplayplayer])
|
||||
{
|
||||
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 2;
|
||||
if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT)))
|
||||
perplayershuffle |= 8;
|
||||
x += adjustx;
|
||||
y += adjusty;
|
||||
c &= ~V_SNAPTOTOP|V_SNAPTOLEFT;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
// 2 players
|
||||
{
|
||||
if (stplyr == &players[displayplayer])
|
||||
{
|
||||
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 1;
|
||||
c &= ~V_SNAPTOBOTTOM;
|
||||
}
|
||||
else //if (stplyr == &players[secondarydisplayplayer])
|
||||
{
|
||||
if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM)))
|
||||
perplayershuffle |= 2;
|
||||
y += adjusty;
|
||||
c &= ~V_SNAPTOTOP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(c & V_NOSCALESTART))
|
||||
{
|
||||
INT32 dupx = vid.dupx, dupy = vid.dupy;
|
||||
|
||||
x *= dupx;
|
||||
y *= dupy;
|
||||
w *= dupx;
|
||||
h *= dupy;
|
||||
|
||||
// Center it if necessary
|
||||
if (vid.width != BASEVIDWIDTH * dupx)
|
||||
{
|
||||
// dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx,
|
||||
// so center this imaginary screen
|
||||
if (c & V_SNAPTORIGHT)
|
||||
x += (vid.width - (BASEVIDWIDTH * dupx));
|
||||
else if (!(c & V_SNAPTOLEFT))
|
||||
x += (vid.width - (BASEVIDWIDTH * dupx)) / 2;
|
||||
if (perplayershuffle & 4)
|
||||
x -= (vid.width - (BASEVIDWIDTH * dupx)) / 4;
|
||||
else if (perplayershuffle & 8)
|
||||
x += (vid.width - (BASEVIDWIDTH * dupx)) / 4;
|
||||
}
|
||||
if (vid.height != BASEVIDHEIGHT * dupy)
|
||||
{
|
||||
// same thing here
|
||||
if (c & V_SNAPTOBOTTOM)
|
||||
y += (vid.height - (BASEVIDHEIGHT * dupy));
|
||||
else if (!(c & V_SNAPTOTOP))
|
||||
y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2;
|
||||
if (perplayershuffle & 1)
|
||||
y -= (vid.height - (BASEVIDHEIGHT * dupy)) / 4;
|
||||
else if (perplayershuffle & 2)
|
||||
y += (vid.height - (BASEVIDHEIGHT * dupy)) / 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (x >= vid.width || y >= vid.height)
|
||||
return; // off the screen
|
||||
if (x < 0) {
|
||||
w += x;
|
||||
x = 0;
|
||||
}
|
||||
if (y < 0) {
|
||||
h += y;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
if (w <= 0 || h <= 0)
|
||||
return; // zero width/height wouldn't draw anything
|
||||
if (x + w > vid.width)
|
||||
w = vid.width-x;
|
||||
if (y + h > vid.height)
|
||||
h = vid.height-y;
|
||||
|
||||
dest = screens[0] + y*vid.width + x;
|
||||
deststop = screens[0] + vid.rowbytes * vid.height;
|
||||
|
||||
c &= 255;
|
||||
|
||||
fadetable = ((color & 0xFF00) // Color is not palette index?
|
||||
? ((UINT8 *)colormaps + strength*256) // Do COLORMAP fade.
|
||||
: ((UINT8 *)transtables + ((9-strength)<<FF_TRANSSHIFT) + color*256)); // Else, do TRANSMAP** fade.
|
||||
for (;(--h >= 0) && dest < deststop; dest += vid.width)
|
||||
{
|
||||
u = 0;
|
||||
while (u < w)
|
||||
{
|
||||
dest[u] = fadetable[dest[u]];
|
||||
u++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -158,6 +158,8 @@ void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum);
|
|||
|
||||
// fade down the screen buffer before drawing the menu over
|
||||
void V_DrawFadeScreen(UINT16 color, UINT8 strength);
|
||||
// available to lua over my dead body, which will probably happen in this heat
|
||||
void V_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c, UINT16 color, UINT8 strength);
|
||||
|
||||
void V_DrawFadeConsBack(INT32 plines);
|
||||
void V_DrawPromptBack(INT32 boxheight, INT32 color);
|
||||
|
|
28
src/w_wad.c
28
src/w_wad.c
|
@ -162,9 +162,15 @@ FILE *W_OpenWadFile(const char **filename, boolean useerrors)
|
|||
{
|
||||
FILE *handle;
|
||||
|
||||
strncpy(filenamebuf, *filename, MAX_WADPATH);
|
||||
filenamebuf[MAX_WADPATH - 1] = '\0';
|
||||
*filename = filenamebuf;
|
||||
// Officially, strncpy should not have overlapping buffers, since W_VerifyNMUSlumps is called after this, and it
|
||||
// changes filename to point at filenamebuf, it would technically be doing that. I doubt any issue will occur since
|
||||
// they point to the same location, but it's better to be safe and this is a simple change.
|
||||
if (filenamebuf != *filename)
|
||||
{
|
||||
strncpy(filenamebuf, *filename, MAX_WADPATH);
|
||||
filenamebuf[MAX_WADPATH - 1] = '\0';
|
||||
*filename = filenamebuf;
|
||||
}
|
||||
|
||||
// open wad file
|
||||
if ((handle = fopen(*filename, "rb")) == NULL)
|
||||
|
@ -1133,6 +1139,22 @@ boolean W_IsLumpWad(lumpnum_t lumpnum)
|
|||
return false; // WADs should never be inside non-PK3s as far as SRB2 is concerned
|
||||
}
|
||||
|
||||
//
|
||||
// W_IsLumpFolder
|
||||
// Is the lump a folder? (in a PK3 obviously)
|
||||
//
|
||||
boolean W_IsLumpFolder(UINT16 wad, UINT16 lump)
|
||||
{
|
||||
if (wadfiles[wad]->type == RET_PK3)
|
||||
{
|
||||
const char *name = wadfiles[wad]->lumpinfo[lump].name2;
|
||||
|
||||
return (name[strlen(name)-1] == '/'); // folders end in '/'
|
||||
}
|
||||
|
||||
return false; // non-PK3s don't have folders
|
||||
}
|
||||
|
||||
#ifdef HAVE_ZLIB
|
||||
/* report a zlib or i/o error */
|
||||
void zerr(int ret)
|
||||
|
|
|
@ -151,6 +151,7 @@ size_t W_LumpLengthPwad(UINT16 wad, UINT16 lump);
|
|||
size_t W_LumpLength(lumpnum_t lumpnum);
|
||||
|
||||
boolean W_IsLumpWad(lumpnum_t lumpnum); // for loading maps from WADs in PK3s
|
||||
boolean W_IsLumpFolder(UINT16 wad, UINT16 lump); // for detecting folder "lumps"
|
||||
|
||||
#ifdef HAVE_ZLIB
|
||||
void zerr(int ret); // zlib error checking
|
||||
|
|
|
@ -293,6 +293,7 @@
|
|||
</ClCompile>
|
||||
<ClCompile Include="..\r_main.c" />
|
||||
<ClCompile Include="..\r_plane.c" />
|
||||
<ClCompile Include="..\r_portal.c" />
|
||||
<ClCompile Include="..\r_segs.c" />
|
||||
<ClCompile Include="..\r_sky.c" />
|
||||
<ClCompile Include="..\r_splats.c" />
|
||||
|
@ -443,6 +444,7 @@
|
|||
<ClInclude Include="..\r_local.h" />
|
||||
<ClInclude Include="..\r_main.h" />
|
||||
<ClInclude Include="..\r_plane.h" />
|
||||
<ClInclude Include="..\r_portal.h" />
|
||||
<ClInclude Include="..\r_segs.h" />
|
||||
<ClInclude Include="..\r_sky.h" />
|
||||
<ClInclude Include="..\r_splats.h" />
|
||||
|
|
|
@ -456,6 +456,10 @@
|
|||
<ClCompile Include="..\hardware\hw_clip.c">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\apng.c" />
|
||||
<ClCompile Include="..\r_portal.c">
|
||||
<Filter>R_Rend</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="afxres.h">
|
||||
|
@ -857,6 +861,10 @@
|
|||
<ClInclude Include="..\hardware\hw_clip.h">
|
||||
<Filter>Hw_Hardware</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\apng.h" />
|
||||
<ClInclude Include="..\r_portal.h">
|
||||
<Filter>R_Rend</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="Srb2win.ico">
|
||||
|
|
151
src/y_inter.c
151
src/y_inter.c
|
@ -86,8 +86,8 @@ typedef union
|
|||
INT32 passedx3;
|
||||
INT32 passedx4;
|
||||
|
||||
y_bonus_t bonus;
|
||||
patch_t *bonuspatch;
|
||||
y_bonus_t bonuses[2];
|
||||
patch_t *bonuspatches[2];
|
||||
|
||||
patch_t *pscore; // SCORE
|
||||
UINT32 score; // fake score
|
||||
|
@ -326,34 +326,36 @@ void Y_IntermissionDrawer(void)
|
|||
// draw the header
|
||||
if (intertic <= 2*TICRATE)
|
||||
animatetic = 0;
|
||||
else if (!animatetic && data.spec.bonus.points == 0 && data.spec.passed3[0] != '\0')
|
||||
else if (!animatetic && data.spec.bonuses[0].points == 0 && data.spec.bonuses[1].points == 0 && data.spec.passed3[0] != '\0')
|
||||
animatetic = intertic + TICRATE;
|
||||
|
||||
if (animatetic && (tic_t)intertic >= animatetic)
|
||||
{
|
||||
const INT32 scradjust = (vid.width/vid.dupx)>>3; // 40 for BASEVIDWIDTH
|
||||
INT32 animatetimer = (intertic - animatetic);
|
||||
if (animatetimer <= 14)
|
||||
if (animatetimer <= 16)
|
||||
{
|
||||
xoffset1 = -(animatetimer * scradjust);
|
||||
xoffset2 = -((animatetimer-2) * scradjust);
|
||||
xoffset3 = -((animatetimer-4) * scradjust);
|
||||
xoffset4 = -((animatetimer-6) * scradjust);
|
||||
xoffset5 = -((animatetimer-8) * scradjust);
|
||||
xoffset1 = -(animatetimer * scradjust);
|
||||
xoffset2 = -((animatetimer- 2) * scradjust);
|
||||
xoffset3 = -((animatetimer- 4) * scradjust);
|
||||
xoffset4 = -((animatetimer- 6) * scradjust);
|
||||
xoffset5 = -((animatetimer- 8) * scradjust);
|
||||
xoffset6 = -((animatetimer-10) * scradjust);
|
||||
if (xoffset2 > 0) xoffset2 = 0;
|
||||
if (xoffset3 > 0) xoffset3 = 0;
|
||||
if (xoffset4 > 0) xoffset4 = 0;
|
||||
if (xoffset5 > 0) xoffset5 = 0;
|
||||
if (xoffset6 > 0) xoffset6 = 0;
|
||||
}
|
||||
else if (animatetimer < 32)
|
||||
else if (animatetimer < 34)
|
||||
{
|
||||
drawsection = 1;
|
||||
xoffset1 = (22-animatetimer) * scradjust;
|
||||
xoffset2 = (24-animatetimer) * scradjust;
|
||||
xoffset3 = (26-animatetimer) * scradjust;
|
||||
xoffset4 = (28-animatetimer) * scradjust;
|
||||
xoffset5 = (30-animatetimer) * scradjust;
|
||||
xoffset6 = (32-animatetimer) * scradjust;
|
||||
xoffset1 = (24-animatetimer) * scradjust;
|
||||
xoffset2 = (26-animatetimer) * scradjust;
|
||||
xoffset3 = (28-animatetimer) * scradjust;
|
||||
xoffset4 = (30-animatetimer) * scradjust;
|
||||
xoffset5 = (32-animatetimer) * scradjust;
|
||||
xoffset6 = (34-animatetimer) * scradjust;
|
||||
if (xoffset1 < 0) xoffset1 = 0;
|
||||
if (xoffset2 < 0) xoffset2 = 0;
|
||||
if (xoffset3 < 0) xoffset3 = 0;
|
||||
|
@ -370,9 +372,9 @@ void Y_IntermissionDrawer(void)
|
|||
|
||||
if (drawsection == 1)
|
||||
{
|
||||
const char *ringtext = "\x86" "50 RINGS, NO SHIELD";
|
||||
const char *tut1text = "\x86" "PRESS " "\x82" "SPIN";
|
||||
const char *tut2text = "\x86" "MID-" "\x82" "JUMP";
|
||||
const char *ringtext = "\x82" "50 RINGS, NO SHIELD";
|
||||
const char *tut1text = "\x82" "PRESS " "\x80" "SPIN";
|
||||
const char *tut2text = "\x82" "MID-" "\x80" "JUMP";
|
||||
ttheight = 16;
|
||||
V_DrawLevelTitle(data.spec.passedx1 + xoffset1, ttheight, 0, data.spec.passed1);
|
||||
ttheight += V_LevelNameHeight(data.spec.passed3) + 2;
|
||||
|
@ -389,6 +391,7 @@ void Y_IntermissionDrawer(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
INT32 yoffset = 0;
|
||||
if (data.spec.passed1[0] != '\0')
|
||||
{
|
||||
ttheight = 24;
|
||||
|
@ -402,22 +405,31 @@ void Y_IntermissionDrawer(void)
|
|||
V_DrawLevelTitle(data.spec.passedx2 + xoffset1, ttheight, 0, data.spec.passed2);
|
||||
}
|
||||
|
||||
V_DrawScaledPatch(152 + xoffset3, 108, 0, data.spec.bonuspatch);
|
||||
V_DrawTallNum(BASEVIDWIDTH + xoffset3 - 68, 109, 0, data.spec.bonus.points);
|
||||
V_DrawScaledPatch(152 + xoffset4, 124, 0, data.spec.pscore);
|
||||
V_DrawTallNum(BASEVIDWIDTH + xoffset4 - 68, 125, 0, data.spec.score);
|
||||
V_DrawScaledPatch(152 + xoffset3, 108, 0, data.spec.bonuspatches[0]);
|
||||
V_DrawTallNum(BASEVIDWIDTH + xoffset3 - 68, 109, 0, data.spec.bonuses[0].points);
|
||||
if (data.spec.bonuses[1].display)
|
||||
{
|
||||
V_DrawScaledPatch(152 + xoffset4, 124, 0, data.spec.bonuspatches[1]);
|
||||
V_DrawTallNum(BASEVIDWIDTH + xoffset4 - 68, 125, 0, data.spec.bonuses[1].points);
|
||||
yoffset = 16;
|
||||
// hack; pass the buck along...
|
||||
xoffset4 = xoffset5;
|
||||
xoffset5 = xoffset6;
|
||||
}
|
||||
V_DrawScaledPatch(152 + xoffset4, 124+yoffset, 0, data.spec.pscore);
|
||||
V_DrawTallNum(BASEVIDWIDTH + xoffset4 - 68, 125+yoffset, 0, data.spec.score);
|
||||
|
||||
// Draw continues!
|
||||
if (!multiplayer /* && (data.spec.continues & 0x80) */) // Always draw outside of netplay
|
||||
{
|
||||
UINT8 continues = data.spec.continues & 0x7F;
|
||||
|
||||
V_DrawScaledPatch(152 + xoffset5, 150, 0, data.spec.pcontinues);
|
||||
V_DrawScaledPatch(152 + xoffset5, 150+yoffset, 0, data.spec.pcontinues);
|
||||
for (i = 0; i < continues; ++i)
|
||||
{
|
||||
if ((data.spec.continues & 0x80) && i == continues-1 && (endtic < 0 || intertic%20 < 10))
|
||||
break;
|
||||
V_DrawContinueIcon(246 + xoffset5 - (i*12), 162, 0, *data.spec.playerchar, *data.spec.playercolor);
|
||||
V_DrawContinueIcon(246 + xoffset5 - (i*12), 162+yoffset, 0, *data.spec.playerchar, *data.spec.playercolor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -904,7 +916,7 @@ void Y_Ticker(void)
|
|||
{
|
||||
INT32 i;
|
||||
UINT32 oldscore = data.spec.score;
|
||||
boolean skip = false, super = false;
|
||||
boolean skip = false, super = false, anybonuses = false;
|
||||
|
||||
if (!intertic) // first time only
|
||||
{
|
||||
|
@ -946,16 +958,26 @@ void Y_Ticker(void)
|
|||
return;
|
||||
}
|
||||
|
||||
// ring bonus counts down by 222 each tic
|
||||
data.spec.bonus.points -= 222;
|
||||
data.spec.score += 222;
|
||||
if (data.spec.bonus.points < 0 || skip == true) // went too far
|
||||
// bonuses count down by 222 each tic
|
||||
for (i = 0; i < 2; ++i)
|
||||
{
|
||||
data.spec.score += data.spec.bonus.points;
|
||||
data.spec.bonus.points = 0;
|
||||
if (!data.spec.bonuses[i].points)
|
||||
continue;
|
||||
|
||||
data.spec.bonuses[i].points -= 222;
|
||||
data.spec.score += 222;
|
||||
if (data.spec.bonuses[i].points < 0 || skip == true) // too far?
|
||||
{
|
||||
data.spec.score += data.spec.bonuses[i].points;
|
||||
data.spec.bonuses[i].points = 0;
|
||||
}
|
||||
if (data.spec.score > MAXSCORE)
|
||||
data.spec.score = MAXSCORE;
|
||||
if (data.spec.bonuses[i].points > 0)
|
||||
anybonuses = true;
|
||||
}
|
||||
|
||||
if (!data.spec.bonus.points)
|
||||
if (!anybonuses)
|
||||
{
|
||||
tallydonetic = intertic;
|
||||
if (!((data.spec.continues & 0x80) || (super && ALL7EMERALDS(emeralds)))) // don't set endtic yet!
|
||||
|
@ -1301,7 +1323,9 @@ void Y_StartIntermission(void)
|
|||
// give out ring bonuses
|
||||
Y_AwardSpecialStageBonus();
|
||||
|
||||
data.spec.bonuspatch = W_CachePatchName(data.spec.bonus.patch, PU_STATIC);
|
||||
for (i = 0; i < 2; ++i)
|
||||
data.spec.bonuspatches[i] = W_CachePatchName(data.spec.bonuses[i].patch, PU_STATIC);
|
||||
|
||||
data.spec.pscore = W_CachePatchName("YB_SCORE", PU_STATIC);
|
||||
data.spec.pcontinues = W_CachePatchName("YB_CONTI", PU_STATIC);
|
||||
|
||||
|
@ -1831,7 +1855,7 @@ static void Y_SetPerfectBonus(player_t *player, y_bonus_t *bstruct)
|
|||
memset(bstruct, 0, sizeof(y_bonus_t));
|
||||
strncpy(bstruct->patch, "YB_PERFE", sizeof(bstruct->patch));
|
||||
|
||||
if (data.coop.gotperfbonus == -1)
|
||||
if (intertype != int_coop || data.coop.gotperfbonus == -1)
|
||||
{
|
||||
INT32 sharedringtotal = 0;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
@ -1840,15 +1864,33 @@ static void Y_SetPerfectBonus(player_t *player, y_bonus_t *bstruct)
|
|||
sharedringtotal += players[i].rings;
|
||||
}
|
||||
if (!sharedringtotal || nummaprings == -1 || sharedringtotal < nummaprings)
|
||||
data.coop.gotperfbonus = 0;
|
||||
bstruct->display = false;
|
||||
else
|
||||
data.coop.gotperfbonus = 1;
|
||||
{
|
||||
bstruct->display = true;
|
||||
bstruct->points = 50000;
|
||||
}
|
||||
}
|
||||
if (!data.coop.gotperfbonus)
|
||||
if (intertype != int_coop)
|
||||
return;
|
||||
|
||||
data.coop.gotperfbonus = (bstruct->display ? 1 : 0);
|
||||
}
|
||||
|
||||
static void Y_SetSpecialRingBonus(player_t *player, y_bonus_t *bstruct)
|
||||
{
|
||||
INT32 i, sharedringtotal = 0;
|
||||
|
||||
(void)player;
|
||||
strncpy(bstruct->patch, "YB_RING", sizeof(bstruct->patch));
|
||||
bstruct->display = true;
|
||||
bstruct->points = 50000;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i]) continue;
|
||||
sharedringtotal += players[i].rings;
|
||||
}
|
||||
bstruct->points = max(0, (sharedringtotal) * 100);
|
||||
}
|
||||
|
||||
// This list can be extended in the future with SOC/Lua, perhaps.
|
||||
|
@ -1953,23 +1995,33 @@ static void Y_AwardCoopBonuses(void)
|
|||
static void Y_AwardSpecialStageBonus(void)
|
||||
{
|
||||
INT32 i, oldscore, ptlives;
|
||||
y_bonus_t localbonus;
|
||||
y_bonus_t localbonuses[2];
|
||||
|
||||
data.spec.score = players[consoleplayer].score;
|
||||
memset(&data.spec.bonus, 0, sizeof(data.spec.bonus));
|
||||
data.spec.bonuspatch = NULL;
|
||||
memset(data.spec.bonuses, 0, sizeof(data.spec.bonuses));
|
||||
memset(data.spec.bonuspatches, 0, sizeof(data.coop.bonuspatches));
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
oldscore = players[i].score;
|
||||
|
||||
if (!playeringame[i] || players[i].lives < 1) // not active or game over
|
||||
Y_SetNullBonus(&players[i], &localbonus);
|
||||
else if (maptol & TOL_NIGHTS) // Mare score instead of Rings
|
||||
Y_SetNightsBonus(&players[i], &localbonus);
|
||||
{
|
||||
Y_SetNullBonus(&players[i], &localbonuses[0]);
|
||||
Y_SetNullBonus(&players[i], &localbonuses[1]);
|
||||
}
|
||||
else if (maptol & TOL_NIGHTS) // NiGHTS bonus score instead of Rings
|
||||
{
|
||||
Y_SetNightsBonus(&players[i], &localbonuses[0]);
|
||||
Y_SetNullBonus(&players[i], &localbonuses[1]);
|
||||
}
|
||||
else
|
||||
Y_SetRingBonus(&players[i], &localbonus);
|
||||
players[i].score += localbonus.points;
|
||||
{
|
||||
Y_SetSpecialRingBonus(&players[i], &localbonuses[0]);
|
||||
Y_SetPerfectBonus(&players[i], &localbonuses[1]);
|
||||
}
|
||||
players[i].score += localbonuses[0].points;
|
||||
players[i].score += localbonuses[1].points;
|
||||
if (players[i].score > MAXSCORE)
|
||||
players[i].score = MAXSCORE;
|
||||
|
||||
|
@ -1982,7 +2034,7 @@ static void Y_AwardSpecialStageBonus(void)
|
|||
if (i == consoleplayer)
|
||||
{
|
||||
data.spec.gotlife = (((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 0) ? 0 : ptlives);
|
||||
M_Memcpy(&data.spec.bonus, &localbonus, sizeof(data.spec.bonus));
|
||||
M_Memcpy(&data.spec.bonuses, &localbonuses, sizeof(data.spec.bonuses));
|
||||
|
||||
// Continues related
|
||||
data.spec.continues = min(players[i].continues, 8);
|
||||
|
@ -2057,7 +2109,8 @@ static void Y_UnloadData(void)
|
|||
// unload the special stage patches
|
||||
//UNLOAD(data.spec.cemerald);
|
||||
//UNLOAD(data.spec.nowsuper);
|
||||
UNLOAD(data.spec.bonuspatch);
|
||||
UNLOAD(data.spec.bonuspatches[1]);
|
||||
UNLOAD(data.spec.bonuspatches[0]);
|
||||
UNLOAD(data.spec.pscore);
|
||||
UNLOAD(data.spec.pcontinues);
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue