diff --git a/src/command.c b/src/command.c index aecbe5ae8..a602fe886 100644 --- a/src/command.c +++ b/src/command.c @@ -810,12 +810,14 @@ static void COM_Echo_f(void) static void COM_CEcho_f(void) { size_t i; - char cechotext[1024] = ""; + char cechotext[1024]; - for (i = 1; i < COM_Argc(); i++) + strlcpy(cechotext, COM_Argc() > 1 ? COM_Argv(1) : "", sizeof(cechotext)); + + for (i = 2; i < COM_Argc(); i++) { - strlcpy(cechotext, COM_Argv(i), sizeof(cechotext)-1); - strlcpy(cechotext, " ", sizeof(cechotext)-1); + strlcat(cechotext, " ", sizeof(cechotext)); + strlcat(cechotext, COM_Argv(i), sizeof(cechotext)); } HU_DoCEcho(cechotext); diff --git a/src/g_game.c b/src/g_game.c index ad20b510b..6bc4fd964 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2034,13 +2034,20 @@ boolean G_Responder(event_t *ev) return false; } - if (gamestate == GS_LEVEL) + if (Playing()) { + // If you're playing, chat is real. + // Neatly sidesteps a class of bugs where whenever we add a + // new gamestate accessible in netplay, chat was console-only. if (HU_Responder(ev)) { hu_keystrokes = true; return true; // chat ate the event } + } + + if (gamestate == GS_LEVEL) + { if (AM_Responder(ev)) return true; // automap ate it // map the event (key/mouse/joy) to a gamecontrol @@ -2056,12 +2063,6 @@ boolean G_Responder(event_t *ev) } else if (gamestate == GS_CUTSCENE) { - if (HU_Responder(ev)) - { - hu_keystrokes = true; - return true; // chat ate the event - } - if (F_CutsceneResponder(ev)) { D_StartTitle(); @@ -2070,12 +2071,6 @@ boolean G_Responder(event_t *ev) } else if (gamestate == GS_CREDITS) // todo: keep ending here? { - if (HU_Responder(ev)) - { - hu_keystrokes = true; - return true; // chat ate the event - } - if (F_CreditResponder(ev)) { // Skip credits for everyone @@ -2088,12 +2083,6 @@ boolean G_Responder(event_t *ev) } else if (gamestate == GS_BLANCREDITS) { - if (HU_Responder(ev)) - { - hu_keystrokes = true; - return true; // chat ate the event - } - if (F_CreditResponder(ev)) { // Skip credits for everyone @@ -2106,12 +2095,6 @@ boolean G_Responder(event_t *ev) } else if (gamestate == GS_SECRETCREDITS) { - if (HU_Responder(ev)) - { - hu_keystrokes = true; - return true; // chat ate the event - } - if (F_CreditResponder(ev)) { // Skip credits for everyone @@ -2122,12 +2105,6 @@ boolean G_Responder(event_t *ev) return true; } } - else if (gamestate == GS_INTERMISSION || gamestate == GS_VOTING || gamestate == GS_EVALUATION) - if (HU_Responder(ev)) - { - hu_keystrokes = true; - return true; // chat ate the event - } // allow spy mode changes even during the demo if (gamestate == GS_LEVEL && ev->type == ev_keydown diff --git a/src/k_collide.c b/src/k_collide.c index a222b2103..52df67007 100644 --- a/src/k_collide.c +++ b/src/k_collide.c @@ -1099,7 +1099,28 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2) t1Condition = (t1->scale > t2->scale + (mapobjectscale/8)); t2Condition = (t2->scale > t1->scale + (mapobjectscale/8)); - + + // Merritt suggestion: ONLY make Alt. Shrink squish/flipover interactions happen if and only + // if the crushing player doesn't have an S-Monitor active + + if (t1Condition && (t1->player && t1->player->smonitortimer) && (t2->player && K_IsAltShrunk(t2->player))) + { + // t1Condition: t1's player has an S-Monitor, don't do squat + // Extend some mercy to the players phasing through one another + t1->player->justbumped = 6; + t2->player->justbumped = 6; + return false; + } + + if (t2Condition && (t2->player && t2->player->smonitortimer) && (t1->player && K_IsAltShrunk(t1->player))) + { + // t2Condition: t2's player has an S-Monitor, don't do squat + // Extend some mercy to the players phasing through one another + t1->player->justbumped = 6; + t2->player->justbumped = 6; + return false; + } + if ((t1Condition == true || flameT1 == true) && (t2Condition == true || flameT2 == true)) { return false; diff --git a/src/k_kart.c b/src/k_kart.c index 3748ca104..26b20c36b 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7296,7 +7296,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) || player->squishedtimer != 0 || player->flipovertimer != 0) { - if (!player->flipovertimer && ( player->spinouttype & KSPIN_IFRAMES ) == 0) + if ((player->spinouttimer || player->wipeoutslow) && ( player->spinouttype & KSPIN_IFRAMES ) == 0) player->flashing = 0; else player->flashing = K_GetKartFlashing(player); diff --git a/src/p_local.h b/src/p_local.h index d754bac74..ab53d5f6c 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -366,8 +366,9 @@ fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, f INT32 P_FloorPicAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height); boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover); -boolean P_CheckDeathPitCollide(mobj_t *mo); +boolean P_CheckDeathPitCollide(const mobj_t *mo); boolean P_CheckSolidLava(ffloor_t *rover); +boolean P_CheckDeathPitFOFs(const mobj_t *mo); void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motype); mobj_t *P_SpawnMobjFromMobjUnscaled(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zofs, mobjtype_t type); diff --git a/src/p_mobj.c b/src/p_mobj.c index ab6fd98c8..6916c4069 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2162,7 +2162,7 @@ void P_RingZMovement(mobj_t *mo) } } -boolean P_CheckDeathPitCollide(mobj_t *mo) +boolean P_CheckDeathPitCollide(const mobj_t *mo) { I_Assert(mo != NULL); I_Assert(!P_MobjWasRemoved(mo)); @@ -2197,6 +2197,25 @@ boolean P_CheckSolidLava(ffloor_t *rover) return false; } +boolean P_CheckDeathPitFOFs(const mobj_t *mo) +{ + if (P_CheckDeathPitCollide(mo)) + return true; + + const sector_t *sector = mo->subsector->sector; + + for (ffloor_t *rover = sector->ffloors; rover != NULL; rover = rover->next) + { + // i... think these are the right checks? + if (rover->fofflags & FOF_EXISTS + && rover->master->frontsector->damagetype == SD_DEATHPIT + && P_IsMobjTouching3DFloor(mo, rover, sector)) + return true; + } + + return false; +} + // // P_ZMovement // Returns false if the mobj was killed/exploded/removed, true otherwise. @@ -2440,7 +2459,8 @@ boolean P_ZMovement(mobj_t *mo) ; else if (mo->type == MT_PLAYER) // only DEAD players { - mom.z = -4*mom.z/5; + if (!P_CheckDeathPitFOFs(mo)) + mom.z = -4*mom.z/5; mo->flags |= MF_NOCLIPHEIGHT; // fall through floor next time } else if (mo->flags & MF_MISSILE) @@ -3015,7 +3035,8 @@ boolean P_SceneryZMovement(mobj_t *mo) if (mo->type == MT_KART_TIRE) { - mo->momz = -mo->momz; + if (!P_CheckDeathPitFOFs(mo)) + mo->momz = -mo->momz; mo->flags |= MF_NOCLIPHEIGHT; } else if (g_tm.floorthing) diff --git a/src/p_setup.c b/src/p_setup.c index da5a04c1d..1c8e87898 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -6166,6 +6166,14 @@ static void P_ConvertBinaryLinedefTypes(void) } P_WriteDuplicateText(sides[lines[i].sidenum[0]].text, &lines[i].stringargs[0]); break; + case 415: //Run script + if (strlen(G_BuildMapName(gamemap)) != 5) + break; // good enough check methinks + INT32 scrnum = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + if (scrnum < 0 || scrnum > 999) + scrnum = 0; + P_WriteDuplicateText(va("SCR%s%03u", G_BuildMapName(gamemap) + 3, scrnum), &lines[i].stringargs[0]); + break; case 416: //Start adjustable flickering light case 417: //Start adjustable pulsating light case 602: //Adjustable pulsating light diff --git a/src/p_spec.c b/src/p_spec.c index c596fa5d4..20ee7edf8 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3007,7 +3007,15 @@ boolean P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, cha if (lumpnum == LUMPERROR || W_LumpLength(lumpnum) == 0) CONS_Debug(DBG_SETUP, "Line type 415 Executor: script lump %s not found/not valid.\n", stringargs[0]); else - COM_BufInsertText(W_CacheLumpNum(lumpnum, PU_CACHE)); + { + void *lump = W_CacheLumpNum(lumpnum, PU_CACHE); + size_t len = W_LumpLength(lumpnum); + char *text = Z_Malloc(len + 1, PU_CACHE, NULL); + memcpy(text, lump, len); + text[len] = '\0'; + COM_BufInsertText(text); + Z_Free(text); + } } break; @@ -4611,19 +4619,19 @@ void P_SetupSignExit(player_t *player) } } -static boolean P_IsMobjTouchingPlane(mobj_t *mo, sector_t *sec, fixed_t floorz, fixed_t ceilingz) +static boolean P_IsMobjTouchingPlane(const mobj_t *mo, const sector_t *sec, fixed_t floorz, fixed_t ceilingz) { boolean floorallowed = ((sec->flags & MSF_FLIPSPECIAL_FLOOR) && ((sec->flags & MSF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->z == floorz)); boolean ceilingallowed = ((sec->flags & MSF_FLIPSPECIAL_CEILING) && ((sec->flags & MSF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->z + mo->height == ceilingz)); return (floorallowed || ceilingallowed); } -boolean P_IsMobjTouchingSectorPlane(mobj_t *mo, sector_t *sec) +boolean P_IsMobjTouchingSectorPlane(const mobj_t *mo, const sector_t *sec) { return P_IsMobjTouchingPlane(mo, sec, P_GetSpecialBottomZ(mo, sec, sec), P_GetSpecialTopZ(mo, sec, sec)); } -boolean P_IsMobjTouching3DFloor(mobj_t *mo, ffloor_t *fof, sector_t *sec) +boolean P_IsMobjTouching3DFloor(const mobj_t *mo, const ffloor_t *fof, const sector_t *sec) { fixed_t topheight = P_GetSpecialTopZ(mo, sectors + fof->secnum, sec); fixed_t bottomheight = P_GetSpecialBottomZ(mo, sectors + fof->secnum, sec); @@ -4641,7 +4649,7 @@ boolean P_IsMobjTouching3DFloor(mobj_t *mo, ffloor_t *fof, sector_t *sec) } } -boolean P_IsMobjTouchingPolyobj(mobj_t *mo, polyobj_t *po, sector_t *polysec) +boolean P_IsMobjTouchingPolyobj(const mobj_t *mo, const polyobj_t *po, const sector_t *polysec) { if (!(po->flags & POF_TESTHEIGHT)) // Don't do height checking return true; diff --git a/src/p_spec.h b/src/p_spec.h index c873ffaea..79b8e414c 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -627,9 +627,9 @@ boolean P_AllowFriction(mobj_t *mobj); void P_SetupSignExit(player_t *player); -boolean P_IsMobjTouchingSectorPlane(mobj_t *mo, sector_t *sec); -boolean P_IsMobjTouching3DFloor(mobj_t *mo, ffloor_t *ffloor, sector_t *sec); -boolean P_IsMobjTouchingPolyobj(mobj_t *mo, polyobj_t *po, sector_t *polysec); +boolean P_IsMobjTouchingSectorPlane(const mobj_t *mo, const sector_t *sec); +boolean P_IsMobjTouching3DFloor(const mobj_t *mo, const ffloor_t *ffloor, const sector_t *sec); +boolean P_IsMobjTouchingPolyobj(const mobj_t *mo, const polyobj_t *po, const sector_t *polysec); void P_SwitchWeather(preciptype_t newWeather); diff --git a/src/p_user.c b/src/p_user.c index 747994780..37a9fa9ff 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1455,7 +1455,7 @@ boolean P_PlayerHitFloor(player_t *player, boolean fromAir) clipmomz = !(P_CheckDeathPitCollide(player->mo)); - if (player->airtime > 10 && player->prevonground == false && fromAir == true && clipmomz == true) + if (player->airtime > 10 && player->prevonground == false && fromAir == true && !P_CheckDeathPitFOFs(player->mo)) { K_SpawnSplashForMobj(player->mo, abs(player->mo->momz)); }