Port v1 objects pt 4

This commit is contained in:
NepDisk 2025-04-09 13:45:35 -04:00
parent c3dc9918ba
commit f0a6a112ac
10 changed files with 588 additions and 404 deletions

View file

@ -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.

View file

@ -1,3 +1,4 @@
_(A_MonitorPop, MONITORPOP)
_(A_Explode, EXPLODE)
_(A_Pain, PAIN)
_(A_Fall, FALL)

View file

@ -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)

View file

@ -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

View file

@ -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)

View file

@ -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.

View file

@ -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"
}

View file

@ -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)

View file

@ -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)

View file

@ -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: