From f0a6a112acb913c1ba7fea5fe800fd9cce53e8e6 Mon Sep 17 00:00:00 2001 From: NepDisk Date: Wed, 9 Apr 2025 13:45:35 -0400 Subject: [PATCH] Port v1 objects pt 4 --- src/doomdef.h | 4 - src/info/actions.h | 1 + src/info/mobjs.h | 115 ++++++-------- src/info/sprites.h | 49 +++--- src/info/states.h | 367 ++++++++++++++++++++++++--------------------- src/p_enemy.c | 307 ++++++++++++++++++++++--------------- src/p_floor.c | 8 + src/p_inter.c | 26 ++++ src/p_local.h | 2 + src/p_mobj.c | 113 ++++++++++++-- 10 files changed, 588 insertions(+), 404 deletions(-) diff --git a/src/doomdef.h b/src/doomdef.h index fd61076ce..92dcc9986 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -492,10 +492,6 @@ extern int compuncommitted; /// Dumps the contents of a network save game upon consistency failure for debugging. //#define DUMPCONSISTENCY -/// Who put weights on my recycler? ... Inuyasha did. -/// \note XMOD port. -//#define WEIGHTEDRECYCLER - /// Allow loading of savegames between different versions of the game. /// \note XMOD port. /// Most modifications should probably enable this. diff --git a/src/info/actions.h b/src/info/actions.h index 48cae73ca..676e0caac 100644 --- a/src/info/actions.h +++ b/src/info/actions.h @@ -1,3 +1,4 @@ +_(A_MonitorPop, MONITORPOP) _(A_Explode, EXPLODE) _(A_Pain, PAIN) _(A_Fall, FALL) diff --git a/src/info/mobjs.h b/src/info/mobjs.h index d46d3e983..9458fe8de 100644 --- a/src/info/mobjs.h +++ b/src/info/mobjs.h @@ -14,6 +14,7 @@ _(REDCRAWLA) // Crawla (Red) _(GFZFISH) // SDURF _(GOLDBUZZ) // Buzz (Gold) _(REDBUZZ) // Buzz (Red) +_(AQUABUZZ) _(JETTBOMBER) // Jetty-Syn Bomber _(JETTGUNNER) // Jetty-Syn Gunner _(CRAWLACOMMANDER) // Crawla Commander @@ -33,7 +34,6 @@ _(EGGGUARD) // Egg Guard _(EGGSHIELD) // Egg Guard's shield _(GSNAPPER) // Green Snapper _(MINUS) // Minus -_(MINUSDIRT) // Minus dirt _(SPRINGSHELL) // Spring Shell _(YELLOWSHELL) // Spring Shell (yellow) _(UNIDUS) // Unidus @@ -106,6 +106,7 @@ _(FLINGBLUESPHERE) // Lost blue sphere _(BOMBSPHERE) _(REDTEAMRING) // Rings collectable by red team. _(BLUETEAMRING) // Rings collectable by blue team. +_(EMMY) // Special Stage token for special stage _(TOKEN) // Special Stage token for special stage _(REDFLAG) // Red CTF Flag _(BLUEFLAG) // Blue CTF Flag @@ -156,73 +157,51 @@ _(WALLSPIKE) _(WALLSPIKEBASE) _(STARPOST) _(BIGMINE) +_(BIGAIRMINE) _(BLASTEXECUTOR) _(CANNONLAUNCHER) +// Monitor Boxes +_(SUPERRINGBOX) +_(REDRINGBOX) +_(BLUERINGBOX) +_(SNEAKERTV) +_(INV) +_(PRUP) // 1up Box +_(YELLOWTV) +_(BLUETV) +_(BLACKTV) // Bomb shield TV +_(WHITETV) // Jump shield TV +_(GREENTV) +_(PITYTV) // Pity Shield TV +_(EGGMANBOX) +_(MIXUPBOX) +_(RECYCLETV) +_(RECYCLEICO) +_(QUESTIONBOX) +_(GRAVITYBOX) +_(SCORETVSMALL) +_(SCORETVLARGE) + // Monitor miscellany -_(BOXSPARKLE) - -// Monitor boxes -- regular -_(RING_BOX) -_(PITY_BOX) -_(ATTRACT_BOX) -_(FORCE_BOX) -_(ARMAGEDDON_BOX) -_(WHIRLWIND_BOX) -_(ELEMENTAL_BOX) -_(SNEAKERS_BOX) -_(INVULN_BOX) -_(1UP_BOX) -_(EGGMAN_BOX) -_(MIXUP_BOX) -_(MYSTERY_BOX) -_(GRAVITY_BOX) -_(RECYCLER_BOX) -_(SCORE1K_BOX) -_(SCORE10K_BOX) -_(FLAMEAURA_BOX) -_(BUBBLEWRAP_BOX) -_(THUNDERCOIN_BOX) - -// Monitor boxes -- repeating (big) boxes -_(PITY_GOLDBOX) -_(ATTRACT_GOLDBOX) -_(FORCE_GOLDBOX) -_(ARMAGEDDON_GOLDBOX) -_(WHIRLWIND_GOLDBOX) -_(ELEMENTAL_GOLDBOX) -_(SNEAKERS_GOLDBOX) -_(INVULN_GOLDBOX) -_(EGGMAN_GOLDBOX) -_(GRAVITY_GOLDBOX) -_(FLAMEAURA_GOLDBOX) -_(BUBBLEWRAP_GOLDBOX) -_(THUNDERCOIN_GOLDBOX) - -// Monitor boxes -- special -_(RING_REDBOX) -_(RING_BLUEBOX) - -// Monitor icons -_(RING_ICON) -_(PITY_ICON) -_(ATTRACT_ICON) -_(FORCE_ICON) -_(ARMAGEDDON_ICON) -_(WHIRLWIND_ICON) -_(ELEMENTAL_ICON) -_(SNEAKERS_ICON) -_(INVULN_ICON) -_(1UP_ICON) -_(EGGMAN_ICON) -_(MIXUP_ICON) -_(GRAVITY_ICON) -_(RECYCLER_ICON) -_(SCORE1K_ICON) -_(SCORE10K_ICON) -_(FLAMEAURA_ICON) -_(BUBBLEWRAP_ICON) -_(THUNDERCOIN_ICON) +_(MONITOREXPLOSION) +_(REDMONITOREXPLOSION) +_(BLUEMONITOREXPLOSION) +_(RINGICO) +_(SHOESICO) +_(INVCICO) +_(1UPICO) +_(YSHIELDICO) +_(BSHIELDICO) +_(KSHIELDICO) +_(WSHIELDICO) +_(GSHIELDICO) +_(PITYSHIELDICO) +_(EGGMANICO) +_(MIXUPICO) +_(GRAVITYICO) +_(SCOREICOSMALL) +_(SCOREICOLARGE) // Projectiles _(ROCKET) @@ -305,10 +284,10 @@ _(FLAMEJETFLAMEB) // Blade's flame // Egg Rock Scenery // Azure Temple Scenery -_(GLAREGOYLE) -_(GLAREGOYLEUP) -_(GLAREGOYLEDOWN) -_(GLAREGOYLELONG) +_(TRAPGOYLE) +_(TRAPGOYLEUP) +_(TRAPGOYLEDOWN) +_(TRAPGOYLELONG) _(TARGET) // AKA Red Crystal _(GREENFLAME) _(BLUEGARGOYLE) diff --git a/src/info/sprites.h b/src/info/sprites.h index adf03818a..210902f9d 100644 --- a/src/info/sprites.h +++ b/src/info/sprites.h @@ -34,7 +34,6 @@ _(SPSH) // Egg Guard _(ESHI) // Egg Guard's shield _(GSNP) // Green Snapper _(MNUS) // Minus -_(MNUD) // Minus dirt _(SSHL) // Spring Shell _(UNID) // Unidus @@ -98,6 +97,7 @@ _(MSCB) // Collectible Items _(RING) _(TRNG) // Team Rings +_(EMMY) // Special Stage Token _(TOKE) // Special Stage Token _(RFLG) // Red CTF Flag _(BFLG) // Blue CTF Flag @@ -122,33 +122,27 @@ _(BMNE) // Big floating mine _(PUMI) // Rollout Rock // Monitor Boxes -_(MSTV) // MiSc TV sprites -_(XLTV) // eXtra Large TV sprites +_(SRBX) +_(RRBX) +_(BRBX) +_(SHTV) +_(PINV) +_(YLTV) +_(BLTV) // Force shield +_(BKTV) // Bomb shield TV +_(WHTV) // Jump shield TV +_(GRTV) // Pity shield TV +_(ELTV) // Elemental shield TV +_(EGGB) // Eggman box +_(MIXU) // Player mixing monitor +_(RECY) // Recycler (power mixing) monitor +_(QUES) // Random monitor +_(GBTV) // Gravity boots TV +_(PRUP) // 1up +_(PTTV) // Score TVs -_(TRRI) // Red team: 10 RIngs -_(TBRI) // Blue team: 10 RIngs - -_(TVRI) // 10 RIng -_(TVPI) // PIty shield -_(TVAT) // ATtraction shield -_(TVFO) // FOrce shield -_(TVAR) // ARmageddon shield -_(TVWW) // WhirlWind shield -_(TVEL) // ELemental shield -_(TVSS) // Super Sneakers -_(TVIV) // InVincibility -_(TV1U) // 1Up -_(TV1P) // 1uP (textless) -_(TVEG) // EGgman -_(TVMX) // MiXup -_(TVMY) // MYstery -_(TVGV) // GraVity boots -_(TVRC) // ReCycler -_(TV1K) // 1,000 points (1 K) -_(TVTK) // 10,000 points (Ten K) -_(TVFL) // FLame shield -_(TVBB) // BuBble shield -_(TVZP) // Thunder shield (ZaP) +// Monitor Miscellany +_(MTEX) // Exploding monitor // Projectiles _(MISL) @@ -220,7 +214,6 @@ _(XMS6) // Mistletoe _(FHZI) // FHZ Ice _(ROSY) // Azure Temple Scenery -_(BGAR) // ATZ Gargoyles _(RCRY) // ATZ Red Crystal (Target) _(CFLM) // Green torch flame diff --git a/src/info/states.h b/src/info/states.h index f2fd095a7..1524c4efa 100644 --- a/src/info/states.h +++ b/src/info/states.h @@ -87,6 +87,10 @@ _(RBUZZLOOK2) _(RBUZZFLY1) _(RBUZZFLY2) +// AquaBuzz +_(BBUZZFLY1) +_(BBUZZFLY2) + // Jetty-Syn Bomber _(JETBLOOK1) _(JETBLOOK2) @@ -260,32 +264,25 @@ _(GSNAPPER3) _(GSNAPPER4) // Minus -_(MINUS_INIT) _(MINUS_STND) -_(MINUS_DIGGING1) -_(MINUS_DIGGING2) -_(MINUS_DIGGING3) -_(MINUS_DIGGING4) -_(MINUS_BURST0) -_(MINUS_BURST1) -_(MINUS_BURST2) -_(MINUS_BURST3) -_(MINUS_BURST4) -_(MINUS_BURST5) +_(MINUS_DIGGING) _(MINUS_POPUP) -_(MINUS_AERIAL1) -_(MINUS_AERIAL2) -_(MINUS_AERIAL3) -_(MINUS_AERIAL4) - -// Minus dirt -_(MINUSDIRT1) -_(MINUSDIRT2) -_(MINUSDIRT3) -_(MINUSDIRT4) -_(MINUSDIRT5) -_(MINUSDIRT6) -_(MINUSDIRT7) +_(MINUS_UPWARD1) +_(MINUS_UPWARD2) +_(MINUS_UPWARD3) +_(MINUS_UPWARD4) +_(MINUS_UPWARD5) +_(MINUS_UPWARD6) +_(MINUS_UPWARD7) +_(MINUS_UPWARD8) +_(MINUS_DOWNWARD1) +_(MINUS_DOWNWARD2) +_(MINUS_DOWNWARD3) +_(MINUS_DOWNWARD4) +_(MINUS_DOWNWARD5) +_(MINUS_DOWNWARD6) +_(MINUS_DOWNWARD7) +_(MINUS_DOWNWARD8) // Spring Shell _(SSHELL_STND) @@ -814,7 +811,9 @@ _(GRAVWELLRED) _(TEAMRING) // Special Stage Token +_(EMMY) _(TOKEN) +_(MOVINGTOKEN) // CTF Flags _(REDFLAG) @@ -945,148 +944,184 @@ _(STARPOST_SPIN) _(STARPOST_ENDSPIN) // Big floating mine -_(BIGMINE_IDLE) -_(BIGMINE_ALERT1) -_(BIGMINE_ALERT2) -_(BIGMINE_ALERT3) -_(BIGMINE_SET1) -_(BIGMINE_SET2) -_(BIGMINE_SET3) -_(BIGMINE_BLAST1) -_(BIGMINE_BLAST2) -_(BIGMINE_BLAST3) -_(BIGMINE_BLAST4) -_(BIGMINE_BLAST5) +_(BIGMINE1) +_(BIGMINE2) +_(BIGMINE3) +_(BIGMINE4) +_(BIGMINE5) +_(BIGMINE6) +_(BIGMINE7) +_(BIGMINE8) // Cannon Launcher _(CANNONLAUNCHER1) _(CANNONLAUNCHER2) _(CANNONLAUNCHER3) -// Monitor Miscellany -_(BOXSPARKLE1) -_(BOXSPARKLE2) -_(BOXSPARKLE3) -_(BOXSPARKLE4) +// Super Ring Box +_(SUPERRINGBOX) +_(SUPERRINGBOX1) +_(SUPERRINGBOX2) +_(SUPERRINGBOX3) +_(SUPERRINGBOX4) +_(SUPERRINGBOX5) +_(SUPERRINGBOX6) -_(BOX_FLICKER) -_(BOX_POP1) -_(BOX_POP2) +// Red Team Ring Box +_(REDRINGBOX) +_(REDRINGBOX1) -_(GOLDBOX_FLICKER) -_(GOLDBOX_OFF1) -_(GOLDBOX_OFF2) -_(GOLDBOX_OFF3) -_(GOLDBOX_OFF4) -_(GOLDBOX_OFF5) -_(GOLDBOX_OFF6) -_(GOLDBOX_OFF7) +// Blue Team Ring Box +_(BLUERINGBOX) +_(BLUERINGBOX1) -// Monitor States (one per box) -_(MYSTERY_BOX) -_(RING_BOX) -_(PITY_BOX) -_(ATTRACT_BOX) -_(FORCE_BOX) -_(ARMAGEDDON_BOX) -_(WHIRLWIND_BOX) -_(ELEMENTAL_BOX) -_(SNEAKERS_BOX) -_(INVULN_BOX) -_(1UP_BOX) -_(EGGMAN_BOX) -_(MIXUP_BOX) -_(GRAVITY_BOX) -_(RECYCLER_BOX) -_(SCORE1K_BOX) -_(SCORE10K_BOX) -_(FLAMEAURA_BOX) -_(BUBBLEWRAP_BOX) -_(THUNDERCOIN_BOX) +// Super Sneakers Box +_(SHTV) +_(SHTV1) +_(SHTV2) +_(SHTV3) +_(SHTV4) +_(SHTV5) +_(SHTV6) -// Gold Repeat Monitor States (one per box) -_(PITY_GOLDBOX) -_(ATTRACT_GOLDBOX) -_(FORCE_GOLDBOX) -_(ARMAGEDDON_GOLDBOX) -_(WHIRLWIND_GOLDBOX) -_(ELEMENTAL_GOLDBOX) -_(SNEAKERS_GOLDBOX) -_(INVULN_GOLDBOX) -_(EGGMAN_GOLDBOX) -_(GRAVITY_GOLDBOX) -_(FLAMEAURA_GOLDBOX) -_(BUBBLEWRAP_GOLDBOX) -_(THUNDERCOIN_GOLDBOX) +// Invincibility Box +_(PINV) +_(PINV1) +_(PINV2) +_(PINV3) +_(PINV4) +_(PINV5) +_(PINV6) -// Team Ring Boxes (these are special) -_(RING_REDBOX1) -_(RING_REDBOX2) -_(REDBOX_POP1) -_(REDBOX_POP2) +// 1up Box +_(PRUP) +_(PRUP1) +_(PRUP2) +_(PRUP3) +_(PRUP4) +_(PRUP5) +_(PRUP6) -_(RING_BLUEBOX1) -_(RING_BLUEBOX2) -_(BLUEBOX_POP1) -_(BLUEBOX_POP2) +// Ring Shield Box +_(YLTV) +_(YLTV1) +_(YLTV2) +_(YLTV3) +_(YLTV4) +_(YLTV5) +_(YLTV6) -// Box Icons -- 2 states each, animation and action -_(RING_ICON1) -_(RING_ICON2) +// Force Shield Box +_(BLTV1) +_(BLTV2) +_(BLTV3) +_(BLTV4) +_(BLTV5) +_(BLTV6) +_(BLTV7) -_(PITY_ICON1) -_(PITY_ICON2) +// Bomb Shield Box +_(BKTV1) +_(BKTV2) +_(BKTV3) +_(BKTV4) +_(BKTV5) +_(BKTV6) +_(BKTV7) -_(ATTRACT_ICON1) -_(ATTRACT_ICON2) +// Jump Shield Box +_(WHTV1) +_(WHTV2) +_(WHTV3) +_(WHTV4) +_(WHTV5) +_(WHTV6) +_(WHTV7) -_(FORCE_ICON1) -_(FORCE_ICON2) +// Water Shield Box +_(GRTV) +_(GRTV1) +_(GRTV2) +_(GRTV3) +_(GRTV4) +_(GRTV5) +_(GRTV6) -_(ARMAGEDDON_ICON1) -_(ARMAGEDDON_ICON2) +// Pity Shield Box +_(PITV1) +_(PITV2) +_(PITV3) +_(PITV4) +_(PITV5) +_(PITV6) +_(PITV7) -_(WHIRLWIND_ICON1) -_(WHIRLWIND_ICON2) +// Eggman Box +_(EGGTV1) +_(EGGTV2) +_(EGGTV3) +_(EGGTV4) +_(EGGTV5) +_(EGGTV6) +_(EGGTV7) -_(ELEMENTAL_ICON1) -_(ELEMENTAL_ICON2) +// Teleport Box +_(MIXUPBOX1) +_(MIXUPBOX2) +_(MIXUPBOX3) +_(MIXUPBOX4) +_(MIXUPBOX5) +_(MIXUPBOX6) +_(MIXUPBOX7) -_(SNEAKERS_ICON1) -_(SNEAKERS_ICON2) +// Recycler Box +_(RECYCLETV1) +_(RECYCLETV2) +_(RECYCLETV3) +_(RECYCLETV4) +_(RECYCLETV5) +_(RECYCLETV6) +_(RECYCLETV7) -_(INVULN_ICON1) -_(INVULN_ICON2) +// Question Box +_(RANDOMBOX1) +_(RANDOMBOX2) +_(RANDOMBOX3) -_(1UP_ICON1) -_(1UP_ICON2) +// Gravity Boots Box +_(GBTV1) +_(GBTV2) +_(GBTV3) +_(GBTV4) +_(GBTV5) +_(GBTV6) +_(GBTV7) -_(EGGMAN_ICON1) -_(EGGMAN_ICON2) +// Score boxes +_(SCORETVA1) +_(SCORETVA2) +_(SCORETVA3) +_(SCORETVA4) +_(SCORETVA5) +_(SCORETVA6) +_(SCORETVA7) +_(SCORETVB1) +_(SCORETVB2) +_(SCORETVB3) +_(SCORETVB4) +_(SCORETVB5) +_(SCORETVB6) +_(SCORETVB7) -_(MIXUP_ICON1) -_(MIXUP_ICON2) +// Monitor Explosion +_(MONITOREXPLOSION1) +_(MONITOREXPLOSION2) -_(GRAVITY_ICON1) -_(GRAVITY_ICON2) +_(REDMONITOREXPLOSION1) +_(REDMONITOREXPLOSION2) -_(RECYCLER_ICON1) -_(RECYCLER_ICON2) - -_(SCORE1K_ICON1) -_(SCORE1K_ICON2) - -_(SCORE10K_ICON1) -_(SCORE10K_ICON2) - -_(FLAMEAURA_ICON1) -_(FLAMEAURA_ICON2) - -_(BUBBLEWRAP_ICON1) -_(BUBBLEWRAP_ICON2) - -_(THUNDERCOIN_ICON1) -_(THUNDERCOIN_ICON2) +_(BLUEMONITOREXPLOSION1) +_(BLUEMONITOREXPLOSION2) // --- @@ -1311,35 +1346,29 @@ _(FLAMEJETFLAMEB1) _(FLAMEJETFLAMEB2) _(FLAMEJETFLAMEB3) -// Glaregoyles -_(GLAREGOYLE) -_(GLAREGOYLE_CHARGE) -_(GLAREGOYLE_BLINK) -_(GLAREGOYLE_HOLD) -_(GLAREGOYLE_FIRE) -_(GLAREGOYLE_LOOP) -_(GLAREGOYLE_COOLDOWN) -_(GLAREGOYLEUP) -_(GLAREGOYLEUP_CHARGE) -_(GLAREGOYLEUP_BLINK) -_(GLAREGOYLEUP_HOLD) -_(GLAREGOYLEUP_FIRE) -_(GLAREGOYLEUP_LOOP) -_(GLAREGOYLEUP_COOLDOWN) -_(GLAREGOYLEDOWN) -_(GLAREGOYLEDOWN_CHARGE) -_(GLAREGOYLEDOWN_BLINK) -_(GLAREGOYLEDOWN_HOLD) -_(GLAREGOYLEDOWN_FIRE) -_(GLAREGOYLEDOWN_LOOP) -_(GLAREGOYLEDOWN_COOLDOWN) -_(GLAREGOYLELONG) -_(GLAREGOYLELONG_CHARGE) -_(GLAREGOYLELONG_BLINK) -_(GLAREGOYLELONG_HOLD) -_(GLAREGOYLELONG_FIRE) -_(GLAREGOYLELONG_LOOP) -_(GLAREGOYLELONG_COOLDOWN) +// Trapgoyles +_(TRAPGOYLE) +_(TRAPGOYLE_CHECK) +_(TRAPGOYLE_FIRE1) +_(TRAPGOYLE_FIRE2) +_(TRAPGOYLE_FIRE3) +_(TRAPGOYLEUP) +_(TRAPGOYLEUP_CHECK) +_(TRAPGOYLEUP_FIRE1) +_(TRAPGOYLEUP_FIRE2) +_(TRAPGOYLEUP_FIRE3) +_(TRAPGOYLEDOWN) +_(TRAPGOYLEDOWN_CHECK) +_(TRAPGOYLEDOWN_FIRE1) +_(TRAPGOYLEDOWN_FIRE2) +_(TRAPGOYLEDOWN_FIRE3) +_(TRAPGOYLELONG) +_(TRAPGOYLELONG_CHECK) +_(TRAPGOYLELONG_FIRE1) +_(TRAPGOYLELONG_FIRE2) +_(TRAPGOYLELONG_FIRE3) +_(TRAPGOYLELONG_FIRE4) +_(TRAPGOYLELONG_FIRE5) // ATZ's Red Crystal/Target _(TARGET_IDLE) diff --git a/src/p_enemy.c b/src/p_enemy.c index 9f9e2eefb..5179c90ce 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -505,6 +505,55 @@ boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed //return false; } +void P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target +{ + fixed_t dist; + fixed_t ns = 0; + + if (!enemy) + return; + + if (!(enemy->health)) + return; + + // change angle + source->angle = R_PointToAngle2(source->x, source->y, enemy->x, enemy->y); + if (source->player) + { + for (SINT8 j = 0; j <= r_splitscreen; j++) + { + if (source->player == &players[displayplayers[j]]) + { + localangle[j] = source->angle; + break; + } + } + } + + // change slope + dist = P_AproxDistance(P_AproxDistance(enemy->x - source->x, enemy->y - source->y), + enemy->z - source->z); + + if (dist < 1) + dist = 1; + + if (source->type == MT_DETON && enemy->player) // For Deton Chase (Unused) + ns = FixedDiv(FixedMul(K_GetKartSpeed(enemy->player, false, true), enemy->scale), FixedDiv(20*FRACUNIT,17*FRACUNIT)); + else if (source->type != MT_PLAYER) + { + if (source->threshold == 32000) + ns = FixedMul(source->info->speed/2, source->scale); + else + ns = FixedMul(source->info->speed, source->scale); + } + else if (source->player) + ns = FixedDiv(FixedMul(K_GetKartSpeed(source->player, false, true), source->scale), 3*FRACUNIT/2); + + source->momx = FixedMul(FixedDiv(enemy->x - source->x, dist), ns); + source->momy = FixedMul(FixedDiv(enemy->y - source->y, dist), ns); + source->momz = FixedMul(FixedDiv(enemy->z - source->z, dist), ns); +} + // // ACTION ROUTINES // @@ -2628,6 +2677,102 @@ void A_Fall(mobj_t *actor) actor->extravalue2 = locvar1; } +// Function: A_MonitorPop +// +// Description: Used by monitors when they explode. +// +// var1 = unused +// var2 = unused +// +void A_MonitorPop(mobj_t *actor) +{ + mobj_t *remains; + mobjtype_t explode; + mobjtype_t item = 0; + //mobjtype_t newbox; + + if (LUA_CallAction(A_MONITORPOP, actor)) + return; + + // 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) + { + remains->eflags |= MFE_VERTICALFLIP; + remains->flags2 |= MF2_OBJECTFLIP; + } + remains->destscale = actor->destscale; + P_SetScale(remains, actor->scale); + + 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(&g_tm.thing, remains); + + if (actor->info->deathsound) + S_StartSound(remains, actor->info->deathsound); + + switch (actor->type) + { + 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); + + newmobj->destscale = actor->destscale; + P_SetScale(newmobj, actor->scale); + P_SetTarget(&newmobj->target, actor->target); // Transfer target + if (item == MT_1UPICO && newmobj->target->player) + { + if (actor->tracer) // Remove the old lives icon. + P_RemoveMobj(actor->tracer); + + newmobj->frame -= 2; // No lives icon for this player, use the default. + } + } + else + CONS_Debug(DBG_GAMELOGIC, "Powerup item not defined in 'damage' field for A_MonitorPop\n"); + + P_RemoveMobj(actor); +} + // Function: A_Explode // // Description: Explodes an object, doing damage to any objects nearby. The target is used as the cause of the explosion. Damage value is used as explosion range. @@ -3738,114 +3883,55 @@ void A_ShootBullet(mobj_t *actor) S_StartSound(actor, actor->info->attacksound); } -static mobj_t *minus; - -static BlockItReturn_t PIT_MinusCarry(mobj_t *thing) -{ - if (minus->tracer) - return BMIT_CONTINUE; - - if (minus->type == thing->type) - return BMIT_CONTINUE; - - if (!(thing->flags & (MF_PUSHABLE|MF_ENEMY))) - return BMIT_CONTINUE; - - if (P_AproxDistance(minus->x - thing->x, minus->y - thing->y) >= minus->radius*3) - return BMIT_CONTINUE; - - if (abs(thing->z - minus->z) > minus->height) - return BMIT_CONTINUE; - - P_SetTarget(&minus->tracer, thing); - - return BMIT_CONTINUE; -} - // Function: A_MinusDigging // // Description: Minus digging in the ground. // -// var1 = If 1, play digging sound. +// var1 = unused // var2 = unused // void A_MinusDigging(mobj_t *actor) { - INT32 locvar1 = var1; - INT32 rad = 32; - angle_t fa = (actor->angle >> ANGLETOFINESHIFT) & FINEMASK; - fixed_t dis = actor->info->speed*4; - fixed_t x = FINECOSINE(fa)*dis + actor->x + FRACUNIT*P_RandomRange(-rad, rad); - fixed_t y = FINESINE(fa)*dis + actor->y + FRACUNIT*P_RandomRange(-rad, rad); - fixed_t mz = (actor->eflags & MFE_VERTICALFLIP) ? actor->ceilingz : actor->floorz; - mobj_t *par; - if (LUA_CallAction(A_MINUSDIGGING, actor)) return; + actor->flags &= ~MF_SPECIAL; + actor->flags &= ~MF_SHOOTABLE; + if (!actor->target) { - P_SetMobjState(actor, actor->info->spawnstate); + A_Look(actor); return; } - par = P_SpawnMobj(actor->x, actor->y, mz, MT_MINUSDIRT); - if (actor->eflags & MFE_VERTICALFLIP) - par->eflags |= MFE_VERTICALFLIP; - P_TryMove(par, x, y, false, NULL); - - // If close enough, prepare to attack - if (P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y) < actor->radius*2) + if (actor->reactiontime) { - P_SetMobjState(actor, actor->info->meleestate); - P_TryMove(actor, actor->target->x, actor->target->y, false, NULL); - S_StartSound(actor, actor->info->attacksound); - - // Spawn growing dirt pile. - par = P_SpawnMobj(actor->x, actor->y, mz, MT_MINUSDIRT); - P_SetMobjState(par, actor->info->raisestate); - P_SetScale(par, actor->scale*2); - if (actor->eflags & MFE_VERTICALFLIP) - par->eflags |= MFE_VERTICALFLIP; + actor->reactiontime--; return; } - // Play digging sound - if (locvar1 == 1) - A_PlayActiveSound(actor); + // Dirt trail + P_SpawnGhostMobj(actor); - // Move + actor->flags |= MF_NOCLIPTHING; var1 = 3; A_Chase(actor); + actor->flags &= ~MF_NOCLIPTHING; - // Carry over shit, maybe - if (P_MobjWasRemoved(actor->tracer) || !actor->tracer->health) - P_SetTarget(&actor->tracer, NULL); + // Play digging sound + if (!(leveltime & 15)) + S_StartSound(actor, actor->info->activesound); - if (!actor->tracer) - { - fixed_t radius = 3*actor->radius; - fixed_t yh = (unsigned)(actor->y + radius - bmaporgy) >> MAPBLOCKSHIFT; - fixed_t yl = (unsigned)(actor->y - radius - bmaporgy) >> MAPBLOCKSHIFT; - fixed_t xh = (unsigned)(actor->x + radius - bmaporgx) >> MAPBLOCKSHIFT; - fixed_t xl = (unsigned)(actor->x - radius - bmaporgx) >> MAPBLOCKSHIFT; - fixed_t bx, by; + // If we're close enough to our target, pop out of the ground + if (P_AproxDistance(actor->target->x-actor->x, actor->target->y-actor->y) < actor->radius + && abs(actor->target->z - actor->z) < actor->height) + P_SetMobjState(actor, actor->info->missilestate); - BMBOUNDFIX(xl, xh, yl, yh); - - minus = actor; - - for (bx = xl; bx <= xh; bx++) - for (by = yl; by <= yh; by++) - P_BlockThingsIterator(bx, by, PIT_MinusCarry); - } + // Snap to ground + if (actor->eflags & MFE_VERTICALFLIP) + actor->z = actor->ceilingz - actor->height; else - { - if (P_TryMove(actor->tracer, actor->x, actor->y, false, NULL)) - actor->tracer->z = mz; - else - P_SetTarget(&actor->tracer, NULL); - } + actor->z = actor->floorz; } // Function: A_MinusPopup @@ -3857,65 +3943,44 @@ void A_MinusDigging(mobj_t *actor) // void A_MinusPopup(mobj_t *actor) { - INT32 num = 6; - angle_t ani = FixedAngle(FRACUNIT*360/num); - INT32 i; if (LUA_CallAction(A_MINUSPOPUP, actor)) return; - if (actor->eflags & MFE_VERTICALFLIP) - actor->momz = -10*FRACUNIT; - else - actor->momz = 10*FRACUNIT; + P_SetObjectMomZ(actor, 10*FRACUNIT, false); - S_StartSound(actor, sfx_s3k82); - for (i = 1; i <= num; i++) - { - mobj_t *rock = P_SpawnMobjFromMobj(actor, 0, 0, actor->height/4, MT_ROCKCRUMBLE1); - P_Thrust(rock, ani*i, FRACUNIT); - P_SetObjectMomZ(rock, 3*FRACUNIT, false); - P_SetScale(rock, rock->scale/3); - } - P_RadiusAttack(actor, actor, 2*actor->radius, 0, true); - if (actor->tracer) - P_DamageMobj(actor->tracer, actor, actor, 1, DMG_NORMAL); + actor->flags |= MF_SPECIAL; + actor->flags |= MF_SHOOTABLE; - actor->flags = (actor->flags & ~MF_NOCLIPTHING)|MF_SPECIAL|MF_SHOOTABLE; + // Sound for busting out of the ground. + S_StartSound(actor, actor->info->attacksound); } // Function: A_MinusCheck // // Description: If the minus hits the floor, dig back into the ground. // -// var1 = State to switch to (if 0, use seestate). -// var2 = If not 0, spawn debris when hitting the floor. +// var1 = unused +// var2 = unused // void A_MinusCheck(mobj_t *actor) { - INT32 locvar1 = var1; - INT32 locvar2 = var2; - if (LUA_CallAction(A_MINUSCHECK, actor)) return; - if (((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz) || (!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz)) + if ((!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz) + || ((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz)) { - P_SetMobjState(actor, locvar1 ? (statenum_t)locvar1 : actor->info->seestate); - actor->flags = actor->info->flags; - if (locvar2) - { - INT32 i, num = 6; - angle_t ani = FixedAngle(FRACUNIT*360/num); - for (i = 1; i <= num; i++) - { - mobj_t *rock = P_SpawnMobjFromMobj(actor, 0, 0, actor->height/4, MT_ROCKCRUMBLE1); - P_Thrust(rock, ani*i, FRACUNIT); - P_SetObjectMomZ(rock, 3*FRACUNIT, false); - P_SetScale(rock, rock->scale/3); - } - } + actor->flags &= ~MF_SPECIAL; + actor->flags &= ~MF_SHOOTABLE; + actor->reactiontime = TICRATE; + P_SetMobjState(actor, actor->info->seestate); + return; } + + // 'Falling' animation + if (P_MobjFlip(actor)*actor->momz < 0 && actor->state < &states[actor->info->meleestate]) + P_SetMobjState(actor, actor->info->meleestate); } // Function: A_ChickenCheck @@ -11515,7 +11580,7 @@ void A_MementosTPParticles(mobj_t *actor) particle->frame = 0; particle->color = ((i%2) ? (SKINCOLOR_RED) : (SKINCOLOR_BLACK)); particle->destscale = 1; - //P_HomingAttack(particle, actor); // Really now, Lat... + P_HomingAttack(particle, actor); // Really now, Lat... } // Although this is mostly used to spawn particles, we will also save the OTHER teleport inside actor->target. That way teleporting doesn't require a thinker iteration. diff --git a/src/p_floor.c b/src/p_floor.c index bd7104b35..05cfe8191 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -2456,6 +2456,14 @@ void EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher) } else { + if (thing->type == MT_EMMY && thing->spawnpoint && (thing->spawnpoint->options & MTF_OBJECTSPECIAL)) + { + mobj_t *tokenobj = P_SpawnMobj(thing->x, thing->y, topheight, MT_TOKEN); + P_SetTarget(&thing->tracer, tokenobj); + P_SetTarget(&tokenobj->target, thing); + P_SetMobjState(tokenobj, mobjinfo[MT_TOKEN].seestate); + } + // "Powerup rise" sound S_StartSound(puncher, sfx_mario9); // Puncher is "close enough" } diff --git a/src/p_inter.c b/src/p_inter.c index 402d715ab..68aae9b73 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -689,6 +689,23 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) player->pickuprings++; return; + // Special Stage Token + case MT_EMMY: + if (player->bot) + return; + tokenlist += special->health; + + if (ALL7EMERALDS(emeralds)) // Got all 7 + { + P_GivePlayerRings(player, 50); + nummaprings += 50; // no cheating towards Perfect! + } + else + token++; + + if (special->tracer) // token BG + P_RemoveMobj(special->tracer); + break; // Secret emblem thingy case MT_EMBLEM: @@ -825,6 +842,15 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) Obj_LoopEndpointCollide(special, toucher); return; + case MT_BIGMINE: + case MT_BIGAIRMINE: + // Spawn explosion! + P_SpawnMobj(special->x, special->y, special->z, special->info->mass); + P_RadiusAttack(special, special, special->info->damage, DMG_NORMAL, true); + S_StartSound(special, special->info->deathsound); + P_SetMobjState(special, special->info->deathstate); + return; + case MT_NIGHTSBUMPER: // Don't trigger if the stage is ended/failed if (player->exiting) diff --git a/src/p_local.h b/src/p_local.h index 25c9c94c4..8df94fe9e 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -397,6 +397,8 @@ boolean P_CheckMissileRange(mobj_t *actor); void P_NewChaseDir(mobj_t *actor); boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed_t dist); +void P_HomingAttack(mobj_t *source, mobj_t *enemy); + mobj_t *P_InternalFlickySpawn(mobj_t *actor, mobjtype_t flickytype, fixed_t momz, boolean lookforplayers, SINT8 moveforward); void P_InternalFlickySetColor(mobj_t *actor, UINT8 color); #define P_IsFlickyCenter(type) (type > MT_FLICKY_01 && type < MT_SEED && (type - MT_FLICKY_01) % 2 ? 1 : 0) diff --git a/src/p_mobj.c b/src/p_mobj.c index 3e22ac8ff..b4cd4438d 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6406,6 +6406,61 @@ static boolean P_MobjRegularThink(mobj_t *mobj) } P_MobjCheckWater(mobj); break; + case MT_AQUABUZZ: + case MT_BIGAIRMINE: + { + if (mobj->tracer && mobj->tracer->player && mobj->tracer->health > 0 + && P_AproxDistance(P_AproxDistance(mobj->tracer->x - mobj->x, mobj->tracer->y - mobj->y), mobj->tracer->z - mobj->z) <= mobj->radius * 16) + { + // Home in on the target. + P_HomingAttack(mobj, mobj->tracer); + + if (mobj->z < mobj->floorz) + mobj->z = mobj->floorz; + + if (leveltime % mobj->info->painchance == 0) + S_StartSound(mobj, mobj->info->activesound); + } + else + { + // Try to find a player + P_LookForPlayers(mobj, true, true, mobj->radius * 16); + mobj->momx >>= 1; + mobj->momy >>= 1; + mobj->momz >>= 1; + } + } + break; + case MT_BIGMINE: + { + if (mobj->tracer && mobj->tracer->player && mobj->tracer->health > 0 + && P_AproxDistance(P_AproxDistance(mobj->tracer->x - mobj->x, mobj->tracer->y - mobj->y), mobj->tracer->z - mobj->z) <= mobj->radius * 16) + { + P_MobjCheckWater(mobj); + + // Home in on the target. + P_HomingAttack(mobj, mobj->tracer); + + // Don't let it go out of water + if (mobj->z + mobj->height > mobj->watertop) + mobj->z = mobj->watertop - mobj->height; + + if (mobj->z < mobj->floorz) + mobj->z = mobj->floorz; + + if (leveltime % mobj->info->painchance == 0) + S_StartSound(mobj, mobj->info->activesound); + } + else + { + // Try to find a player + P_LookForPlayers(mobj, true, true, mobj->radius * 16); + mobj->momx >>= 1; + mobj->momy >>= 1; + mobj->momz >>= 1; + } + } + break; case MT_FLAME: if (mobj->flags2 & MF2_BOSSNOTRAP) { @@ -8288,21 +8343,21 @@ static void P_MonitorFuseThink(mobj_t *mobj) // 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 + 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 + // 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 @@ -10556,6 +10611,7 @@ fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mt case MT_EMBLEM: case MT_RING: case MT_BLUESPHERE: + case MT_EMMY: offset += mthing->args[0] ? 0 : 24*FRACUNIT; break; @@ -11615,6 +11671,35 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean Obj_InitLoopCenter(mobj); break; } + case MT_EMMY: + { + if (mthing->options & MTF_OBJECTSPECIAL) // Mario Block version + mobj->flags &= ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT); + else + { + fixed_t zheight = mobj->z; + mobj_t *tokenobj; + + if (mthing->options & MTF_OBJECTFLIP) + zheight += mobj->height-FixedMul(mobjinfo[MT_TOKEN].height, mobj->scale); // align with emmy properly! + + tokenobj = P_SpawnMobj(mobj->x, mobj->y, zheight, MT_TOKEN); + P_SetTarget(&mobj->tracer, tokenobj); + tokenobj->destscale = mobj->scale; + P_SetScale(tokenobj, mobj->scale); + if (mthing->options & MTF_OBJECTFLIP) // flip token to match emmy + { + tokenobj->eflags |= MFE_VERTICALFLIP; + tokenobj->flags2 |= MF2_OBJECTFLIP; + } + } + + // We advanced tokenbits earlier due to the return check. + // Subtract 1 here for the correct value. + mobj->health = 1 << (tokenbits - 1); + break; + + } case MT_REDDIAG: case MT_YELLOWDIAG: case MT_BLUEDIAG: