X-Git-Url: http://deadsoftware.ru/gitweb?p=d2df-sdl.git;a=blobdiff_plain;f=src%2Fgame%2Fg_netmsg.pas;h=9563b8083f9fd7d1f7955a35fb0a36a96200cf35;hp=94326281ae68a2627669144725ed9f0b9aae50c0;hb=f666629aca7f9df2fa9363d66f388fd5b30f76b3;hpb=829537fc7b2b29baaab7287e54fba2cdd8d00b5c diff --git a/src/game/g_netmsg.pas b/src/game/g_netmsg.pas index 9432628..9563b80 100644 --- a/src/game/g_netmsg.pas +++ b/src/game/g_netmsg.pas @@ -1,4 +1,4 @@ -(* Copyright (C) DooM 2D:Forever Developers +(* Copyright (C) Doom 2D: Forever Developers * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,6 +16,8 @@ {$INCLUDE ../shared/a_modes.inc} unit g_netmsg; +{.$DEFINE K8_XXX_WEAPON_DEBUG} + interface uses e_msg, g_net, g_triggers, Classes, SysUtils, md5; @@ -52,8 +54,8 @@ const NET_MSG_MSHOT = 134; NET_MSG_MDEL = 135; - NET_MSG_PSTATE = 141; - NET_MSG_PTEX = 142; + NET_MSG_PSTATE = 141; + NET_MSG_PTEX = 142; NET_MSG_TSOUND = 151; NET_MSG_TMUSIC = 152; @@ -168,8 +170,8 @@ procedure MH_SEND_PlayerSettings(PID: Word; Mdl: string = ''; ID: Integer = NET_ procedure MH_SEND_ItemSpawn(Quiet: Boolean; IID: Word; ID: Integer = NET_EVERYONE); procedure MH_SEND_ItemDestroy(Quiet: Boolean; IID: Word; ID: Integer = NET_EVERYONE); // PANEL -procedure MH_SEND_PanelTexture(PType: Word; PID: LongWord; AnimLoop: Byte; ID: Integer = NET_EVERYONE); -procedure MH_SEND_PanelState(PType: Word; PID: LongWord; ID: Integer = NET_EVERYONE); +procedure MH_SEND_PanelTexture(PGUID: Integer; AnimLoop: Byte; ID: Integer = NET_EVERYONE); +procedure MH_SEND_PanelState(PGUID: Integer; ID: Integer = NET_EVERYONE); // MONSTER procedure MH_SEND_MonsterSpawn(UID: Word; ID: Integer = NET_EVERYONE); procedure MH_SEND_MonsterPos(UID: Word; ID: Integer = NET_EVERYONE); @@ -384,7 +386,7 @@ begin g_Console_Add(Format(_lc[I_PLAYER_JOIN], [PName]), True); e_WriteLog('NET: Client ' + PName + ' [' + IntToStr(C^.ID) + - '] connected. Assigned player #' + IntToStr(PID) + '.', MSG_NOTIFY); + '] connected. Assigned player #' + IntToStr(PID) + '.', TMsgType.Notify); MH_SEND_Info(C^.ID); @@ -430,12 +432,13 @@ end; function MH_RECV_PlayerPos(C: pTNetClient; var M: TMsg): Word; var - Dir, i: Byte; - WeaponSelect: Word; + Dir{, i}: Byte; + //WeaponSelect: Word; PID: Word; kByte: Word; Pl: TPlayer; GT: LongWord; + newweapon: Byte; begin Result := 0; if not gGameOn then Exit; @@ -453,13 +456,22 @@ begin NetTime := GT; kByte := M.ReadWord(); Dir := M.ReadByte(); - WeaponSelect := M.ReadWord(); + //WeaponSelect := M.ReadWord(); + newweapon := M.ReadByte(); + if (newweapon <> CurrWeap) then + begin +{$IFDEF K8_XXX_WEAPON_DEBUG} + writeln('HOST PLRPOS: got: currweap=', CurrWeap, '; curfrm=', gTime, '; netweap=', newweapon, '; oldweap=', CurrWeap); +{$ENDIF} + //NetForceWeap := newweapon; + SetWeapon(newweapon); + end; //e_WriteLog(Format('R:ws=%d', [WeaponSelect]), MSG_WARNING); if Direction <> TDirection(Dir) then JustTeleported := False; SetDirection(TDirection(Dir)); - ReleaseKeys; + ReleaseKeysNoWeapon(); if kByte = NET_KEY_CHAT then begin @@ -474,9 +486,10 @@ begin if LongBool(kByte and NET_KEY_JUMP) then PressKey(KEY_JUMP, 10000); if LongBool(kByte and NET_KEY_FIRE) then PressKey(KEY_FIRE, 10000); if LongBool(kByte and NET_KEY_OPEN) then PressKey(KEY_OPEN, 10000); - if LongBool(kByte and NET_KEY_NW) then PressKey(KEY_NEXTWEAPON, 10000); - if LongBool(kByte and NET_KEY_PW) then PressKey(KEY_PREVWEAPON, 10000); + //if LongBool(kByte and NET_KEY_NW) then PressKey(KEY_NEXTWEAPON, 10000); + //if LongBool(kByte and NET_KEY_PW) then PressKey(KEY_PREVWEAPON, 10000); + (* for i := 0 to 15 do begin if (WeaponSelect and Word(1 shl i)) <> 0 then @@ -485,6 +498,7 @@ begin QueueWeaponSwitch(i); end; end; + *) end; // MH_SEND_PlayerPos(False, PID, C^.ID); @@ -634,12 +648,19 @@ procedure MH_SEND_Everything(CreatePlayers: Boolean = False; ID: Integer = NET_E MH_SEND_ItemSpawn(True, it.myid, ID); end; - function sendMonSpawn (monidx: Integer; mon: TMonster): Boolean; + function sendMonSpawn (mon: TMonster): Boolean; begin result := false; // don't stop MH_SEND_MonsterSpawn(mon.UID, ID); end; + function sendPanelState (pan: TPanel): Boolean; + begin + result := false; // don't stop + MH_SEND_PanelState(pan.guid, ID); // anyway, to sync mplats + if (pan.CanChangeTexture) then MH_SEND_PanelTexture(pan.guid, pan.LastAnimLoop, ID); + end; + var I: Integer; begin @@ -654,86 +675,38 @@ begin MH_SEND_PlayerStats(gPlayers[I].UID, ID); if (gPlayers[I].Flag <> FLAG_NONE) and (gGameSettings.GameMode = GM_CTF) then + begin MH_SEND_FlagEvent(FLAG_STATE_CAPTURED, gPlayers[I].Flag, gPlayers[I].UID, True, ID); + end; end; end; end; g_Items_ForEachAlive(sendItemRespawn, true); // backwards g_Mons_ForEach(sendMonSpawn); - - if gWalls <> nil then - for I := Low(gWalls) to High(gWalls) do - if gWalls[I] <> nil then - with gWalls[I] do - begin - if Door then - MH_SEND_PanelState(PanelType, I, ID); - - if GetTextureCount > 1 then - MH_SEND_PanelTexture(PanelType, I, LastAnimLoop, ID); - end; - - if gLifts <> nil then - for I := Low(gLifts) to High(gLifts) do - if gLifts[I] <> nil then - with gLifts[I] do - MH_SEND_PanelState(PanelType, I, ID); - - if gRenderForegrounds <> nil then - for I := Low(gRenderForegrounds) to High(gRenderForegrounds) do - if gRenderForegrounds[I] <> nil then - with gRenderForegrounds[I] do - begin - if (GetTextureCount > 1) then - MH_SEND_PanelTexture(PanelType, I, LastAnimLoop, ID); - if Moved then - MH_SEND_PanelState(PanelType, I, ID); - end; - if gRenderBackgrounds <> nil then - for I := Low(gRenderBackgrounds) to High(gRenderBackgrounds) do - if gRenderBackgrounds[I] <> nil then - with gRenderBackgrounds[I] do - begin - if (GetTextureCount > 1) then - MH_SEND_PanelTexture(PanelType, I, LastAnimLoop, ID); - if Moved then - MH_SEND_PanelState(PanelType, I, ID); - end; - if gWater <> nil then - for I := Low(gWater) to High(gWater) do - if gWater[I] <> nil then - with gWater[I] do - if GetTextureCount > 1 then - MH_SEND_PanelTexture(PanelType, I, LastAnimLoop, ID); - if gAcid1 <> nil then - for I := Low(gAcid1) to High(gAcid1) do - if gAcid1[I] <> nil then - with gAcid1[I] do - if GetTextureCount > 1 then - MH_SEND_PanelTexture(PanelType, I, LastAnimLoop, ID); - if gAcid2 <> nil then - for I := Low(gAcid2) to High(gAcid2) do - if gAcid2[I] <> nil then - with gAcid2[I] do - if GetTextureCount > 1 then - MH_SEND_PanelTexture(PanelType, I, LastAnimLoop, ID); - if gSteps <> nil then - for I := Low(gSteps) to High(gSteps) do - if gSteps[I] <> nil then - with gSteps[I] do - if GetTextureCount > 1 then - MH_SEND_PanelTexture(PanelType, I, LastAnimLoop, ID); + g_Map_ForEachPanel(sendPanelState); if gTriggers <> nil then + begin for I := Low(gTriggers) to High(gTriggers) do + begin if gTriggers[I].TriggerType = TRIGGER_SOUND then + begin MH_SEND_TriggerSound(gTriggers[I], ID); + end; + end; + end; if Shots <> nil then + begin for I := Low(Shots) to High(Shots) do + begin if Shots[i].ShotType in [6, 7, 8] then + begin MH_SEND_CreateShot(i, ID); + end; + end; + end; MH_SEND_TriggerMusic(ID); @@ -742,16 +715,16 @@ begin if gGameSettings.GameMode = GM_CTF then begin - if gFlags[FLAG_RED].State <> FLAG_STATE_CAPTURED then - MH_SEND_FlagEvent(gFlags[FLAG_RED].State, FLAG_RED, 0, True, ID); - if gFlags[FLAG_BLUE].State <> FLAG_STATE_CAPTURED then - MH_SEND_FlagEvent(gFlags[FLAG_BLUE].State, FLAG_BLUE, 0, True, ID); + if gFlags[FLAG_RED].State <> FLAG_STATE_CAPTURED then MH_SEND_FlagEvent(gFlags[FLAG_RED].State, FLAG_RED, 0, True, ID); + if gFlags[FLAG_BLUE].State <> FLAG_STATE_CAPTURED then MH_SEND_FlagEvent(gFlags[FLAG_BLUE].State, FLAG_BLUE, 0, True, ID); end; if CreatePlayers and (ID >= 0) then NetClients[ID].State := NET_STATE_GAME; if gLMSRespawn > LMS_RESPAWN_NONE then + begin MH_SEND_GameEvent(NET_EV_LMS_WARMUP, (gLMSRespawnTime - gTime) div 1000, 'N', ID); + end; end; procedure MH_SEND_Info(ID: Byte); @@ -818,8 +791,8 @@ begin if Mode = NET_CHAT_PLAYER then begin g_Console_Add(Txt, True); - e_WriteLog('[Chat] ' + b_Text_Unformat(Txt), MSG_NOTIFY); - g_Sound_PlayEx('SOUND_GAME_RADIO'); + e_WriteLog('[Chat] ' + b_Text_Unformat(Txt), TMsgType.Notify); + g_Game_ChatSound(b_Text_Unformat(Txt)); end else if Mode = NET_CHAT_TEAM then @@ -828,14 +801,14 @@ begin if (gPlayer1.Team = TEAM_RED) and (Team = TEAM_RED) then begin g_Console_Add(#18'[Team] '#2 + Txt, True); - e_WriteLog('[Team Chat] ' + b_Text_Unformat(Txt), MSG_NOTIFY); - g_Sound_PlayEx('SOUND_GAME_RADIO'); + e_WriteLog('[Team Chat] ' + b_Text_Unformat(Txt), TMsgType.Notify); + g_Game_ChatSound(b_Text_Unformat(Txt)); end else if (gPlayer1.Team = TEAM_BLUE) and (Team = TEAM_BLUE) then begin g_Console_Add(#20'[Team] '#2 + Txt, True); - e_WriteLog('[Team Chat] ' + b_Text_Unformat(Txt), MSG_NOTIFY); - g_Sound_PlayEx('SOUND_GAME_RADIO'); + e_WriteLog('[Team Chat] ' + b_Text_Unformat(Txt), TMsgType.Notify); + g_Game_ChatSound(b_Text_Unformat(Txt)); end; end; end @@ -843,8 +816,8 @@ begin begin Name := g_Net_ClientName_ByID(ID); g_Console_Add('-> ' + Name + ': ' + Txt, True); - e_WriteLog('[Tell ' + Name + '] ' + b_Text_Unformat(Txt), MSG_NOTIFY); - g_Sound_PlayEx('SOUND_GAME_RADIO'); + e_WriteLog('[Tell ' + Name + '] ' + b_Text_Unformat(Txt), TMsgType.Notify); + g_Game_ChatSound(b_Text_Unformat(Txt), False); end; end; @@ -955,7 +928,7 @@ begin NetOut.Write(EvStr); NetOut.Write(Byte(gLastMap)); NetOut.Write(gTime); - if (EvType = NET_EV_MAPSTART) and (Pos(':\', EvStr) > 0) then + if (EvType = NET_EV_MAPSTART) and isWadPath(EvStr) then begin NetOut.Write(Byte(1)); NetOut.Write(gWADHash); @@ -1048,7 +1021,7 @@ begin end; NetOut.Write(kByte); - if Direction = D_LEFT then NetOut.Write(Byte(0)) else NetOut.Write(Byte(1)); + if Direction = TDirection.D_LEFT then NetOut.Write(Byte(0)) else NetOut.Write(Byte(1)); NetOut.Write(GameX); NetOut.Write(GameY); NetOut.Write(GameVelX); @@ -1064,6 +1037,7 @@ procedure MH_SEND_PlayerStats(PID: Word; ID: Integer = NET_EVERYONE); var P: TPlayer; I: Integer; + ww: Word; begin P := g_Player_Get(PID); if P = nil then Exit; @@ -1073,7 +1047,7 @@ begin with P do begin - NetOut.Write(Byte(Live)); + NetOut.Write(Byte(alive)); NetOut.Write(Byte(GodMode)); NetOut.Write(Health); NetOut.Write(Armor); @@ -1082,8 +1056,10 @@ begin NetOut.Write(Lives); NetOut.Write(Team); - for I := WP_FIRST to WP_LAST do - NetOut.Write(Byte(FWeapon[I])); + // collect all weapons in one word + ww := 0; + for I := WP_FIRST to WP_LAST do if (FWeapon[I]) then ww := ww or (1 shl (i-WP_FIRST)); + NetOut.Write(Word(ww)); for I := A_BULLETS to A_HIGH do NetOut.Write(FAmmo[I]); @@ -1094,22 +1070,30 @@ begin for I := MR_SUIT to MR_MAX do NetOut.Write(LongWord(FMegaRulez[I])); - NetOut.Write(Byte(R_ITEM_BACKPACK in FRulez)); - NetOut.Write(Byte(R_KEY_RED in FRulez)); - NetOut.Write(Byte(R_KEY_GREEN in FRulez)); - NetOut.Write(Byte(R_KEY_BLUE in FRulez)); - NetOut.Write(Byte(R_BERSERK in FRulez)); + // collect all special flags in one byte + ww := 0; + if (R_ITEM_BACKPACK in FRulez) then ww := ww or $01; + if (R_KEY_RED in FRulez) then ww := ww or $02; + if (R_KEY_GREEN in FRulez) then ww := ww or $04; + if (R_KEY_BLUE in FRulez) then ww := ww or $08; + if (R_BERSERK in FRulez) then ww := ww or $10; + NetOut.Write(Byte(ww)); NetOut.Write(Frags); NetOut.Write(Death); - NetOut.Write(CurrWeap); + //NetOut.Write(CurrWeap); + NetOut.Write(Byte(CurrWeap)); + + // other flags + ww := 0; + if (FSpectator) then ww := ww or $01; + if (FGhost) then ww := ww or $02; + if (FPhysics) then ww := ww or $04; + if (FNoRespawn) then ww := ww or $08; + if (FJetpack) then ww := ww or $10; + NetOut.Write(Byte(ww)); - NetOut.Write(Byte(FSpectator)); - NetOut.Write(Byte(FGhost)); - NetOut.Write(Byte(FPhysics)); - NetOut.Write(Byte(FNoRespawn)); - NetOut.Write(Byte(FJetpack)); NetOut.Write(FFireTime); end; @@ -1189,13 +1173,16 @@ end; procedure MH_SEND_ItemSpawn(Quiet: Boolean; IID: Word; ID: Integer = NET_EVERYONE); var it: PItem; + tt: Byte; begin it := g_Items_ByIdx(IID); NetOut.Write(Byte(NET_MSG_ISPAWN)); NetOut.Write(IID); NetOut.Write(Byte(Quiet)); - NetOut.Write(it.ItemType); + tt := it.ItemType; + if it.dropped then tt := tt or $80; + NetOut.Write(tt); NetOut.Write(Byte(it.Fall)); NetOut.Write(Byte(it.Respawnable)); NetOut.Write(it.Obj.X); @@ -1217,34 +1204,17 @@ end; // PANEL -procedure MH_SEND_PanelTexture(PType: Word; PID: LongWord; AnimLoop: Byte; ID: Integer = NET_EVERYONE); +procedure MH_SEND_PanelTexture(PGUID: Integer; AnimLoop: Byte; ID: Integer = NET_EVERYONE); var TP: TPanel; begin - case PType of - PANEL_WALL, PANEL_OPENDOOR, PANEL_CLOSEDOOR: - TP := gWalls[PID]; - PANEL_FORE: - TP := gRenderForegrounds[PID]; - PANEL_BACK: - TP := gRenderBackgrounds[PID]; - PANEL_WATER: - TP := gWater[PID]; - PANEL_ACID1: - TP := gAcid1[PID]; - PANEL_ACID2: - TP := gAcid2[PID]; - PANEL_STEP: - TP := gSteps[PID]; - else - Exit; - end; + TP := g_Map_PanelByGUID(PGUID); + if (TP = nil) then exit; with TP do begin NetOut.Write(Byte(NET_MSG_PTEX)); - NetOut.Write(PType); - NetOut.Write(PID); + NetOut.Write(LongWord(PGUID)); NetOut.Write(FCurTexture); NetOut.Write(FCurFrame); NetOut.Write(FCurFrameCount); @@ -1254,36 +1224,36 @@ begin g_Net_Host_Send(ID, True, NET_CHAN_LARGEDATA); end; -procedure MH_SEND_PanelState(PType: Word; PID: LongWord; ID: Integer = NET_EVERYONE); +procedure MH_SEND_PanelState(PGUID: Integer; ID: Integer = NET_EVERYONE); var TP: TPanel; + mpflags: Byte = 0; begin - case PType of - PANEL_WALL, PANEL_OPENDOOR, PANEL_CLOSEDOOR: - TP := gWalls[PID]; - PANEL_LIFTUP, PANEL_LIFTDOWN, PANEL_LIFTLEFT, PANEL_LIFTRIGHT: - TP := gLifts[PID]; - PANEL_BACK: - begin - TP := gRenderBackgrounds[PID]; - TP.Moved := True; - end; - PANEL_FORE: - begin - TP := gRenderForegrounds[PID]; - TP.Moved := True; - end; - else - Exit; - end; + TP := g_Map_PanelByGUID(PGUID); + if (TP = nil) then exit; NetOut.Write(Byte(NET_MSG_PSTATE)); - NetOut.Write(PType); - NetOut.Write(PID); + NetOut.Write(LongWord(PGUID)); NetOut.Write(Byte(TP.Enabled)); NetOut.Write(TP.LiftType); NetOut.Write(TP.X); NetOut.Write(TP.Y); + NetOut.Write(Word(TP.Width)); + NetOut.Write(Word(TP.Height)); + // mplats + NetOut.Write(LongInt(TP.movingSpeedX)); + NetOut.Write(LongInt(TP.movingSpeedY)); + NetOut.Write(LongInt(TP.movingStartX)); + NetOut.Write(LongInt(TP.movingStartY)); + NetOut.Write(LongInt(TP.movingEndX)); + NetOut.Write(LongInt(TP.movingEndY)); + NetOut.Write(LongInt(TP.sizeSpeedX)); + NetOut.Write(LongInt(TP.sizeSpeedY)); + NetOut.Write(LongInt(TP.sizeEndX)); + NetOut.Write(LongInt(TP.sizeEndY)); + if TP.movingActive then mpflags := mpflags or 1; + if TP.moveOnce then mpflags := mpflags or 2; + NetOut.Write(Byte(mpflags)); g_Net_Host_Send(ID, True, NET_CHAN_LARGEDATA); end; @@ -1321,7 +1291,7 @@ procedure MH_SEND_MonsterSpawn(UID: Word; ID: Integer = NET_EVERYONE); var M: TMonster; begin - M := g_Monsters_Get(UID); + M := g_Monsters_ByUID(UID); if M = nil then Exit; @@ -1352,7 +1322,7 @@ procedure MH_SEND_MonsterPos(UID: Word; ID: Integer = NET_EVERYONE); var M: TMonster; begin - M := g_Monsters_Get(UID); + M := g_Monsters_ByUID(UID); if M = nil then Exit; NetOut.Write(Byte(NET_MSG_MPOS)); @@ -1374,7 +1344,7 @@ procedure MH_SEND_MonsterState(UID: Word; ForcedAnim: Byte = 255; ID: Integer = var M: TMonster; begin - M := g_Monsters_Get(UID); + M := g_Monsters_ByUID(UID); if M = nil then Exit; NetOut.Write(Byte(NET_MSG_MSTATE)); @@ -1413,7 +1383,7 @@ procedure MH_SEND_MonsterDelete(UID: Word; ID: Integer = NET_EVERYONE); var M: TMonster; begin - M := g_Monsters_Get(UID); + M := g_Monsters_ByUID(UID); if M = nil then Exit; NetOut.Write(Byte(NET_MSG_MDEL)); @@ -1464,8 +1434,8 @@ begin if Mode = NET_CHAT_PLAYER then begin g_Console_Add(Txt, True); - e_WriteLog('[Chat] ' + b_Text_Unformat(Txt), MSG_NOTIFY); - g_Sound_PlayEx('SOUND_GAME_RADIO'); + e_WriteLog('[Chat] ' + b_Text_Unformat(Txt), TMsgType.Notify); + g_Game_ChatSound(b_Text_Unformat(Txt)); end else if (Mode = NET_CHAT_TEAM) and (gPlayer1 <> nil) then begin @@ -1473,8 +1443,8 @@ begin g_Console_Add(b_Text_Format('\r[Team] ') + Txt, True); if gPlayer1.Team = TEAM_BLUE then g_Console_Add(b_Text_Format('\b[Team] ') + Txt, True); - e_WriteLog('[Team Chat] ' + b_Text_Unformat(Txt), MSG_NOTIFY); - g_Sound_PlayEx('SOUND_GAME_RADIO'); + e_WriteLog('[Team Chat] ' + b_Text_Unformat(Txt), TMsgType.Notify); + g_Game_ChatSound(b_Text_Unformat(Txt)); end; end else g_Console_Add(Txt, True); @@ -1726,7 +1696,7 @@ begin gWADHash := EvHash; if not g_Game_StartMap(EvStr, True) then begin - if Pos(':\', EvStr) = 0 then + if not isWadPath(EvStr) then g_FatalError(Format(_lc[I_GAME_ERROR_MAP_LOAD], [gGameSettings.WAD + ':\' + EvStr])) else g_FatalError(Format(_lc[I_GAME_ERROR_MAP_LOAD], [EvStr])); @@ -2051,7 +2021,7 @@ begin end; g_Console_Add(Format(_lc[I_PLAYER_JOIN], [PName]), True); - e_WriteLog('NET: Player ' + PName + ' [' + IntToStr(PID) + '] added.', MSG_NOTIFY); + e_WriteLog('NET: Player ' + PName + ' [' + IntToStr(PID) + '] added.', TMsgType.Notify); Result := PID; end; @@ -2073,6 +2043,8 @@ begin Exit; end; gTime := GT; + if g_Game_IsClient and (gPlayer1 <> nil) and (gPlayer1.NetForceWeapFIdx >= gTime+15) then gPlayer1.NetForceWeapFIdx := 0; + if g_Game_IsClient and (gPlayer2 <> nil) and (gPlayer2.NetForceWeapFIdx >= gTime+15) then gPlayer2.NetForceWeapFIdx := 0; PID := M.ReadWord(); Pl := g_Player_Get(PID); @@ -2091,7 +2063,7 @@ begin TmpX := M.ReadLongInt(); TmpY := M.ReadLongInt(); - ReleaseKeys; + ReleaseKeysNoWeapon; if (kByte = NET_KEY_CHAT) then PressKey(KEY_CHAT, 10000) @@ -2123,6 +2095,8 @@ var I: Integer; OldJet: Boolean; NewTeam: Byte; + ww: Word; + newweapon: Byte; begin PID := M.ReadWord(); Pl := g_Player_Get(PID); @@ -2132,7 +2106,7 @@ begin with Pl do begin - Live := (M.ReadByte() <> 0); + alive := (M.ReadByte() <> 0); GodMode := (M.ReadByte() <> 0); Health := M.ReadLongInt(); Armor := M.ReadLongInt(); @@ -2141,8 +2115,12 @@ begin Lives := M.ReadByte(); NewTeam := M.ReadByte(); + ww := M.ReadWord(); for I := WP_FIRST to WP_LAST do - FWeapon[I] := (M.ReadByte() <> 0); + begin + FWeapon[I] := ((ww and $01) <> 0); + ww := ww shr 1; + end; for I := A_BULLETS to A_HIGH do FAmmo[I] := M.ReadWord(); @@ -2154,23 +2132,32 @@ begin FMegaRulez[I] := M.ReadLongWord(); FRulez := []; - if (M.ReadByte() <> 0) then - FRulez := FRulez + [R_ITEM_BACKPACK]; - if (M.ReadByte() <> 0) then - FRulez := FRulez + [R_KEY_RED]; - if (M.ReadByte() <> 0) then - FRulez := FRulez + [R_KEY_GREEN]; - if (M.ReadByte() <> 0) then - FRulez := FRulez + [R_KEY_BLUE]; - if (M.ReadByte() <> 0) then - FRulez := FRulez + [R_BERSERK]; + // unpack special flags + ww := M.ReadByte(); + if ((ww and $01) <> 0) then FRulez := FRulez+[R_ITEM_BACKPACK]; + if ((ww and $02) <> 0) then FRulez := FRulez+[R_KEY_RED]; + if ((ww and $04) <> 0) then FRulez := FRulez+[R_KEY_GREEN]; + if ((ww and $08) <> 0) then FRulez := FRulez+[R_KEY_BLUE]; + if ((ww and $10) <> 0) then FRulez := FRulez+[R_BERSERK]; Frags := M.ReadLongInt(); Death := M.ReadLongInt(); - SetWeapon(M.ReadByte()); + newweapon := M.ReadByte(); +{$IFDEF K8_XXX_WEAPON_DEBUG} + writeln('CLIENT PLRSTATS: got: currweap=', CurrWeap, '; curfrm=', gTime, '; netweap=', newweapon, '; lastnwfrm=', NetForceWeapFIdx); +{$ENDIF} + if (gTime >= NetForceWeapFIdx) then + begin + //NetForceWeap := newweapon; + SetWeapon(newweapon); + end; + //SetWeapon(M.ReadByte()); + + // other flags + ww := M.ReadByte(); - FSpectator := M.ReadByte() <> 0; + FSpectator := ((ww and $01) <> 0); if FSpectator then begin if Pl = gPlayer1 then @@ -2191,11 +2178,12 @@ begin if (gPlayer2 = nil) and (gLMSPID2 > 0) then gPlayer2 := g_Player_Get(gLMSPID2); end; - FGhost := M.ReadByte() <> 0; - FPhysics := M.ReadByte() <> 0; - FNoRespawn := M.ReadByte() <> 0; + + FGhost := ((ww and $02) <> 0); + FPhysics := ((ww and $04) <> 0); + FNoRespawn := ((ww and $08) <> 0); OldJet := FJetpack; - FJetpack := M.ReadByte() <> 0; + FJetpack := ((ww and $10) <> 0); FFireTime := M.ReadLongInt(); if OldJet and not FJetpack then JetpackOff @@ -2269,7 +2257,7 @@ begin if Pl = nil then Exit; g_Console_Add(Format(_lc[I_PLAYER_LEAVE], [Pl.Name]), True); - e_WriteLog('NET: Player ' + Pl.Name + ' [' + IntToStr(PID) + '] removed.', MSG_NOTIFY); + e_WriteLog('NET: Player ' + Pl.Name + ' [' + IntToStr(PID) + '] removed.', TMsgType.Notify); g_Player_Remove(PID); @@ -2298,7 +2286,7 @@ begin SHID := M.ReadLongInt(); with Pl do - if Live then NetFire(Weap, X, Y, AX, AY, SHID); + if alive then NetFire(Weap, X, Y, AX, AY, SHID); end; procedure MC_RECV_PlayerSettings(var M: TMsg); @@ -2364,7 +2352,8 @@ begin VX := M.ReadLongInt(); VY := M.ReadLongInt(); - g_Items_Create(X, Y, T, Fall, False, False, ID); + g_Items_Create(X, Y, T and $7F, Fall, False, False, ID); + if ((T and $80) <> 0) then g_Items_SetDrop(ID); it := g_Items_ByIdx(ID); it.Obj.Vel.X := VX; @@ -2403,94 +2392,89 @@ end; procedure MC_RECV_PanelTexture(var M: TMsg); var TP: TPanel; - PType: Word; - ID: LongWord; + PGUID: Integer; Tex, Fr: Integer; Loop, Cnt: Byte; begin if not gGameOn then Exit; - PType := M.ReadWord(); - ID := M.ReadLongWord(); + + PGUID := Integer(M.ReadLongWord()); Tex := M.ReadLongInt(); Fr := M.ReadLongInt(); Cnt := M.ReadByte(); Loop := M.ReadByte(); - TP := nil; - - case PType of - PANEL_WALL, PANEL_OPENDOOR, PANEL_CLOSEDOOR: - if gWalls <> nil then - TP := gWalls[ID]; - PANEL_FORE: - if gRenderForegrounds <> nil then - TP := gRenderForegrounds[ID]; - PANEL_BACK: - if gRenderBackgrounds <> nil then - TP := gRenderBackgrounds[ID]; - PANEL_WATER: - if gWater <> nil then - TP := gWater[ID]; - PANEL_ACID1: - if gAcid1 <> nil then - TP := gAcid1[ID]; - PANEL_ACID2: - if gAcid2 <> nil then - TP := gAcid2[ID]; - PANEL_STEP: - if gSteps <> nil then - TP := gSteps[ID]; - else - Exit; + TP := g_Map_PanelByGUID(PGUID); + if (TP <> nil) then + begin + // switch texture + TP.SetTexture(Tex, Loop); + TP.SetFrame(Fr, Cnt); end; - - if TP <> nil then - if Loop = 0 then - begin // switch texture - TP.SetTexture(Tex, Loop); - TP.SetFrame(Fr, Cnt); - end else // looped or non-looped animation - TP.NextTexture(Loop); end; procedure MC_RECV_PanelState(var M: TMsg); var - ID: LongWord; + PGUID: Integer; E: Boolean; Lift: Byte; - PType: Word; - X, Y: Integer; + X, Y, W, H: Integer; + TP: TPanel; + speedX, speedY, startX, startY, endX, endY: Integer; + sizeSpX, sizeSpY, sizeEX, sizeEY: Integer; + mpflags: Byte; begin if not gGameOn then Exit; - PType := M.ReadWord(); - ID := M.ReadLongWord(); + + PGUID := Integer(M.ReadLongWord()); E := (M.ReadByte() <> 0); Lift := M.ReadByte(); X := M.ReadLongInt(); Y := M.ReadLongInt(); - - case PType of - PANEL_WALL, PANEL_OPENDOOR, PANEL_CLOSEDOOR: - if E then - g_Map_EnableWall(ID) - else - g_Map_DisableWall(ID); - - PANEL_LIFTUP, PANEL_LIFTDOWN, PANEL_LIFTLEFT, PANEL_LIFTRIGHT: - g_Map_SetLift(ID, Lift); - - PANEL_BACK: - begin - gRenderBackgrounds[ID].X := X; - gRenderBackgrounds[ID].Y := Y; - end; - - PANEL_FORE: - begin - gRenderForegrounds[ID].X := X; - gRenderForegrounds[ID].Y := Y; - end; - end; + W := M.ReadWord(); + H := M.ReadWord(); + // mplats + speedX := M.ReadLongInt(); + speedY := M.ReadLongInt(); + startX := M.ReadLongInt(); + startY := M.ReadLongInt(); + endX := M.ReadLongInt(); + endY := M.ReadLongInt(); + sizeSpX := M.ReadLongInt(); + sizeSpY := M.ReadLongInt(); + sizeEX := M.ReadLongInt(); + sizeEY := M.ReadLongInt(); + mpflags := M.ReadByte(); // bit0: TP.movingActive; bit1: TP.moveOnce + + TP := g_Map_PanelByGUID(PGUID); + if (TP = nil) then exit; + + // update lifts state + if TP.isGLift then g_Map_SetLiftGUID(PGUID, Lift); + + // update enabled/disabled state for all panels + if E then g_Map_EnableWallGUID(PGUID) else g_Map_DisableWallGUID(PGUID); + + // update panel position, as it can be moved (mplat) + TP.X := X; + TP.Y := Y; + TP.Width := W; + TP.Height := H; + // update mplat state + TP.movingSpeedX := speedX; + TP.movingSpeedY := speedY; + TP.movingStartX := startX; + TP.movingStartY := startY; + TP.movingEndX := endX; + TP.movingEndY := endY; + TP.sizeSpeedX := sizeSpX; + TP.sizeSpeedY := sizeSpY; + TP.sizeEndX := sizeEX; + TP.sizeEndY := sizeEY; + TP.movingActive := ((mpflags and 1) <> 0); + TP.moveOnce := ((mpflags and 2) <> 0); + // notify panel of it's position/size change, so it can fix other internal structures + TP.positionChanged(); end; // TRIGGERS @@ -2515,16 +2499,19 @@ begin if gTriggers[I].ClientID = SID then with gTriggers[I] do begin - if SPlaying then + if Sound <> nil then begin - if Data.Local then - Sound.PlayVolumeAt(X+(Width div 2), Y+(Height div 2), Data.Volume/255.0) + if SPlaying then + begin + if tgcLocal then + Sound.PlayVolumeAt(X+(Width div 2), Y+(Height div 2), tgcVolume/255.0) + else + Sound.PlayPanVolume((tgcPan-127.0)/128.0, tgcVolume/255.0); + Sound.SetPosition(SPos); + end else - Sound.PlayPanVolume((Data.Pan-127.0)/128.0, Data.Volume/255.0); - Sound.SetPosition(SPos); - end - else - if Sound.IsPlaying then Sound.Stop; + if Sound.IsPlaying then Sound.Stop; + end; SoundPlayCount := SCount; end; @@ -2566,7 +2553,7 @@ var Mon: TMonster; begin ID := M.ReadWord(); - Mon := g_Monsters_Get(ID); + Mon := g_Monsters_ByUID(ID); if Mon <> nil then Exit; @@ -2587,16 +2574,12 @@ begin MDir := M.ReadByte(); g_Monsters_Create(MType, X, Y, TDirection(MDir), False, ID); - Mon := g_Monsters_Get(ID); + Mon := g_Monsters_ByUID(ID); if Mon = nil then Exit; with Mon do begin - GameX := X; - GameY := Y; - GameVelX := VX; - GameVelY := VY; MonsterAnim := MAnim; MonsterTargetUID := MTarg; @@ -2608,7 +2591,9 @@ begin SetState(MState); - positionChanged(); // this updates spatial accelerators + setPosition(X, Y); // this will call positionChanged(); + GameVelX := VX; + GameVelY := VY; end; end; @@ -2616,20 +2601,21 @@ procedure MC_RECV_MonsterPos(var M: TMsg); var Mon: TMonster; ID: Word; + X, Y: Integer; begin ID := M.ReadWord(); - Mon := g_Monsters_Get(ID); + Mon := g_Monsters_ByUID(ID); if Mon = nil then Exit; with Mon do begin - GameX := M.ReadLongInt(); - GameY := M.ReadLongInt(); + X := M.ReadLongInt(); + Y := M.ReadLongInt(); + Mon.setPosition(X, Y); // this will call `positionChanged()` GameVelX := M.ReadLongInt(); GameVelY := M.ReadLongInt(); GameDirection := TDirection(M.ReadByte()); - positionChanged(); // this updates spatial accelerators end; end; @@ -2641,7 +2627,7 @@ var AnimRevert: Boolean; begin ID := M.ReadWord(); - Mon := g_Monsters_Get(ID); + Mon := g_Monsters_ByUID(ID); if Mon = nil then Exit; MState := M.ReadByte(); @@ -2661,16 +2647,11 @@ begin if MonsterState <> MState then begin - if (MState = MONSTATE_GO) and (MonsterState = MONSTATE_SLEEP) then - WakeUpSound; - if (MState = MONSTATE_DIE) then - DieSound; - if (MState = MONSTATE_PAIN) then - MakeBloodSimple(Min(200, MonsterPain)); - if (MState = MONSTATE_ATTACK) then - kick(nil); - if (MState = MONSTATE_DEAD) then - SetDeadAnim; + if (MState = MONSTATE_GO) and (MonsterState = MONSTATE_SLEEP) then WakeUpSound(); + if (MState = MONSTATE_DIE) then DieSound(); + if (MState = MONSTATE_PAIN) then MakeBloodSimple(Min(200, MonsterPain)); + if (MState = MONSTATE_ATTACK) then kick(nil); + if (MState = MONSTATE_DEAD) then SetDeadAnim(); SetState(MState, MFAnm); end; @@ -2685,7 +2666,7 @@ var begin ID := M.ReadWord(); - Mon := g_Monsters_Get(ID); + Mon := g_Monsters_ByUID(ID); if Mon = nil then Exit; X := M.ReadLongInt(); @@ -2702,7 +2683,7 @@ var Mon: TMonster; begin ID := M.ReadWord(); - Mon := g_Monsters_Get(ID); + Mon := g_Monsters_ByUID(ID); if Mon = nil then Exit; Mon.SetState(5); Mon.MonsterRemoved := True; @@ -2784,7 +2765,7 @@ var kByte: Word; Predict: Boolean; strafeDir: Byte; - WeaponSelect: Word = 0; + //WeaponSelect: Word = 0; I: Integer; begin if not gGameOn then Exit; @@ -2810,17 +2791,20 @@ begin // new strafe mechanics if (strafeDir = 0) then strafeDir := P1MoveButton; // start strafing // now set direction according to strafe (reversed) - if (strafeDir = 2) then gPlayer1.SetDirection(D_LEFT) - else if (strafeDir = 1) then gPlayer1.SetDirection(D_RIGHT); + if (strafeDir = 2) then gPlayer1.SetDirection(TDirection.D_LEFT) + else if (strafeDir = 1) then gPlayer1.SetDirection(TDirection.D_RIGHT); end else begin - if (P1MoveButton = 2) and isKeyPressed(KeyLeft, KeyLeft2) then gPlayer1.SetDirection(D_LEFT) - else if (P1MoveButton = 1) and isKeyPressed(KeyRight, KeyRight2) then gPlayer1.SetDirection(D_RIGHT) + if (P1MoveButton = 2) and isKeyPressed(KeyLeft, KeyLeft2) then gPlayer1.SetDirection(TDirection.D_LEFT) + else if (P1MoveButton = 1) and isKeyPressed(KeyRight, KeyRight2) then gPlayer1.SetDirection(TDirection.D_RIGHT) else if P1MoveButton <> 0 then gPlayer1.SetDirection(TDirection(P1MoveButton-1)); end; gPlayer1.ReleaseKeys; + gPlayer1.weaponSwitchKeysStateChange(-1, isKeyPressed(KeyNextWeapon, KeyNextWeapon2)); + gPlayer1.weaponSwitchKeysStateChange(-2, isKeyPressed(KeyPrevWeapon, KeyPrevWeapon2)); + if P1MoveButton = 1 then begin kByte := kByte or NET_KEY_LEFT; @@ -2848,11 +2832,25 @@ begin end; if isKeyPressed(KeyFire, KeyFire2) then kByte := kByte or NET_KEY_FIRE; if isKeyPressed(KeyOpen, KeyOpen2) then kByte := kByte or NET_KEY_OPEN; - if isKeyPressed(KeyNextWeapon, KeyNextWeapon2) then kByte := kByte or NET_KEY_NW; - if isKeyPressed(KeyPrevWeapon, KeyPrevWeapon2) then kByte := kByte or NET_KEY_PW; + // do not send weapon switch keys, `MH_SEND_PlayerStats()` will send changed weapon anyway + if isKeyPressed(KeyNextWeapon, KeyNextWeapon2) and gPlayer1.isWeaponSwitchKeyReleased(-1) then gPlayer1.PressKey(KEY_NEXTWEAPON); //kByte := kByte or NET_KEY_NW; + if isKeyPressed(KeyPrevWeapon, KeyPrevWeapon2) and gPlayer1.isWeaponSwitchKeyReleased(-2) then gPlayer1.PressKey(KEY_PREVWEAPON); //kByte := kByte or NET_KEY_PW; for I := 0 to High(KeyWeapon) do + begin if isKeyPressed(KeyWeapon[I], KeyWeapon2[I]) then - WeaponSelect := WeaponSelect or Word(1 shl I); + begin + gPlayer1.weaponSwitchKeysStateChange(i, true); + if gPlayer1.isWeaponSwitchKeyReleased(i) then + begin + gPlayer1.QueueWeaponSwitch(i); // all choices are passed there, and god will take the best + //WeaponSelect := WeaponSelect or Word(1 shl I); + end; + end + else + begin + gPlayer1.weaponSwitchKeysStateChange(i, false); + end; + end; end; // fix movebutton state P1MoveButton := P1MoveButton or (strafeDir shl 4); @@ -2860,14 +2858,24 @@ begin else kByte := NET_KEY_CHAT; + gPlayer1.weaponSwitchKeysShiftNewStates(); + NetOut.Write(Byte(NET_MSG_PLRPOS)); NetOut.Write(gTime); NetOut.Write(kByte); NetOut.Write(Byte(gPlayer1.Direction)); - NetOut.Write(WeaponSelect); + NetOut.Write(Byte(gPlayer1.CurrWeap)); +{$IFDEF K8_XXX_WEAPON_DEBUG} + if (kByte and NET_KEY_FIRE) <> 0 then writeln('FIRE: CurrWeap=', gPlayer1.CurrWeap); +{$ENDIF} + //e_WriteLog(Format('S:nwp=%d; nwfidx=%d', [Integer(gPlayer1.NetForceWeap), Integer(gPlayer1.NetForceWeapFIdx)]), TMsgType.Warning); + //NetOut.Write(WeaponSelect); //e_WriteLog(Format('S:ws=%d', [WeaponSelect]), MSG_WARNING); g_Net_Client_Send(True, NET_CHAN_PLAYERPOS); + // force player weapon + //{if (gPlayer1.NetForceWeapFIdx < gTime) then} gPlayer1.SetWeapon(gPlayer1.NetForceWeap); + //kBytePrev := kByte; //kDirPrev := gPlayer1.Direction; end; @@ -2929,15 +2937,15 @@ var FileStream : TStream; fname: string; begin - e_WriteLog(Format('NETWORK: looking for file "%s"', [FileName]), MSG_NOTIFY); + e_WriteLog(Format('NETWORK: looking for file "%s"', [FileName]), TMsgType.Notify); fname := findDiskWad(FileName); if length(fname) = 0 then begin - e_WriteLog(Format('NETWORK: file "%s" not found!', [FileName]), MSG_FATALERROR); + e_WriteLog(Format('NETWORK: file "%s" not found!', [FileName]), TMsgType.Fatal); SetLength(Result, 0); exit; end; - e_WriteLog(Format('NETWORK: found file "%s"', [fname]), MSG_NOTIFY); + e_WriteLog(Format('NETWORK: found file "%s"', [fname]), TMsgType.Notify); Result := nil; FileStream := openDiskFileRO(fname); try @@ -3076,10 +3084,10 @@ var mapDataMsg: TMapDataMsg; begin e_WriteLog('NET: Received map request from ' + - DecodeIPV4(C.Peer.address.host), MSG_NOTIFY); + DecodeIPV4(C^.Peer.address.host), TMsgType.Notify); mapDataMsg := CreateMapDataMsg(MapsDir + gGameSettings.WAD, gExternalResources); - peer := NetClients[C.ID].Peer; + peer := NetClients[C^.ID].Peer; MapDataMsgToBytes(payload, mapDataMsg); g_Net_SendData(payload, peer, True, NET_CHAN_DOWNLOAD); @@ -3098,15 +3106,15 @@ var begin FileName := ExtractFileName(M.ReadString()); e_WriteLog('NET: Received res request: ' + FileName + - ' from ' + DecodeIPV4(C.Peer.address.host), MSG_NOTIFY); + ' from ' + DecodeIPV4(C^.Peer.address.host), TMsgType.Notify); if not IsValidFilePath(FileName) then begin - e_WriteLog('Invalid filename: ' + FileName, MSG_WARNING); + e_WriteLog('Invalid filename: ' + FileName, TMsgType.Warning); exit; end; - peer := NetClients[C.ID].Peer; + peer := NetClients[C^.ID].Peer; if gExternalResources.IndexOf(FileName) > -1 then begin