diff --git a/src/blua/ldump.c b/src/blua/ldump.c index c9d3d4870..b69a12729 100644 --- a/src/blua/ldump.c +++ b/src/blua/ldump.c @@ -60,7 +60,7 @@ static void DumpVector(const void* b, int n, size_t size, DumpState* D) static void DumpString(const TString* s, DumpState* D) { - if (s==NULL || getstr(s)==NULL) + if (s==NULL) { size_t size=0; DumpVar(size,D); diff --git a/src/d_netfil.c b/src/d_netfil.c index dc5d84e4c..18b07b94c 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -194,6 +194,12 @@ UINT8 *PutFileNeeded(UINT16 firstfile) filestatus = 1; // Importance - not really used any more, holds 1 by default for backwards compat with MS + /* don't send mainwads!! */ +#ifdef DEVELOP + if (i <= mainwads) + filestatus += (2 << 4); +#endif + // Store in the upper four bits if (!cv_downloading.value) filestatus += (2 << 4); // Won't send diff --git a/src/d_player.h b/src/d_player.h index 55c2857d5..60ca7c4bd 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -437,6 +437,8 @@ typedef struct player_s UINT16 draftleeway; // Leniency timer before removing draft power SINT8 lastdraft; // (-1 to 15) - Last player being drafted + UINT16 tripwireLeniency; // When reaching a state that lets you go thru tripwire, you get an extra second leniency after it ends to still go through it. + UINT16 itemroulette; // Used for the roulette when deciding what item to give you (was "pw_kartitem") UINT8 roulettetype; // Used for the roulette, for deciding type (0 = normal, 1 = better, 2 = eggman mark) @@ -488,6 +490,7 @@ typedef struct player_s UINT8 trickboostdecay; // used to know how long you've waited UINT8 trickboost; // Trick boost. This one is weird and has variable speed. Dear god. + tic_t ebrakefor; // Ebrake timer, used for visuals. UINT32 roundscore; // battle score this round UINT8 emeralds; diff --git a/src/deh_tables.c b/src/deh_tables.c index 1f22d4f85..421a2ecbd 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -129,7 +129,6 @@ actionpointer_t actionpointers[] = {{A_BossZoom}, "A_BOSSZOOM"}, {{A_BossScream}, "A_BOSSSCREAM"}, {{A_Boss2TakeDamage}, "A_BOSS2TAKEDAMAGE"}, - {{A_Boss7Chase}, "A_BOSS7CHASE"}, {{A_GoopSplat}, "A_GOOPSPLAT"}, {{A_Boss2PogoSFX}, "A_BOSS2POGOSFX"}, {{A_Boss2PogoTarget}, "A_BOSS2POGOTARGET"}, @@ -1094,236 +1093,6 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_FSGNC", "S_FSGND", - // Black Eggman (Boss 7) - "S_BLACKEGG_STND", - "S_BLACKEGG_STND2", - "S_BLACKEGG_WALK1", - "S_BLACKEGG_WALK2", - "S_BLACKEGG_WALK3", - "S_BLACKEGG_WALK4", - "S_BLACKEGG_WALK5", - "S_BLACKEGG_WALK6", - "S_BLACKEGG_SHOOT1", - "S_BLACKEGG_SHOOT2", - "S_BLACKEGG_PAIN1", - "S_BLACKEGG_PAIN2", - "S_BLACKEGG_PAIN3", - "S_BLACKEGG_PAIN4", - "S_BLACKEGG_PAIN5", - "S_BLACKEGG_PAIN6", - "S_BLACKEGG_PAIN7", - "S_BLACKEGG_PAIN8", - "S_BLACKEGG_PAIN9", - "S_BLACKEGG_PAIN10", - "S_BLACKEGG_PAIN11", - "S_BLACKEGG_PAIN12", - "S_BLACKEGG_PAIN13", - "S_BLACKEGG_PAIN14", - "S_BLACKEGG_PAIN15", - "S_BLACKEGG_PAIN16", - "S_BLACKEGG_PAIN17", - "S_BLACKEGG_PAIN18", - "S_BLACKEGG_PAIN19", - "S_BLACKEGG_PAIN20", - "S_BLACKEGG_PAIN21", - "S_BLACKEGG_PAIN22", - "S_BLACKEGG_PAIN23", - "S_BLACKEGG_PAIN24", - "S_BLACKEGG_PAIN25", - "S_BLACKEGG_PAIN26", - "S_BLACKEGG_PAIN27", - "S_BLACKEGG_PAIN28", - "S_BLACKEGG_PAIN29", - "S_BLACKEGG_PAIN30", - "S_BLACKEGG_PAIN31", - "S_BLACKEGG_PAIN32", - "S_BLACKEGG_PAIN33", - "S_BLACKEGG_PAIN34", - "S_BLACKEGG_PAIN35", - "S_BLACKEGG_HITFACE1", - "S_BLACKEGG_HITFACE2", - "S_BLACKEGG_HITFACE3", - "S_BLACKEGG_HITFACE4", - "S_BLACKEGG_DIE1", - "S_BLACKEGG_DIE2", - "S_BLACKEGG_DIE3", - "S_BLACKEGG_DIE4", - "S_BLACKEGG_DIE5", - "S_BLACKEGG_MISSILE1", - "S_BLACKEGG_MISSILE2", - "S_BLACKEGG_MISSILE3", - "S_BLACKEGG_GOOP", - "S_BLACKEGG_JUMP1", - "S_BLACKEGG_JUMP2", - "S_BLACKEGG_DESTROYPLAT1", - "S_BLACKEGG_DESTROYPLAT2", - "S_BLACKEGG_DESTROYPLAT3", - - "S_BLACKEGG_HELPER", // Collision helper - - "S_BLACKEGG_GOOP1", - "S_BLACKEGG_GOOP2", - "S_BLACKEGG_GOOP3", - "S_BLACKEGG_GOOP4", - "S_BLACKEGG_GOOP5", - "S_BLACKEGG_GOOP6", - "S_BLACKEGG_GOOP7", - - "S_BLACKEGG_MISSILE", - - // New Very-Last-Minute 2.1 Brak Eggman (Cy-Brak-demon) - "S_CYBRAKDEMON_IDLE", - "S_CYBRAKDEMON_WALK1", - "S_CYBRAKDEMON_WALK2", - "S_CYBRAKDEMON_WALK3", - "S_CYBRAKDEMON_WALK4", - "S_CYBRAKDEMON_WALK5", - "S_CYBRAKDEMON_WALK6", - "S_CYBRAKDEMON_CHOOSE_ATTACK1", - "S_CYBRAKDEMON_MISSILE_ATTACK1", // Aim - "S_CYBRAKDEMON_MISSILE_ATTACK2", // Fire - "S_CYBRAKDEMON_MISSILE_ATTACK3", // Aim - "S_CYBRAKDEMON_MISSILE_ATTACK4", // Fire - "S_CYBRAKDEMON_MISSILE_ATTACK5", // Aim - "S_CYBRAKDEMON_MISSILE_ATTACK6", // Fire - "S_CYBRAKDEMON_FLAME_ATTACK1", // Reset - "S_CYBRAKDEMON_FLAME_ATTACK2", // Aim - "S_CYBRAKDEMON_FLAME_ATTACK3", // Fire - "S_CYBRAKDEMON_FLAME_ATTACK4", // Loop - "S_CYBRAKDEMON_CHOOSE_ATTACK2", - "S_CYBRAKDEMON_VILE_ATTACK1", - "S_CYBRAKDEMON_VILE_ATTACK2", - "S_CYBRAKDEMON_VILE_ATTACK3", - "S_CYBRAKDEMON_VILE_ATTACK4", - "S_CYBRAKDEMON_VILE_ATTACK5", - "S_CYBRAKDEMON_VILE_ATTACK6", - "S_CYBRAKDEMON_NAPALM_ATTACK1", - "S_CYBRAKDEMON_NAPALM_ATTACK2", - "S_CYBRAKDEMON_NAPALM_ATTACK3", - "S_CYBRAKDEMON_FINISH_ATTACK1", // If just attacked, remove MF2_FRET w/out going back to spawnstate - "S_CYBRAKDEMON_FINISH_ATTACK2", // Force a delay between attacks so you don't get bombarded with them back-to-back - "S_CYBRAKDEMON_PAIN1", - "S_CYBRAKDEMON_PAIN2", - "S_CYBRAKDEMON_PAIN3", - "S_CYBRAKDEMON_DIE1", - "S_CYBRAKDEMON_DIE2", - "S_CYBRAKDEMON_DIE3", - "S_CYBRAKDEMON_DIE4", - "S_CYBRAKDEMON_DIE5", - "S_CYBRAKDEMON_DIE6", - "S_CYBRAKDEMON_DIE7", - "S_CYBRAKDEMON_DIE8", - "S_CYBRAKDEMON_DEINVINCIBLERIZE", - "S_CYBRAKDEMON_INVINCIBLERIZE", - - "S_CYBRAKDEMONMISSILE", - "S_CYBRAKDEMONMISSILE_EXPLODE1", - "S_CYBRAKDEMONMISSILE_EXPLODE2", - "S_CYBRAKDEMONMISSILE_EXPLODE3", - - "S_CYBRAKDEMONFLAMESHOT_FLY1", - "S_CYBRAKDEMONFLAMESHOT_FLY2", - "S_CYBRAKDEMONFLAMESHOT_FLY3", - "S_CYBRAKDEMONFLAMESHOT_DIE", - - "S_CYBRAKDEMONFLAMEREST", - - "S_CYBRAKDEMONELECTRICBARRIER_INIT1", - "S_CYBRAKDEMONELECTRICBARRIER_INIT2", - "S_CYBRAKDEMONELECTRICBARRIER_PLAYSOUND", - "S_CYBRAKDEMONELECTRICBARRIER1", - "S_CYBRAKDEMONELECTRICBARRIER2", - "S_CYBRAKDEMONELECTRICBARRIER3", - "S_CYBRAKDEMONELECTRICBARRIER4", - "S_CYBRAKDEMONELECTRICBARRIER5", - "S_CYBRAKDEMONELECTRICBARRIER6", - "S_CYBRAKDEMONELECTRICBARRIER7", - "S_CYBRAKDEMONELECTRICBARRIER8", - "S_CYBRAKDEMONELECTRICBARRIER9", - "S_CYBRAKDEMONELECTRICBARRIER10", - "S_CYBRAKDEMONELECTRICBARRIER11", - "S_CYBRAKDEMONELECTRICBARRIER12", - "S_CYBRAKDEMONELECTRICBARRIER13", - "S_CYBRAKDEMONELECTRICBARRIER14", - "S_CYBRAKDEMONELECTRICBARRIER15", - "S_CYBRAKDEMONELECTRICBARRIER16", - "S_CYBRAKDEMONELECTRICBARRIER17", - "S_CYBRAKDEMONELECTRICBARRIER18", - "S_CYBRAKDEMONELECTRICBARRIER19", - "S_CYBRAKDEMONELECTRICBARRIER20", - "S_CYBRAKDEMONELECTRICBARRIER21", - "S_CYBRAKDEMONELECTRICBARRIER22", - "S_CYBRAKDEMONELECTRICBARRIER23", - "S_CYBRAKDEMONELECTRICBARRIER24", - "S_CYBRAKDEMONELECTRICBARRIER_DIE1", - "S_CYBRAKDEMONELECTRICBARRIER_DIE2", - "S_CYBRAKDEMONELECTRICBARRIER_DIE3", - "S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMCHECK", - "S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMSUCCESS", - "S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMCHOOSE", - "S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM1", - "S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM2", - "S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM3", - "S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM4", - "S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM5", - "S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM6", - "S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM7", - "S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM8", - "S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM9", - "S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM10", - "S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM11", - "S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM12", - "S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMFAIL", - "S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMLOOP", - "S_CYBRAKDEMONELECTRICBARRIER_REVIVE1", - "S_CYBRAKDEMONELECTRICBARRIER_REVIVE2", - "S_CYBRAKDEMONELECTRICBARRIER_REVIVE3", - - "S_CYBRAKDEMONTARGETRETICULE1", - "S_CYBRAKDEMONTARGETRETICULE2", - "S_CYBRAKDEMONTARGETRETICULE3", - "S_CYBRAKDEMONTARGETRETICULE4", - "S_CYBRAKDEMONTARGETRETICULE5", - "S_CYBRAKDEMONTARGETRETICULE6", - "S_CYBRAKDEMONTARGETRETICULE7", - "S_CYBRAKDEMONTARGETRETICULE8", - "S_CYBRAKDEMONTARGETRETICULE9", - "S_CYBRAKDEMONTARGETRETICULE10", - "S_CYBRAKDEMONTARGETRETICULE11", - "S_CYBRAKDEMONTARGETRETICULE12", - "S_CYBRAKDEMONTARGETRETICULE13", - "S_CYBRAKDEMONTARGETRETICULE14", - - "S_CYBRAKDEMONTARGETDOT", - - "S_CYBRAKDEMONNAPALMBOMBLARGE_FLY1", - "S_CYBRAKDEMONNAPALMBOMBLARGE_FLY2", - "S_CYBRAKDEMONNAPALMBOMBLARGE_FLY3", - "S_CYBRAKDEMONNAPALMBOMBLARGE_FLY4", - "S_CYBRAKDEMONNAPALMBOMBLARGE_DIE1", // Explode - "S_CYBRAKDEMONNAPALMBOMBLARGE_DIE2", // Outer ring - "S_CYBRAKDEMONNAPALMBOMBLARGE_DIE3", // Center - "S_CYBRAKDEMONNAPALMBOMBLARGE_DIE4", // Sound - - "S_CYBRAKDEMONNAPALMBOMBSMALL", - "S_CYBRAKDEMONNAPALMBOMBSMALL_DIE1", // Explode - "S_CYBRAKDEMONNAPALMBOMBSMALL_DIE2", // Outer ring - "S_CYBRAKDEMONNAPALMBOMBSMALL_DIE3", // Inner ring - "S_CYBRAKDEMONNAPALMBOMBSMALL_DIE4", // Center - "S_CYBRAKDEMONNAPALMBOMBSMALL_DIE5", // Sound - - "S_CYBRAKDEMONNAPALMFLAME_FLY1", - "S_CYBRAKDEMONNAPALMFLAME_FLY2", - "S_CYBRAKDEMONNAPALMFLAME_FLY3", - "S_CYBRAKDEMONNAPALMFLAME_FLY4", - "S_CYBRAKDEMONNAPALMFLAME_FLY5", - "S_CYBRAKDEMONNAPALMFLAME_FLY6", - "S_CYBRAKDEMONNAPALMFLAME_DIE", - - "S_CYBRAKDEMONVILEEXPLOSION1", - "S_CYBRAKDEMONVILEEXPLOSION2", - "S_CYBRAKDEMONVILEEXPLOSION3", - // Metal Sonic (Race) "S_METALSONIC_RACE", // Metal Sonic (Battle) @@ -3538,6 +3307,10 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi // Brake drift sparks "S_BRAKEDRIFT", + // Brake dust + "S_BRAKEDUST1", + "S_BRAKEDUST2", + // Drift Smoke "S_DRIFTDUST1", "S_DRIFTDUST2", @@ -3784,8 +3557,7 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_SSMINE_DEPLOY12", "S_SSMINE_DEPLOY13", "S_SSMINE_EXPLODE", - "S_MINEEXPLOSION1", - "S_MINEEXPLOSION2", + "S_SSMINE_EXPLODE2", // New explosion "S_QUICKBOOM1", @@ -4540,6 +4312,7 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_EBARREL16", "S_EBARREL17", "S_EBARREL18", + "S_EBARREL19", "S_MERRYHORSE", "S_BLUEFRUIT", "S_ORANGEFRUIT", @@ -4662,6 +4435,20 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_SPINDASHDUST", "S_SPINDASHWIND", + "S_SOFTLANDING1", + "S_SOFTLANDING2", + "S_SOFTLANDING3", + "S_SOFTLANDING4", + "S_SOFTLANDING5", + + "S_DOWNLINE1", + "S_DOWNLINE2", + "S_DOWNLINE3", + "S_DOWNLINE4", + "S_DOWNLINE5", + + "S_HOLDBUBBLE", + // Finish line beam "S_FINISHBEAM1", "S_FINISHBEAM2", @@ -4802,25 +4589,6 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_FSGNB", "MT_FANGWAYPOINT", - // Black Eggman (Boss 7) - "MT_BLACKEGGMAN", - "MT_BLACKEGGMAN_HELPER", - "MT_BLACKEGGMAN_GOOPFIRE", - "MT_BLACKEGGMAN_MISSILE", - - // New Very-Last-Minute 2.1 Brak Eggman (Cy-Brak-demon) - "MT_CYBRAKDEMON", - "MT_CYBRAKDEMON_ELECTRIC_BARRIER", - "MT_CYBRAKDEMON_MISSILE", - "MT_CYBRAKDEMON_FLAMESHOT", - "MT_CYBRAKDEMON_FLAMEREST", - "MT_CYBRAKDEMON_TARGET_RETICULE", - "MT_CYBRAKDEMON_TARGET_DOT", - "MT_CYBRAKDEMON_NAPALM_BOMB_LARGE", - "MT_CYBRAKDEMON_NAPALM_BOMB_SMALL", - "MT_CYBRAKDEMON_NAPALM_FLAMES", - "MT_CYBRAKDEMON_VILE_EXPLOSION", - // Metal Sonic (Boss 9) "MT_METALSONIC_RACE", "MT_METALSONIC_BATTLE", @@ -5495,6 +5263,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_WIPEOUTTRAIL", "MT_DRIFTSPARK", "MT_BRAKEDRIFT", + "MT_BRAKEDUST", "MT_DRIFTDUST", "MT_DRIFTELECTRICITY", "MT_DRIFTELECTRICSPARK", @@ -5519,8 +5288,6 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_SSMINE_SHIELD", // Special Stage Mine stuff "MT_SSMINE", - "MT_MINEEXPLOSION", - "MT_MINEEXPLOSIONSOUND", "MT_SMOLDERING", // New explosion "MT_BOOMEXPLODE", @@ -5781,6 +5548,9 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_SPINDASHDUST", "MT_SPINDASHWIND", + "MT_SOFTLANDING", + "MT_DOWNLINE", + "MT_HOLDBUBBLE", "MT_PAPERITEMSPOT", @@ -6153,7 +5923,9 @@ const char *COLOR_ENUMS[] = { "CHAOSEMERALD4", "CHAOSEMERALD5", "CHAOSEMERALD6", - "CHAOSEMERALD7" + "CHAOSEMERALD7", + + "INVINCFLASH" }; const char *const KARTHUD_LIST[] = { diff --git a/src/doomdef.h b/src/doomdef.h index 07ba829c7..5a9f542aa 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -399,6 +399,8 @@ typedef enum SKINCOLOR_CHAOSEMERALD6, SKINCOLOR_CHAOSEMERALD7, + SKINCOLOR_INVINCFLASH, + SKINCOLOR_FIRSTFREESLOT, SKINCOLOR_LASTFREESLOT = SKINCOLOR_FIRSTFREESLOT + NUMCOLORFREESLOTS - 1, diff --git a/src/f_finale.c b/src/f_finale.c index a6dcd226c..d28fa3d9d 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1944,8 +1944,17 @@ void F_TitleScreenDrawer(void) V_DrawSmallScaledPatch(84, 36, transval<health <= 0) + return true; + + if (!(thing->flags & MF_SHOOTABLE) || (thing->flags & MF_SCENERY)) + return true; + + if (thing->player && thing->player->spectator) + return true; + + if (P_AproxDistance(P_AproxDistance(thing->x - grenade->x, thing->y - grenade->y), thing->z - grenade->z) > explodedist) + return true; // Too far away + + if (P_CheckSight(grenade, thing) == false) + return true; // Not in sight + + return false; +} + +static inline boolean PIT_SSMineSearch(mobj_t *thing) +{ + if (grenade == NULL || P_MobjWasRemoved(grenade)) + return false; // There's the possibility these can chain react onto themselves after they've already died if there are enough all in one spot + + if (grenade->flags2 & MF2_DEBRIS) // don't explode twice + return false; + + if (thing->type != MT_PLAYER) // Don't explode for anything but an actual player. + return true; + + if (thing == grenade->target && grenade->threshold != 0) // Don't blow up at your owner instantly. + return true; + + if (PIT_SSMineChecks(thing) == true) + return true; + + // Explode! + P_SetMobjState(grenade, grenade->info->deathstate); + return false; +} + +void K_DoMineSearch(mobj_t *actor, fixed_t size) +{ + INT32 bx, by, xl, xh, yl, yh; + + explodedist = FixedMul(size, actor->scale); + grenade = actor; + + yh = (unsigned)(actor->y + explodedist - bmaporgy)>>MAPBLOCKSHIFT; + yl = (unsigned)(actor->y - explodedist - bmaporgy)>>MAPBLOCKSHIFT; + xh = (unsigned)(actor->x + explodedist - bmaporgx)>>MAPBLOCKSHIFT; + xl = (unsigned)(actor->x - explodedist - bmaporgx)>>MAPBLOCKSHIFT; + + BMBOUNDFIX (xl, xh, yl, yh); + + for (by = yl; by <= yh; by++) + for (bx = xl; bx <= xh; bx++) + P_BlockThingsIterator(bx, by, PIT_SSMineSearch); +} + +static inline boolean PIT_SSMineExplode(mobj_t *thing) +{ + if (grenade == NULL || P_MobjWasRemoved(grenade)) + return false; // There's the possibility these can chain react onto themselves after they've already died if there are enough all in one spot + +#if 0 + if (grenade->flags2 & MF2_DEBRIS) // don't explode twice + return false; +#endif + + if (PIT_SSMineChecks(thing) == true) + return true; + + P_DamageMobj(thing, grenade, grenade->target, 1, (explodespin ? DMG_NORMAL : DMG_EXPLODE)); + return true; +} + +void K_MineExplodeAttack(mobj_t *actor, fixed_t size, boolean spin) +{ + INT32 bx, by, xl, xh, yl, yh; + + explodespin = spin; + explodedist = FixedMul(size, actor->scale); + grenade = actor; + + // Use blockmap to check for nearby shootables + yh = (unsigned)(actor->y + explodedist - bmaporgy)>>MAPBLOCKSHIFT; + yl = (unsigned)(actor->y - explodedist - bmaporgy)>>MAPBLOCKSHIFT; + xh = (unsigned)(actor->x + explodedist - bmaporgx)>>MAPBLOCKSHIFT; + xl = (unsigned)(actor->x - explodedist - bmaporgx)>>MAPBLOCKSHIFT; + + BMBOUNDFIX (xl, xh, yl, yh); + + for (by = yl; by <= yh; by++) + for (bx = xl; bx <= xh; bx++) + P_BlockThingsIterator(bx, by, PIT_SSMineExplode); + + // Set this flag to ensure that the inital action won't be triggered twice. + actor->flags2 |= MF2_DEBRIS; +} + boolean K_MineCollide(mobj_t *t1, mobj_t *t2) { if ((t1->threshold > 0 && t2->hitlag > 0) || (t2->threshold > 0 && t1->hitlag > 0)) @@ -349,31 +458,6 @@ boolean K_MineCollide(mobj_t *t1, mobj_t *t2) return true; } -boolean K_MineExplosionCollide(mobj_t *t1, mobj_t *t2) -{ - if (t2->player) - { - if (t2->player->flashing > 0 && t2->hitlag == 0) - return true; - - if (t1->state == &states[S_MINEEXPLOSION1]) - { - P_DamageMobj(t2, t1, t1->target, 1, DMG_EXPLODE); - } - else - { - P_DamageMobj(t2, t1, t1->target, 1, DMG_NORMAL); - } - } - else if (t2->flags & MF_SHOOTABLE) - { - // Shootable damage - P_DamageMobj(t2, t1, t1->target, 1, DMG_NORMAL); - } - - return true; -} - boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2) { if ((t1->threshold > 0 && t2->hitlag > 0) || (t2->threshold > 0 && t1->hitlag > 0)) @@ -560,6 +644,14 @@ boolean K_DropTargetCollide(mobj_t *t1, mobj_t *t2) t2->threshold = 10; } + if (t1->reactiontime > 1000) { + S_StartSound(t2, sfx_kdtrg3); + } else if (t1->reactiontime > 500) { + S_StartSound(t2, sfx_kdtrg2); + } else { + S_StartSound(t2, sfx_kdtrg1); + } + if (draggeddroptarget && draggeddroptarget->player) { // The following removes t1, be warned diff --git a/src/k_collide.h b/src/k_collide.h index 11af0502b..49cc3fa08 100644 --- a/src/k_collide.h +++ b/src/k_collide.h @@ -5,17 +5,27 @@ #include "p_mobj.h" angle_t K_GetCollideAngle(mobj_t *t1, mobj_t *t2); + boolean K_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2); + boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2); boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2); + +void K_DoMineSearch(mobj_t *actor, fixed_t size); +void K_MineExplodeAttack(mobj_t *actor, fixed_t size, boolean spin); boolean K_MineCollide(mobj_t *t1, mobj_t *t2); -boolean K_MineExplosionCollide(mobj_t *t1, mobj_t *t2); + boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2); + boolean K_DropTargetCollide(mobj_t *t1, mobj_t *t2); + boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2); + boolean K_KitchenSinkCollide(mobj_t *t1, mobj_t *t2); + boolean K_FallingRockCollide(mobj_t *t1, mobj_t *t2); boolean K_SMKIceBlockCollide(mobj_t *t1, mobj_t *t2); + boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2); #endif diff --git a/src/k_kart.c b/src/k_kart.c index 58cb6fe31..1071f0371 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1275,7 +1275,8 @@ static void K_SpawnBumpForObjs(mobj_t *mobj1, mobj_t *mobj2) } else if (mobj1->type == MT_DROPTARGET || mobj1->type == MT_DROPTARGET_SHIELD) // no need to check the other way around { - S_StartSound(mobj2, sfx_s258); + // Sound handled in K_DropTargetCollide + // S_StartSound(mobj2, sfx_s258); fx->colorized = true; fx->color = mobj1->color; } @@ -1591,6 +1592,10 @@ static UINT8 K_CheckOffroadCollide(mobj_t *mo) I_Assert(mo != NULL); I_Assert(!P_MobjWasRemoved(mo)); + // If tiregrease is active, don't + if (mo->player && mo->player->tiregrease) + return 0; + for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next) { if (!node->m_sector) @@ -2024,6 +2029,17 @@ void K_SpawnDashDustRelease(player_t *player) } } +static fixed_t K_GetBrakeFXScale(player_t *player, fixed_t maxScale) +{ + fixed_t s = FixedDiv(player->speed, + K_GetKartSpeed(player, false)); + + s = max(s, FRACUNIT); + s = min(s, maxScale); + + return s; +} + static void K_SpawnBrakeDriftSparks(player_t *player) // Be sure to update the mobj thinker case too! { mobj_t *sparks; @@ -2036,11 +2052,84 @@ static void K_SpawnBrakeDriftSparks(player_t *player) // Be sure to update the m // This avoids needing to dupe code if we don't need it. sparks = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BRAKEDRIFT); P_SetTarget(&sparks->target, player->mo); - P_SetScale(sparks, (sparks->destscale = player->mo->scale)); + P_SetScale(sparks, (sparks->destscale = FixedMul(K_GetBrakeFXScale(player, 3*FRACUNIT), player->mo->scale))); K_MatchGenericExtraFlags(sparks, player->mo); sparks->renderflags |= RF_DONTDRAW; } +static void +spawn_brake_dust +( mobj_t * master, + angle_t aoff, + fixed_t rad, + fixed_t scale) +{ + const angle_t a = master->angle + aoff; + + mobj_t *spark = P_SpawnMobjFromMobj(master, + P_ReturnThrustX(NULL, a, rad), + P_ReturnThrustY(NULL, a, rad), 0, + MT_BRAKEDUST); + + spark->momx = master->momx; + spark->momy = master->momy; + spark->momz = P_GetMobjZMovement(master); + spark->angle = a - ANGLE_180; + spark->pitch = master->pitch; + spark->roll = master->roll; + + P_Thrust(spark, a, 16 * spark->scale); + + P_SetScale(spark, (spark->destscale = + FixedMul(scale, spark->scale))); +} + +static void K_SpawnBrakeVisuals(player_t *player) +{ + const fixed_t scale = + K_GetBrakeFXScale(player, 2*FRACUNIT); + + if (leveltime & 1) + { + angle_t aoff; + fixed_t radf; + + UINT8 wheel = 3; + + if (player->drift) + { + /* brake-drifting: dust flies from outer wheel */ + wheel ^= 1 << (player->drift < 0); + + aoff = 7 * ANG10; + radf = 32 * FRACUNIT; + } + else + { + aoff = ANG30; + radf = 24 * FRACUNIT; + } + + if (wheel & 1) + { + spawn_brake_dust(player->mo, + aoff, radf, scale); + } + + if (wheel & 2) + { + spawn_brake_dust(player->mo, + InvAngle(aoff), radf, scale); + } + } + + if (leveltime % 4 == 0) + S_StartSound(player->mo, sfx_s3k67); + + /* vertical shaking, scales with speed */ + player->mo->spriteyoffset = P_RandomFlip(2 * scale); +} + void K_SpawnDriftBoostClip(player_t *player) { mobj_t *clip; @@ -2099,32 +2188,61 @@ void K_SpawnNormalSpeedLines(player_t *player) K_MatchGenericExtraFlags(fast, player->mo); - // Make it red when you have the eggman speed boost + if (player->tripwireLeniency) + { + fast->destscale = fast->destscale * 2; + P_SetScale(fast, 3*fast->scale/2); + } + if (player->eggmanexplode) { + // Make it red when you have the eggman speed boost fast->color = SKINCOLOR_RED; fast->colorized = true; } + else if (player->invincibilitytimer) + { + const tic_t defaultTime = itemtime+(2*TICRATE); + if (player->invincibilitytimer > defaultTime) + { + fast->color = player->mo->color; + } + else + { + fast->color = SKINCOLOR_INVINCFLASH; + } + fast->colorized = true; + } + else if (player->tripwireLeniency) + { + // Make it pink+blue+big when you can go through tripwire + fast->color = (leveltime & 1) ? SKINCOLOR_LILAC : SKINCOLOR_JAWZ; + fast->colorized = true; + fast->renderflags |= RF_ADD; + } } void K_SpawnInvincibilitySpeedLines(mobj_t *mo) { mobj_t *fast = P_SpawnMobjFromMobj(mo, P_RandomRange(-48, 48) * FRACUNIT, - P_RandomRange(-48, 48) * FRACUNIT, - P_RandomRange(0, 64) * FRACUNIT, - MT_FASTLINE); + P_RandomRange(-48, 48) * FRACUNIT, + P_RandomRange(0, 64) * FRACUNIT, + MT_FASTLINE); + P_SetMobjState(fast, S_KARTINVLINES1); + + P_SetTarget(&fast->target, mo); + P_InitAngle(fast, K_MomentumAngle(mo)); fast->momx = 3*mo->momx/4; fast->momy = 3*mo->momy/4; fast->momz = 3*P_GetMobjZMovement(mo)/4; - P_SetTarget(&fast->target, mo); - P_InitAngle(fast, K_MomentumAngle(mo)); + K_MatchGenericExtraFlags(fast, mo); + fast->color = mo->color; fast->colorized = true; - K_MatchGenericExtraFlags(fast, mo); - P_SetMobjState(fast, S_KARTINVLINES1); + if (mo->player->invincibilitytimer < 10*TICRATE) fast->destscale = 6*((mo->player->invincibilitytimer/TICRATE)*FRACUNIT)/8; } @@ -2737,7 +2855,7 @@ boolean K_SlopeResistance(player_t *player) return false; } -boolean K_TripwirePass(player_t *player) +boolean K_TripwirePassConditions(player_t *player) { if ( player->invincibilitytimer || @@ -2750,6 +2868,11 @@ boolean K_TripwirePass(player_t *player) return false; } +boolean K_TripwirePass(player_t *player) +{ + return (K_TripwirePassConditions(player) || (player->tripwireLeniency > 0)); +} + boolean K_WaterRun(player_t *player) { if ( @@ -2772,8 +2895,8 @@ static fixed_t K_FlameShieldDashVar(INT32 val) INT16 K_GetSpindashChargeTime(player_t *player) { // more charge time for higher speed - // Tails = 2s, Mighty = 3s, Fang = 4s, Metal = 4s - return (player->kartspeed + 4) * (TICRATE/3); + // Tails = 2s, Knuckles = 2.6s, Metal = 3.2s + return (player->kartspeed + 8) * (TICRATE/5); } fixed_t K_GetSpindashChargeSpeed(player_t *player) @@ -3690,88 +3813,6 @@ void K_TakeBumpersFromPlayer(player_t *player, player_t *victim, UINT8 amount) K_HandleBumperChanges(victim, oldVictimBumpers); } -// source is the mobj that originally threw the bomb that exploded etc. -// Spawns the sphere around the explosion that handles spinout -void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle, boolean spawncenter, boolean ghostit, mobj_t *source) -{ - mobj_t *mobj; - mobj_t *ghost = NULL; - INT32 i; - TVector v; - TVector *res; - fixed_t finalx, finaly, finalz, dist; - //mobj_t hoopcenter; - angle_t degrees, fa, closestangle; - fixed_t mobjx, mobjy, mobjz; - - //hoopcenter.x = x; - //hoopcenter.y = y; - //hoopcenter.z = z; - - //hoopcenter.z = z - mobjinfo[type].height/2; - - degrees = FINEANGLES/number; - - closestangle = 0; - - // Create the hoop! - for (i = 0; i < number; i++) - { - fa = (i*degrees); - v[0] = FixedMul(FINECOSINE(fa),radius); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa),radius); - v[3] = FRACUNIT; - - res = VectorMatrixMultiply(v, *RotateXMatrix(rotangle)); - M_Memcpy(&v, res, sizeof (v)); - res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle)); - M_Memcpy(&v, res, sizeof (v)); - - finalx = x + v[0]; - finaly = y + v[1]; - finalz = z + v[2]; - - mobj = P_SpawnMobj(finalx, finaly, finalz, type); - - mobj->z -= mobj->height>>1; - - // change angle - P_InitAngle(mobj, R_PointToAngle2(mobj->x, mobj->y, x, y)); - - // change slope - dist = P_AproxDistance(P_AproxDistance(x - mobj->x, y - mobj->y), z - mobj->z); - - if (dist < 1) - dist = 1; - - mobjx = mobj->x; - mobjy = mobj->y; - mobjz = mobj->z; - - if (ghostit) - { - ghost = P_SpawnGhostMobj(mobj); - P_SetMobjState(mobj, S_NULL); - mobj = ghost; - } - - if (spawncenter) - { - mobj->x = x; - mobj->y = y; - mobj->z = z; - } - - mobj->momx = FixedMul(FixedDiv(mobjx - x, dist), FixedDiv(dist, 6*FRACUNIT)); - mobj->momy = FixedMul(FixedDiv(mobjy - y, dist), FixedDiv(dist, 6*FRACUNIT)); - mobj->momz = FixedMul(FixedDiv(mobjz - z, dist), FixedDiv(dist, 6*FRACUNIT)); - - if (source && !P_MobjWasRemoved(source)) - P_SetTarget(&mobj->target, source); - } -} - #define MINEQUAKEDIST 4096 // Does the proximity screen flash and quake for explosions @@ -3817,6 +3858,8 @@ void K_SpawnMineExplosion(mobj_t *source, UINT8 color) radius = source->radius>>FRACBITS; height = source->height>>FRACBITS; + S_StartSound(smoldering, sfx_s3k4e); + if (!color) color = SKINCOLOR_KETCHUP; @@ -4463,7 +4506,6 @@ void K_SpawnSparkleTrail(mobj_t *mo) { const INT32 rad = (mo->radius*3)/FRACUNIT; mobj_t *sparkle; - INT32 i; UINT8 invanimnum; // Current sparkle animation number INT32 invtime;// Invincibility time left, in seconds UINT8 index = 0; @@ -4472,13 +4514,6 @@ void K_SpawnSparkleTrail(mobj_t *mo) I_Assert(mo != NULL); I_Assert(!P_MobjWasRemoved(mo)); - if ((mo->player->sneakertimer - || mo->player->ringboost || mo->player->driftboost - || mo->player->startboost || mo->player->eggmanexplode)) - { - return; - } - if (leveltime & 2) index = 1; @@ -4486,34 +4521,37 @@ void K_SpawnSparkleTrail(mobj_t *mo) //CONS_Printf("%d\n", index); - for (i = 0; i < 8; i++) - { - newx = mo->x + (P_RandomRange(-rad, rad)*FRACUNIT); - newy = mo->y + (P_RandomRange(-rad, rad)*FRACUNIT); - newz = mo->z + (P_RandomRange(0, mo->height>>FRACBITS)*FRACUNIT); + newx = mo->x + (P_RandomRange(-rad, rad)*FRACUNIT); + newy = mo->y + (P_RandomRange(-rad, rad)*FRACUNIT); + newz = mo->z + (P_RandomRange(0, mo->height>>FRACBITS)*FRACUNIT); - sparkle = P_SpawnMobj(newx, newy, newz, MT_SPARKLETRAIL); - P_InitAngle(sparkle, R_PointToAngle2(mo->x, mo->y, sparkle->x, sparkle->y)); - sparkle->movefactor = R_PointToDist2(mo->x, mo->y, sparkle->x, sparkle->y); // Save the distance we spawned away from the player. - //CONS_Printf("movefactor: %d\n", sparkle->movefactor/FRACUNIT); - sparkle->extravalue1 = (sparkle->z - mo->z); // Keep track of our Z position relative to the player's, I suppose. - sparkle->extravalue2 = P_RandomRange(0, 1) ? 1 : -1; // Rotation direction? - sparkle->cvmem = P_RandomRange(-25, 25)*mo->scale; // Vertical "angle" - K_FlipFromObject(sparkle, mo); + sparkle = P_SpawnMobj(newx, newy, newz, MT_SPARKLETRAIL); - //if (i == 0) - //P_SetMobjState(sparkle, S_KARTINVULN_LARGE1); + P_InitAngle(sparkle, R_PointToAngle2(mo->x, mo->y, sparkle->x, sparkle->y)); - P_SetTarget(&sparkle->target, mo); - sparkle->destscale = mo->destscale; - P_SetScale(sparkle, mo->scale); - } + sparkle->movefactor = R_PointToDist2(mo->x, mo->y, sparkle->x, sparkle->y); // Save the distance we spawned away from the player. + //CONS_Printf("movefactor: %d\n", sparkle->movefactor/FRACUNIT); + + sparkle->extravalue1 = (sparkle->z - mo->z); // Keep track of our Z position relative to the player's, I suppose. + sparkle->extravalue2 = P_RandomRange(0, 1) ? 1 : -1; // Rotation direction? + sparkle->cvmem = P_RandomRange(-25, 25)*mo->scale; // Vertical "angle" + + K_FlipFromObject(sparkle, mo); + P_SetTarget(&sparkle->target, mo); + + sparkle->destscale = mo->destscale; + P_SetScale(sparkle, mo->scale); invanimnum = (invtime >= 11) ? 11 : invtime; //CONS_Printf("%d\n", invanimnum); + P_SetMobjState(sparkle, K_SparkleTrailStartStates[invanimnum][index]); - sparkle->colorized = true; - sparkle->color = mo->color; + + if (mo->player->invincibilitytimer > itemtime+(2*TICRATE)) + { + sparkle->color = mo->color; + sparkle->colorized = true; + } } void K_SpawnWipeoutTrail(mobj_t *mo) @@ -4717,6 +4755,90 @@ void K_DriftDustHandling(mobj_t *spawner) } } +static void K_SpawnTripwireVFX(mobj_t *mo) +{ + tic_t t = leveltime; + angle_t ang, aoff; + SINT8 sign = 1; + boolean altColor = false; + mobj_t *dust; + boolean drifting = false; + UINT8 i; + + I_Assert(mo != NULL); + I_Assert(!P_MobjWasRemoved(mo)); + + if (!P_IsObjectOnGround(mo)) + return; + + if (mo->player) + { + ang = mo->player->drawangle; + + if (mo->player->drift != 0) + { + drifting = true; + ang += (mo->player->drift * ((ANGLE_270 + ANGLE_22h) / 5)); // -112.5 doesn't work. I fucking HATE SRB2 angles + if (mo->player->drift < 0) + sign = 1; + else + sign = -1; + } + } + else + ang = mo->angle; + + if (drifting == false) + { + i = (t & 1); + + if (i & 1) + sign = -1; + else + sign = 1; + } + else + { + if (t & 1) + { + return; + } + + t /= 2; + i = (t & 1); + } + + aoff = (ang + ANGLE_180) + (ANGLE_45 * sign); + + dust = P_SpawnMobj(mo->x + FixedMul(24*mo->scale, FINECOSINE(aoff>>ANGLETOFINESHIFT)), + mo->y + FixedMul(24*mo->scale, FINESINE(aoff>>ANGLETOFINESHIFT)), + mo->z, MT_DRIFTDUST); + + P_SetTarget(&dust->target, mo); + P_InitAngle(dust, ang - (ANGLE_90 * sign)); // point completely perpendicular from the player + P_SetScale(dust, mo->scale); + dust->destscale = mo->scale * 6; + dust->scalespeed = mo->scale/12; + K_FlipFromObject(dust, mo); + + altColor = (sign > 0); + + if ((t / 2) & 1) + { + dust->tics++; // "randomize" animation + altColor = !altColor; + } + + dust->colorized = true; + dust->color = altColor ? SKINCOLOR_BLOSSOM : SKINCOLOR_JAWZ; + + dust->momx = (4*mo->momx)/5; + dust->momy = (4*mo->momy)/5; + dust->momz = (4*P_GetMobjZMovement(mo))/5; + + P_Thrust(dust, dust->angle, 4*mo->scale); +} + void K_Squish(mobj_t *mo) { const fixed_t maxstretch = 4*FRACUNIT; @@ -6943,9 +7065,11 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) || player->driftboost || player->startboost || player->eggmanexplode || player->trickboost) { +#if 0 if (player->invincibilitytimer) K_SpawnInvincibilitySpeedLines(player->mo); else +#endif K_SpawnNormalSpeedLines(player); } @@ -7025,56 +7149,6 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) } } - if (player->playerstate == PST_DEAD || (player->respawn.state == RESPAWNST_MOVE)) // Ensure these are set correctly here - { - player->mo->colorized = (player->dye != 0); - player->mo->color = player->dye ? player->dye : player->skincolor; - } - else if (player->eggmanexplode) // You're gonna diiiiie - { - const INT32 flashtime = 4<<(player->eggmanexplode/TICRATE); - if (player->eggmanexplode == 1 || (player->eggmanexplode % (flashtime/2) != 0)) - { - player->mo->colorized = (player->dye != 0); - player->mo->color = player->dye ? player->dye : player->skincolor; - } - else if (player->eggmanexplode % flashtime == 0) - { - player->mo->colorized = true; - player->mo->color = SKINCOLOR_BLACK; - } - else - { - player->mo->colorized = true; - player->mo->color = SKINCOLOR_CRIMSON; - } - } - else if (player->invincibilitytimer) // setting players to use the star colormap and spawning afterimages - { - player->mo->colorized = true; - } - else if (player->growshrinktimer) // Ditto, for grow/shrink - { - if (player->growshrinktimer % 5 == 0) - { - player->mo->colorized = true; - player->mo->color = (player->growshrinktimer < 0 ? SKINCOLOR_CREAMSICLE : SKINCOLOR_PERIWINKLE); - } - else - { - player->mo->colorized = (player->dye != 0); - player->mo->color = player->dye ? player->dye : player->skincolor; - } - } - else if (player->ringboost && (leveltime & 1)) // ring boosting - { - player->mo->colorized = true; - } - else - { - player->mo->colorized = (player->dye != 0); - } - if (player->itemtype == KITEM_NONE) player->pflags &= ~PF_HOLDREADY; @@ -7302,6 +7376,17 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) K_HandleTumbleBounce(player); } + if (player->tripwireLeniency > 0) + { + player->tripwireLeniency--; + K_SpawnTripwireVFX(player->mo); + } + + if (K_TripwirePassConditions(player) == true) + { + player->tripwireLeniency = max(player->tripwireLeniency, TICRATE); + } + K_KartPlayerHUDUpdate(player); if (battleovertime.enabled && !(player->pflags & PF_ELIMINATED) && player->bumpers <= 0 && player->karmadelay <= 0) @@ -7415,13 +7500,103 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->tripWireState = TRIP_NONE; } + + K_KartEbrakeVisuals(player); + + if (K_GetKartButtons(player) & BT_BRAKE && + P_IsObjectOnGround(player->mo) && + K_GetKartSpeed(player, false) / 2 <= player->speed) + { + K_SpawnBrakeVisuals(player); + } } void K_KartPlayerAfterThink(player_t *player) { - if (player->curshield - || player->invincibilitytimer - || (player->growshrinktimer != 0 && player->growshrinktimer % 5 == 4)) // 4 instead of 0 because this is afterthink! + boolean fullbright = false; + + if (player->playerstate == PST_DEAD || (player->respawn.state == RESPAWNST_MOVE)) // Ensure these are set correctly here + { + player->mo->colorized = (player->dye != 0); + player->mo->color = player->dye ? player->dye : player->skincolor; + } + else if (player->eggmanexplode) // You're gonna diiiiie + { + const INT32 flashtime = 4<<(player->eggmanexplode/TICRATE); + if (player->eggmanexplode == 1 || (player->eggmanexplode % (flashtime/2) != 0)) + { + player->mo->colorized = (player->dye != 0); + player->mo->color = player->dye ? player->dye : player->skincolor; + } + else if (player->eggmanexplode % flashtime == 0) + { + player->mo->colorized = true; + player->mo->color = SKINCOLOR_BLACK; + fullbright = true; + } + else + { + player->mo->colorized = true; + player->mo->color = SKINCOLOR_CRIMSON; + fullbright = true; + } + } + else if (player->invincibilitytimer) + { + const tic_t defaultTime = itemtime+(2*TICRATE); + tic_t flicker = 2; + + fullbright = true; + + if (player->invincibilitytimer > defaultTime) + { + player->mo->color = K_RainbowColor(leveltime / 2); + player->mo->colorized = true; + } + else + { + player->mo->color = player->skincolor; + player->mo->colorized = false; + + flicker += (defaultTime - player->invincibilitytimer) / TICRATE / 2; + } + + if (leveltime % flicker == 0) + { + player->mo->color = SKINCOLOR_INVINCFLASH; + player->mo->colorized = true; + } + } + else if (player->growshrinktimer) // Ditto, for grow/shrink + { + if (player->growshrinktimer % 5 == 0) + { + player->mo->colorized = true; + player->mo->color = (player->growshrinktimer < 0 ? SKINCOLOR_CREAMSICLE : SKINCOLOR_PERIWINKLE); + fullbright = true; + } + else + { + player->mo->colorized = (player->dye != 0); + player->mo->color = player->dye ? player->dye : player->skincolor; + } + } + else if (player->ringboost && (leveltime & 1)) // ring boosting + { + player->mo->colorized = true; + fullbright = true; + } + else + { + player->mo->colorized = (player->dye != 0); + } + + if (player->curshield) + { + fullbright = true; + } + + if (fullbright == true) { player->mo->frame |= FF_FULLBRIGHT; } @@ -8584,6 +8759,134 @@ INT32 K_StairJankFlip(INT32 value) return P_AltFlip(value, 2); } +// Ebraking visuals for mo +// we use mo->hprev for the hold bubble. If another hprev exists for some reason, remove it. + +void K_KartEbrakeVisuals(player_t *p) +{ + mobj_t *wave; + mobj_t *spdl; + fixed_t sx, sy; + + if (K_PlayerEBrake(p)) + { + + if (p->ebrakefor % 20 == 0) + { + wave = P_SpawnMobj(p->mo->x, p->mo->y, p->mo->z, MT_SOFTLANDING); + P_SetScale(wave, p->mo->scale); + wave->momx = p->mo->momx; + wave->momy = p->mo->momy; + wave->momz = p->mo->momz; + wave->standingslope = p->mo->standingslope; + } + + // sound + if (!S_SoundPlaying(p->mo, sfx_s3kd9s)) + S_StartSound(p->mo, sfx_s3kd9s); + + // HOLD! bubble. + if (!p->ebrakefor) + { + if (p->mo->hprev && !P_MobjWasRemoved(p->mo->hprev)) + { + // for some reason, there's already an hprev. Remove it. + P_RemoveMobj(p->mo->hprev); + } + + p->mo->hprev = P_SpawnMobj(p->mo->x, p->mo->y, p->mo->z, MT_HOLDBUBBLE); + p->mo->hprev->renderflags |= (RF_DONTDRAW & ~K_GetPlayerDontDrawFlag(p)); + } + + // Update HOLD bubble. + if (p->mo->hprev && !P_MobjWasRemoved(p->mo->hprev)) + { + P_MoveOrigin(p->mo->hprev, p->mo->x, p->mo->y, p->mo->z); + p->mo->hprev->angle = p->mo->angle; + p->mo->hprev->fuse = TICRATE/2; // When we leave spindash for any reason, make sure this bubble goes away soon after. + K_FlipFromObject(p->mo->hprev, p->mo); + } + + + if (!p->spindash) + { + // Spawn downwards fastline + sx = p->mo->x + P_RandomRange(-48, 48)*p->mo->scale; + sy = p->mo->y + P_RandomRange(-48, 48)*p->mo->scale; + + spdl = P_SpawnMobj(sx, sy, p->mo->z, MT_DOWNLINE); + spdl->colorized = true; + spdl->color = SKINCOLOR_WHITE; + K_MatchGenericExtraFlags(spdl, p->mo); + P_SetScale(spdl, p->mo->scale); + + // squish the player a little bit. + p->mo->spritexscale = FRACUNIT*115/100; + p->mo->spriteyscale = FRACUNIT*85/100; + } + else + { + const UINT16 MAXCHARGETIME = K_GetSpindashChargeTime(p); + const fixed_t MAXSHAKE = FRACUNIT; + + // update HOLD bubble with numbers based on charge. + if (p->mo->hprev && !P_MobjWasRemoved(p->mo->hprev)) + { + UINT8 frame = min(1 + ((p->spindash*3) / MAXCHARGETIME), 4); + + // ?! limit. + if (p->spindash >= MAXCHARGETIME +TICRATE) + frame = 5; + + p->mo->hprev->frame = frame|FF_FULLBRIGHT; + } + + // shake the player as they charge their spindash! + + // "gentle" shaking as we start... + if (p->spindash < MAXCHARGETIME) + { + fixed_t shake = FixedMul(((p->spindash)*FRACUNIT/MAXCHARGETIME), MAXSHAKE); + SINT8 mult = leveltime & 1 ? 1 : -1; + + p->mo->spritexoffset = shake*mult; + } + else // get VIOLENT on overcharge :) + { + fixed_t shake = MAXSHAKE + FixedMul(((p->spindash-MAXCHARGETIME)*FRACUNIT/TICRATE), MAXSHAKE)*3; + SINT8 mult = leveltime & 1 ? 1 : -1; + + p->mo->spritexoffset = shake*mult; + } + + // sqish them a little MORE.... + p->mo->spritexscale = FRACUNIT*12/10; + p->mo->spriteyscale = FRACUNIT*8/10; + } + + + p->ebrakefor++; + } + else if (p->ebrakefor) // cancel effects + { + // reset scale + p->mo->spritexscale = FRACUNIT; + p->mo->spriteyscale = FRACUNIT; + + // reset shake + p->mo->spritexoffset = 0; + + // remove the bubble instantly unless it's in the !? state + if (p->mo->hprev && !P_MobjWasRemoved(p->mo->hprev) && (p->mo->hprev->frame & FF_FRAMEMASK) != 5) + { + P_RemoveMobj(p->mo->hprev); + p->mo->hprev = NULL; + } + + p->ebrakefor = 0; + } +} + static void K_KartSpindashDust(mobj_t *parent) { fixed_t rad = FixedDiv(FixedHypot(parent->radius, parent->radius), parent->scale); @@ -8640,6 +8943,9 @@ static void K_KartSpindashWind(mobj_t *parent) K_MatchGenericExtraFlags(wind, parent); } +// Time after which you get a thrust for releasing spindash +#define SPINDASHTHRUSTTIME 20 + static void K_KartSpindash(player_t *player) { const INT16 MAXCHARGETIME = K_GetSpindashChargeTime(player); @@ -8651,11 +8957,18 @@ static void K_KartSpindash(player_t *player) player->spindash = 0; } - if (player->spindash > 0 && (cmd->buttons & (BT_DRIFT|BT_BRAKE)) != (BT_DRIFT|BT_BRAKE)) + if (player->spindash > 0 && (cmd->buttons & (BT_DRIFT|BT_BRAKE|BT_ACCELERATE)) != (BT_DRIFT|BT_BRAKE|BT_ACCELERATE)) { player->spindashspeed = (player->spindash * FRACUNIT) / MAXCHARGETIME; player->spindashboost = TICRATE; + // if spindash was charged enough, give a small thrust. + if (player->spindash >= SPINDASHTHRUSTTIME) + { + // Give a bit of a boost depending on charge. + P_InstaThrust(player->mo, player->mo->angle, FixedMul(player->mo->scale, player->spindash*FRACUNIT/5)); + } + if (!player->tiregrease) { UINT8 i; @@ -8702,10 +9015,11 @@ static void K_KartSpindash(player_t *player) { if ((cmd->buttons & (BT_DRIFT|BT_BRAKE)) == (BT_DRIFT|BT_BRAKE)) { + UINT8 ringdropframes = 2 + (player->kartspeed + player->kartweight); INT16 chargetime = MAXCHARGETIME - ++player->spindash; boolean spawnOldEffect = true; - if (chargetime <= (MAXCHARGETIME / 2)) + if (player->spindash >= SPINDASHTHRUSTTIME) { K_KartSpindashDust(player->mo); spawnOldEffect = false; @@ -8716,7 +9030,7 @@ static void K_KartSpindash(player_t *player) K_KartSpindashWind(player->mo); } - if (player->flashing > 0 && (leveltime & 1) && player->hyudorotimer == 0) + if (player->flashing > 0 && (player->spindash % ringdropframes == 0) && player->hyudorotimer == 0) { // Every frame that you're invisible from flashing, spill a ring. // Intentionally a lop-sided trade-off, so the game doesn't become @@ -8752,6 +9066,8 @@ static void K_KartSpindash(player_t *player) } } +#undef SPINDASHTHRUSTTIME + static void K_AirFailsafe(player_t *player) { const fixed_t maxSpeed = 6*player->mo->scale; @@ -9124,7 +9440,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) overlay->destscale = player->mo->scale; P_SetScale(overlay, player->mo->scale); } - player->invincibilitytimer = itemtime+(2*TICRATE); // 10 seconds + player->invincibilitytimer += itemtime+(2*TICRATE); // 10 seconds if (P_IsLocalPlayer(player) == true) { diff --git a/src/k_kart.h b/src/k_kart.h index 91024488f..aef18b19e 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -75,7 +75,6 @@ void K_DebtStingPlayer(player_t *player, mobj_t *source); void K_HandleBumperChanges(player_t *player, UINT8 prevBumpers); void K_DestroyBumpers(player_t *player, UINT8 amount); void K_TakeBumpersFromPlayer(player_t *player, player_t *victim, UINT8 amount); -void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle, boolean spawncenter, boolean ghostit, mobj_t *source); void K_MineFlashScreen(mobj_t *source); void K_SpawnMineExplosion(mobj_t *source, UINT8 color); void K_RunFinishLineBeam(void); @@ -116,6 +115,7 @@ void K_StripOther(player_t *player); void K_MomentumToFacing(player_t *player); boolean K_ApplyOffroad(player_t *player); boolean K_SlopeResistance(player_t *player); +boolean K_TripwirePassConditions(player_t *player); boolean K_TripwirePass(player_t *player); boolean K_WaterRun(player_t *player); void K_ApplyTripWire(player_t *player, tripwirestate_t state); @@ -141,6 +141,7 @@ void K_CheckSpectateStatus(void); UINT8 K_GetInvincibilityItemFrame(void); UINT8 K_GetOrbinautItemFrame(UINT8 count); boolean K_IsSPBInGame(void); +void K_KartEbrakeVisuals(player_t *p); // sound stuff for lua void K_PlayAttackTaunt(mobj_t *source); diff --git a/src/k_race.c b/src/k_race.c index f459e7a80..fde4c9be2 100644 --- a/src/k_race.c +++ b/src/k_race.c @@ -125,7 +125,7 @@ boolean K_GenerateFinishBeamLine(void) mapthing_t *mt; INT64 bounds[4]; - angle_t angle; + angle_t angle = 0; boolean valid = false; size_t i; diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 7b125b378..4d334a9a4 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -3549,25 +3549,6 @@ static int lib_kTakeBumpersFromPlayer(lua_State *L) return 0; } -static int lib_kSpawnKartExplosion(lua_State *L) -{ - fixed_t x = luaL_checkfixed(L, 1); - fixed_t y = luaL_checkfixed(L, 2); - fixed_t z = luaL_checkfixed(L, 3); - fixed_t radius = (fixed_t)luaL_optinteger(L, 4, 32*FRACUNIT); - INT32 number = (INT32)luaL_optinteger(L, 5, 32); - mobjtype_t type = luaL_optinteger(L, 6, MT_MINEEXPLOSION); - angle_t rotangle = luaL_optinteger(L, 7, 0); - boolean spawncenter = lua_opttrueboolean(L, 8); - boolean ghostit = lua_optboolean(L, 9); - mobj_t *source = NULL; - NOHUD - if (!lua_isnone(L, 10) && lua_isuserdata(L, 10)) - source = *((mobj_t **)luaL_checkudata(L, 10, META_MOBJ)); - K_SpawnKartExplosion(x, y, z, radius, number, type, rotangle, spawncenter, ghostit, source); - return 0; -} - static int lib_kSpawnMineExplosion(lua_State *L) { mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); @@ -4100,7 +4081,6 @@ static luaL_Reg lib[] = { {"K_TumblePlayer",lib_kTumblePlayer}, {"K_ExplodePlayer",lib_kExplodePlayer}, {"K_TakeBumpersFromPlayer",lib_kTakeBumpersFromPlayer}, - {"K_SpawnKartExplosion",lib_kSpawnKartExplosion}, {"K_SpawnMineExplosion",lib_kSpawnMineExplosion}, {"K_SpawnBoostTrail",lib_kSpawnBoostTrail}, {"K_SpawnSparkleTrail",lib_kSpawnSparkleTrail}, diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 6b297c240..3d05d9c15 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -288,6 +288,8 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->draftleeway); else if (fastcmp(field,"lastdraft")) lua_pushinteger(L, plr->lastdraft); + else if (fastcmp(field,"tripwireLeniency")) + lua_pushinteger(L, plr->tripwireLeniency); else if (fastcmp(field,"itemroulette")) lua_pushinteger(L, plr->itemroulette); else if (fastcmp(field,"roulettetype")) @@ -630,6 +632,8 @@ static int player_set(lua_State *L) plr->draftleeway = luaL_checkinteger(L, 3); else if (fastcmp(field,"lastdraft")) plr->lastdraft = luaL_checkinteger(L, 3); + else if (fastcmp(field,"tripwireLeniency")) + plr->tripwireLeniency = luaL_checkinteger(L, 3); else if (fastcmp(field,"itemroulette")) plr->itemroulette = luaL_checkinteger(L, 3); else if (fastcmp(field,"roulettetype")) diff --git a/src/m_misc.c b/src/m_misc.c index d3e663f27..c00d7ee70 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -969,7 +969,7 @@ static void M_PNGText(png_structp png_ptr, png_infop png_info_ptr, PNG_CONST png else snprintf(lvlttltext, 48, "Unknown"); - if (gamestate == GS_LEVEL && &players[g_localplayers[0]] && players[g_localplayers[0]].mo) + if (gamestate == GS_LEVEL && players[g_localplayers[0]].mo) snprintf(locationtxt, 40, "X:%d Y:%d Z:%d A:%d", players[g_localplayers[0]].mo->x>>FRACBITS, players[g_localplayers[0]].mo->y>>FRACBITS, diff --git a/src/p_enemy.c b/src/p_enemy.c index 0edfbb5e8..7b6d12983 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -25,10 +25,13 @@ #include "i_video.h" #include "z_zone.h" #include "lua_hook.h" -#include "k_kart.h" // SRB2kart + +// SRB2kart +#include "k_kart.h" #include "k_waypoint.h" #include "k_battle.h" #include "k_respawn.h" +#include "k_collide.h" #ifdef HW3SOUND #include "hardware/hw3sound.h" @@ -141,7 +144,6 @@ void A_RingExplode(mobj_t *actor); void A_OldRingExplode(mobj_t *actor); void A_MixUp(mobj_t *actor); void A_Boss2TakeDamage(mobj_t *actor); -void A_Boss7Chase(mobj_t *actor); void A_GoopSplat(mobj_t *actor); void A_Boss2PogoSFX(mobj_t *actor); void A_Boss2PogoTarget(mobj_t *actor); @@ -2490,26 +2492,15 @@ void A_LobShot(mobj_t *actor) if (actor->eflags & MFE_VERTICALFLIP) { z = actor->z + actor->height - FixedMul(locvar2*FRACUNIT, actor->scale); - if (actor->type == MT_BLACKEGGMAN) - z -= FixedMul(mobjinfo[locvar1].height, actor->scale/2); - else - z -= FixedMul(mobjinfo[locvar1].height, actor->scale); + z -= FixedMul(mobjinfo[locvar1].height, actor->scale); } else z = actor->z + FixedMul(locvar2*FRACUNIT, actor->scale); shot = P_SpawnMobj(actor->x, actor->y, z, locvar1); - if (actor->type == MT_BLACKEGGMAN) - { - shot->destscale = actor->scale/2; - P_SetScale(shot, actor->scale/2); - } - else - { - shot->destscale = actor->scale; - P_SetScale(shot, actor->scale); - } + shot->destscale = actor->scale; + P_SetScale(shot, actor->scale); // Keep track of where it's going to land hitspot = P_SpawnMobj(actor->target->x&(64*FRACUNIT-1), actor->target->y&(64*FRACUNIT-1), actor->target->subsector->sector->floorheight, MT_NULL); @@ -3576,28 +3567,6 @@ bossjustdie: // now do another switch case for escaping switch (mo->type) { - case MT_BLACKEGGMAN: - { - mo->flags |= MF_NOCLIP; - mo->flags &= ~MF_SPECIAL; - - S_StartSound(NULL, sfx_befall); - break; - } - case MT_CYBRAKDEMON: - { - mo->flags |= MF_NOCLIP; - mo->flags &= ~(MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT); - - S_StartSound(NULL, sfx_bedie2); - P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_CYBRAKDEMON_VILE_EXPLOSION); - mo->z += P_MobjFlip(mo); - P_SetObjectMomZ(mo, 12*FRACUNIT, false); - S_StartSound(mo, sfx_bgxpld); - if (mo->spawnpoint && !(mo->spawnpoint->options & MTF_EXTRA)) - P_InstaThrust(mo, R_PointToAngle2(0, 0, mo->x, mo->y), 14*FRACUNIT); - break; - } case MT_KOOPA: { // Initialize my junk @@ -4047,7 +4016,7 @@ void A_AttractChase(mobj_t *actor) } else { - fixed_t dist = (actor->target->radius/4) * (16 - actor->extravalue1); + fixed_t dist = (4*actor->target->scale) * (16 - actor->extravalue1); P_SetScale(actor, (actor->destscale = actor->target->scale - ((actor->target->scale/14) * actor->extravalue1))); actor->z = actor->target->z; @@ -6190,128 +6159,6 @@ void A_Boss2TakeDamage(mobj_t *actor) actor->movecount = locvar1; // become flashing invulnerable for this long. } -// Function: A_Boss7Chase -// -// Description: Like A_Chase, but for Black Eggman -// -// var1 = unused -// var2 = unused -// -void A_Boss7Chase(mobj_t *actor) -{ - INT32 delta; - INT32 i; - - if (LUA_CallAction(A_BOSS7CHASE, actor)) - return; - - if (actor->z != actor->floorz) - return; - - // Self-adjust if stuck on the edge - if (actor->tracer) - { - if (P_AproxDistance(actor->x - actor->tracer->x, actor->y - actor->tracer->y) > 128*FRACUNIT - actor->radius) - P_InstaThrust(actor, R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y), FRACUNIT); - } - - if (actor->flags2 & MF2_FRET) - { - P_SetMobjState(actor, S_BLACKEGG_DESTROYPLAT1); - S_StartSound(0, sfx_s3k53); - actor->flags2 &= ~MF2_FRET; - return; - } - - // turn towards movement direction if not there yet - if (actor->movedir < NUMDIRS) - { - actor->angle &= (7<<29); - delta = actor->angle - (actor->movedir << 29); - - if (delta > 0) - actor->angle -= ANGLE_45; - else if (delta < 0) - actor->angle += ANGLE_45; - } - - // Is a player on top of us? - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) - continue; - - if (!players[i].mo) - continue; - - if (players[i].mo->health <= 0) - continue; - - if (P_AproxDistance(players[i].mo->x - actor->x, players[i].mo->y - actor->y) > actor->radius) - continue; - - if (players[i].mo->z > actor->z + actor->height - 2*FRACUNIT - && players[i].mo->z < actor->z + actor->height + 32*FRACUNIT) - { - // Punch him! - P_SetMobjState(actor, actor->info->meleestate); - S_StartSound(0, sfx_begrnd); // warning sound - return; - } - } - - if (actor->reactiontime) - actor->reactiontime--; - - if (actor->reactiontime <= 0 && actor->z == actor->floorz) - { - // Here, we'll call P_RandomByte() and decide what kind of attack to do - switch(actor->threshold) - { - case 0: // Lob cannon balls - if (actor->z < 1056*FRACUNIT) - { - A_FaceTarget(actor); - P_SetMobjState(actor, actor->info->xdeathstate); - actor->movecount = 7*TICRATE + P_RandomByte(); - break; - } - actor->threshold++; - /* FALLTHRU */ - case 1: // Chaingun Goop - A_FaceTarget(actor); - P_SetMobjState(actor, S_BLACKEGG_SHOOT1); - - if (actor->health > actor->info->damage) - actor->movecount = TICRATE + P_RandomByte()/3; - else - actor->movecount = TICRATE + P_RandomByte()/2; - break; - case 2: // Homing Missile - A_FaceTarget(actor); - P_SetMobjState(actor, actor->info->missilestate); - S_StartSound(0, sfx_beflap); - break; - } - - actor->threshold++; - actor->threshold %= 3; - return; - } - - // possibly choose another target - if (multiplayer && (actor->target->health <= 0 || !P_CheckSight(actor, actor->target)) - && P_BossTargetPlayer(actor, false)) - return; // got a new target - - if (leveltime & 1) - { - // chase towards player - if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed)) - P_NewChaseDir(actor); - } -} - // Function: A_GoopSplat // // Description: Black Eggman goop hits a target and sticks around for awhile. @@ -9846,7 +9693,7 @@ void A_VileTarget(mobj_t *actor) // Determine object to spawn if (locvar1 <= 0 || locvar1 >= NUMMOBJTYPES) - fogtype = MT_CYBRAKDEMON_TARGET_RETICULE; + return; else fogtype = (mobjtype_t)locvar1; @@ -10142,8 +9989,6 @@ void A_BrakChase(mobj_t *actor) if (actor->reactiontime) { actor->reactiontime--; - if (actor->reactiontime == 0 && actor->type == MT_CYBRAKDEMON) - S_StartSound(0, sfx_bewar1 + P_RandomKey(4)); } // modify target threshold @@ -10222,7 +10067,7 @@ void A_BrakChase(mobj_t *actor) S_StartSound(actor, (sfxenum_t)locvar2); // make active sound - if (actor->type != MT_CYBRAKDEMON && actor->info->activesound && P_RandomChance(3*FRACUNIT/256)) + if (actor->info->activesound && P_RandomChance(3*FRACUNIT/256)) { S_StartSound(actor, actor->info->activesound); } @@ -14050,55 +13895,9 @@ void A_SPBChase(mobj_t *actor) return; } -static mobj_t *grenade; -static fixed_t explodedist; - -static inline boolean PIT_SSMineSearch(mobj_t *thing) -{ - if (!grenade) - return false; - - if (grenade->flags2 & MF2_DEBRIS) - return false; - - if (thing->type != MT_PLAYER) // Don't explode for anything but an actual player. - return true; - - if (!(thing->flags & MF_SHOOTABLE)) - { - // didn't do any damage - return true; - } - - if (netgame && thing->player && thing->player->spectator) - return true; - - if (thing == grenade->target && grenade->threshold != 0) // Don't blow up at your owner. - return true; - - if (thing->player && (thing->player->hyudorotimer - || ((gametyperules & GTR_BUMPERS) && thing->player && thing->player->bumpers <= 0 && thing->player->karmadelay))) - return true; - - // see if it went over / under - if (grenade->z - explodedist > thing->z + thing->height) - return true; // overhead - if (grenade->z + grenade->height + explodedist < thing->z) - return true; // underneath - - if (P_AproxDistance(P_AproxDistance(thing->x - grenade->x, thing->y - grenade->y), - thing->z - grenade->z) > explodedist) - return true; // Too far away - - // Explode! - P_SetMobjState(grenade, grenade->info->deathstate); - return false; -} - void A_SSMineSearch(mobj_t *actor) { - INT32 bx, by, xl, xh, yl, yh; - explodedist = FixedMul(actor->info->painchance, mapobjectscale); + fixed_t dis = INT32_MAX; if (LUA_CallAction(A_SSMINESEARCH, actor)) return; @@ -14106,66 +13905,19 @@ void A_SSMineSearch(mobj_t *actor) if (actor->flags2 & MF2_DEBRIS) return; - if (actor->state == &states[S_SSMINE_DEPLOY8]) - explodedist = (3*explodedist)/2; - if (leveltime % 35 == 0) S_StartSound(actor, actor->info->activesound); - // Use blockmap to check for nearby shootables - yh = (unsigned)(actor->y + explodedist - bmaporgy)>>MAPBLOCKSHIFT; - yl = (unsigned)(actor->y - explodedist - bmaporgy)>>MAPBLOCKSHIFT; - xh = (unsigned)(actor->x + explodedist - bmaporgx)>>MAPBLOCKSHIFT; - xl = (unsigned)(actor->x - explodedist - bmaporgx)>>MAPBLOCKSHIFT; + dis = actor->info->painchance; + if (actor->state == &states[S_SSMINE_DEPLOY8]) + dis = (3*dis)>>1; - grenade = actor; - - for (by = yl; by <= yh; by++) - for (bx = xl; bx <= xh; bx++) - P_BlockThingsIterator(bx, by, PIT_SSMineSearch); -} - -static inline boolean PIT_MineExplode(mobj_t *thing) -{ - if (!grenade || P_MobjWasRemoved(grenade)) - return false; // There's the possibility these can chain react onto themselves after they've already died if there are enough all in one spot - - if (grenade->flags2 & MF2_DEBRIS) // don't explode twice - return false; - - if (thing == grenade || thing->type == MT_MINEEXPLOSIONSOUND) // Don't explode yourself! Endless loop! - return true; - - if (!(thing->flags & MF_SHOOTABLE) || (thing->flags & MF_SCENERY)) - return true; - - if (netgame && thing->player && thing->player->spectator) - return true; - - if ((gametyperules & GTR_BUMPERS) && grenade->target && grenade->target->player && grenade->target->player->bumpers <= 0 && thing == grenade->target) - return true; - - // see if it went over / under - if (grenade->z - explodedist > thing->z + thing->height) - return true; // overhead - if (grenade->z + grenade->height + explodedist < thing->z) - return true; // underneath - - if (P_AproxDistance(P_AproxDistance(thing->x - grenade->x, thing->y - grenade->y), - thing->z - grenade->z) > explodedist) - return true; // Too far away - - P_DamageMobj(thing, grenade, grenade->target, 1, DMG_EXPLODE); - return true; + K_DoMineSearch(actor, dis); } void A_SSMineExplode(mobj_t *actor) { - INT32 bx, by, xl, xh, yl, yh; - INT32 d; INT32 locvar1 = var1; - mobjtype_t type; - explodedist = FixedMul((3*actor->info->painchance)/2, actor->scale); if (LUA_CallAction(A_SSMINEEXPLODE, actor)) return; @@ -14173,33 +13925,8 @@ void A_SSMineExplode(mobj_t *actor) if (actor->flags2 & MF2_DEBRIS) return; - type = (mobjtype_t)locvar1; - - // Use blockmap to check for nearby shootables - yh = (unsigned)(actor->y + explodedist - bmaporgy)>>MAPBLOCKSHIFT; - yl = (unsigned)(actor->y - explodedist - bmaporgy)>>MAPBLOCKSHIFT; - xh = (unsigned)(actor->x + explodedist - bmaporgx)>>MAPBLOCKSHIFT; - xl = (unsigned)(actor->x - explodedist - bmaporgx)>>MAPBLOCKSHIFT; - - BMBOUNDFIX (xl, xh, yl, yh); - - grenade = actor; - - for (by = yl; by <= yh; by++) - for (bx = xl; bx <= xh; bx++) - P_BlockThingsIterator(bx, by, PIT_MineExplode); - - for (d = 0; d < 16; d++) - K_SpawnKartExplosion(actor->x, actor->y, actor->z, explodedist + 32*mapobjectscale, 32, type, d*(ANGLE_45/4), true, false, actor->target); // 32 <-> 64 - - if (actor->target && actor->target->player) - K_SpawnMineExplosion(actor, actor->target->player->skincolor); - else - K_SpawnMineExplosion(actor, SKINCOLOR_KETCHUP); - - P_SpawnMobj(actor->x, actor->y, actor->z, MT_MINEEXPLOSIONSOUND); - - actor->flags2 |= MF2_DEBRIS; // Set this flag to ensure that the explosion won't be effective more than 1 frame. + K_SpawnMineExplosion(actor, (actor->target && actor->target->player) ? actor->target->player->skincolor : SKINCOLOR_KETCHUP); + K_MineExplodeAttack(actor, (3*actor->info->painchance)>>1, (boolean)locvar1); } void A_LandMineExplode(mobj_t *actor) @@ -14748,6 +14475,7 @@ void A_FlameShieldPaper(mobj_t *actor) void A_InvincSparkleRotate(mobj_t *actor) { fixed_t sx, sy, sz; // Teleport dests. + mobj_t *ghost = NULL; if (LUA_CallAction(A_INVINCSPARKLEROTATE, actor)) return; @@ -14766,4 +14494,11 @@ void A_InvincSparkleRotate(mobj_t *actor) actor->momz = actor->target->momz; // Give momentum for eventual interp builds idk. actor->angle += ANG1*10*(actor->extravalue2); // Arbitrary value, change this if you want, I suppose. + + ghost = P_SpawnGhostMobj(actor); + if (ghost != NULL && P_MobjWasRemoved(ghost) == false) + { + ghost->frame |= FF_ADD; + ghost->fuse = 4; + } } diff --git a/src/p_map.c b/src/p_map.c index 6954d6e11..9d3df593b 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -892,27 +892,6 @@ static boolean PIT_CheckThing(mobj_t *thing) return K_MineCollide(thing, tmthing); } - if (tmthing->type == MT_MINEEXPLOSION) - { - // see if it went over / under - if (tmthing->z > thing->z + thing->height) - return true; // overhead - if (tmthing->z + tmthing->height < thing->z) - return true; // underneath - - return K_MineExplosionCollide(tmthing, thing); - } - else if (thing->type == MT_MINEEXPLOSION) - { - // see if it went over / under - if (tmthing->z > thing->z + thing->height) - return true; // overhead - if (tmthing->z + tmthing->height < thing->z) - return true; // underneath - - return K_MineExplosionCollide(thing, tmthing); - } - if (tmthing->type == MT_LANDMINE) { // see if it went over / under @@ -2490,8 +2469,10 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) // This makes sure that there are no freezes from computing extremely small movements. // Originally was MAXRADIUS/2, but that causes some inconsistencies for small players. - if (radius < mapobjectscale) - radius = mapobjectscale; + radius = max(radius, mapobjectscale); + + // And Big Large (tm) movements can skip over slopes. + radius = min(radius, 16*mapobjectscale); #if 0 if (thing->hitlag > 0) @@ -3922,7 +3903,7 @@ bounceback: tmxmove = FixedMul(mmomx, (FRACUNIT - (FRACUNIT>>6) - (FRACUNIT>>5))); tmymove = FixedMul(mmomy, (FRACUNIT - (FRACUNIT>>6) - (FRACUNIT>>5))); } - else if (mo->type == MT_THROWNGRENADE || mo->type == MT_CYBRAKDEMON_NAPALM_BOMB_LARGE) + else if (mo->type == MT_THROWNGRENADE) { // Quickly decay speed as it bounces tmxmove = FixedDiv(mmomx, 2*FRACUNIT); diff --git a/src/p_mobj.c b/src/p_mobj.c index d9ab80de4..155f9bf3e 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -42,6 +42,7 @@ #include "k_respawn.h" #include "k_bot.h" #include "k_terrain.h" +#include "k_collide.h" static CV_PossibleValue_t CV_BobSpeed[] = {{0, "MIN"}, {4*FRACUNIT, "MAX"}, {0, NULL}}; consvar_t cv_movebob = CVAR_INIT ("movebob", "1.0", CV_FLOAT|CV_SAVE, CV_BobSpeed, NULL); @@ -1171,7 +1172,6 @@ fixed_t P_GetMobjGravity(mobj_t *mo) } break; case MT_WATERDROP: - case MT_CYBRAKDEMON: case MT_BATTLEBUMPER: gravityadd /= 2; break; @@ -2342,10 +2342,6 @@ boolean P_ZMovement(mobj_t *mo) if (abs(mom.z) < mo->scale) { mom.x = mom.y = mom.z = 0; - - // Napalm hack - if (mo->type == MT_CYBRAKDEMON_NAPALM_BOMB_LARGE && mo->fuse) - mo->fuse = 1; } // Otherwise bounce up at half speed. else @@ -6274,9 +6270,6 @@ static boolean P_MobjDeadThink(mobj_t *mobj) return false; } break; - case MT_MINEEXPLOSIONSOUND: - P_RemoveMobj(mobj); - return false; case MT_CDUFO: if (mobj->fuse > TICRATE) mobj->renderflags ^= RF_DONTDRAW; // only by good fortune does this end with it having RF_DONTDRAW... don't touch! @@ -6965,34 +6958,6 @@ static boolean P_MobjRegularThink(mobj_t *mobj) case MT_SPBEXPLOSION: mobj->health--; break; - case MT_MINEEXPLOSION: - if ((mobj->z < mobj->floorz - mobj->height) || (mobj->z > mobj->ceilingz + mobj->height)) - { - P_KillMobj(mobj, NULL, NULL, DMG_NORMAL); - break; - } - - if (mobj->tics != -1) - { - mobj->tics--; - - // you can cycle through multiple states in a tic - if (!mobj->tics) - if (!P_SetMobjState(mobj, mobj->state->nextstate)) - return false; // freed itself - } - - P_UnsetThingPosition(mobj); - mobj->x += mobj->momx; - mobj->y += mobj->momy; - mobj->z += mobj->momz; - P_SetThingPosition(mobj); - return false; - case MT_MINEEXPLOSIONSOUND: - if (mobj->health == 100) - S_StartSound(mobj, sfx_s3k4e); - mobj->health--; - break; case MT_EMERALD: { if (battleovertime.enabled >= 10*TICRATE) @@ -7168,15 +7133,6 @@ static boolean P_MobjRegularThink(mobj_t *mobj) P_Thrust(smoke, mobj->angle+FixedAngle(P_RandomRange(135, 225)<target->scale); } break; - case MT_SPARKLETRAIL: - if (!mobj->target) - { - P_RemoveMobj(mobj); - return false; - } - mobj->color = mobj->target->color; - mobj->colorized = mobj->target->colorized; - break; case MT_INVULNFLASH: if (!mobj->target || !mobj->target->health || (mobj->target->player && !mobj->target->player->invincibilitytimer)) { @@ -7222,6 +7178,9 @@ static boolean P_MobjRegularThink(mobj_t *mobj) mobj->renderflags |= RF_DONTDRAW; } break; + case MT_BRAKEDUST: + //mobj->renderflags ^= RF_DONTDRAW; + break; case MT_JANKSPARK: if (!mobj->target) { @@ -8955,6 +8914,17 @@ static void P_FiringThink(mobj_t *mobj) mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); } +static void K_MineExplodeThink(mobj_t *mobj) +{ + if (mobj->state->action.acp1 == (actionf_p1)A_SSMineExplode) + { + if (mobj->state->tics > 1) + { + K_MineExplodeAttack(mobj, mobj->info->painchance, (boolean)mobj->state->var1); + } + } +} + static void P_MonitorFuseThink(mobj_t *mobj) { mobj_t *newmobj; @@ -9306,6 +9276,9 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->flags2 & MF2_FIRING) P_FiringThink(mobj); + if (mobj->flags2 & MF2_DEBRIS) + K_MineExplodeThink(mobj); + if (mobj->flags & MF_AMBIENT) { if (!(leveltime % mobj->health) && mobj->info->seesound) @@ -9583,6 +9556,16 @@ void P_SceneryThinker(mobj_t *mobj) P_CycleMobjState(mobj); + // Flicker softlanding mobj, this just prevents us from needing like 20 states. + if (mobj->type == MT_SOFTLANDING) + { + mobj->renderflags |= RF_NOSPLATBILLBOARD|RF_OBJECTSLOPESPLAT; + if (mobj->tics & 1) + mobj->renderflags |= RF_DONTDRAW; + else + mobj->renderflags &= ~RF_DONTDRAW; + } + if (mobj->type != MT_RANDOMAUDIENCE) return; @@ -9632,6 +9615,8 @@ static void P_DefaultMobjShadowScale(mobj_t *thing) { case MT_PLAYER: case MT_KART_LEFTOVER: + thing->shadowscale = FRACUNIT; + break; case MT_SMALLMACE: case MT_BIGMACE: case MT_PUMA: @@ -9825,17 +9810,6 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) case MT_LOCKONINF: P_SetScale(mobj, (mobj->destscale = 3*mobj->scale)); break; - case MT_CYBRAKDEMON_NAPALM_BOMB_LARGE: - mobj->fuse = mobj->info->painchance; - break; - case MT_BLACKEGGMAN: - { - mobj_t *spawn = P_SpawnMobj(mobj->x, mobj->z, mobj->z+mobj->height-16*FRACUNIT, MT_BLACKEGGMAN_HELPER); - spawn->destscale = mobj->scale; - P_SetScale(spawn, mobj->scale); - P_SetTarget(&spawn->target, mobj); - } - break; case MT_FAKEMOBILE: case MT_EGGSHIELD: mobj->flags2 |= MF2_INVERTAIMABLE; diff --git a/src/p_saveg.c b/src/p_saveg.c index 18cef0e94..bebc5c161 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -278,6 +278,8 @@ static void P_NetArchivePlayers(void) WRITEUINT16(save_p, players[i].draftleeway); WRITESINT8(save_p, players[i].lastdraft); + WRITEUINT16(save_p, players[i].tripwireLeniency); + WRITEUINT16(save_p, players[i].itemroulette); WRITEUINT8(save_p, players[i].roulettetype); @@ -326,6 +328,8 @@ static void P_NetArchivePlayers(void) WRITEUINT8(save_p, players[i].trickboostdecay); WRITEUINT8(save_p, players[i].trickboost); + WRITEUINT32(save_p, players[i].ebrakefor); + WRITEUINT32(save_p, players[i].roundscore); WRITEUINT8(save_p, players[i].emeralds); WRITEUINT8(save_p, players[i].bumpers); @@ -544,6 +548,8 @@ static void P_NetUnArchivePlayers(void) players[i].draftleeway = READUINT16(save_p); players[i].lastdraft = READSINT8(save_p); + players[i].tripwireLeniency = READUINT16(save_p); + players[i].itemroulette = READUINT16(save_p); players[i].roulettetype = READUINT8(save_p); @@ -592,6 +598,8 @@ static void P_NetUnArchivePlayers(void) players[i].trickboostdecay = READUINT8(save_p); players[i].trickboost = READUINT8(save_p); + players[i].ebrakefor = READUINT32(save_p); + players[i].roundscore = READUINT32(save_p); players[i].emeralds = READUINT8(save_p); players[i].bumpers = READUINT8(save_p); diff --git a/src/p_setup.c b/src/p_setup.c index e027181cc..f2da9c0f8 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4260,15 +4260,6 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) } F_RunWipe(wipedefs[wipe_level_toblack], false, ((levelfadecol == 0) ? "FADEMAP1" : "FADEMAP0"), false, false); - - { - sfxenum_t kstart = sfx_kstart; - if (bossinfo.boss) - kstart = sfx_ssa021; - else if (encoremode) - kstart = sfx_ruby2; - S_StartSound(NULL, kstart); - } } /*if (!titlemapinaction) wipegamestate = GS_LEVEL;*/ diff --git a/src/p_user.c b/src/p_user.c index 2f3c13c4c..bdc45a844 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1672,15 +1672,15 @@ static void P_CheckInvincibilityTimer(player_t *player) if (!player->invincibilitytimer) return; - player->mo->color = K_RainbowColor(leveltime); - // Resume normal music stuff. if (player->invincibilitytimer == 1) { player->mo->color = player->skincolor; + player->mo->colorized = false; G_GhostAddColor((INT32) (player - players), GHC_NORMAL); P_RestoreMusic(player); + return; } } diff --git a/src/r_plane.c b/src/r_plane.c index ccd4994ce..0a4e8ef0d 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -921,8 +921,8 @@ void R_DrawSinglePlane(visplane_t *pl) if (top < 0) top = 0; - if (bottom > vid.height) - bottom = vid.height; + if (bottom > viewheight) + bottom = viewheight; // Only copy the part of the screen we need for (i = 0; i <= r_splitscreen; i++) @@ -956,9 +956,10 @@ void R_DrawSinglePlane(visplane_t *pl) offset = (scry*vid.width) + scrx; // No idea if this works - VID_BlitLinearScreen(screens[0] + offset, screens[1] + offset, - viewwidth, bottom-top, - vid.width, vid.width); + VID_BlitLinearScreen(screens[0] + offset, + screens[1] + (top*vid.width), // intentionally not +offset + viewwidth, bottom-top, + vid.width, vid.width); } } } diff --git a/src/s_sound.c b/src/s_sound.c index abc3707c5..1214472d7 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -520,6 +520,7 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) sfxinfo_t *sfx; INT32 sep, pitch, priority, cnum; boolean anyListeners = false; + boolean itsUs = false; INT32 i; listener_t listener[MAXSPLITSCREENPLAYERS]; @@ -557,6 +558,11 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) { listenmobj[i] = player->mo; } + + if (origin && origin == listenmobj[i]) + { + itsUs = true; + } } #ifdef HW3SOUND @@ -616,40 +622,51 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) // Initialize sound parameters pitch = NORM_PITCH; priority = NORM_PRIORITY; + sep = NORM_SEP; + + i = 0; // sensible default - for (i = r_splitscreen; i >= 0; i--) { - // Copy the sound for the splitscreen players! - if (listenmobj[i] == NULL && i != 0) - { - continue; - } - // Check to see if it is audible, and if not, modify the params - if (origin && origin != listenmobj[i]) + if (origin && !itsUs) { - boolean rc = S_AdjustSoundParams(listenmobj[i], origin, &volume, &sep, &pitch, sfx); + boolean audible = false; - if (!rc) + if (r_splitscreen > 0) { - continue; // Maybe the other player can hear it... + fixed_t recdist = INT32_MAX; + UINT8 j = 0; + + for (; j <= r_splitscreen; j++) + { + fixed_t thisdist = INT32_MAX; + + if (!listenmobj[j]) + { + continue; + } + + thisdist = P_AproxDistance(listener[j].x - origin->x, listener[j].y - origin->y); + + if (thisdist >= recdist) + { + continue; + } + + recdist = thisdist; + i = j; + } } - if (origin->x == listener[i].x && origin->y == listener[i].y) + if (listenmobj[i]) { - sep = NORM_SEP; + audible = S_AdjustSoundParams(listenmobj[i], origin, &volume, &sep, &pitch, sfx); + } + + if (!audible) + { + return; } - } - else if (i > 0 && !origin) - { - // Do not play origin-less sounds for the splitscreen players. - // The first player will be able to hear it just fine, - // we really don't want it playing twice. - continue; - } - else - { - sep = NORM_SEP; } // This is supposed to handle the loading/caching. @@ -857,43 +874,50 @@ void S_UpdateSounds(void) { boolean itsUs = false; - for (i = 0; i <= r_splitscreen; i++) + for (i = r_splitscreen; i >= 0; i--) { - if (c->origin == players[displayplayers[i]].mo) - { - itsUs = true; - break; - } + if (c->origin != listenmobj[i]) + continue; + + itsUs = true; } if (itsUs == false) { - const mobj_t *soundmobj = c->origin; - fixed_t recdist = INT32_MAX; - UINT8 p = 0; + const mobj_t *origin = c->origin; - for (i = 0; i <= r_splitscreen; i++) + i = 0; + + if (r_splitscreen > 0) { - fixed_t thisdist = INT32_MAX; + fixed_t recdist = INT32_MAX; + UINT8 j = 0; - if (!listenmobj[i]) + for (; j <= r_splitscreen; j++) { - continue; - } + fixed_t thisdist = INT32_MAX; - thisdist = P_AproxDistance(listener[i].x - soundmobj->x, listener[i].y - soundmobj->y); + if (!listenmobj[j]) + { + continue; + } + + thisdist = P_AproxDistance(listener[j].x - origin->x, listener[j].y - origin->y); + + if (thisdist >= recdist) + { + continue; + } - if (thisdist < recdist) - { recdist = thisdist; - p = i; + i = j; } } - if (listenmobj[p]) + if (listenmobj[i]) { audible = S_AdjustSoundParams( - listenmobj[p], c->origin, + listenmobj[i], c->origin, &volume, &sep, &pitch, c->sfxinfo ); @@ -1032,7 +1056,6 @@ boolean S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, INT32 const boolean reverse = (stereoreverse.value ^ encoremode); fixed_t approx_dist; - angle_t angle; listener_t listensource; INT32 i; @@ -1110,28 +1133,35 @@ boolean S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, INT32 if (approx_dist > S_CLIPPING_DIST) return false; - // angle of source to listener - angle = R_PointToAngle2(listensource.x, listensource.y, source->x, source->y); - - if (angle > listensource.angle) - angle = angle - listensource.angle; + if (source->x == listensource.x && source->y == listensource.y) + { + *sep = NORM_SEP; + } else - angle = angle + InvAngle(listensource.angle); + { + // angle of source to listener + angle_t angle = R_PointToAngle2(listensource.x, listensource.y, source->x, source->y); - if (reverse) - angle = InvAngle(angle); + if (angle > listensource.angle) + angle = angle - listensource.angle; + else + angle = angle + InvAngle(listensource.angle); + + if (reverse) + angle = InvAngle(angle); #ifdef SURROUND - // Produce a surround sound for angle from 105 till 255 - if (surround.value == 1 && (angle > ANG105 && angle < ANG255 )) - *sep = SURROUND_SEP; - else + // Produce a surround sound for angle from 105 till 255 + if (surround.value == 1 && (angle > ANG105 && angle < ANG255 )) + *sep = SURROUND_SEP; + else #endif - { - angle >>= ANGLETOFINESHIFT; + { + angle >>= ANGLETOFINESHIFT; - // stereo separation - *sep = 128 - (FixedMul(S_STEREO_SWING, FINESINE(angle))>>FRACBITS); + // stereo separation + *sep = 128 - (FixedMul(S_STEREO_SWING, FINESINE(angle))>>FRACBITS); + } } // volume calculation diff --git a/src/sounds.c b/src/sounds.c index cae8496f1..851c69518 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -1103,6 +1103,11 @@ sfxinfo_t S_sfx[NUMSFX] = {"typri1", false, 64, 16, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SA2 boss typewriting 1 {"typri2", false, 64, 16, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SA2 final boss-type typewriting + // SRB2Kart - Drop target sounds + {"kdtrg1", false, 64, 16, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Low energy, SF_X8AWAYSOUND + {"kdtrg2", false, 64, 16, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Medium energy, SF_X8AWAYSOUND + {"kdtrg3", false, 64, 80, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // High energy, SF_X2AWAYSOUND|SF_X8AWAYSOUND + // SRB2Kart - Engine sounds // Engine class A {"krta00", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, diff --git a/src/sounds.h b/src/sounds.h index 63e115566..0686cab46 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -1167,6 +1167,11 @@ typedef enum sfx_typri1, sfx_typri2, + // SRB2Kart - Drop target sounds + sfx_kdtrg1, + sfx_kdtrg2, + sfx_kdtrg3, + // Next up: UNIQUE ENGINE SOUNDS! Hoooooo boy... // Engine class A - Low Speed, Low Weight sfx_krta00, diff --git a/src/w_wad.c b/src/w_wad.c index df8df7928..e1cb6b1aa 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -637,8 +637,6 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp) lump_p->fullname = Z_Calloc(zentry.namelen + 1, PU_STATIC, NULL); strncpy(lump_p->fullname, fullname, zentry.namelen); - free(fullname); - switch(zentry.compression) { case 0: @@ -658,6 +656,8 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp) break; } + free(fullname); + // skip and ignore comments/extra fields if (fseek(handle, zentry.xtralen + zentry.commlen, SEEK_CUR) != 0) {