From ff04f6a5fc5200dfe2d6e951f774b50f64dc7077 Mon Sep 17 00:00:00 2001 From: Ketmar Dark Date: Mon, 11 Sep 2017 22:30:44 +0300 Subject: [PATCH] render monster drop after monsters, so monster corpses will not obscure ammo clips, for example --- src/game/g_game.pas | 1 + src/game/g_items.pas | 70 ++++++++++++++++++++++++++++++----------- src/game/g_monsters.pas | 3 +- src/game/g_netmsg.pas | 8 +++-- 4 files changed, 61 insertions(+), 21 deletions(-) diff --git a/src/game/g_game.pas b/src/game/g_game.pas index d1ffd7a..89d46d5 100644 --- a/src/game/g_game.pas +++ b/src/game/g_game.pas @@ -2939,6 +2939,7 @@ begin drawOther('corpses', @g_Player_DrawCorpses); drawPanelType('*wall', PANEL_WALL, g_rlayer_wall); drawOther('monsters', @g_Monsters_Draw); + drawOther('itemdrop', @g_Items_DrawDrop); drawPanelType('*door', PANEL_CLOSEDOOR, g_rlayer_door); drawOther('gfx', @g_GFX_Draw); drawOther('flags', @g_Map_DrawFlags); diff --git a/src/game/g_items.pas b/src/game/g_items.pas index 6365d7b..ef2e925 100644 --- a/src/game/g_items.pas +++ b/src/game/g_items.pas @@ -30,16 +30,17 @@ Type arrIdx: Integer; // in ggItems public - ItemType: Byte; - Respawnable: Boolean; - InitX, InitY: Integer; - RespawnTime: Word; - alive: Boolean; - Fall: Boolean; - QuietRespawn: Boolean; - SpawnTrigger: Integer; - Obj: TObj; - Animation: TAnimation; + ItemType: Byte; + Respawnable: Boolean; + InitX, InitY: Integer; + RespawnTime: Word; + alive: Boolean; + Fall: Boolean; + QuietRespawn: Boolean; + SpawnTrigger: Integer; + Obj: TObj; + Animation: TAnimation; + dropped: Boolean; // dropped from the monster? drops should be rendered after corpses, so zombie corpse will not obscure ammo container, for example procedure positionChanged (); //WARNING! call this after monster position was changed, or coldet will not work right! @@ -52,8 +53,10 @@ procedure g_Items_Init(); procedure g_Items_Free(); function g_Items_Create(X, Y: Integer; ItemType: Byte; Fall, Respawnable: Boolean; AdjCoord: Boolean = False; ForcedID: Integer = -1): DWORD; +procedure g_Items_SetDrop (ID: DWORD); procedure g_Items_Update(); procedure g_Items_Draw(); +procedure g_Items_DrawDrop(); procedure g_Items_Pick(ID: DWORD); procedure g_Items_Remove(ID: DWORD); procedure g_Items_SaveState(var Mem: TBinMemoryWriter); @@ -458,6 +461,7 @@ begin it.Fall := Fall; it.alive := True; it.QuietRespawn := False; + it.dropped := false; g_Obj_Init(@it.Obj); it.Obj.X := X; @@ -618,17 +622,20 @@ begin end; -procedure g_Items_Draw (); +procedure itemsDrawInternal (dropflag: Boolean); var i: Integer; + it: PItem; begin if (ggItems = nil) then exit; for i := 0 to High(ggItems) do begin - if not ggItems[i].alive then continue; + it := @ggItems[i]; + if not it.alive then continue; + if (it.dropped <> dropflag) then continue; - with ggItems[i] do + with it^ do begin if g_Collide(Obj.X, Obj.Y, Obj.Rect.Width, Obj.Rect.Height, sX, sY, sWidth, sHeight) then begin @@ -655,10 +662,33 @@ begin end; +procedure g_Items_Draw (); +begin + itemsDrawInternal(false); +end; + +procedure g_Items_DrawDrop (); +begin + itemsDrawInternal(true); +end; + + +procedure g_Items_SetDrop (ID: DWORD); +begin + if (ID < Length(ggItems)) then + begin + ggItems[ID].dropped := true; + end; +end; + + procedure g_Items_Pick (ID: DWORD); begin - ggItems[ID].alive := false; - ggItems[ID].RespawnTime := ITEM_RESPAWNTIME; + if (ID < Length(ggItems)) then + begin + ggItems[ID].alive := false; + ggItems[ID].RespawnTime := ITEM_RESPAWNTIME; + end; end; @@ -684,6 +714,7 @@ procedure g_Items_SaveState (var Mem: TBinMemoryWriter); var count, i: Integer; sig: DWORD; + tt: Byte; begin // Ñ÷èòàåì êîëè÷åñòâî ñóùåñòâóþùèõ ïðåäìåòîâ count := 0; @@ -707,7 +738,9 @@ begin sig := ITEM_SIGNATURE; // 'ITEM' Mem.WriteDWORD(sig); // Òèï ïðåäìåòà - Mem.WriteByte(ggItems[i].ItemType); + tt := ggItems[i].ItemType; + if ggItems[i].dropped then tt := tt or $80; + Mem.WriteByte(tt); // Åñòü ëè ðåñïàóí Mem.WriteBoolean(ggItems[i].Respawnable); // Êîîðäèíàòû ðåñïóíà @@ -749,9 +782,10 @@ begin Mem.ReadDWORD(sig); if (sig <> ITEM_SIGNATURE) then raise EBinSizeError.Create('g_Items_LoadState: Wrong Item Signature'); // 'ITEM' // Òèï ïðåäìåòà - Mem.ReadByte(b); + Mem.ReadByte(b); // bit7=1: monster drop // Ñîçäàåì ïðåäìåò - i := g_Items_Create(0, 0, b, False, False); + i := g_Items_Create(0, 0, b and $7F, False, False); + if ((b and $80) <> 0) then g_Items_SetDrop(i); // Åñòü ëè ðåñïàóí Mem.ReadBoolean(ggItems[i].Respawnable); // Êîîðäèíàòû ðåñïóíà diff --git a/src/game/g_monsters.pas b/src/game/g_monsters.pas index 8629bc9..1b39ee8 100644 --- a/src/game/g_monsters.pas +++ b/src/game/g_monsters.pas @@ -2077,9 +2077,10 @@ begin it := g_Items_Create(FObj.X + (FObj.Rect.Width div 2), FObj.Y + (FObj.Rect.Height div 2), c, True, False); + g_Items_SetDrop(it); // mark it as monster drop g_Obj_Push(g_Items_ObjByIdx(it), (FObj.Vel.X div 2)-3+Random(7), (FObj.Vel.Y div 2)-Random(4)); - positionChanged(); // this updates spatial accelerators + //positionChanged(); // this updates spatial accelerators if g_Game_IsServer and g_Game_IsNet then MH_SEND_ItemSpawn(True, it); end; diff --git a/src/game/g_netmsg.pas b/src/game/g_netmsg.pas index 3a2304b..98ef654 100644 --- a/src/game/g_netmsg.pas +++ b/src/game/g_netmsg.pas @@ -1148,13 +1148,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); @@ -2306,7 +2309,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; -- 2.29.2