diff --git a/src/d_net.cpp b/src/d_net.cpp index b2742871..27af76c8 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -592,13 +592,16 @@ void PlayerIsGone (int netnode, int netconsole) Printf ("%s left the game\n", players[netconsole].userinfo.netname); } - // [RH] Revert to your own view if spying through the player who left - if (players[consoleplayer].camera == players[netconsole].mo) + // [RH] Revert each player to their own view if spying through the player who left + for (int ii = 0; ii < MAXPLAYERS; ++ii) { - players[consoleplayer].camera = players[consoleplayer].mo; - if (StatusBar != NULL) + if (playeringame[ii] && players[ii].camera == players[netconsole].mo) { - StatusBar->AttachToPlayer (&players[consoleplayer]); + players[ii].camera = players[ii].mo; + if (ii == consoleplayer && StatusBar != NULL) + { + StatusBar->AttachToPlayer (&players[ii]); + } } } @@ -2460,6 +2463,10 @@ void Net_DoCommand (int type, BYTE **stream, int player) F_AdvanceIntermission(); break; + case DEM_REVERTCAMERA: + players[player].camera = players[player].mo; + break; + default: I_Error ("Unknown net command: %d", type); break; diff --git a/src/d_protocol.h b/src/d_protocol.h index 22461010..cee2fca6 100644 --- a/src/d_protocol.h +++ b/src/d_protocol.h @@ -162,6 +162,7 @@ enum EDemoCommand DEM_SETPITCHLIMIT, // 63 Byte: Up limit, Byte: Down limit (in degrees) DEM_ADVANCEINTER, // 64 Advance intermission screen state DEM_RUNNAMEDSCRIPT, // 65 String: Script name, Byte: Arg count + Always flag; each arg is a 4-byte int + DEM_REVERTCAMERA, // 66 }; // The following are implemented by cht_DoCheat in m_cheat.cpp diff --git a/src/g_game.cpp b/src/g_game.cpp index ee8092b7..a090dd64 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -831,7 +831,12 @@ static void ChangeSpy (bool forward) // If not viewing through a player, return your eyes to your own head. if (players[consoleplayer].camera->player == NULL) { - players[consoleplayer].camera = players[consoleplayer].mo; + // When watching demos, you will just have to wait until your player + // has done this for you, since it could desync otherwise. + if (!demoplayback) + { + Net_WriteByte(DEM_REVERTCAMERA); + } return; } diff --git a/src/g_level.cpp b/src/g_level.cpp index 9e874c5d..903a9a6c 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -920,10 +920,13 @@ void G_DoLoadLevel (int position, bool autosave) level.starttime = gametic; G_UnSnapshotLevel (!savegamerestore); // [RH] Restore the state of the level. G_FinishTravel (); - if (players[consoleplayer].camera == NULL || - players[consoleplayer].camera->player != NULL) - { // If we are viewing through a player, make sure it is us. - players[consoleplayer].camera = players[consoleplayer].mo; + // For each player, if they are viewing through a player, make sure it is themselves. + for (int ii = 0; i < MAXPLAYERS; ++i) + { + if (playeringame[ii] && (players[ii].camera == NULL || players[ii].camera->player != NULL)) + { + players[ii].camera = players[ii].mo; + } } StatusBar->AttachToPlayer (&players[consoleplayer]); P_DoDeferedScripts (); // [RH] Do script actions that were triggered on another map. @@ -1143,6 +1146,7 @@ void G_FinishTravel () pawn->target = NULL; pawn->lastenemy = NULL; pawn->player->mo = pawn; + pawn->player->camera = pawn; DObject::StaticPointerSubstitution (oldpawn, pawn); oldpawn->Destroy(); pawndup->Destroy (); diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 78207595..96c30c8f 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -5255,6 +5255,9 @@ int DLevelScript::RunScript () STACK(1) = !STACK(1); break; + + + case PCD_NEGATEBINARY: STACK(1) = ~STACK(1); break; @@ -7400,11 +7403,11 @@ static void addDefered (level_info_t *i, acsdefered_t::EType type, int script, c def->next = i->defered; def->type = type; def->script = script; - for (j = 0; j < countof(def->args) && j < argcount; ++j) + for (j = 0; (size_t)j < countof(def->args) && j < argcount; ++j) { def->args[j] = args[j]; } - while (j < countof(def->args)) + while ((size_t)j < countof(def->args)) { def->args[j++] = 0; } diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index ad637c39..3ecd4f5f 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -720,7 +720,7 @@ public: toSay = GStrings[dlgtext]; if (toSay == NULL) { - toSay = "Go away!"; // Ok, it's lame - but it doesn't look like an error to the player. ;) + toSay = GStrings["TXT_GOAWAY"]; // Ok, it's lame - but it doesn't look like an error to the player. ;) } } else diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 3d676cdd..c9ed7e30 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -4051,9 +4051,12 @@ APlayerPawn *P_SpawnPlayer (FMapThing *mthing, bool tempplayer) p->velx = p->vely = 0; // killough 10/98: initialize bobbing to 0. - if (players[consoleplayer].camera == oldactor) + for (int ii = 0; ii < MAXPLAYERS; ++ii) { - players[consoleplayer].camera = mobj; + if (playeringame[ii] && players[ii].camera == oldactor) + { + players[ii].camera = oldactor; + } } // [RH] Allow chasecam for demo watching diff --git a/src/p_user.cpp b/src/p_user.cpp index de48cf20..1e5dd2bd 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -326,21 +326,25 @@ size_t player_t::FixPointers (const DObject *old, DObject *rep) { APlayerPawn *replacement = static_cast(rep); size_t changed = 0; - if (mo == old) mo = replacement, changed++; - if (poisoner == old) poisoner = replacement, changed++; - if (attacker == old) attacker = replacement, changed++; - if (camera == old) camera = replacement, changed++; - if (dest == old) dest = replacement, changed++; - if (prev == old) prev = replacement, changed++; - if (enemy == old) enemy = replacement, changed++; - if (missile == old) missile = replacement, changed++; - if (mate == old) mate = replacement, changed++; - if (last_mate == old) last_mate = replacement, changed++; - if (ReadyWeapon == old) ReadyWeapon = static_cast(rep), changed++; - if (PendingWeapon == old) PendingWeapon = static_cast(rep), changed++; - if (PremorphWeapon == old) PremorphWeapon = static_cast(rep), changed++; - if (ConversationNPC == old) ConversationNPC = replacement, changed++; - if (ConversationPC == old) ConversationPC = replacement, changed++; + + // The construct *& is used in several of these to avoid the read barriers + // that would turn the pointer we want to check to NULL if the old object + // is pending deletion. + if (mo == old) mo = replacement, changed++; + if (*&poisoner == old) poisoner = replacement, changed++; + if (*&attacker == old) attacker = replacement, changed++; + if (*&camera == old) camera = replacement, changed++; + if (*&dest == old) dest = replacement, changed++; + if (*&prev == old) prev = replacement, changed++; + if (*&enemy == old) enemy = replacement, changed++; + if (*&missile == old) missile = replacement, changed++; + if (*&mate == old) mate = replacement, changed++; + if (*&last_mate == old) last_mate = replacement, changed++; + if (ReadyWeapon == old) ReadyWeapon = static_cast(rep), changed++; + if (PendingWeapon == old) PendingWeapon = static_cast(rep), changed++; + if (*&PremorphWeapon == old) PremorphWeapon = static_cast(rep), changed++; + if (*&ConversationNPC == old) ConversationNPC = replacement, changed++; + if (*&ConversationPC == old) ConversationPC = replacement, changed++; return changed; } diff --git a/src/svnrevision.h b/src/svnrevision.h index 18cda2db..f86a42e8 100644 --- a/src/svnrevision.h +++ b/src/svnrevision.h @@ -3,5 +3,5 @@ // This file was automatically generated by the // updaterevision tool. Do not edit by hand. -#define ZD_SVN_REVISION_STRING "3446" -#define ZD_SVN_REVISION_NUMBER 3446 +#define ZD_SVN_REVISION_STRING "3450" +#define ZD_SVN_REVISION_NUMBER 3450 diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index d2ff8dda..a3288db8 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -2253,7 +2253,20 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckSight) for (int i = 0; i < MAXPLAYERS; i++) { - if (playeringame[i] && P_CheckSight(players[i].camera, self, SF_IGNOREVISIBILITY)) return; + if (playeringame[i]) + { + // Always check sight from each player. + if (P_CheckSight(players[i].mo, self, SF_IGNOREVISIBILITY)) + { + return; + } + // If a player is viewing from a non-player, then check that too. + if (players[i].camera != NULL && players[i].camera->player == NULL && + P_CheckSight(players[i].camera, self, SF_IGNOREVISIBILITY)) + { + return; + } + } } ACTION_JUMP(jump); @@ -2266,6 +2279,42 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckSight) // Useful for maps with many multi-actor special effects. // //=========================================================================== +static bool DoCheckSightOrRange(AActor *self, AActor *camera, double range) +{ + if (camera == NULL) + { + return false; + } + // Check distance first, since it's cheaper than checking sight. + double dx = self->x - camera->x; + double dy = self->y - camera->y; + double dz; + fixed_t eyez = (camera->z + camera->height - (camera->height>>2)); // same eye height as P_CheckSight + if (eyez > self->z + self->height) + { + dz = self->z + self->height - eyez; + } + else if (eyez < self->z) + { + dz = self->z - eyez; + } + else + { + dz = 0; + } + if ((dx*dx) + (dy*dy) + (dz*dz) <= range) + { // Within range + return true; + } + + // Now check LOS. + if (P_CheckSight(camera, self, SF_IGNOREVISIBILITY)) + { // Visible + return true; + } + return false; +} + DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckSightOrRange) { ACTION_PARAM_START(2); @@ -2279,33 +2328,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckSightOrRange) { if (playeringame[i]) { - AActor *camera = players[i].camera; - - // Check distance first, since it's cheaper than checking sight. - double dx = self->x - camera->x; - double dy = self->y - camera->y; - double dz; - fixed_t eyez = (camera->z + camera->height - (camera->height>>2)); // same eye height as P_CheckSight - if (eyez > self->z + self->height) + // Always check from each player. + if (DoCheckSightOrRange(self, players[i].mo, range)) { - dz = self->z + self->height - eyez; - } - else if (eyez < self->z) - { - dz = self->z - eyez; - } - else - { - dz = 0; - } - if ((dx*dx) + (dy*dy) + (dz*dz) <= range) - { // Within range return; } - - // Now check LOS. - if (P_CheckSight(camera, self, SF_IGNOREVISIBILITY)) - { // Visible + // If a player is viewing from a non-player, check that too. + if (players[i].camera != NULL && players[i].camera->player == NULL && + DoCheckSightOrRange(self, players[i].camera, range)) + { return; } } diff --git a/src/version.h b/src/version.h index bfe7f1fa..9f1a5eb6 100644 --- a/src/version.h +++ b/src/version.h @@ -56,7 +56,7 @@ // Version identifier for network games. // Bump it every time you do a release unless you're certain you // didn't change anything that will affect sync. -#define NETGAMEVERSION 226 +#define NETGAMEVERSION 227 // Version stored in the ini's [LastRun] section. // Bump it if you made some configuration change that you want to @@ -66,7 +66,7 @@ // Protocol version used in demos. // Bump it if you change existing DEM_ commands or add new ones. // Otherwise, it should be safe to leave it alone. -#define DEMOGAMEVERSION 0x217 +#define DEMOGAMEVERSION 0x218 // Minimum demo version we can play. // Bump it whenever you change or remove existing DEM_ commands. diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt index dc46fa2f..7b6db270 100644 --- a/wadsrc/static/compatibility.txt +++ b/wadsrc/static/compatibility.txt @@ -159,8 +159,9 @@ E2B5D1400279335811C1C1C0B437D9C8 // Deathknights of the Dark Citidel, map54 2B65CB046EA40D2E44576949381769CA // Commercial Doom e3m4 { - // This line is erroneously flagged as a door that monsters can operate. - // If they do, they block you off from half the map. Since the attached - // sector isn't a door, remove the special. - clearlinespecial 1069 + // This line is erroneously specified as Door_Raise that monsters + // can operate. If they do, they block you off from half the map. Change + // this into a one-shot Door_Open so that it won't close. + setlinespecial 1069 Door_Open 0 16 0 0 0 + clearlineflags 1069 0x200 } diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index 3acfe404..4c1e4af6 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -1481,7 +1481,8 @@ TXT_RANDOM_PGUARD_10 = "If there is any honor inside that pathetic shell of a bo TXT_RANDOMGOODBYE_1 = "Bye!"; TXT_RANDOMGOODBYE_2 = "Thanks, bye!"; TXT_RANDOMGOODBYE_3 = "See you later!"; -TXT_HAVEENOUGH = "You seem to have enough!"; +TXT_HAVEENOUGH = "You seem to have enough!"; +TXT_GOAWAY = "Go away!"; // Skills: