diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 72288d017..e8149e385 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -1381,6 +1381,8 @@ void CGameClient::OnNewSnapshot() pClient->m_HasTelegunLaser = pCharacterData->m_Flags & CHARACTERFLAG_TELEGUN_LASER; pClient->m_Predicted.ReadDDNet(pCharacterData); + + m_Teams.SetSolo(Item.m_ID, pClient->m_Solo); } } else if(Item.m_Type == NETOBJTYPE_SPECCHAR) @@ -2441,9 +2443,8 @@ void CGameClient::UpdatePrediction() } // update the local gameworld with the new snapshot - m_GameWorld.m_Teams = m_Teams; + m_GameWorld.NetObjBegin(m_Teams, m_Snap.m_LocalClientID); - m_GameWorld.NetObjBegin(); for(int i = 0; i < MAX_CLIENTS; i++) if(m_Snap.m_aCharacters[i].m_Active) { @@ -2457,7 +2458,7 @@ void CGameClient::UpdatePrediction() for(const CSnapEntities &EntData : SnapEntities()) m_GameWorld.NetObjAdd(EntData.m_Item.m_ID, EntData.m_Item.m_Type, EntData.m_pData, EntData.m_pDataEx); - m_GameWorld.NetObjEnd(m_Snap.m_LocalClientID); + m_GameWorld.NetObjEnd(); } void CGameClient::UpdateRenderedCharacters() @@ -2476,7 +2477,8 @@ void CGameClient::UpdateRenderedCharacters() Client()->IntraGameTick(g_Config.m_ClDummy)); vec2 Pos = UnpredPos; - if(Predict() && (i == m_Snap.m_LocalClientID || (AntiPingPlayers() && !IsOtherTeam(i)))) + CCharacter *pChar = m_PredictedWorld.GetCharacterByID(i); + if(Predict() && (i == m_Snap.m_LocalClientID || (AntiPingPlayers() && !IsOtherTeam(i))) && pChar) { m_aClients[i].m_Predicted.Write(&m_aClients[i].m_RenderCur); m_aClients[i].m_PrevPredicted.Write(&m_aClients[i].m_RenderPrev); @@ -2491,8 +2493,7 @@ void CGameClient::UpdateRenderedCharacters() if(i == m_Snap.m_LocalClientID) { m_aClients[i].m_IsPredictedLocal = true; - CCharacter *pChar = m_PredictedWorld.GetCharacterByID(i); - if(pChar && AntiPingGunfire() && ((pChar->m_NinjaJetpack && pChar->m_FreezeTime == 0) || m_Snap.m_aCharacters[i].m_Cur.m_Weapon != WEAPON_NINJA || m_Snap.m_aCharacters[i].m_Cur.m_Weapon == m_aClients[i].m_Predicted.m_ActiveWeapon)) + if(AntiPingGunfire() && ((pChar->m_NinjaJetpack && pChar->m_FreezeTime == 0) || m_Snap.m_aCharacters[i].m_Cur.m_Weapon != WEAPON_NINJA || m_Snap.m_aCharacters[i].m_Cur.m_Weapon == m_aClients[i].m_Predicted.m_ActiveWeapon)) { m_aClients[i].m_RenderCur.m_AttackTick = pChar->GetAttackTick(); if(m_Snap.m_aCharacters[i].m_Cur.m_Weapon != WEAPON_NINJA && !(pChar->m_NinjaJetpack && pChar->Core()->m_ActiveWeapon == WEAPON_GUN)) diff --git a/src/game/client/prediction/gameworld.cpp b/src/game/client/prediction/gameworld.cpp index 159ff84a8..aa3a7ffb3 100644 --- a/src/game/client/prediction/gameworld.cpp +++ b/src/game/client/prediction/gameworld.cpp @@ -377,8 +377,16 @@ void CGameWorld::CreateExplosion(vec2 Pos, int Owner, int Weapon, bool NoDamage, } } -void CGameWorld::NetObjBegin() +bool CGameWorld::IsLocalTeam(int OwnerID) { + return OwnerID < 0 || m_Teams.CanCollide(m_LocalClientID, OwnerID); +} + +void CGameWorld::NetObjBegin(CTeamsCore Teams, int LocalClientID) +{ + m_Teams = Teams; + m_LocalClientID = LocalClientID; + for(int i = 0; i < NUM_ENTTYPES; i++) for(CEntity *pEnt = FindFirst(i); pEnt; pEnt = pEnt->TypeNext()) { @@ -391,20 +399,23 @@ void CGameWorld::NetObjBegin() void CGameWorld::NetCharAdd(int ObjID, CNetObj_Character *pCharObj, CNetObj_DDNetCharacter *pExtended, int GameTeam, bool IsLocal) { - CCharacter *pChar; - if((pChar = (CCharacter *)GetEntity(ObjID, ENTTYPE_CHARACTER))) + if(IsLocalTeam(ObjID)) { - pChar->Read(pCharObj, pExtended, IsLocal); - pChar->Keep(); - } - else - { - pChar = new CCharacter(this, ObjID, pCharObj, pExtended); - InsertEntity(pChar); - } + CCharacter *pChar; + if((pChar = (CCharacter *)GetEntity(ObjID, ENTTYPE_CHARACTER))) + { + pChar->Read(pCharObj, pExtended, IsLocal); + pChar->Keep(); + } + else + { + pChar = new CCharacter(this, ObjID, pCharObj, pExtended); + InsertEntity(pChar); + } - if(pChar) - pChar->m_GameTeam = GameTeam; + if(pChar) + pChar->m_GameTeam = GameTeam; + } } void CGameWorld::NetObjAdd(int ObjID, int ObjType, const void *pObjData, const CNetObj_EntityEx *pDataEx) @@ -412,6 +423,9 @@ void CGameWorld::NetObjAdd(int ObjID, int ObjType, const void *pObjData, const C if((ObjType == NETOBJTYPE_PROJECTILE || ObjType == NETOBJTYPE_DDRACEPROJECTILE || ObjType == NETOBJTYPE_DDNETPROJECTILE) && m_WorldConfig.m_PredictWeapons) { CProjectileData Data = ExtractProjectileInfo(ObjType, pObjData, this, pDataEx); + if(!IsLocalTeam(Data.m_Owner)) + return; + CProjectile NetProj = CProjectile(this, ObjID, &Data); if(NetProj.m_Type != WEAPON_SHOTGUN && absolute(length(NetProj.m_Direction) - 1.f) > 0.02f) // workaround to skip grenades on ball mod @@ -483,7 +497,7 @@ void CGameWorld::NetObjAdd(int ObjID, int ObjType, const void *pObjData, const C else if((ObjType == NETOBJTYPE_LASER || ObjType == NETOBJTYPE_DDNETLASER) && m_WorldConfig.m_PredictWeapons) { CLaserData Data = ExtractLaserInfo(ObjType, pObjData, this, pDataEx); - if(Data.m_Type >= 0 && Data.m_Type != LASERTYPE_RIFLE && Data.m_Type != LASERTYPE_SHOTGUN) + if((Data.m_Type >= 0 && Data.m_Type != LASERTYPE_RIFLE && Data.m_Type != LASERTYPE_SHOTGUN) || !IsLocalTeam(Data.m_Owner)) { return; } @@ -519,7 +533,7 @@ void CGameWorld::NetObjAdd(int ObjID, int ObjType, const void *pObjData, const C } } -void CGameWorld::NetObjEnd(int LocalID) +void CGameWorld::NetObjEnd() { // keep predicting hooked characters, based on hook position for(int i = 0; i < MAX_CLIENTS; i++) diff --git a/src/game/client/prediction/gameworld.h b/src/game/client/prediction/gameworld.h index 2f0930329..588096f31 100644 --- a/src/game/client/prediction/gameworld.h +++ b/src/game/client/prediction/gameworld.h @@ -84,11 +84,14 @@ public: CGameWorld *m_pParent; CGameWorld *m_pChild; + int m_LocalClientID; + + bool IsLocalTeam(int OwnerID); void OnModified(); - void NetObjBegin(); + void NetObjBegin(CTeamsCore Teams, int LocalClientID); void NetCharAdd(int ObjID, CNetObj_Character *pChar, CNetObj_DDNetCharacter *pExtended, int GameTeam, bool IsLocal); void NetObjAdd(int ObjID, int ObjType, const void *pObjData, const CNetObj_EntityEx *pDataEx); - void NetObjEnd(int LocalID); + void NetObjEnd(); void CopyWorld(CGameWorld *pFrom); CEntity *FindMatch(int ObjID, int ObjType, const void *pObjData); void Clear();