mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-11-15 17:22:12 +00:00
Merge branch 'repeat-monitors' into 'master'
Monitor reworking + infinite repeat use 'gold' monitors All the monitor sprites, states, and objects are completely changed to be simpler. 'Gold' repeat use monitors are also introduced. I'm gonna be keeping my playtest EXEs in !LSF from now on. See merge request !20
This commit is contained in:
commit
7997753d24
12 changed files with 2002 additions and 1471 deletions
329
src/dehacked.c
329
src/dehacked.c
|
@ -1659,6 +1659,9 @@ static actionpointer_t actionpointers[] =
|
|||
{{A_Pain}, "A_PAIN"},
|
||||
{{A_Fall}, "A_FALL"},
|
||||
{{A_MonitorPop}, "A_MONITORPOP"},
|
||||
{{A_GoldMonitorPop}, "A_GOLDMONITORPOP"},
|
||||
{{A_GoldMonitorRestore}, "A_GOLDMONITORRESTORE"},
|
||||
{{A_GoldMonitorSparkle}, "A_GOLDMONITORSPARKLE"},
|
||||
{{A_Look}, "A_LOOK"},
|
||||
{{A_Chase}, "A_CHASE"},
|
||||
{{A_FaceStabChase}, "A_FACESTABCHASE"},
|
||||
|
@ -4869,170 +4872,114 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
|||
"S_CANNONLAUNCHER2",
|
||||
"S_CANNONLAUNCHER3",
|
||||
|
||||
// Super Ring Box
|
||||
"S_SUPERRINGBOX",
|
||||
"S_SUPERRINGBOX1",
|
||||
"S_SUPERRINGBOX2",
|
||||
"S_SUPERRINGBOX3",
|
||||
"S_SUPERRINGBOX4",
|
||||
"S_SUPERRINGBOX5",
|
||||
"S_SUPERRINGBOX6",
|
||||
// Monitor Miscellany
|
||||
"S_BOXSPARKLE1",
|
||||
"S_BOXSPARKLE2",
|
||||
"S_BOXSPARKLE3",
|
||||
|
||||
// Red Team Ring Box
|
||||
"S_REDRINGBOX",
|
||||
"S_REDRINGBOX1",
|
||||
"S_BOX_FLICKER",
|
||||
"S_BOX_POP1",
|
||||
"S_BOX_POP2",
|
||||
|
||||
// Blue Team Ring Box
|
||||
"S_BLUERINGBOX",
|
||||
"S_BLUERINGBOX1",
|
||||
"S_GOLDBOX_FLICKER",
|
||||
"S_GOLDBOX_OFF1",
|
||||
"S_GOLDBOX_OFF2",
|
||||
"S_GOLDBOX_OFF3",
|
||||
"S_GOLDBOX_OFF4",
|
||||
"S_GOLDBOX_OFF5",
|
||||
"S_GOLDBOX_OFF6",
|
||||
"S_GOLDBOX_OFF7",
|
||||
|
||||
// Super Sneakers Box
|
||||
"S_SHTV",
|
||||
"S_SHTV1",
|
||||
"S_SHTV2",
|
||||
"S_SHTV3",
|
||||
"S_SHTV4",
|
||||
"S_SHTV5",
|
||||
"S_SHTV6",
|
||||
// Monitor States (one per box)
|
||||
"S_MYSTERY_BOX",
|
||||
"S_RING_BOX",
|
||||
"S_PITY_BOX",
|
||||
"S_ATTRACT_BOX",
|
||||
"S_FORCE_BOX",
|
||||
"S_ARMAGEDDON_BOX",
|
||||
"S_WHIRLWIND_BOX",
|
||||
"S_ELEMENTAL_BOX",
|
||||
"S_SNEAKERS_BOX",
|
||||
"S_INVULN_BOX",
|
||||
"S_1UP_BOX",
|
||||
"S_EGGMAN_BOX",
|
||||
"S_MIXUP_BOX",
|
||||
"S_GRAVITY_BOX",
|
||||
"S_RECYCLER_BOX",
|
||||
"S_SCORE1K_BOX",
|
||||
"S_SCORE10K_BOX",
|
||||
|
||||
// Invincibility Box
|
||||
"S_PINV",
|
||||
"S_PINV1",
|
||||
"S_PINV2",
|
||||
"S_PINV3",
|
||||
"S_PINV4",
|
||||
"S_PINV5",
|
||||
"S_PINV6",
|
||||
// Gold Repeat Monitor States (one per box)
|
||||
"S_PITY_GOLDBOX",
|
||||
"S_ATTRACT_GOLDBOX",
|
||||
"S_FORCE_GOLDBOX",
|
||||
"S_ARMAGEDDON_GOLDBOX",
|
||||
"S_WHIRLWIND_GOLDBOX",
|
||||
"S_ELEMENTAL_GOLDBOX",
|
||||
"S_SNEAKERS_GOLDBOX",
|
||||
"S_INVULN_GOLDBOX",
|
||||
"S_EGGMAN_GOLDBOX",
|
||||
"S_GRAVITY_GOLDBOX",
|
||||
|
||||
// 1-Up Box
|
||||
"S_PRUP",
|
||||
"S_PRUP1",
|
||||
"S_PRUP2",
|
||||
"S_PRUP3",
|
||||
"S_PRUP4",
|
||||
"S_PRUP5",
|
||||
"S_PRUP6",
|
||||
// Team Ring Boxes (these are special)
|
||||
"S_RING_REDBOX1",
|
||||
"S_RING_REDBOX2",
|
||||
"S_REDBOX_POP1",
|
||||
"S_REDBOX_POP2",
|
||||
|
||||
// Ring Shield Box
|
||||
"S_YLTV",
|
||||
"S_YLTV1",
|
||||
"S_YLTV2",
|
||||
"S_YLTV3",
|
||||
"S_YLTV4",
|
||||
"S_YLTV5",
|
||||
"S_YLTV6",
|
||||
"S_RING_BLUEBOX1",
|
||||
"S_RING_BLUEBOX2",
|
||||
"S_BLUEBOX_POP1",
|
||||
"S_BLUEBOX_POP2",
|
||||
|
||||
// Force Shield Box
|
||||
"S_BLTV1",
|
||||
"S_BLTV2",
|
||||
"S_BLTV3",
|
||||
"S_BLTV4",
|
||||
"S_BLTV5",
|
||||
"S_BLTV6",
|
||||
"S_BLTV7",
|
||||
// Box Icons -- 2 states each, animation and action
|
||||
"S_RING_ICON1",
|
||||
"S_RING_ICON2",
|
||||
|
||||
// Bomb Shield Box
|
||||
"S_BKTV1",
|
||||
"S_BKTV2",
|
||||
"S_BKTV3",
|
||||
"S_BKTV4",
|
||||
"S_BKTV5",
|
||||
"S_BKTV6",
|
||||
"S_BKTV7",
|
||||
"S_PITY_ICON1",
|
||||
"S_PITY_ICON2",
|
||||
|
||||
// Jump Shield Box
|
||||
"S_WHTV1",
|
||||
"S_WHTV2",
|
||||
"S_WHTV3",
|
||||
"S_WHTV4",
|
||||
"S_WHTV5",
|
||||
"S_WHTV6",
|
||||
"S_WHTV7",
|
||||
"S_ATTRACT_ICON1",
|
||||
"S_ATTRACT_ICON2",
|
||||
|
||||
// Water Shield Box
|
||||
"S_GRTV",
|
||||
"S_GRTV1",
|
||||
"S_GRTV2",
|
||||
"S_GRTV3",
|
||||
"S_GRTV4",
|
||||
"S_GRTV5",
|
||||
"S_GRTV6",
|
||||
"S_FORCE_ICON1",
|
||||
"S_FORCE_ICON2",
|
||||
|
||||
// Pity Shield Box
|
||||
"S_PITV1",
|
||||
"S_PITV2",
|
||||
"S_PITV3",
|
||||
"S_PITV4",
|
||||
"S_PITV5",
|
||||
"S_PITV6",
|
||||
"S_PITV7",
|
||||
"S_ARMAGEDDON_ICON1",
|
||||
"S_ARMAGEDDON_ICON2",
|
||||
|
||||
// Eggman Box
|
||||
"S_EGGTV1",
|
||||
"S_EGGTV2",
|
||||
"S_EGGTV3",
|
||||
"S_EGGTV4",
|
||||
"S_EGGTV5",
|
||||
"S_EGGTV6",
|
||||
"S_EGGTV7",
|
||||
"S_WHIRLWIND_ICON1",
|
||||
"S_WHIRLWIND_ICON2",
|
||||
|
||||
// Teleport Box
|
||||
"S_MIXUPBOX1",
|
||||
"S_MIXUPBOX2",
|
||||
"S_MIXUPBOX3",
|
||||
"S_MIXUPBOX4",
|
||||
"S_MIXUPBOX5",
|
||||
"S_MIXUPBOX6",
|
||||
"S_MIXUPBOX7",
|
||||
"S_ELEMENTAL_ICON1",
|
||||
"S_ELEMENTAL_ICON2",
|
||||
|
||||
// Recycler Box
|
||||
"S_RECYCLETV1",
|
||||
"S_RECYCLETV2",
|
||||
"S_RECYCLETV3",
|
||||
"S_RECYCLETV4",
|
||||
"S_RECYCLETV5",
|
||||
"S_RECYCLETV6",
|
||||
"S_RECYCLETV7",
|
||||
"S_SNEAKERS_ICON1",
|
||||
"S_SNEAKERS_ICON2",
|
||||
|
||||
// Question Box
|
||||
"S_RANDOMBOX1",
|
||||
"S_RANDOMBOX2",
|
||||
"S_RANDOMBOX3",
|
||||
"S_INVULN_ICON1",
|
||||
"S_INVULN_ICON2",
|
||||
|
||||
// Gravity Boots Box
|
||||
"S_GBTV1",
|
||||
"S_GBTV2",
|
||||
"S_GBTV3",
|
||||
"S_GBTV4",
|
||||
"S_GBTV5",
|
||||
"S_GBTV6",
|
||||
"S_GBTV7",
|
||||
"S_1UP_ICON1",
|
||||
"S_1UP_ICON2",
|
||||
|
||||
// Score boxes
|
||||
"S_SCORETVA1",
|
||||
"S_SCORETVA2",
|
||||
"S_SCORETVA3",
|
||||
"S_SCORETVA4",
|
||||
"S_SCORETVA5",
|
||||
"S_SCORETVA6",
|
||||
"S_SCORETVA7",
|
||||
"S_SCORETVB1",
|
||||
"S_SCORETVB2",
|
||||
"S_SCORETVB3",
|
||||
"S_SCORETVB4",
|
||||
"S_SCORETVB5",
|
||||
"S_SCORETVB6",
|
||||
"S_SCORETVB7",
|
||||
"S_EGGMAN_ICON1",
|
||||
"S_EGGMAN_ICON2",
|
||||
|
||||
// Monitor Explosion
|
||||
"S_MONITOREXPLOSION1",
|
||||
"S_MONITOREXPLOSION2",
|
||||
"S_MIXUP_ICON1",
|
||||
"S_MIXUP_ICON2",
|
||||
|
||||
"S_REDMONITOREXPLOSION1",
|
||||
"S_REDMONITOREXPLOSION2",
|
||||
"S_GRAVITY_ICON1",
|
||||
"S_GRAVITY_ICON2",
|
||||
|
||||
"S_BLUEMONITOREXPLOSION1",
|
||||
"S_BLUEMONITOREXPLOSION2",
|
||||
"S_RECYCLER_ICON1",
|
||||
"S_RECYCLER_ICON2",
|
||||
|
||||
"S_SCORE1K_ICON1",
|
||||
"S_SCORE1K_ICON2",
|
||||
|
||||
"S_SCORE10K_ICON1",
|
||||
"S_SCORE10K_ICON2",
|
||||
|
||||
"S_ROCKET",
|
||||
|
||||
|
@ -6260,47 +6207,61 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
|
|||
"MT_BIGAIRMINE",
|
||||
"MT_CANNONLAUNCHER",
|
||||
|
||||
// Monitor Boxes
|
||||
"MT_SUPERRINGBOX",
|
||||
"MT_REDRINGBOX",
|
||||
"MT_BLUERINGBOX",
|
||||
"MT_SNEAKERTV",
|
||||
"MT_INV",
|
||||
"MT_PRUP", // 1up Box
|
||||
"MT_YELLOWTV", // Attract shield TV
|
||||
"MT_BLUETV", // Force shield TV
|
||||
"MT_BLACKTV", // Bomb shield TV
|
||||
"MT_WHITETV", // Jump shield TV
|
||||
"MT_GREENTV", // Elemental shield TV
|
||||
"MT_PITYTV", // Pity shield TV
|
||||
"MT_EGGMANBOX",
|
||||
"MT_MIXUPBOX",
|
||||
"MT_RECYCLETV",
|
||||
"MT_RECYCLEICO",
|
||||
"MT_QUESTIONBOX",
|
||||
"MT_GRAVITYBOX",
|
||||
"MT_SCORETVSMALL",
|
||||
"MT_SCORETVLARGE",
|
||||
|
||||
// Monitor miscellany
|
||||
"MT_MONITOREXPLOSION",
|
||||
"MT_REDMONITOREXPLOSION",
|
||||
"MT_BLUEMONITOREXPLOSION",
|
||||
"MT_RINGICO",
|
||||
"MT_SHOESICO",
|
||||
"MT_INVCICO",
|
||||
"MT_1UPICO",
|
||||
"MT_YSHIELDICO",
|
||||
"MT_BSHIELDICO",
|
||||
"MT_KSHIELDICO",
|
||||
"MT_WSHIELDICO",
|
||||
"MT_GSHIELDICO",
|
||||
"MT_PITYSHIELDICO",
|
||||
"MT_EGGMANICO",
|
||||
"MT_MIXUPICO",
|
||||
"MT_GRAVITYICO",
|
||||
"MT_SCOREICOSMALL",
|
||||
"MT_SCOREICOLARGE",
|
||||
"MT_BOXSPARKLE",
|
||||
|
||||
// Monitor boxes -- regular
|
||||
"MT_RING_BOX",
|
||||
"MT_PITY_BOX",
|
||||
"MT_ATTRACT_BOX",
|
||||
"MT_FORCE_BOX",
|
||||
"MT_ARMAGEDDON_BOX",
|
||||
"MT_WHIRLWIND_BOX",
|
||||
"MT_ELEMENTAL_BOX",
|
||||
"MT_SNEAKERS_BOX",
|
||||
"MT_INVULN_BOX",
|
||||
"MT_1UP_BOX",
|
||||
"MT_EGGMAN_BOX",
|
||||
"MT_MIXUP_BOX",
|
||||
"MT_MYSTERY_BOX",
|
||||
"MT_GRAVITY_BOX",
|
||||
"MT_RECYCLER_BOX",
|
||||
"MT_SCORE1K_BOX",
|
||||
"MT_SCORE10K_BOX",
|
||||
|
||||
// Monitor boxes -- repeating (big) boxes
|
||||
"MT_PITY_GOLDBOX",
|
||||
"MT_ATTRACT_GOLDBOX",
|
||||
"MT_FORCE_GOLDBOX",
|
||||
"MT_ARMAGEDDON_GOLDBOX",
|
||||
"MT_WHIRLWIND_GOLDBOX",
|
||||
"MT_ELEMENTAL_GOLDBOX",
|
||||
"MT_SNEAKERS_GOLDBOX",
|
||||
"MT_INVULN_GOLDBOX",
|
||||
"MT_EGGMAN_GOLDBOX",
|
||||
"MT_GRAVITY_GOLDBOX",
|
||||
|
||||
// Monitor boxes -- special
|
||||
"MT_RING_REDBOX",
|
||||
"MT_RING_BLUEBOX",
|
||||
|
||||
// Monitor icons
|
||||
"MT_RING_ICON",
|
||||
"MT_PITY_ICON",
|
||||
"MT_ATTRACT_ICON",
|
||||
"MT_FORCE_ICON",
|
||||
"MT_ARMAGEDDON_ICON",
|
||||
"MT_WHIRLWIND_ICON",
|
||||
"MT_ELEMENTAL_ICON",
|
||||
"MT_SNEAKERS_ICON",
|
||||
"MT_INVULN_ICON",
|
||||
"MT_1UP_ICON",
|
||||
"MT_EGGMAN_ICON",
|
||||
"MT_MIXUP_ICON",
|
||||
"MT_GRAVITY_ICON",
|
||||
"MT_RECYCLER_ICON",
|
||||
"MT_SCORE1K_ICON",
|
||||
"MT_SCORE10K_ICON",
|
||||
|
||||
// Projectiles
|
||||
"MT_ROCKET",
|
||||
|
|
|
@ -247,27 +247,30 @@ light_t *t_lspr[NUMSPRITES] =
|
|||
&lspr[NOLIGHT], // SPR_BMNE
|
||||
|
||||
// Monitor Boxes
|
||||
&lspr[NOLIGHT], // SPR_SRBX
|
||||
&lspr[NOLIGHT], // SPR_RRBX
|
||||
&lspr[NOLIGHT], // SPR_BRBX
|
||||
&lspr[NOLIGHT], // SPR_SHTV
|
||||
&lspr[NOLIGHT], // SPR_PINV
|
||||
&lspr[NOLIGHT], // SPR_YLTV
|
||||
&lspr[NOLIGHT], // SPR_BLTV
|
||||
&lspr[NOLIGHT], // SPR_BKTV
|
||||
&lspr[NOLIGHT], // SPR_WHTV
|
||||
&lspr[NOLIGHT], // SPR_GRTV
|
||||
&lspr[NOLIGHT], // SPR_ELTV
|
||||
&lspr[NOLIGHT], // SPR_EGGB
|
||||
&lspr[NOLIGHT], // SPR_MIXU
|
||||
&lspr[NOLIGHT], // SPR_RECY
|
||||
&lspr[NOLIGHT], // SPR_QUES
|
||||
&lspr[NOLIGHT], // SPR_GBTV
|
||||
&lspr[NOLIGHT], // SPR_PRUP
|
||||
&lspr[NOLIGHT], // SPR_PTTV
|
||||
&lspr[NOLIGHT], // SPR_MSTV
|
||||
&lspr[NOLIGHT], // SPR_XLTV
|
||||
|
||||
// Monitor Miscellany
|
||||
&lspr[NOLIGHT], // SPR_MTEX
|
||||
&lspr[NOLIGHT], // SPR_TRRI
|
||||
&lspr[NOLIGHT], // SPR_TBRI
|
||||
|
||||
&lspr[NOLIGHT], // SPR_TVRI
|
||||
&lspr[NOLIGHT], // SPR_TVPI
|
||||
&lspr[NOLIGHT], // SPR_TVAT
|
||||
&lspr[NOLIGHT], // SPR_TVFO
|
||||
&lspr[NOLIGHT], // SPR_TVAR
|
||||
&lspr[NOLIGHT], // SPR_TVWW
|
||||
&lspr[NOLIGHT], // SPR_TVEL
|
||||
&lspr[NOLIGHT], // SPR_TVSS
|
||||
&lspr[NOLIGHT], // SPR_TVIV
|
||||
&lspr[NOLIGHT], // SPR_TV1U
|
||||
&lspr[NOLIGHT], // SPR_TV1P
|
||||
&lspr[NOLIGHT], // SPR_TVEG
|
||||
&lspr[NOLIGHT], // SPR_TVMX
|
||||
&lspr[NOLIGHT], // SPR_TVMY
|
||||
&lspr[NOLIGHT], // SPR_TVGV
|
||||
&lspr[NOLIGHT], // SPR_TVRC
|
||||
&lspr[NOLIGHT], // SPR_TV1K
|
||||
&lspr[NOLIGHT], // SPR_TVTK
|
||||
|
||||
// Projectiles
|
||||
&lspr[NOLIGHT], // SPR_MISL
|
||||
|
|
2153
src/info.c
2153
src/info.c
File diff suppressed because it is too large
Load diff
374
src/info.h
374
src/info.h
|
@ -28,6 +28,9 @@ void A_Explode();
|
|||
void A_Pain();
|
||||
void A_Fall();
|
||||
void A_MonitorPop();
|
||||
void A_GoldMonitorPop();
|
||||
void A_GoldMonitorRestore();
|
||||
void A_GoldMonitorSparkle();
|
||||
void A_Look();
|
||||
void A_Chase();
|
||||
void A_FaceStabChase();
|
||||
|
@ -324,27 +327,30 @@ typedef enum sprite
|
|||
SPR_BMNE, // Big floating mine
|
||||
|
||||
// Monitor Boxes
|
||||
SPR_SRBX,
|
||||
SPR_RRBX,
|
||||
SPR_BRBX,
|
||||
SPR_SHTV,
|
||||
SPR_PINV,
|
||||
SPR_YLTV,
|
||||
SPR_BLTV, // Force shield
|
||||
SPR_BKTV, // Bomb shield TV
|
||||
SPR_WHTV, // Jump shield TV
|
||||
SPR_GRTV, // Pity shield TV
|
||||
SPR_ELTV, // Elemental shield TV
|
||||
SPR_EGGB, // Eggman box
|
||||
SPR_MIXU, // Player mixing monitor
|
||||
SPR_RECY, // Recycler (power mixing) monitor
|
||||
SPR_QUES, // Random monitor
|
||||
SPR_GBTV, // Gravity boots TV
|
||||
SPR_PRUP, // 1up
|
||||
SPR_PTTV, // Score TVs
|
||||
SPR_MSTV, // MiSc TV sprites
|
||||
SPR_XLTV, // eXtra Large TV sprites
|
||||
|
||||
// Monitor Miscellany
|
||||
SPR_MTEX, // Exploding monitor
|
||||
SPR_TRRI, // Red team: 10 RIngs
|
||||
SPR_TBRI, // Blue team: 10 RIngs
|
||||
|
||||
SPR_TVRI, // 10 RIng
|
||||
SPR_TVPI, // PIty shield
|
||||
SPR_TVAT, // ATtraction shield
|
||||
SPR_TVFO, // FOrce shield
|
||||
SPR_TVAR, // ARmageddon shield
|
||||
SPR_TVWW, // WhirlWind shield
|
||||
SPR_TVEL, // ELemental shield
|
||||
SPR_TVSS, // Super Sneakers
|
||||
SPR_TVIV, // InVincibility
|
||||
SPR_TV1U, // 1Up
|
||||
SPR_TV1P, // 1uP (textless)
|
||||
SPR_TVEG, // EGgman
|
||||
SPR_TVMX, // MiXup
|
||||
SPR_TVMY, // MYstery
|
||||
SPR_TVGV, // GraVity boots
|
||||
SPR_TVRC, // ReCycler
|
||||
SPR_TV1K, // 1,000 points (1 K)
|
||||
SPR_TVTK, // 10,000 points (Ten K)
|
||||
|
||||
// Projectiles
|
||||
SPR_MISL,
|
||||
|
@ -1772,170 +1778,116 @@ typedef enum state
|
|||
S_CANNONLAUNCHER2,
|
||||
S_CANNONLAUNCHER3,
|
||||
|
||||
// Super Ring Box
|
||||
S_SUPERRINGBOX,
|
||||
S_SUPERRINGBOX1,
|
||||
S_SUPERRINGBOX2,
|
||||
S_SUPERRINGBOX3,
|
||||
S_SUPERRINGBOX4,
|
||||
S_SUPERRINGBOX5,
|
||||
S_SUPERRINGBOX6,
|
||||
// Monitor Miscellany
|
||||
S_BOXSPARKLE1,
|
||||
S_BOXSPARKLE2,
|
||||
S_BOXSPARKLE3,
|
||||
|
||||
// Red Team Ring Box
|
||||
S_REDRINGBOX,
|
||||
S_REDRINGBOX1,
|
||||
S_BOX_FLICKER,
|
||||
S_BOX_POP1,
|
||||
S_BOX_POP2,
|
||||
|
||||
// Blue Team Ring Box
|
||||
S_BLUERINGBOX,
|
||||
S_BLUERINGBOX1,
|
||||
S_GOLDBOX_FLICKER,
|
||||
S_GOLDBOX_OFF1,
|
||||
S_GOLDBOX_OFF2,
|
||||
S_GOLDBOX_OFF3,
|
||||
S_GOLDBOX_OFF4,
|
||||
S_GOLDBOX_OFF5,
|
||||
S_GOLDBOX_OFF6,
|
||||
S_GOLDBOX_OFF7,
|
||||
|
||||
// Super Sneakers Box
|
||||
S_SHTV,
|
||||
S_SHTV1,
|
||||
S_SHTV2,
|
||||
S_SHTV3,
|
||||
S_SHTV4,
|
||||
S_SHTV5,
|
||||
S_SHTV6,
|
||||
// Monitor States (one per box)
|
||||
S_MYSTERY_BOX,
|
||||
S_RING_BOX,
|
||||
S_PITY_BOX,
|
||||
S_ATTRACT_BOX,
|
||||
S_FORCE_BOX,
|
||||
S_ARMAGEDDON_BOX,
|
||||
S_WHIRLWIND_BOX,
|
||||
S_ELEMENTAL_BOX,
|
||||
S_SNEAKERS_BOX,
|
||||
S_INVULN_BOX,
|
||||
S_1UP_BOX,
|
||||
S_EGGMAN_BOX,
|
||||
S_MIXUP_BOX,
|
||||
S_GRAVITY_BOX,
|
||||
S_RECYCLER_BOX,
|
||||
S_SCORE1K_BOX,
|
||||
S_SCORE10K_BOX,
|
||||
|
||||
// Invincibility Box
|
||||
S_PINV,
|
||||
S_PINV1,
|
||||
S_PINV2,
|
||||
S_PINV3,
|
||||
S_PINV4,
|
||||
S_PINV5,
|
||||
S_PINV6,
|
||||
// Gold Repeat Monitor States (one per box)
|
||||
S_PITY_GOLDBOX,
|
||||
S_ATTRACT_GOLDBOX,
|
||||
S_FORCE_GOLDBOX,
|
||||
S_ARMAGEDDON_GOLDBOX,
|
||||
S_WHIRLWIND_GOLDBOX,
|
||||
S_ELEMENTAL_GOLDBOX,
|
||||
S_SNEAKERS_GOLDBOX,
|
||||
S_INVULN_GOLDBOX,
|
||||
S_EGGMAN_GOLDBOX,
|
||||
S_GRAVITY_GOLDBOX,
|
||||
|
||||
// 1up Box
|
||||
S_PRUP,
|
||||
S_PRUP1,
|
||||
S_PRUP2,
|
||||
S_PRUP3,
|
||||
S_PRUP4,
|
||||
S_PRUP5,
|
||||
S_PRUP6,
|
||||
// Team Ring Boxes (these are special)
|
||||
S_RING_REDBOX1,
|
||||
S_RING_REDBOX2,
|
||||
S_REDBOX_POP1,
|
||||
S_REDBOX_POP2,
|
||||
|
||||
// Ring Shield Box
|
||||
S_YLTV,
|
||||
S_YLTV1,
|
||||
S_YLTV2,
|
||||
S_YLTV3,
|
||||
S_YLTV4,
|
||||
S_YLTV5,
|
||||
S_YLTV6,
|
||||
S_RING_BLUEBOX1,
|
||||
S_RING_BLUEBOX2,
|
||||
S_BLUEBOX_POP1,
|
||||
S_BLUEBOX_POP2,
|
||||
|
||||
// Force Shield Box
|
||||
S_BLTV1,
|
||||
S_BLTV2,
|
||||
S_BLTV3,
|
||||
S_BLTV4,
|
||||
S_BLTV5,
|
||||
S_BLTV6,
|
||||
S_BLTV7,
|
||||
// Box Icons -- 2 states each, animation and action
|
||||
S_RING_ICON1,
|
||||
S_RING_ICON2,
|
||||
|
||||
// Bomb Shield Box
|
||||
S_BKTV1,
|
||||
S_BKTV2,
|
||||
S_BKTV3,
|
||||
S_BKTV4,
|
||||
S_BKTV5,
|
||||
S_BKTV6,
|
||||
S_BKTV7,
|
||||
S_PITY_ICON1,
|
||||
S_PITY_ICON2,
|
||||
|
||||
// Jump Shield Box
|
||||
S_WHTV1,
|
||||
S_WHTV2,
|
||||
S_WHTV3,
|
||||
S_WHTV4,
|
||||
S_WHTV5,
|
||||
S_WHTV6,
|
||||
S_WHTV7,
|
||||
S_ATTRACT_ICON1,
|
||||
S_ATTRACT_ICON2,
|
||||
|
||||
// Water Shield Box
|
||||
S_GRTV,
|
||||
S_GRTV1,
|
||||
S_GRTV2,
|
||||
S_GRTV3,
|
||||
S_GRTV4,
|
||||
S_GRTV5,
|
||||
S_GRTV6,
|
||||
S_FORCE_ICON1,
|
||||
S_FORCE_ICON2,
|
||||
|
||||
// Pity Shield Box
|
||||
S_PITV1,
|
||||
S_PITV2,
|
||||
S_PITV3,
|
||||
S_PITV4,
|
||||
S_PITV5,
|
||||
S_PITV6,
|
||||
S_PITV7,
|
||||
S_ARMAGEDDON_ICON1,
|
||||
S_ARMAGEDDON_ICON2,
|
||||
|
||||
// Eggman Box
|
||||
S_EGGTV1,
|
||||
S_EGGTV2,
|
||||
S_EGGTV3,
|
||||
S_EGGTV4,
|
||||
S_EGGTV5,
|
||||
S_EGGTV6,
|
||||
S_EGGTV7,
|
||||
S_WHIRLWIND_ICON1,
|
||||
S_WHIRLWIND_ICON2,
|
||||
|
||||
// Teleport Box
|
||||
S_MIXUPBOX1,
|
||||
S_MIXUPBOX2,
|
||||
S_MIXUPBOX3,
|
||||
S_MIXUPBOX4,
|
||||
S_MIXUPBOX5,
|
||||
S_MIXUPBOX6,
|
||||
S_MIXUPBOX7,
|
||||
S_ELEMENTAL_ICON1,
|
||||
S_ELEMENTAL_ICON2,
|
||||
|
||||
// Recycler Box
|
||||
S_RECYCLETV1,
|
||||
S_RECYCLETV2,
|
||||
S_RECYCLETV3,
|
||||
S_RECYCLETV4,
|
||||
S_RECYCLETV5,
|
||||
S_RECYCLETV6,
|
||||
S_RECYCLETV7,
|
||||
S_SNEAKERS_ICON1,
|
||||
S_SNEAKERS_ICON2,
|
||||
|
||||
// Question Box
|
||||
S_RANDOMBOX1,
|
||||
S_RANDOMBOX2,
|
||||
S_RANDOMBOX3,
|
||||
S_INVULN_ICON1,
|
||||
S_INVULN_ICON2,
|
||||
|
||||
// Gravity Boots Box
|
||||
S_GBTV1,
|
||||
S_GBTV2,
|
||||
S_GBTV3,
|
||||
S_GBTV4,
|
||||
S_GBTV5,
|
||||
S_GBTV6,
|
||||
S_GBTV7,
|
||||
S_1UP_ICON1,
|
||||
S_1UP_ICON2,
|
||||
|
||||
// Score boxes
|
||||
S_SCORETVA1,
|
||||
S_SCORETVA2,
|
||||
S_SCORETVA3,
|
||||
S_SCORETVA4,
|
||||
S_SCORETVA5,
|
||||
S_SCORETVA6,
|
||||
S_SCORETVA7,
|
||||
S_SCORETVB1,
|
||||
S_SCORETVB2,
|
||||
S_SCORETVB3,
|
||||
S_SCORETVB4,
|
||||
S_SCORETVB5,
|
||||
S_SCORETVB6,
|
||||
S_SCORETVB7,
|
||||
S_EGGMAN_ICON1,
|
||||
S_EGGMAN_ICON2,
|
||||
|
||||
// Monitor Explosion
|
||||
S_MONITOREXPLOSION1,
|
||||
S_MONITOREXPLOSION2,
|
||||
S_MIXUP_ICON1,
|
||||
S_MIXUP_ICON2,
|
||||
|
||||
S_REDMONITOREXPLOSION1,
|
||||
S_REDMONITOREXPLOSION2,
|
||||
S_GRAVITY_ICON1,
|
||||
S_GRAVITY_ICON2,
|
||||
|
||||
S_BLUEMONITOREXPLOSION1,
|
||||
S_BLUEMONITOREXPLOSION2,
|
||||
S_RECYCLER_ICON1,
|
||||
S_RECYCLER_ICON2,
|
||||
|
||||
S_SCORE1K_ICON1,
|
||||
S_SCORE1K_ICON2,
|
||||
|
||||
S_SCORE10K_ICON1,
|
||||
S_SCORE10K_ICON2,
|
||||
|
||||
// ---
|
||||
|
||||
S_ROCKET,
|
||||
|
||||
|
@ -3182,47 +3134,61 @@ typedef enum mobj_type
|
|||
MT_BIGAIRMINE,
|
||||
MT_CANNONLAUNCHER,
|
||||
|
||||
// Monitor Boxes
|
||||
MT_SUPERRINGBOX,
|
||||
MT_REDRINGBOX,
|
||||
MT_BLUERINGBOX,
|
||||
MT_SNEAKERTV,
|
||||
MT_INV,
|
||||
MT_PRUP, // 1up Box
|
||||
MT_YELLOWTV,
|
||||
MT_BLUETV,
|
||||
MT_BLACKTV, // Bomb shield TV
|
||||
MT_WHITETV, // Jump shield TV
|
||||
MT_GREENTV,
|
||||
MT_PITYTV, // Pity Shield TV
|
||||
MT_EGGMANBOX,
|
||||
MT_MIXUPBOX,
|
||||
MT_RECYCLETV,
|
||||
MT_RECYCLEICO,
|
||||
MT_QUESTIONBOX,
|
||||
MT_GRAVITYBOX,
|
||||
MT_SCORETVSMALL,
|
||||
MT_SCORETVLARGE,
|
||||
|
||||
// Monitor miscellany
|
||||
MT_MONITOREXPLOSION,
|
||||
MT_REDMONITOREXPLOSION,
|
||||
MT_BLUEMONITOREXPLOSION,
|
||||
MT_RINGICO,
|
||||
MT_SHOESICO,
|
||||
MT_INVCICO,
|
||||
MT_1UPICO,
|
||||
MT_YSHIELDICO,
|
||||
MT_BSHIELDICO,
|
||||
MT_KSHIELDICO,
|
||||
MT_WSHIELDICO,
|
||||
MT_GSHIELDICO,
|
||||
MT_PITYSHIELDICO,
|
||||
MT_EGGMANICO,
|
||||
MT_MIXUPICO,
|
||||
MT_GRAVITYICO,
|
||||
MT_SCOREICOSMALL,
|
||||
MT_SCOREICOLARGE,
|
||||
MT_BOXSPARKLE,
|
||||
|
||||
// Monitor boxes -- regular
|
||||
MT_RING_BOX,
|
||||
MT_PITY_BOX,
|
||||
MT_ATTRACT_BOX,
|
||||
MT_FORCE_BOX,
|
||||
MT_ARMAGEDDON_BOX,
|
||||
MT_WHIRLWIND_BOX,
|
||||
MT_ELEMENTAL_BOX,
|
||||
MT_SNEAKERS_BOX,
|
||||
MT_INVULN_BOX,
|
||||
MT_1UP_BOX,
|
||||
MT_EGGMAN_BOX,
|
||||
MT_MIXUP_BOX,
|
||||
MT_MYSTERY_BOX,
|
||||
MT_GRAVITY_BOX,
|
||||
MT_RECYCLER_BOX,
|
||||
MT_SCORE1K_BOX,
|
||||
MT_SCORE10K_BOX,
|
||||
|
||||
// Monitor boxes -- repeating (big) boxes
|
||||
MT_PITY_GOLDBOX,
|
||||
MT_ATTRACT_GOLDBOX,
|
||||
MT_FORCE_GOLDBOX,
|
||||
MT_ARMAGEDDON_GOLDBOX,
|
||||
MT_WHIRLWIND_GOLDBOX,
|
||||
MT_ELEMENTAL_GOLDBOX,
|
||||
MT_SNEAKERS_GOLDBOX,
|
||||
MT_INVULN_GOLDBOX,
|
||||
MT_EGGMAN_GOLDBOX,
|
||||
MT_GRAVITY_GOLDBOX,
|
||||
|
||||
// Monitor boxes -- special
|
||||
MT_RING_REDBOX,
|
||||
MT_RING_BLUEBOX,
|
||||
|
||||
// Monitor icons
|
||||
MT_RING_ICON,
|
||||
MT_PITY_ICON,
|
||||
MT_ATTRACT_ICON,
|
||||
MT_FORCE_ICON,
|
||||
MT_ARMAGEDDON_ICON,
|
||||
MT_WHIRLWIND_ICON,
|
||||
MT_ELEMENTAL_ICON,
|
||||
MT_SNEAKERS_ICON,
|
||||
MT_INVULN_ICON,
|
||||
MT_1UP_ICON,
|
||||
MT_EGGMAN_ICON,
|
||||
MT_MIXUP_ICON,
|
||||
MT_GRAVITY_ICON,
|
||||
MT_RECYCLER_ICON,
|
||||
MT_SCORE1K_ICON,
|
||||
MT_SCORE10K_ICON,
|
||||
|
||||
// Projectiles
|
||||
MT_ROCKET,
|
||||
|
|
299
src/p_enemy.c
299
src/p_enemy.c
|
@ -818,6 +818,32 @@ static int P_RecycleCompare(const void *p1, const void *p2)
|
|||
}
|
||||
#endif
|
||||
|
||||
// Handles random monitor weights via console.
|
||||
static mobjtype_t P_DoRandomBoxChances(void)
|
||||
{
|
||||
mobjtype_t spawnchance[256];
|
||||
INT32 numchoices = 0, i = 0;
|
||||
|
||||
#define QUESTIONBOXCHANCES(type, cvar) \
|
||||
for (i = cvar.value; i; --i) spawnchance[numchoices++] = type
|
||||
QUESTIONBOXCHANCES(MT_RING_ICON, cv_superring);
|
||||
QUESTIONBOXCHANCES(MT_SNEAKERS_ICON, cv_supersneakers);
|
||||
QUESTIONBOXCHANCES(MT_INVULN_ICON, cv_invincibility);
|
||||
QUESTIONBOXCHANCES(MT_WHIRLWIND_ICON, cv_jumpshield);
|
||||
QUESTIONBOXCHANCES(MT_ELEMENTAL_ICON, cv_watershield);
|
||||
QUESTIONBOXCHANCES(MT_ATTRACT_ICON, cv_ringshield);
|
||||
QUESTIONBOXCHANCES(MT_FORCE_ICON, cv_forceshield);
|
||||
QUESTIONBOXCHANCES(MT_ARMAGEDDON_ICON, cv_bombshield);
|
||||
QUESTIONBOXCHANCES(MT_1UP_ICON, cv_1up);
|
||||
QUESTIONBOXCHANCES(MT_EGGMAN_ICON, cv_eggmanbox);
|
||||
QUESTIONBOXCHANCES(MT_MIXUP_ICON, cv_teleporters);
|
||||
QUESTIONBOXCHANCES(MT_RECYCLER_ICON, cv_recycler);
|
||||
#undef QUESTIONBOXCHANCES
|
||||
|
||||
if (numchoices == 0) return MT_NULL;
|
||||
return spawnchance[P_RandomKey(numchoices)];
|
||||
}
|
||||
|
||||
//
|
||||
// ACTION ROUTINES
|
||||
//
|
||||
|
@ -2510,7 +2536,6 @@ 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.
|
||||
actor->frame = 0;
|
||||
if (actor->tracer) {
|
||||
P_RemoveMobj(actor->tracer);
|
||||
actor->tracer = NULL;
|
||||
|
@ -2518,11 +2543,19 @@ void A_1upThinker(mobj_t *actor)
|
|||
return;
|
||||
}
|
||||
|
||||
// We're using the overlay, so use the overlay 1up box (no text)
|
||||
actor->sprite = SPR_TV1P;
|
||||
|
||||
if (!actor->tracer)
|
||||
{
|
||||
P_SetTarget(&actor->tracer, P_SpawnMobj(actor->x, actor->y, actor->z, MT_OVERLAY));
|
||||
P_SetTarget(&actor->tracer->target, actor);
|
||||
P_SetMobjState(actor->tracer, actor->info->seestate);
|
||||
|
||||
// The overlay is going to be one tic early turning off and on
|
||||
// because it's going to get its thinker run the frame we spawned it.
|
||||
// So make it take one tic longer if it just spawned.
|
||||
++actor->tracer->tics;
|
||||
}
|
||||
|
||||
actor->tracer->color = players[closestplayer].mo->color;
|
||||
|
@ -2538,139 +2571,200 @@ void A_1upThinker(mobj_t *actor)
|
|||
//
|
||||
void A_MonitorPop(mobj_t *actor)
|
||||
{
|
||||
mobj_t *remains;
|
||||
mobjtype_t explode;
|
||||
mobjtype_t item = 0;
|
||||
mobjtype_t newbox;
|
||||
mobj_t *newmobj;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_MonitorPop", actor))
|
||||
return;
|
||||
#endif
|
||||
|
||||
// de-solidify
|
||||
// Spawn the "pop" explosion.
|
||||
if (actor->info->deathsound)
|
||||
S_StartSound(actor, actor->info->deathsound);
|
||||
P_SpawnMobjFromMobj(actor, 0, 0, actor->height/4, MT_EXPLODE);
|
||||
|
||||
// We're dead now. De-solidify.
|
||||
actor->health = 0;
|
||||
P_UnsetThingPosition(actor);
|
||||
actor->flags &= ~MF_SOLID;
|
||||
actor->flags |= MF_NOCLIP;
|
||||
P_SetThingPosition(actor);
|
||||
|
||||
// Monitor explosion
|
||||
explode = mobjinfo[actor->info->speed].mass;
|
||||
remains = P_SpawnMobj(actor->x, actor->y,
|
||||
((actor->eflags & MFE_VERTICALFLIP) ? (actor->z + 3*(actor->height/4) - FixedMul(mobjinfo[explode].height, actor->scale)) : (actor->z + actor->height/4)), explode);
|
||||
if (actor->eflags & MFE_VERTICALFLIP)
|
||||
if (actor->info->damage == MT_UNKNOWN)
|
||||
{
|
||||
remains->eflags |= MFE_VERTICALFLIP;
|
||||
remains->flags2 |= MF2_OBJECTFLIP;
|
||||
}
|
||||
remains->destscale = actor->destscale;
|
||||
P_SetScale(remains, actor->scale);
|
||||
// MT_UNKNOWN is random. Because it's unknown to us... get it?
|
||||
item = P_DoRandomBoxChances();
|
||||
|
||||
remains = P_SpawnMobj(actor->x, actor->y,
|
||||
((actor->eflags & MFE_VERTICALFLIP) ? (actor->z + actor->height - FixedMul(mobjinfo[actor->info->speed].height, actor->scale)) : actor->z),
|
||||
actor->info->speed);
|
||||
remains->type = actor->type; // Transfer type information
|
||||
P_UnsetThingPosition(remains);
|
||||
if (sector_list)
|
||||
{
|
||||
P_DelSeclist(sector_list);
|
||||
sector_list = NULL;
|
||||
}
|
||||
P_SetThingPosition(remains);
|
||||
remains->destscale = actor->destscale;
|
||||
P_SetScale(remains, actor->scale);
|
||||
remains->flags = actor->flags; // Transfer flags
|
||||
remains->flags2 = actor->flags2; // Transfer flags2
|
||||
remains->fuse = actor->fuse; // Transfer respawn timer
|
||||
remains->threshold = 68;
|
||||
remains->skin = NULL;
|
||||
|
||||
P_SetTarget(&tmthing, remains);
|
||||
|
||||
if (actor->info->deathsound)
|
||||
S_StartSound(remains, actor->info->deathsound);
|
||||
|
||||
switch (actor->type)
|
||||
{
|
||||
case MT_QUESTIONBOX: // Random!
|
||||
{
|
||||
mobjtype_t spawnchance[256];
|
||||
INT32 numchoices = 0, i = 0;
|
||||
|
||||
#define QUESTIONBOXCHANCES(type, cvar) \
|
||||
for (i = cvar.value; i; --i) spawnchance[numchoices++] = type
|
||||
|
||||
QUESTIONBOXCHANCES(MT_SUPERRINGBOX, cv_superring);
|
||||
QUESTIONBOXCHANCES(MT_SNEAKERTV, cv_supersneakers);
|
||||
QUESTIONBOXCHANCES(MT_INV, cv_invincibility);
|
||||
QUESTIONBOXCHANCES(MT_WHITETV, cv_jumpshield);
|
||||
QUESTIONBOXCHANCES(MT_GREENTV, cv_watershield);
|
||||
QUESTIONBOXCHANCES(MT_YELLOWTV, cv_ringshield);
|
||||
QUESTIONBOXCHANCES(MT_BLUETV, cv_forceshield);
|
||||
QUESTIONBOXCHANCES(MT_BLACKTV, cv_bombshield);
|
||||
QUESTIONBOXCHANCES(MT_PRUP, cv_1up);
|
||||
QUESTIONBOXCHANCES(MT_EGGMANBOX, cv_eggmanbox);
|
||||
QUESTIONBOXCHANCES(MT_MIXUPBOX, cv_teleporters);
|
||||
QUESTIONBOXCHANCES(MT_RECYCLETV, cv_recycler);
|
||||
|
||||
#undef QUESTIONBOXCHANCES
|
||||
|
||||
if (numchoices == 0)
|
||||
if (item == MT_NULL)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("All monitors turned off.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
newbox = spawnchance[P_RandomKey(numchoices)];
|
||||
item = mobjinfo[newbox].damage;
|
||||
|
||||
remains->flags &= ~MF_AMBUSH;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
item = actor->info->damage;
|
||||
break;
|
||||
}
|
||||
|
||||
if (item != 0)
|
||||
{
|
||||
mobj_t *newmobj;
|
||||
|
||||
if (actor->eflags & MFE_VERTICALFLIP)
|
||||
{
|
||||
newmobj = P_SpawnMobj(actor->x, actor->y, actor->z + actor->height - FixedMul(13*FRACUNIT + mobjinfo[item].height, actor->scale), item);
|
||||
newmobj->eflags |= MFE_VERTICALFLIP;
|
||||
}
|
||||
else
|
||||
newmobj = P_SpawnMobj(actor->x, actor->y, actor->z + FixedMul(13*FRACUNIT, actor->scale), item);
|
||||
item = actor->info->damage;
|
||||
|
||||
newmobj->destscale = actor->destscale;
|
||||
P_SetScale(newmobj, actor->scale);
|
||||
if (item == 0)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Powerup item not defined in 'damage' field for A_MonitorPop\n");
|
||||
return;
|
||||
}
|
||||
|
||||
newmobj = P_SpawnMobjFromMobj(actor, 0, 0, 13*FRACUNIT, item);
|
||||
P_SetTarget(&newmobj->target, actor->target); // Transfer target
|
||||
if (item == MT_1UPICO && newmobj->target->player)
|
||||
|
||||
if (item == MT_1UP_ICON)
|
||||
{
|
||||
if (actor->tracer) // Remove the old lives icon.
|
||||
P_RemoveMobj(actor->tracer);
|
||||
|
||||
if (!newmobj->target->skin || ((skin_t *)newmobj->target->skin)->sprites[SPR2_LIFE].numframes == 0)
|
||||
newmobj->frame -= 2; // No lives icon for this player, use the default.
|
||||
if (!newmobj->target
|
||||
|| !newmobj->target->player
|
||||
|| !newmobj->target->skin
|
||||
|| ((skin_t *)newmobj->target->skin)->sprites[SPR2_LIFE].numframes == 0)
|
||||
{} // No lives icon for this player, use the default.
|
||||
else
|
||||
{ // Spawn the lives icon.
|
||||
remains = P_SpawnMobj(newmobj->x, newmobj->y, newmobj->z, MT_OVERLAY);
|
||||
P_SetTarget(&remains->target, newmobj);
|
||||
P_SetTarget(&newmobj->tracer, remains);
|
||||
mobj_t *livesico = P_SpawnMobjFromMobj(newmobj, 0, 0, 0, MT_OVERLAY);
|
||||
P_SetTarget(&livesico->target, newmobj);
|
||||
P_SetTarget(&newmobj->tracer, livesico);
|
||||
|
||||
remains->color = newmobj->target->player->mo->color;
|
||||
remains->skin = &skins[newmobj->target->player->skin];
|
||||
P_SetMobjState(remains, newmobj->info->seestate);
|
||||
livesico->color = newmobj->target->player->mo->color;
|
||||
livesico->skin = &skins[newmobj->target->player->skin];
|
||||
P_SetMobjState(livesico, newmobj->info->seestate);
|
||||
|
||||
// We're using the overlay, so use the overlay 1up sprite (no text)
|
||||
newmobj->sprite = SPR_TV1P;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Function: A_GoldMonitorPop
|
||||
//
|
||||
// Description: Used by repeating monitors when they turn off. They don't really pop, but, you know...
|
||||
//
|
||||
// var1 = unused
|
||||
// var2 = unused
|
||||
//
|
||||
void A_GoldMonitorPop(mobj_t *actor)
|
||||
{
|
||||
mobjtype_t item = 0;
|
||||
mobj_t *newmobj;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_GoldMonitorPop", actor))
|
||||
return;
|
||||
#endif
|
||||
|
||||
// Don't spawn the "pop" explosion, because the monitor isn't broken.
|
||||
if (actor->info->deathsound)
|
||||
S_StartSound(actor, actor->info->deathsound);
|
||||
//P_SpawnMobjFromMobj(actor, 0, 0, actor.height/4, MT_EXPLODE);
|
||||
|
||||
// Remove our flags for a bit.
|
||||
// Players can now stand on top of us.
|
||||
P_UnsetThingPosition(actor);
|
||||
actor->flags &= ~(MF_MONITOR|MF_SHOOTABLE);
|
||||
actor->flags2 |= MF2_STANDONME;
|
||||
P_SetThingPosition(actor);
|
||||
|
||||
// Don't count this box in statistics. Sorry.
|
||||
if (actor->target && actor->target->player)
|
||||
--actor->target->player->numboxes;
|
||||
actor->fuse = 0; // Don't let the monitor code screw us up.
|
||||
|
||||
if (actor->info->damage == MT_UNKNOWN)
|
||||
{
|
||||
// MT_UNKNOWN is random. Because it's unknown to us... get it?
|
||||
item = P_DoRandomBoxChances();
|
||||
|
||||
if (item == MT_NULL)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("All monitors turned off.\n"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
CONS_Debug(DBG_GAMELOGIC, "Powerup item not defined in 'damage' field for A_MonitorPop\n");
|
||||
item = actor->info->damage;
|
||||
|
||||
P_RemoveMobj(actor);
|
||||
if (item == 0)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Powerup item not defined in 'damage' field for A_GoldMonitorPop\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Note: the icon spawns 1 fracunit higher
|
||||
newmobj = P_SpawnMobjFromMobj(actor, 0, 0, 14*FRACUNIT, item);
|
||||
P_SetTarget(&newmobj->target, actor->target); // Transfer target
|
||||
|
||||
if (item == MT_1UP_ICON)
|
||||
{
|
||||
if (actor->tracer) // Remove the old lives icon.
|
||||
P_RemoveMobj(actor->tracer);
|
||||
|
||||
if (!newmobj->target
|
||||
|| !newmobj->target->player
|
||||
|| !newmobj->target->skin
|
||||
|| ((skin_t *)newmobj->target->skin)->sprites[SPR2_LIFE].numframes == 0)
|
||||
{} // No lives icon for this player, use the default.
|
||||
else
|
||||
{ // Spawn the lives icon.
|
||||
mobj_t *livesico = P_SpawnMobjFromMobj(newmobj, 0, 0, 0, MT_OVERLAY);
|
||||
P_SetTarget(&livesico->target, newmobj);
|
||||
P_SetTarget(&newmobj->tracer, livesico);
|
||||
|
||||
livesico->color = newmobj->target->player->mo->color;
|
||||
livesico->skin = &skins[newmobj->target->player->skin];
|
||||
P_SetMobjState(livesico, newmobj->info->seestate);
|
||||
|
||||
// We're using the overlay, so use the overlay 1up sprite (no text)
|
||||
newmobj->sprite = SPR_TV1P;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Function: A_GoldMonitorRestore
|
||||
//
|
||||
// Description: A repeating monitor is coming back to life. Reset monitor flags, etc.
|
||||
//
|
||||
// var1 = unused
|
||||
// var2 = unused
|
||||
//
|
||||
void A_GoldMonitorRestore(mobj_t *actor)
|
||||
{
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_GoldMonitorRestore", actor))
|
||||
return;
|
||||
#endif
|
||||
|
||||
actor->flags |= MF_MONITOR|MF_SHOOTABLE;
|
||||
actor->flags2 &= ~MF2_STANDONME;
|
||||
actor->health = 1; // Just in case.
|
||||
}
|
||||
|
||||
// Function: A_GoldMonitorSparkle
|
||||
//
|
||||
// Description: Spawns the little sparkly effect around big monitors. Looks pretty, doesn't it?
|
||||
//
|
||||
// var1 = unused
|
||||
// var2 = unused
|
||||
//
|
||||
void A_GoldMonitorSparkle(mobj_t *actor)
|
||||
{
|
||||
fixed_t i, ngangle, xofs, yofs;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_GoldMonitorSparkle", actor))
|
||||
return;
|
||||
#endif
|
||||
|
||||
ngangle = FixedAngle(((leveltime * 21) % 360) << FRACBITS);
|
||||
xofs = FINESINE((ngangle>>ANGLETOFINESHIFT) & FINEMASK) * (actor->radius>>FRACBITS);
|
||||
yofs = FINECOSINE((ngangle>>ANGLETOFINESHIFT) & FINEMASK) * (actor->radius>>FRACBITS);
|
||||
|
||||
for (i = FRACUNIT*2; i <= FRACUNIT*3; i += FRACUNIT/2)
|
||||
P_SetObjectMomZ(P_SpawnMobjFromMobj(actor, xofs, yofs, 0, MT_BOXSPARKLE), i, false);
|
||||
}
|
||||
|
||||
// Function: A_Explode
|
||||
|
@ -3151,8 +3245,11 @@ void A_ExtraLife(mobj_t *actor)
|
|||
|
||||
player = actor->target->player;
|
||||
|
||||
if (actor->type == MT_1UPICO && !actor->tracer)
|
||||
actor->frame -= 2; // No lives icon for this player, use the default.
|
||||
if (actor->type == MT_1UP_ICON && actor->tracer)
|
||||
{
|
||||
// We're using the overlay, so use the overlay 1up sprite (no text)
|
||||
actor->sprite = SPR_TV1P;
|
||||
}
|
||||
|
||||
if (ultimatemode) //I don't THINK so!
|
||||
{
|
||||
|
|
|
@ -1592,8 +1592,7 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour
|
|||
}
|
||||
else switch (source->type)
|
||||
{
|
||||
case MT_EGGMANICO:
|
||||
case MT_EGGMANBOX:
|
||||
case MT_EGGMAN_ICON:
|
||||
str = M_GetText("%s was %s by Eggman's nefarious TV magic.\n");
|
||||
break;
|
||||
case MT_SPIKE:
|
||||
|
@ -2899,10 +2898,10 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
if (!force)
|
||||
{
|
||||
// Special case for team ring boxes
|
||||
if (target->type == MT_REDRINGBOX && !(source->player->ctfteam == 1))
|
||||
if (target->type == MT_RING_REDBOX && !(source->player->ctfteam == 1))
|
||||
return false;
|
||||
|
||||
if (target->type == MT_BLUERINGBOX && !(source->player->ctfteam == 2))
|
||||
if (target->type == MT_RING_BLUEBOX && !(source->player->ctfteam == 2))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -241,6 +241,8 @@ boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover);
|
|||
boolean P_CheckDeathPitCollide(mobj_t *mo);
|
||||
boolean P_CheckSolidLava(mobj_t *mo, ffloor_t *rover);
|
||||
|
||||
mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zofs, mobjtype_t type);
|
||||
|
||||
mobj_t *P_SpawnMissile(mobj_t *source, mobj_t *dest, mobjtype_t type);
|
||||
mobj_t *P_SpawnXYZMissile(mobj_t *source, mobj_t *dest, mobjtype_t type, fixed_t x, fixed_t y, fixed_t z);
|
||||
mobj_t *P_SpawnPointMissile(mobj_t *source, fixed_t xa, fixed_t ya, fixed_t za, mobjtype_t type, fixed_t x, fixed_t y, fixed_t z);
|
||||
|
|
|
@ -1015,7 +1015,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
|||
|| (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2)
|
||||
|| ((tmthing->player->charflags & SF_STOMPDAMAGE)
|
||||
&& (P_MobjFlip(tmthing)*(tmthing->z - (thing->z + thing->height/2)) > 0) && (P_MobjFlip(tmthing)*tmthing->momz < 0)))
|
||||
&& !((thing->type == MT_REDRINGBOX && tmthing->player->ctfteam != 1) || (thing->type == MT_BLUERINGBOX && tmthing->player->ctfteam != 2)))
|
||||
&& !((thing->type == MT_RING_REDBOX && tmthing->player->ctfteam != 1) || (thing->type == MT_RING_BLUEBOX && tmthing->player->ctfteam != 2)))
|
||||
;
|
||||
// z checking at last
|
||||
// Treat noclip things as non-solid!
|
||||
|
|
220
src/p_mobj.c
220
src/p_mobj.c
|
@ -7588,9 +7588,60 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
mobj_t *flagmo, *newmobj;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (!LUAh_MobjFuse(mobj) && !P_MobjWasRemoved(mobj))
|
||||
if (LUAh_MobjFuse(mobj) || P_MobjWasRemoved(mobj))
|
||||
;
|
||||
else
|
||||
#endif
|
||||
switch (mobj->type)
|
||||
if (mobj->info->flags & MF_MONITOR)
|
||||
{
|
||||
// Special case for ALL monitors.
|
||||
// If a box's speed is nonzero, it's allowed to respawn as a WRM/SRM.
|
||||
if (mobj->info->speed != 0 && (mobj->flags & MF_AMBUSH || mobj->flags2 & MF2_STRONGBOX))
|
||||
{
|
||||
mobjtype_t spawnchance[64];
|
||||
INT32 numchoices = 0, i = 0;
|
||||
|
||||
// This define should make it a lot easier to organize and change monitor weights
|
||||
#define SETMONITORCHANCES(type, strongboxamt, weakboxamt) \
|
||||
for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) spawnchance[numchoices++] = type
|
||||
|
||||
// Type SRM WRM
|
||||
SETMONITORCHANCES(MT_SNEAKERS_BOX, 0, 10); // Super Sneakers
|
||||
SETMONITORCHANCES(MT_INVULN_BOX, 2, 0); // Invincibility
|
||||
SETMONITORCHANCES(MT_WHIRLWIND_BOX, 3, 8); // Whirlwind Shield
|
||||
SETMONITORCHANCES(MT_ELEMENTAL_BOX, 3, 8); // Elemental Shield
|
||||
SETMONITORCHANCES(MT_ATTRACT_BOX, 2, 0); // Attraction Shield
|
||||
SETMONITORCHANCES(MT_FORCE_BOX, 3, 3); // Force Shield
|
||||
SETMONITORCHANCES(MT_ARMAGEDDON_BOX, 2, 0); // Armageddon Shield
|
||||
SETMONITORCHANCES(MT_MIXUP_BOX, 0, 1); // Teleporters
|
||||
SETMONITORCHANCES(MT_RECYCLER_BOX, 0, 1); // Recycler
|
||||
SETMONITORCHANCES(MT_1UP_BOX, 1, 1); // 1-Up
|
||||
// =======================================
|
||||
// Total 16 32
|
||||
|
||||
#undef SETMONITORCHANCES
|
||||
|
||||
i = P_RandomKey(numchoices); // Gotta love those random numbers!
|
||||
newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, spawnchance[i]);
|
||||
|
||||
// If the monitor respawns randomly, transfer the flag.
|
||||
if (mobj->flags & MF_AMBUSH)
|
||||
newmobj->flags |= MF_AMBUSH;
|
||||
|
||||
// Transfer flags2 (strongbox, objectflip)
|
||||
newmobj->flags2 = mobj->flags2;
|
||||
}
|
||||
else
|
||||
{
|
||||
newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->type);
|
||||
|
||||
// Transfer flags2 (strongbox, objectflip)
|
||||
newmobj->flags2 = mobj->flags2;
|
||||
}
|
||||
P_RemoveMobj(mobj); // make sure they disappear
|
||||
return;
|
||||
}
|
||||
else switch (mobj->type)
|
||||
{
|
||||
// gargoyle and snowman handled in P_PushableThinker, not here
|
||||
case MT_THROWNGRENADE:
|
||||
|
@ -7649,68 +7700,6 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
}
|
||||
P_RemoveMobj(mobj);
|
||||
return;
|
||||
case MT_YELLOWTV: // Ring shield box
|
||||
case MT_BLUETV: // Force shield box
|
||||
case MT_GREENTV: // Water shield box
|
||||
case MT_BLACKTV: // Bomb shield box
|
||||
case MT_WHITETV: // Jump shield box
|
||||
case MT_SNEAKERTV: // Super Sneaker box
|
||||
case MT_SUPERRINGBOX: // 10-Ring box
|
||||
case MT_REDRINGBOX: // Red Team 10-Ring box
|
||||
case MT_BLUERINGBOX: // Blue Team 10-Ring box
|
||||
case MT_INV: // Invincibility box
|
||||
case MT_MIXUPBOX: // Teleporter Mixup box
|
||||
case MT_RECYCLETV: // Recycler box
|
||||
case MT_SCORETVSMALL:
|
||||
case MT_SCORETVLARGE:
|
||||
case MT_PRUP: // 1up!
|
||||
case MT_EGGMANBOX: // Eggman box
|
||||
case MT_GRAVITYBOX: // Gravity box
|
||||
case MT_QUESTIONBOX:
|
||||
if ((mobj->flags & MF_AMBUSH || mobj->flags2 & MF2_STRONGBOX) && mobj->type != MT_QUESTIONBOX)
|
||||
{
|
||||
mobjtype_t spawnchance[64];
|
||||
INT32 numchoices = 0, i = 0;
|
||||
|
||||
// This define should make it a lot easier to organize and change monitor weights
|
||||
#define SETMONITORCHANCES(type, strongboxamt, weakboxamt) \
|
||||
for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) spawnchance[numchoices++] = type
|
||||
|
||||
// Type SRM WRM
|
||||
SETMONITORCHANCES(MT_SNEAKERTV, 0, 10); // Super Sneakers
|
||||
SETMONITORCHANCES(MT_INV, 2, 0); // Invincibility
|
||||
SETMONITORCHANCES(MT_WHITETV, 3, 8); // Whirlwind Shield
|
||||
SETMONITORCHANCES(MT_GREENTV, 3, 8); // Elemental Shield
|
||||
SETMONITORCHANCES(MT_YELLOWTV, 2, 0); // Attraction Shield
|
||||
SETMONITORCHANCES(MT_BLUETV, 3, 3); // Force Shield
|
||||
SETMONITORCHANCES(MT_BLACKTV, 2, 0); // Armageddon Shield
|
||||
SETMONITORCHANCES(MT_MIXUPBOX, 0, 1); // Teleporters
|
||||
SETMONITORCHANCES(MT_RECYCLETV, 0, 1); // Recycler
|
||||
SETMONITORCHANCES(MT_PRUP, 1, 1); // 1-Up
|
||||
// ======================================
|
||||
// Total 16 32
|
||||
|
||||
#undef SETMONITORCHANCES
|
||||
|
||||
i = P_RandomKey(numchoices); // Gotta love those random numbers!
|
||||
newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, spawnchance[i]);
|
||||
|
||||
// If the monitor respawns randomly, transfer the flag.
|
||||
if (mobj->flags & MF_AMBUSH)
|
||||
newmobj->flags |= MF_AMBUSH;
|
||||
|
||||
// Transfer flags2 (strongbox, objectflip)
|
||||
newmobj->flags2 = mobj->flags2;
|
||||
}
|
||||
else
|
||||
{
|
||||
newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->type);
|
||||
|
||||
// Transfer flags2 (strongbox, objectflip)
|
||||
newmobj->flags2 = mobj->flags2;
|
||||
}
|
||||
P_RemoveMobj(mobj); // make sure they disappear
|
||||
return;
|
||||
case MT_METALSONIC_BATTLE:
|
||||
break; // don't remove
|
||||
case MT_SPIKE:
|
||||
|
@ -7727,6 +7716,7 @@ for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) s
|
|||
default:
|
||||
P_SetMobjState(mobj, mobj->info->xdeathstate); // will remove the mobj if S_NULL.
|
||||
break;
|
||||
// Looking for monitors? They moved to a special condition above.
|
||||
}
|
||||
if (P_MobjWasRemoved(mobj))
|
||||
return;
|
||||
|
@ -9177,36 +9167,37 @@ void P_SpawnMapThing(mapthing_t *mthing)
|
|||
if ((mobjinfo[i].flags & MF_ENEMY) || (mobjinfo[i].flags & MF_BOSS))
|
||||
return;
|
||||
|
||||
// Set powerup boxes to user settings for competition.
|
||||
// Altering monitor spawns via cvars
|
||||
// If MF_GRENADEBOUNCE is set in the monitor's info,
|
||||
// skip this step. (Used for gold monitors)
|
||||
// Yeah, this is a dirty hack.
|
||||
if ((mobjinfo[i].flags & (MF_MONITOR|MF_GRENADEBOUNCE)) == MF_MONITOR)
|
||||
{
|
||||
if (gametype == GT_COMPETITION)
|
||||
{
|
||||
if ((mobjinfo[i].flags & MF_MONITOR) && cv_competitionboxes.value) // not Normal
|
||||
{
|
||||
// Set powerup boxes to user settings for competition.
|
||||
if (cv_competitionboxes.value == 1) // Random
|
||||
i = MT_QUESTIONBOX;
|
||||
i = MT_MYSTERY_BOX;
|
||||
else if (cv_competitionboxes.value == 2) // Teleports
|
||||
i = MT_MIXUPBOX;
|
||||
i = MT_MIXUP_BOX;
|
||||
else if (cv_competitionboxes.value == 3) // None
|
||||
return; // Don't spawn!
|
||||
// default case: normal
|
||||
}
|
||||
}
|
||||
|
||||
// Set powerup boxes to user settings for other netplay modes
|
||||
else if (gametype != GT_COOP)
|
||||
{
|
||||
if ((mobjinfo[i].flags & MF_MONITOR) && cv_matchboxes.value) // not Normal
|
||||
{
|
||||
if (cv_matchboxes.value == 1) // Random
|
||||
i = MT_QUESTIONBOX;
|
||||
else if (cv_matchboxes.value == 3) // Don't spawn
|
||||
return;
|
||||
else // cv_matchboxes.value == 2, Non-Random
|
||||
i = MT_MYSTERY_BOX;
|
||||
else if (cv_matchboxes.value == 2) // Non-Random
|
||||
{
|
||||
if (i == MT_QUESTIONBOX)
|
||||
if (i == MT_MYSTERY_BOX)
|
||||
return; // don't spawn in Non-Random
|
||||
|
||||
mthing->options &= ~(MTF_AMBUSH|MTF_OBJECTSPECIAL); // no random respawning!
|
||||
}
|
||||
else if (cv_matchboxes.value == 3) // Don't spawn
|
||||
return;
|
||||
// default case: normal
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9214,8 +9205,8 @@ void P_SpawnMapThing(mapthing_t *mthing)
|
|||
{
|
||||
if (i == MT_BLUETEAMRING || i == MT_REDTEAMRING)
|
||||
i = MT_RING;
|
||||
else if (i == MT_BLUERINGBOX || i == MT_REDRINGBOX)
|
||||
i = MT_SUPERRINGBOX;
|
||||
else if (i == MT_RING_BLUEBOX || i == MT_RING_REDBOX)
|
||||
i = MT_RING_BOX;
|
||||
else if (i == MT_BLUEFLAG || i == MT_REDFLAG)
|
||||
return; // No flags in non-CTF modes!
|
||||
}
|
||||
|
@ -9242,23 +9233,27 @@ void P_SpawnMapThing(mapthing_t *mthing)
|
|||
return; /// \todo
|
||||
|
||||
// 1UPs -->> Score TVs
|
||||
else if (i == MT_PRUP) // 1UP
|
||||
else if (i == MT_1UP_BOX) // 1UP
|
||||
{
|
||||
// Either or, doesn't matter which.
|
||||
if (mthing->options & (MTF_AMBUSH|MTF_OBJECTSPECIAL))
|
||||
i = MT_SCORETVLARGE; // 10,000
|
||||
i = MT_SCORE10K_BOX; // 10,000
|
||||
else
|
||||
i = MT_SCORETVSMALL; // 1,000
|
||||
i = MT_SCORE1K_BOX; // 1,000
|
||||
}
|
||||
}
|
||||
|
||||
if (ultimatemode)
|
||||
{
|
||||
if (i == MT_PITYTV || i == MT_GREENTV || i == MT_YELLOWTV || i == MT_BLUETV || i == MT_BLACKTV || i == MT_WHITETV)
|
||||
if (i == MT_PITY_BOX || i == MT_ELEMENTAL_BOX || i == MT_ATTRACT_BOX
|
||||
|| i == MT_FORCE_BOX || i == MT_ARMAGEDDON_BOX || i == MT_WHIRLWIND_BOX)
|
||||
return; // No shields in Ultimate mode
|
||||
|
||||
if (i == MT_SUPERRINGBOX && !G_IsSpecialStage(gamemap))
|
||||
if (i == MT_RING_BOX && !G_IsSpecialStage(gamemap))
|
||||
return; // No rings in Ultimate mode (except special stages)
|
||||
|
||||
// Don't include the gold repeating boxes here please.
|
||||
// They're likely facets of the level's design and therefore required to progress.
|
||||
}
|
||||
|
||||
if (i == MT_EMMY && (gametype != GT_COOP || ultimatemode || tokenbits == 30 || tokenlist & (1 << tokenbits++)))
|
||||
|
@ -9681,7 +9676,7 @@ ML_NOCLIMB : Direction not controllable
|
|||
}
|
||||
|
||||
//count 10 ring boxes into the number of rings equation too.
|
||||
if (i == MT_SUPERRINGBOX)
|
||||
if (i == MT_RING_BOX)
|
||||
nummaprings += 10;
|
||||
|
||||
if (i == MT_BIGTUMBLEWEED || i == MT_LITTLETUMBLEWEED)
|
||||
|
@ -9760,15 +9755,10 @@ ML_NOCLIMB : Direction not controllable
|
|||
mobj->flags2 |= MF2_STANDONME;
|
||||
}
|
||||
|
||||
if (mobj->flags & MF_MONITOR)
|
||||
if ((mobj->flags & MF_MONITOR) && mobj->info->speed != 0)
|
||||
{
|
||||
// flag for strong/weak random boxes
|
||||
if (mthing->type == mobjinfo[MT_SUPERRINGBOX].doomednum || mthing->type == mobjinfo[MT_PRUP].doomednum ||
|
||||
mthing->type == mobjinfo[MT_SNEAKERTV].doomednum || mthing->type == mobjinfo[MT_INV].doomednum ||
|
||||
mthing->type == mobjinfo[MT_WHITETV].doomednum || mthing->type == mobjinfo[MT_GREENTV].doomednum ||
|
||||
mthing->type == mobjinfo[MT_YELLOWTV].doomednum || mthing->type == mobjinfo[MT_BLUETV].doomednum ||
|
||||
mthing->type == mobjinfo[MT_BLACKTV].doomednum || mthing->type == mobjinfo[MT_PITYTV].doomednum ||
|
||||
mthing->type == mobjinfo[MT_RECYCLETV].doomednum || mthing->type == mobjinfo[MT_MIXUPBOX].doomednum)
|
||||
// any monitor with nonzero speed is allowed to respawn like this
|
||||
mobj->flags |= MF_AMBUSH;
|
||||
}
|
||||
|
||||
|
@ -9781,15 +9771,13 @@ ML_NOCLIMB : Direction not controllable
|
|||
}
|
||||
|
||||
if (mthing->options & MTF_OBJECTSPECIAL)
|
||||
{
|
||||
if ((mobj->flags & MF_MONITOR) && mobj->info->speed != 0)
|
||||
{
|
||||
// flag for strong/weak random boxes
|
||||
if (mthing->type == mobjinfo[MT_SUPERRINGBOX].doomednum || mthing->type == mobjinfo[MT_PRUP].doomednum ||
|
||||
mthing->type == mobjinfo[MT_SNEAKERTV].doomednum || mthing->type == mobjinfo[MT_INV].doomednum ||
|
||||
mthing->type == mobjinfo[MT_WHITETV].doomednum || mthing->type == mobjinfo[MT_GREENTV].doomednum ||
|
||||
mthing->type == mobjinfo[MT_YELLOWTV].doomednum || mthing->type == mobjinfo[MT_BLUETV].doomednum ||
|
||||
mthing->type == mobjinfo[MT_BLACKTV].doomednum || mthing->type == mobjinfo[MT_PITYTV].doomednum ||
|
||||
mthing->type == mobjinfo[MT_RECYCLETV].doomednum || mthing->type == mobjinfo[MT_MIXUPBOX].doomednum)
|
||||
// any monitor with nonzero speed is allowed to respawn like this
|
||||
mobj->flags2 |= MF2_STRONGBOX;
|
||||
}
|
||||
|
||||
// Requires you to be in bonus time to activate
|
||||
if (mobj->flags & MF_NIGHTSITEM)
|
||||
|
@ -10778,3 +10766,35 @@ void P_FlashPal(player_t *pl, UINT16 type, UINT16 duration)
|
|||
pl->flashcount = duration;
|
||||
pl->flashpal = type;
|
||||
}
|
||||
|
||||
//
|
||||
// P_SpawnMobjFromMobj
|
||||
// Spawns an object with offsets relative to the position of another object.
|
||||
// Scale, gravity flip, etc. is taken into account automatically.
|
||||
//
|
||||
mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zofs, mobjtype_t type)
|
||||
{
|
||||
mobj_t *newmobj;
|
||||
|
||||
xofs = FixedMul(xofs, mobj->scale);
|
||||
yofs = FixedMul(yofs, mobj->scale);
|
||||
zofs = FixedMul(zofs, mobj->scale);
|
||||
|
||||
newmobj = P_SpawnMobj(mobj->x + xofs, mobj->y + yofs, mobj->z + zofs, type);
|
||||
if (!newmobj)
|
||||
return NULL;
|
||||
|
||||
if (mobj->eflags & MFE_VERTICALFLIP)
|
||||
{
|
||||
fixed_t elementheight = FixedMul(newmobj->info->height, mobj->scale);
|
||||
|
||||
newmobj->eflags |= MFE_VERTICALFLIP;
|
||||
newmobj->flags2 |= MF2_OBJECTFLIP;
|
||||
newmobj->z = mobj->z + mobj->height - zofs - elementheight;
|
||||
}
|
||||
|
||||
newmobj->destscale = mobj->destscale;
|
||||
P_SetScale(newmobj, mobj->scale);
|
||||
return newmobj;
|
||||
}
|
||||
|
||||
|
|
|
@ -8627,7 +8627,7 @@ void P_DoPityCheck(player_t *player)
|
|||
if ((player->pity >= 3 || player->pity < 0) && player->powers[pw_shield] == SH_NONE)
|
||||
{
|
||||
if (player->pity > 0)
|
||||
S_StartSound(player->mo, mobjinfo[MT_PITYSHIELDICO].seesound);
|
||||
S_StartSound(player->mo, mobjinfo[MT_PITY_ICON].seesound);
|
||||
|
||||
player->pity = 0;
|
||||
player->powers[pw_shield] = SH_PITY;
|
||||
|
|
|
@ -159,6 +159,7 @@ sfxinfo_t S_sfx[NUMSFX] =
|
|||
{"lvpass", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR},
|
||||
{"mindig", false, 8, 64, -1, NULL, 0, -1, -1, LUMPERROR},
|
||||
{"mixup", true, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR},
|
||||
{"monton", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
|
||||
{"pogo" , false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
|
||||
{"pop" , false, 78, 0, -1, NULL, 0, -1, -1, LUMPERROR},
|
||||
{"rail1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},
|
||||
|
|
|
@ -222,6 +222,7 @@ typedef enum
|
|||
sfx_lvpass,
|
||||
sfx_mindig,
|
||||
sfx_mixup,
|
||||
sfx_monton,
|
||||
sfx_pogo,
|
||||
sfx_pop,
|
||||
sfx_rail1,
|
||||
|
|
Loading…
Reference in a new issue