From d3ce22f70dfe266676a3fb95d5193238ff5b9e72 Mon Sep 17 00:00:00 2001 From: Ketmar Dark Date: Sat, 2 Sep 2017 02:57:34 +0300 Subject: [PATCH] migrating from PanelIDs to panel GUIDs; part one --- src/game/g_holmes.pas | 27 +- src/game/g_map.pas | 247 ++++++++----- src/game/g_net.pas | 2 +- src/game/g_netmsg.pas | 121 ++++--- src/game/g_panel.pas | 47 ++- src/game/g_triggers.pas | 729 +++++++++++++++++++++------------------ src/mapdef/mapdef.txt | 4 +- src/shared/MAPDEF.pas | 11 + src/shared/hashtable.pas | 7 +- src/shared/mapdef.inc | 5 + 10 files changed, 691 insertions(+), 509 deletions(-) diff --git a/src/game/g_holmes.pas b/src/game/g_holmes.pas index 23c4b13..27fd169 100644 --- a/src/game/g_holmes.pas +++ b/src/game/g_holmes.pas @@ -1041,12 +1041,12 @@ procedure plrDebugDraw (); procedure drawTrigger (var trig: TTrigger); - procedure drawPanelDest (var parr: TPanelArray; idx: Integer); + procedure drawPanelDest (pguid: Integer); var pan: TPanel; begin - if (idx < 0) or (idx >= Length(parr)) then exit; - pan := parr[idx]; + pan := g_Map_PanelByGUID(pguid); + if (pan = nil) then exit; drawLine( trig.trigCenter.x, trig.trigCenter.y, pan.x+pan.width div 2, pan.y+pan.height div 2, @@ -1065,20 +1065,21 @@ procedure plrDebugDraw (); tx := trig.x+(trig.width-Length(trig.mapId)*6) div 2; darkenRect(tx-2, trig.y-20, Length(trig.mapId)*6+4, 10, 64); drawText6(tx, trig.y-19, trig.mapId, 255, 255, 0); + drawPanelDest(trig.trigPanelGUID); case trig.TriggerType of TRIGGER_NONE: begin end; TRIGGER_EXIT: begin end; TRIGGER_TELEPORT: begin end; - TRIGGER_OPENDOOR: begin drawPanelDest(gWalls, trig.trigPanelId); end; - TRIGGER_CLOSEDOOR: begin drawPanelDest(gWalls, trig.trigPanelId); end; - TRIGGER_DOOR: begin drawPanelDest(gWalls, trig.trigPanelId); end; - TRIGGER_DOOR5: begin drawPanelDest(gWalls, trig.trigPanelId); end; - TRIGGER_CLOSETRAP: begin drawPanelDest(gWalls, trig.trigPanelId); end; - TRIGGER_TRAP: begin drawPanelDest(gWalls, trig.trigPanelId); end; + TRIGGER_OPENDOOR: begin end; + TRIGGER_CLOSEDOOR: begin end; + TRIGGER_DOOR: begin end; + TRIGGER_DOOR5: begin end; + TRIGGER_CLOSETRAP: begin end; + TRIGGER_TRAP: begin end; TRIGGER_SECRET: begin end; - TRIGGER_LIFTUP: begin drawPanelDest(gLifts, trig.trigPanelId); end; - TRIGGER_LIFTDOWN: begin drawPanelDest(gLifts, trig.trigPanelId); end; - TRIGGER_LIFT: begin drawPanelDest(gLifts, trig.trigPanelId); end; + TRIGGER_LIFTUP: begin end; + TRIGGER_LIFTDOWN: begin end; + TRIGGER_LIFT: begin end; TRIGGER_TEXTURE: begin end; TRIGGER_ON, TRIGGER_OFF, TRIGGER_ONOFF, TRIGGER_PRESS: begin @@ -1374,7 +1375,7 @@ procedure cbAtcurToggleWalls (); begin result := false; // don't stop //e_WriteLog(Format('wall #%d(%d); enabled=%d (%d); (%d,%d)-(%d,%d)', [pan.arrIdx, pan.proxyId, Integer(pan.Enabled), Integer(mapGrid.proxyEnabled[pan.proxyId]), pan.X, pan.Y, pan.Width, pan.Height]), MSG_NOTIFY); - if pan.Enabled then g_Map_DisableWall(pan.arrIdx) else g_Map_EnableWall(pan.arrIdx); + if pan.Enabled then g_Map_DisableWallGUID(pan.guid) else g_Map_EnableWallGUID(pan.guid); end; begin //e_WriteLog('=== TOGGLE WALL ===', MSG_NOTIFY); diff --git a/src/game/g_map.pas b/src/game/g_map.pas index ff6e757..00f39a1 100644 --- a/src/game/g_map.pas +++ b/src/game/g_map.pas @@ -63,6 +63,8 @@ function g_Map_Exist(Res: String): Boolean; procedure g_Map_Free(freeTextures: Boolean=true); procedure g_Map_Update(); +function g_Map_PanelByGUID (aguid: Integer): TPanel; inline; + procedure g_Map_DrawPanels (PanelType: Word); // unaccelerated procedure g_Map_CollectDrawPanels (x0, y0, wdt, hgt: Integer); @@ -70,10 +72,18 @@ procedure g_Map_DrawBack(dx, dy: Integer); function g_Map_CollidePanel(X, Y: Integer; Width, Height: Word; PanelType: Word; b1x3: Boolean=false): Boolean; function g_Map_CollideLiquid_Texture(X, Y: Integer; Width, Height: Word): DWORD; -procedure g_Map_EnableWall(ID: DWORD); -procedure g_Map_DisableWall(ID: DWORD); -procedure g_Map_SwitchTexture(PanelType: Word; ID: DWORD; AnimLoop: Byte = 0); -procedure g_Map_SetLift(ID: DWORD; t: Integer); + +procedure g_Map_EnableWallGUID (pguid: Integer); +procedure g_Map_DisableWallGUID (pguid: Integer); +procedure g_Map_SetLiftGUID (pguid: Integer; t: Integer); + +// HACK!!! +procedure g_Map_EnableWall_XXX (ID: DWORD); +procedure g_Map_DisableWall_XXX (ID: DWORD); +procedure g_Map_SetLift_XXX (ID: DWORD; t: Integer); + +procedure g_Map_SwitchTextureGUID (PanelType: Word; pguid: Integer; AnimLoop: Byte = 0); + procedure g_Map_ReAdd_DieTriggers(); function g_Map_IsSpecialTexture(Texture: String): Boolean; @@ -161,17 +171,17 @@ const PANEL_FORE *) // sorted by draw priority - GridTagBack = 1 shl 0; - GridTagStep = 1 shl 1; - GridTagWall = 1 shl 2; - GridTagDoor = 1 shl 3; - GridTagAcid1 = 1 shl 4; - GridTagAcid2 = 1 shl 5; - GridTagWater = 1 shl 6; - GridTagFore = 1 shl 7; + GridTagBack = 1 shl 0; // gRenderBackgrounds + GridTagStep = 1 shl 1; // gSteps + GridTagWall = 1 shl 2; // gWalls + GridTagDoor = 1 shl 3; // gWalls + GridTagAcid1 = 1 shl 4; // gAcid1 + GridTagAcid2 = 1 shl 5; // gAcid2 + GridTagWater = 1 shl 6; // gWater + GridTagFore = 1 shl 7; // gRenderForegrounds // the following are invisible - GridTagLift = 1 shl 8; - GridTagBlockMon = 1 shl 9; + GridTagLift = 1 shl 8; // gLifts + GridTagBlockMon = 1 shl 9; // gBlockMon GridDrawableMask = (GridTagBack or GridTagStep or GridTagWall or GridTagDoor or GridTagAcid1 or GridTagAcid2 or GridTagWater or GridTagFore); @@ -231,6 +241,32 @@ const FLAG_SIGNATURE = $47414C46; // 'FLAG' +{ +type + THashIntPanel = specialize THashBase; + +function hashNewIntPanel (): THashIntPanel; +begin + result := THashIntPanel.Create(hiihash, hiiequ); +end; +} + + +var + //panByGUID: THashIntPanel = nil; + panByGUID: array of TPanel = nil; + //panLastGUID: Integer = 0; + + +// ////////////////////////////////////////////////////////////////////////// // +function g_Map_PanelByGUID (aguid: Integer): TPanel; inline; +begin + //if (panByGUID = nil) or (not panByGUID.get(aguid, result)) then result := nil; + if (aguid >= 0) and (aguid < Length(panByGUID)) then result := panByGUID[aguid] else result := nil; +end; + + +// ////////////////////////////////////////////////////////////////////////// // var dfmapdef: TDynMapDef = nil; @@ -284,6 +320,7 @@ begin end; +// ////////////////////////////////////////////////////////////////////////// // function g_Map_ParseMap (data: Pointer; dataLen: Integer): TDynRecord; var wst: TSFSMemoryChunkStream = nil; @@ -331,6 +368,7 @@ begin end; +// ////////////////////////////////////////////////////////////////////////// // var NNF_PureName: String; // Èìÿ òåêñòóðû áåç öèôð â êîíöå NNF_FirstNum: Integer; // ×èñëî ó íà÷àëüíîé òåêñòóðû @@ -395,6 +433,7 @@ begin end; +// ////////////////////////////////////////////////////////////////////////// // function panelTypeToTag (panelType: Word): Integer; begin case panelType of @@ -430,19 +469,12 @@ begin end; -type - TPanelID = record - PWhere: ^TPanelArray; - PArrID: Integer; - end; - var - PanelById: array of TPanelID; - Textures: TLevelTextureArray = nil; + Textures: TLevelTextureArray = nil; TextNameHash: THashStrInt = nil; // key: texture name; value: index in `Textures` BadTextNameHash: THashStrInt = nil; // set; so we won't spam with non-existing texture messages - RespawnPoints: Array of TRespawnPoint; - FlagPoints: Array [FLAG_RED..FLAG_BLUE] of PFlagPoint; + RespawnPoints: array of TRespawnPoint; + FlagPoints: array[FLAG_RED..FLAG_BLUE] of PFlagPoint; //DOMFlagPoints: Array of TFlagPoint; @@ -742,48 +774,41 @@ function CreatePanel(PanelRec: TDynRecord; AddTextures: TAddTextureArray; var len: Integer; panels: ^TPanelArray; + pan: TPanel; + pguid: Integer; begin Result := -1; case PanelRec.PanelType of - PANEL_WALL, PANEL_OPENDOOR, PANEL_CLOSEDOOR: - panels := @gWalls; - PANEL_BACK: - panels := @gRenderBackgrounds; - PANEL_FORE: - panels := @gRenderForegrounds; - PANEL_WATER: - panels := @gWater; - PANEL_ACID1: - panels := @gAcid1; - PANEL_ACID2: - panels := @gAcid2; - PANEL_STEP: - panels := @gSteps; - PANEL_LIFTUP, PANEL_LIFTDOWN, PANEL_LIFTLEFT, PANEL_LIFTRIGHT: - panels := @gLifts; - PANEL_BLOCKMON: - panels := @gBlockMon; - else - Exit; + PANEL_WALL, PANEL_OPENDOOR, PANEL_CLOSEDOOR: panels := @gWalls; + PANEL_BACK: panels := @gRenderBackgrounds; + PANEL_FORE: panels := @gRenderForegrounds; + PANEL_WATER: panels := @gWater; + PANEL_ACID1: panels := @gAcid1; + PANEL_ACID2: panels := @gAcid2; + PANEL_STEP: panels := @gSteps; + PANEL_LIFTUP, PANEL_LIFTDOWN, PANEL_LIFTLEFT, PANEL_LIFTRIGHT: panels := @gLifts; + PANEL_BLOCKMON: panels := @gBlockMon; + else exit; end; len := Length(panels^); - SetLength(panels^, len + 1); - - panels^[len] := TPanel.Create(PanelRec, AddTextures, CurTex, Textures); - panels^[len].arrIdx := len; - panels^[len].proxyId := -1; - panels^[len].tag := panelTypeToTag(PanelRec.PanelType); - if sav then - panels^[len].SaveIt := True; - - Result := len; - - len := Length(PanelByID); - SetLength(PanelByID, len + 1); - PanelByID[len].PWhere := panels; - PanelByID[len].PArrID := Result; + SetLength(panels^, len+1); + + //Inc(panLastGUID); + pguid := Length(panByGUID); + SetLength(panByGUID, pguid+1); //FIXME! + pan := TPanel.Create(PanelRec, AddTextures, CurTex, Textures, pguid); + panels^[len] := pan; + pan.arrIdx := len; + pan.proxyId := -1; + pan.tag := panelTypeToTag(PanelRec.PanelType); + if sav then pan.SaveIt := True; + + PanelRec.user['panel_guid'] := pan.guid; + //panByGUID.put(pan.guid, pan); + + result := len; end; @@ -1265,13 +1290,13 @@ begin Height := Trigger.Height; Enabled := Trigger.Enabled; //TexturePanel := Trigger.TexturePanel; - TexturePanel := atpanid; + TexturePanelGUID := atpanid; TexturePanelType := fTexturePanel1Type; ShotPanelType := fTexturePanel2Type; TriggerType := Trigger.TriggerType; ActivateType := Trigger.ActivateType; Keys := Trigger.Keys; - trigPanelId := atrigpanid; + trigPanelGUID := atrigpanid; //trigShotPanelId := ashotpanid; //Data.Default := Trigger.DATA; if (Trigger.trigRec = nil) then @@ -1537,11 +1562,13 @@ type LiftPanelIdx: Integer; DoorPanelIdx: Integer; ShotPanelIdx: Integer; + MPlatPanelIdx: Integer; trigrec: TDynRecord; texPan: TDynRecord; liftPan: TDynRecord; doorPan: TDynRecord; shotPan: TDynRecord; + mplatPan: TDynRecord; end; var WAD: TWADFile; @@ -1574,6 +1601,11 @@ begin gCurrentMap.Free(); gCurrentMap := nil; + //panByGUID.Free(); + //panByGUID := hashNewIntPanel(); + //panLastGUID := 0; + panByGUID := nil; + Result := False; gMapInfo.Map := Res; TriggersTable := nil; @@ -1739,10 +1771,12 @@ begin pttit.liftPan := nil; pttit.doorPan := nil; pttit.shotPan := nil; + pttit.mplatPan := nil; pttit.texPanIdx := -1; pttit.LiftPanelIdx := -1; pttit.DoorPanelIdx := -1; pttit.ShotPanelIdx := -1; + pttit.MPlatPanelIdx := -1; // Ëèôòû if rec.TriggerType in [TRIGGER_LIFTUP, TRIGGER_LIFTDOWN, TRIGGER_LIFT] then begin @@ -1758,11 +1792,17 @@ begin begin pttit.shotPan := mapReader.panel[rec.trigRec.tgShotPanelID]; end; + // + if rec.TriggerType in [TRIGGER_PRESS, TRIGGER_ON, TRIGGER_OFF, TRIGGER_ONOFF] then + begin + pttit.mplatPan := mapReader.panel[rec.trigRec.tgPanelID]; + end; if (pttit.texPan <> nil) then pttit.texPan.userPanelTrigRef := true; if (pttit.liftPan <> nil) then pttit.liftPan.userPanelTrigRef := true; if (pttit.doorPan <> nil) then pttit.doorPan.userPanelTrigRef := true; if (pttit.shotPan <> nil) then pttit.shotPan.userPanelTrigRef := true; + if (pttit.mplatPan <> nil) then pttit.mplatPan.userPanelTrigRef := true; g_Game_StepLoading(); end; @@ -1970,6 +2010,7 @@ begin if (TriggersTable[b].liftPan <> nil) then TriggersTable[b].LiftPanelIdx := TriggersTable[b].liftPan.userPanelId; if (TriggersTable[b].doorPan <> nil) then TriggersTable[b].DoorPanelIdx := TriggersTable[b].doorPan.userPanelId; if (TriggersTable[b].shotPan <> nil) then TriggersTable[b].ShotPanelIdx := TriggersTable[b].shotPan.userPanelId; + if (TriggersTable[b].mplatPan <> nil) then TriggersTable[b].MPlatPanelIdx := TriggersTable[b].mplatPan.userPanelId; end; // create map grid, init other grids (for monsters, for example) @@ -1992,6 +2033,7 @@ begin if (TriggersTable[trignum].LiftPanelIdx <> -1) then tgpid := TriggersTable[trignum].LiftPanelIdx else if (TriggersTable[trignum].DoorPanelIdx <> -1) then tgpid := TriggersTable[trignum].DoorPanelIdx else if (TriggersTable[trignum].ShotPanelIdx <> -1) then tgpid := TriggersTable[trignum].ShotPanelIdx + else if (TriggersTable[trignum].MPlatPanelIdx <> -1) then tgpid := TriggersTable[trignum].MPlatPanelIdx else tgpid := -1; //e_LogWritefln('creating trigger #%s; texpantype=%s; shotpantype=%s (%d,%d)', [trignum, b, c, TriggersTable[trignum].texPanIdx, TriggersTable[trignum].ShotPanelIdx]); CreateTrigger(trignum, rec, TriggersTable[trignum].texPanIdx, tgpid, Word(b), Word(c)); @@ -2321,6 +2363,11 @@ begin BadTextNameHash := nil; end; + //panByGUID.Free(); + //panByGUID := nil; + //panLastGUID := 0; + panByGUID := nil; + FreePanelArray(gWalls); FreePanelArray(gRenderBackgrounds); FreePanelArray(gRenderForegrounds); @@ -2352,8 +2399,6 @@ begin gDoorMap := nil; gLiftMap := nil; - - PanelByID := nil; end; procedure g_Map_Update(); @@ -2798,11 +2843,18 @@ begin end; -procedure g_Map_EnableWall(ID: DWORD); +procedure g_Map_EnableWall_XXX (ID: DWORD); begin if (ID < Length(gWalls)) then g_Map_EnableWallGUID(gWalls[ID].guid); end; +procedure g_Map_DisableWall_XXX (ID: DWORD); begin if (ID < Length(gWalls)) then g_Map_DisableWallGUID(gWalls[ID].guid); end; +procedure g_Map_SetLift_XXX (ID: DWORD; t: Integer); begin if (ID < Length(gLifts)) then g_Map_SetLiftGUID(gLifts[ID].guid, t); end; + + +procedure g_Map_EnableWallGUID (pguid: Integer); var pan: TPanel; begin - pan := gWalls[ID]; + //pan := gWalls[ID]; + pan := g_Map_PanelByGUID(pguid); + if (pan = nil) then exit; pan.Enabled := True; g_Mark(pan.X, pan.Y, pan.Width, pan.Height, MARK_DOOR, true); @@ -2810,65 +2862,71 @@ begin //if (pan.proxyId >= 0) then mapGrid.proxyEnabled[pan.proxyId] := true //else pan.proxyId := mapGrid.insertBody(pan, pan.X, pan.Y, pan.Width, pan.Height, GridTagDoor); - if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(gWalls[ID].PanelType, ID); + if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState({gWalls[ID]}pan.PanelType, pguid); {$IFDEF MAP_DEBUG_ENABLED_FLAG} //e_WriteLog(Format('ENABLE: wall #%d(%d) enabled (%d) (%d,%d)-(%d,%d)', [Integer(ID), Integer(pan.proxyId), Integer(mapGrid.proxyEnabled[pan.proxyId]), pan.x, pan.y, pan.width, pan.height]), MSG_NOTIFY); {$ENDIF} end; -procedure g_Map_DisableWall(ID: DWORD); + +procedure g_Map_DisableWallGUID (pguid: Integer); var pan: TPanel; begin - pan := gWalls[ID]; + //pan := gWalls[ID]; + pan := g_Map_PanelByGUID(pguid); + if (pan = nil) then exit; pan.Enabled := False; g_Mark(pan.X, pan.Y, pan.Width, pan.Height, MARK_DOOR, false); mapGrid.proxyEnabled[pan.proxyId] := false; //if (pan.proxyId >= 0) then begin mapGrid.removeBody(pan.proxyId); pan.proxyId := -1; end; - if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(pan.PanelType, ID); + if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(pan.PanelType, pguid); {$IFDEF MAP_DEBUG_ENABLED_FLAG} //e_WriteLog(Format('DISABLE: wall #%d(%d) disabled (%d) (%d,%d)-(%d,%d)', [Integer(ID), Integer(pan.proxyId), Integer(mapGrid.proxyEnabled[pan.proxyId]), pan.x, pan.y, pan.width, pan.height]), MSG_NOTIFY); {$ENDIF} end; -procedure g_Map_SwitchTexture(PanelType: Word; ID: DWORD; AnimLoop: Byte = 0); + +procedure g_Map_SwitchTextureGUID (PanelType: Word; pguid: Integer; AnimLoop: Byte = 0); var tp: TPanel; begin + tp := g_Map_PanelByGUID(pguid); + if (tp = nil) then exit; + { case PanelType of - PANEL_WALL, PANEL_OPENDOOR, PANEL_CLOSEDOOR: - tp := gWalls[ID]; - PANEL_FORE: - tp := gRenderForegrounds[ID]; - PANEL_BACK: - tp := gRenderBackgrounds[ID]; - PANEL_WATER: - tp := gWater[ID]; - PANEL_ACID1: - tp := gAcid1[ID]; - PANEL_ACID2: - tp := gAcid2[ID]; - PANEL_STEP: - tp := gSteps[ID]; - else - Exit; + PANEL_WALL, PANEL_OPENDOOR, PANEL_CLOSEDOOR: tp := gWalls[ID]; + PANEL_FORE: tp := gRenderForegrounds[ID]; + PANEL_BACK: tp := gRenderBackgrounds[ID]; + PANEL_WATER: tp := gWater[ID]; + PANEL_ACID1: tp := gAcid1[ID]; + PANEL_ACID2: tp := gAcid2[ID]; + PANEL_STEP: tp := gSteps[ID]; + else exit; end; + } tp.NextTexture(AnimLoop); - if g_Game_IsServer and g_Game_IsNet then - MH_SEND_PanelTexture(PanelType, ID, AnimLoop); + if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelTexture(PanelType, pguid, AnimLoop); end; -procedure g_Map_SetLift(ID: DWORD; t: Integer); + +procedure g_Map_SetLiftGUID (pguid: Integer; t: Integer); +var + pan: TPanel; begin - if gLifts[ID].LiftType = t then - Exit; + //pan := gLifts[ID]; + pan := g_Map_PanelByGUID(pguid); + if (pan = nil) then exit; + if not pan.isGLift then exit; - with gLifts[ID] do + if ({gLifts[ID]}pan.LiftType = t) then exit; //!FIXME!TRIGANY! + + with {gLifts[ID]} pan do begin LiftType := t; @@ -2882,11 +2940,12 @@ begin 3: g_Mark(X, Y, Width, Height, MARK_LIFTRIGHT); end; - if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(PanelType, ID); + if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(PanelType, pguid); end; end; -function g_Map_GetPoint(PointType: Byte; var RespawnPoint: TRespawnPoint): Boolean; + +function g_Map_GetPoint (PointType: Byte; var RespawnPoint: TRespawnPoint): Boolean; var a: Integer; PointsArray: Array of TRespawnPoint; diff --git a/src/game/g_net.pas b/src/game/g_net.pas index b6a60c0..16e6bb5 100644 --- a/src/game/g_net.pas +++ b/src/game/g_net.pas @@ -22,7 +22,7 @@ uses e_log, e_msg, ENet, Classes; const - NET_PROTOCOL_VER = 171; + NET_PROTOCOL_VER = 172; NET_MAXCLIENTS = 24; NET_CHANS = 11; diff --git a/src/game/g_netmsg.pas b/src/game/g_netmsg.pas index f77bdca..53ab6a5 100644 --- a/src/game/g_netmsg.pas +++ b/src/game/g_netmsg.pas @@ -52,8 +52,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 +168,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(PType: Word; PGUID: Integer; AnimLoop: Byte; ID: Integer = NET_EVERYONE); +procedure MH_SEND_PanelState(PType: Word; 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); @@ -1217,10 +1217,13 @@ end; // PANEL -procedure MH_SEND_PanelTexture(PType: Word; PID: LongWord; AnimLoop: Byte; ID: Integer = NET_EVERYONE); +procedure MH_SEND_PanelTexture(PType: Word; PGUID: Integer; AnimLoop: Byte; ID: Integer = NET_EVERYONE); var TP: TPanel; begin + TP := g_Map_PanelByGUID(PGUID); + if (TP = nil) then exit; + { case PType of PANEL_WALL, PANEL_OPENDOOR, PANEL_CLOSEDOOR: TP := gWalls[PID]; @@ -1239,12 +1242,13 @@ begin else Exit; end; + } 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,32 +1258,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(PType: Word; PGUID: Integer; ID: Integer = NET_EVERYONE); var TP: TPanel; begin + TP := g_Map_PanelByGUID(PGUID); + if (TP = nil) then exit; case PType of - PANEL_WALL, PANEL_OPENDOOR, PANEL_CLOSEDOOR: - TP := gWalls[PID]; - PANEL_LIFTUP, PANEL_LIFTDOWN, PANEL_LIFTLEFT, PANEL_LIFTRIGHT: - TP := gLifts[PID]; + { + 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 := gRenderBackgrounds[PID]; TP.Moved := True; end; PANEL_FORE: begin - TP := gRenderForegrounds[PID]; + //TP := gRenderForegrounds[PID]; TP.Moved := True; end; + { else Exit; + } end; 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); @@ -2403,67 +2411,62 @@ end; procedure MC_RECV_PanelTexture(var M: TMsg); var TP: TPanel; - PType: Word; - ID: LongWord; + //PType: Word; + PGUID: Integer; Tex, Fr: Integer; Loop, Cnt: Byte; begin if not gGameOn then Exit; - PType := M.ReadWord(); - ID := M.ReadLongWord(); + {PType :=} M.ReadWord(); + PGUID := Integer(M.ReadLongWord()); Tex := M.ReadLongInt(); Fr := M.ReadLongInt(); Cnt := M.ReadByte(); Loop := M.ReadByte(); - TP := nil; + TP := g_Map_PanelByGUID(PGUID); + { 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; + 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; end; + } if TP <> nil then + begin if Loop = 0 then - begin // switch texture + begin + // switch texture TP.SetTexture(Tex, Loop); TP.SetFrame(Fr, Cnt); - end else // looped or non-looped animation + end + else + begin + // looped or non-looped animation TP.NextTexture(Loop); + end; + end; end; procedure MC_RECV_PanelState(var M: TMsg); var - ID: LongWord; + PGUID: Integer; E: Boolean; Lift: Byte; PType: Word; X, Y: Integer; + TP: TPanel; 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(); @@ -2471,25 +2474,33 @@ begin case PType of PANEL_WALL, PANEL_OPENDOOR, PANEL_CLOSEDOOR: - if E then - g_Map_EnableWall(ID) - else - g_Map_DisableWall(ID); + if E then g_Map_EnableWallGUID(PGUID) else g_Map_DisableWallGUID(PGUID); PANEL_LIFTUP, PANEL_LIFTDOWN, PANEL_LIFTLEFT, PANEL_LIFTRIGHT: - g_Map_SetLift(ID, Lift); + g_Map_SetLiftGUID(PGUID, Lift); - PANEL_BACK: + {PANEL_BACK, + PANEL_FORE:} + else begin - gRenderBackgrounds[ID].X := X; - gRenderBackgrounds[ID].Y := Y; + TP := g_Map_PanelByGUID(PGUID); + if (TP <> nil) then + begin + TP.X := X; + TP.Y := Y; + TP.positionChanged(); + end; + //gRenderBackgrounds[ID].X := X; + //gRenderBackgrounds[ID].Y := Y; end; + { PANEL_FORE: begin gRenderForegrounds[ID].X := X; gRenderForegrounds[ID].Y := Y; - end; + end; + } end; end; diff --git a/src/game/g_panel.pas b/src/game/g_panel.pas index f1aa007..3c95a56 100644 --- a/src/game/g_panel.pas +++ b/src/game/g_panel.pas @@ -31,6 +31,9 @@ type TPanel = Class (TObject) private + const + private + mGUID: Integer; // will be assigned in "g_map.pas" FTextureWidth: Word; FTextureHeight: Word; FAlpha: Byte; @@ -65,14 +68,17 @@ type FMoved: Boolean; FLiftType: Byte; FLastAnimLoop: Byte; + // sorry, there fields are public to allow setting 'em in g_map; this should be fixed later + // for now, PLEASE, don't modify 'em, or all hell will break loose arrIdx: Integer; // index in one of internal arrays; sorry - tag: Integer; // used in coldets and such; sorry + tag: Integer; // used in coldets and such; sorry; see g_map.GridTagXXX proxyId: Integer; // proxy id in map grid (DO NOT USE!) + mapId: AnsiString; // taken directly from map file; dunno why it is here constructor Create(PanelRec: TDynRecord; AddTextures: TAddTextureArray; CurTex: Integer; - var Textures: TLevelTextureArray); + var Textures: TLevelTextureArray; aguid: Integer); destructor Destroy(); override; procedure Draw(); @@ -87,10 +93,24 @@ type procedure SaveState(var Mem: TBinMemoryWriter); procedure LoadState(var Mem: TBinMemoryReader); + procedure positionChanged (); + + function isGBack (): Boolean; inline; // gRenderBackgrounds + function isGStep (): Boolean; inline; // gSteps + function isGWall (): Boolean; inline; // gWalls + function isGAcid1 (): Boolean; inline; // gAcid1 + function isGAcid2 (): Boolean; inline; // gAcid2 + function isGWater (): Boolean; inline; // gWater + function isGFore (): Boolean; inline; // gRenderForegrounds + function isGLift (): Boolean; inline; // gLifts + function isGBlockMon (): Boolean; inline; // gBlockMon + + public property visvalid: Boolean read getvisvalid; // panel is "visvalid" when it's width and height are positive published + property guid: Integer read mGUID; // will be assigned in "g_map.pas" property x0: Integer read FX; property y0: Integer read FY; property x1: Integer read getx1; // inclusive! @@ -131,7 +151,7 @@ const constructor TPanel.Create(PanelRec: TDynRecord; AddTextures: TAddTextureArray; CurTex: Integer; - var Textures: TLevelTextureArray); + var Textures: TLevelTextureArray; aguid: Integer); var i: Integer; begin @@ -146,6 +166,9 @@ begin LastAnimLoop := 0; Moved := False; + mapId := PanelRec.id; + mGUID := aguid; + mMovingSpeed := PanelRec.moveSpeed; mMovingStart := PanelRec.moveStart; mMovingEnd := PanelRec.moveEnd; @@ -295,6 +318,16 @@ function TPanel.getx1 (): Integer; inline; begin result := X+Width-1; end; function TPanel.gety1 (): Integer; inline; begin result := Y+Height-1; end; function TPanel.getvisvalid (): Boolean; inline; begin result := (Width > 0) and (Height > 0); end; +function TPanel.isGBack (): Boolean; inline; begin result := ((tag and GridTagBack) <> 0); end; +function TPanel.isGStep (): Boolean; inline; begin result := ((tag and GridTagStep) <> 0); end; +function TPanel.isGWall (): Boolean; inline; begin result := ((tag and (GridTagWall or GridTagDoor)) <> 0); end; +function TPanel.isGAcid1 (): Boolean; inline; begin result := ((tag and GridTagAcid1) <> 0); end; +function TPanel.isGAcid2 (): Boolean; inline; begin result := ((tag and GridTagAcid2) <> 0); end; +function TPanel.isGWater (): Boolean; inline; begin result := ((tag and GridTagWater) <> 0); end; +function TPanel.isGFore (): Boolean; inline; begin result := ((tag and GridTagFore) <> 0); end; +function TPanel.isGLift (): Boolean; inline; begin result := ((tag and GridTagLift) <> 0); end; +function TPanel.isGBlockMon (): Boolean; inline; begin result := ((tag and GridTagBlockMon) <> 0); end; + procedure TPanel.Draw(); var xx, yy: Integer; @@ -406,6 +439,12 @@ begin end; +procedure TPanel.positionChanged (); +begin + if (proxyId >= 0) then mapGrid.moveBody(proxyId, X, Y); +end; + + var monMoveList: array of TMonster = nil; monMoveListUsed: Integer = 0; @@ -518,7 +557,7 @@ begin Y := ny; g_Mark(nx, ny, Width, Height, MARK_WALL); // fix grid - if (proxyId >= 0) then mapGrid.moveBody(proxyId, nx, ny); + positionChanged(); // notify moved monsters about their movement for f := 0 to monMoveListUsed-1 do monMoveList[f].positionChanged(); end; diff --git a/src/game/g_triggers.pas b/src/game/g_triggers.pas index 6698288..437d1f6 100644 --- a/src/game/g_triggers.pas +++ b/src/game/g_triggers.pas @@ -38,7 +38,7 @@ type Enabled: Boolean; ActivateType: Byte; Keys: Byte; - TexturePanel: Integer; + TexturePanelGUID: Integer; TexturePanelType: Word; TimeOut: Word; @@ -64,8 +64,7 @@ type mapId: AnsiString; // trigger id, from map mapIndex: Integer; // index in fields['trigger'], used in save/load - //trigShotPanelId: Integer; - trigPanelId: Integer; + trigPanelGUID: Integer; //TrigData: TTriggerData; trigData: TDynRecord; // triggerdata; owned by trigger @@ -74,7 +73,7 @@ type function trigCenter (): TDFPoint; inline; public - property trigShotPanelId: Integer read trigPanelId write trigPanelId; + property trigShotPanelGUID: Integer read trigPanelGUID write trigPanelGUID; end; function g_Triggers_Create(Trigger: TTrigger; forceInternalIndex: Integer=-1): DWORD; @@ -92,16 +91,18 @@ procedure g_Triggers_LoadState(var Mem: TBinMemoryReader); function tr_Message(MKind: Integer; MText: string; MSendTo: Integer; MTime: Integer; ActivateUID: Integer): Boolean; -function tr_CloseDoor(PanelID: Integer; NoSound: Boolean; d2d: Boolean): Boolean; -function tr_OpenDoor(PanelID: Integer; NoSound: Boolean; d2d: Boolean): Boolean; -procedure tr_CloseTrap(PanelID: Integer; NoSound: Boolean; d2d: Boolean); -function tr_SetLift(PanelID: Integer; d: Integer; NoSound: Boolean; d2d: Boolean): Boolean; +{ +function tr_CloseDoor (PanelGUID: Integer; NoSound: Boolean; d2d: Boolean): Boolean; +function tr_OpenDoor (PanelGUID: Integer; NoSound: Boolean; d2d: Boolean): Boolean; +procedure tr_CloseTrap (PanelGUID: Integer; NoSound: Boolean; d2d: Boolean); +function tr_SetLift (PanelGUID: Integer; d: Integer; NoSound: Boolean; d2d: Boolean): Boolean; -function tr_Teleport(ActivateUID: Integer; TX, TY: Integer; TDir: Integer; Silent: Boolean; D2D: Boolean): Boolean; -function tr_Push(ActivateUID: Integer; VX, VY: Integer; ResetVel: Boolean): Boolean; +function tr_Teleport (ActivateUID: Integer; TX, TY: Integer; TDir: Integer; Silent: Boolean; D2D: Boolean): Boolean; +function tr_Push (ActivateUID: Integer; VX, VY: Integer; ResetVel: Boolean): Boolean; -procedure tr_MakeEffect(X, Y, VX, VY: Integer; T, ST, CR, CG, CB: Byte; Silent, Send: Boolean); -function tr_SpawnShot(ShotType: Integer; wx, wy, dx, dy: Integer; ShotSound: Boolean; ShotTarget: Word): Integer; +procedure tr_MakeEffect (X, Y, VX, VY: Integer; T, ST, CR, CG, CB: Byte; Silent, Send: Boolean); +function tr_SpawnShot (ShotType: Integer; wx, wy, dx, dy: Integer; ShotSound: Boolean; ShotTarget: Word): Integer; +} var gTriggerClientID: Integer = 0; @@ -112,7 +113,8 @@ var implementation uses - g_player, g_map, Math, g_gfx, g_game, g_textures, + Math, + g_player, g_map, g_panel, g_gfx, g_game, g_textures, g_console, g_monsters, g_items, g_phys, g_weapons, wadreader, g_main, SysUtils, e_log, g_language, g_options, g_net, g_netmsg, utils, xparser; @@ -128,7 +130,7 @@ begin end; -function FindTrigger(): DWORD; +function FindTrigger (): DWORD; var i: Integer; begin @@ -151,85 +153,95 @@ begin end; -function tr_CloseDoor(PanelID: Integer; NoSound: Boolean; d2d: Boolean): Boolean; +function tr_CloseDoor (PanelGUID: Integer; NoSound: Boolean; d2d: Boolean): Boolean; var a, b, c: Integer; + pan: TPanel; + PanelID: Integer; begin - Result := False; - - if PanelID = -1 then Exit; + result := false; + pan := g_Map_PanelByGUID(PanelGUID); + if (pan = nil) or not pan.isGWall then exit; //!FIXME!TRIGANY! + PanelID := pan.arrIdx; if not d2d then begin with gWalls[PanelID] do begin - if g_CollidePlayer(X, Y, Width, Height) or - g_Mons_IsAnyAliveAt(X, Y, Width, Height) then Exit; - + if g_CollidePlayer(X, Y, Width, Height) or g_Mons_IsAnyAliveAt(X, Y, Width, Height) then Exit; if not Enabled then begin if not NoSound then begin g_Sound_PlayExAt('SOUND_GAME_DOORCLOSE', X, Y); - if g_Game_IsServer and g_Game_IsNet then - MH_SEND_Sound(X, Y, 'SOUND_GAME_DOORCLOSE'); + if g_Game_IsServer and g_Game_IsNet then MH_SEND_Sound(X, Y, 'SOUND_GAME_DOORCLOSE'); end; - g_Map_EnableWall(PanelID); - Result := True; + g_Map_EnableWallGUID(PanelGUID); + result := true; end; end; end else begin - if gDoorMap = nil then Exit; + if (gDoorMap = nil) then exit; c := -1; for a := 0 to High(gDoorMap) do begin for b := 0 to High(gDoorMap[a]) do + begin if gDoorMap[a, b] = DWORD(PanelID) then begin c := a; - Break; + break; end; - - if c <> -1 then Break; + end; + if (c <> -1) then break; end; - if c = -1 then Exit; + if (c = -1) then exit; for b := 0 to High(gDoorMap[c]) do + begin with gWalls[gDoorMap[c, b]] do begin - if g_CollidePlayer(X, Y, Width, Height) or - g_Mons_IsAnyAliveAt(X, Y, Width, Height) then Exit; + if g_CollidePlayer(X, Y, Width, Height) or g_Mons_IsAnyAliveAt(X, Y, Width, Height) then exit; end; + end; if not NoSound then + begin for b := 0 to High(gDoorMap[c]) do + begin if not gWalls[gDoorMap[c, b]].Enabled then begin with gWalls[PanelID] do begin g_Sound_PlayExAt('SOUND_GAME_DOORCLOSE', X, Y); - if g_Game_IsServer and g_Game_IsNet then - MH_SEND_Sound(X, Y, 'SOUND_GAME_DOORCLOSE'); + if g_Game_IsServer and g_Game_IsNet then MH_SEND_Sound(X, Y, 'SOUND_GAME_DOORCLOSE'); end; - Break; + break; end; + end; + end; for b := 0 to High(gDoorMap[c]) do + begin if not gWalls[gDoorMap[c, b]].Enabled then begin - g_Map_EnableWall(gDoorMap[c, b]); - Result := True; + g_Map_EnableWall_XXX(gDoorMap[c, b]); + result := true; end; + end; end; end; -procedure tr_CloseTrap(PanelID: Integer; NoSound: Boolean; d2d: Boolean); + +procedure tr_CloseTrap (PanelGUID: Integer; NoSound: Boolean; d2d: Boolean); var a, b, c: Integer; wx, wy, wh, ww: Integer; + pan: TPanel; + PanelID: Integer; function monsDamage (mon: TMonster): Boolean; begin @@ -238,7 +250,9 @@ var end; begin - if PanelID = -1 then Exit; + pan := g_Map_PanelByGUID(PanelGUID); + if (pan = nil) or not pan.isGWall then exit; //!FIXME!TRIGANY! + PanelID := pan.arrIdx; if not d2d then begin @@ -247,8 +261,7 @@ begin if (not NoSound) and (not Enabled) then begin g_Sound_PlayExAt('SOUND_GAME_SWITCH1', X, Y); - if g_Game_IsServer and g_Game_IsNet then - MH_SEND_Sound(X, Y, 'SOUND_GAME_SWITCH1'); + if g_Game_IsServer and g_Game_IsNet then MH_SEND_Sound(X, Y, 'SOUND_GAME_SWITCH1'); end; end; @@ -260,20 +273,25 @@ begin with gWalls[PanelID] do begin if gPlayers <> nil then + begin for a := 0 to High(gPlayers) do - if (gPlayers[a] <> nil) and gPlayers[a].Live and - gPlayers[a].Collide(X, Y, Width, Height) then + begin + if (gPlayers[a] <> nil) and gPlayers[a].Live and gPlayers[a].Collide(X, Y, Width, Height) then + begin gPlayers[a].Damage(TRAP_DAMAGE, 0, 0, 0, HIT_TRAP); + end; + end; + end; //g_Mons_ForEach(monsDamage); g_Mons_ForEachAliveAt(wx, wy, ww, wh, monsDamage); - if not Enabled then g_Map_EnableWall(PanelID); + if not Enabled then g_Map_EnableWallGUID(PanelGUID); end; end else begin - if gDoorMap = nil then Exit; + if (gDoorMap = nil) then exit; c := -1; for a := 0 to High(gDoorMap) do @@ -283,13 +301,12 @@ begin if gDoorMap[a, b] = DWORD(PanelID) then begin c := a; - Break; + break; end; end; - - if c <> -1 then Break; + if (c <> -1) then break; end; - if c = -1 then Exit; + if (c = -1) then exit; if not NoSound then begin @@ -317,10 +334,15 @@ begin with gWalls[gDoorMap[c, b]] do begin if gPlayers <> nil then + begin for a := 0 to High(gPlayers) do - if (gPlayers[a] <> nil) and gPlayers[a].Live and - gPlayers[a].Collide(X, Y, Width, Height) then + begin + if (gPlayers[a] <> nil) and gPlayers[a].Live and gPlayers[a].Collide(X, Y, Width, Height) then + begin gPlayers[a].Damage(TRAP_DAMAGE, 0, 0, 0, HIT_TRAP); + end; + end; + end; //g_Mons_ForEach(monsDamage); g_Mons_ForEachAliveAt(wx, wy, ww, wh, monsDamage); @@ -332,128 +354,146 @@ begin gMonsters[a].Damage(TRAP_DAMAGE, 0, 0, 0, HIT_TRAP); *) - if not Enabled then g_Map_EnableWall(gDoorMap[c, b]); + if not Enabled then g_Map_EnableWall_XXX(gDoorMap[c, b]); end; end; end; end; -function tr_OpenDoor(PanelID: Integer; NoSound: Boolean; d2d: Boolean): Boolean; + +function tr_OpenDoor (PanelGUID: Integer; NoSound: Boolean; d2d: Boolean): Boolean; var a, b, c: Integer; + pan: TPanel; + PanelID: Integer; begin - Result := False; - - if PanelID = -1 then Exit; + result := false; + pan := g_Map_PanelByGUID(PanelGUID); + if (pan = nil) or not pan.isGWall then exit; //!FIXME!TRIGANY! + PanelID := pan.arrIdx; if not d2d then begin with gWalls[PanelID] do + begin if Enabled then begin if not NoSound then begin g_Sound_PlayExAt('SOUND_GAME_DOOROPEN', X, Y); - if g_Game_IsServer and g_Game_IsNet then - MH_SEND_Sound(X, Y, 'SOUND_GAME_DOOROPEN'); + if g_Game_IsServer and g_Game_IsNet then MH_SEND_Sound(X, Y, 'SOUND_GAME_DOOROPEN'); end; - g_Map_DisableWall(PanelID); - Result := True; + g_Map_DisableWallGUID(PanelGUID); + result := true; end; + end end else begin - if gDoorMap = nil then Exit; + if (gDoorMap = nil) then exit; c := -1; for a := 0 to High(gDoorMap) do begin for b := 0 to High(gDoorMap[a]) do + begin if gDoorMap[a, b] = DWORD(PanelID) then begin c := a; - Break; + break; end; - - if c <> -1 then Break; + end; + if (c <> -1) then break; end; - if c = -1 then Exit; + if (c = -1) then exit; if not NoSound then + begin for b := 0 to High(gDoorMap[c]) do + begin if gWalls[gDoorMap[c, b]].Enabled then begin with gWalls[PanelID] do begin g_Sound_PlayExAt('SOUND_GAME_DOOROPEN', X, Y); - if g_Game_IsServer and g_Game_IsNet then - MH_SEND_Sound(X, Y, 'SOUND_GAME_DOOROPEN'); + if g_Game_IsServer and g_Game_IsNet then MH_SEND_Sound(X, Y, 'SOUND_GAME_DOOROPEN'); end; - Break; + break; end; + end; + end; for b := 0 to High(gDoorMap[c]) do + begin if gWalls[gDoorMap[c, b]].Enabled then begin - g_Map_DisableWall(gDoorMap[c, b]); - Result := True; + g_Map_DisableWall_XXX(gDoorMap[c, b]); + result := true; end; + end; end; end; -function tr_SetLift(PanelID: Integer; d: Integer; NoSound: Boolean; d2d: Boolean): Boolean; + +function tr_SetLift (PanelGUID: Integer; d: Integer; NoSound: Boolean; d2d: Boolean): Boolean; var - a, b, c, t: Integer; + a, b, c: Integer; + t: Integer = 0; + pan: TPanel; + PanelID: Integer; begin - t := 0; - Result := False; - - if PanelID = -1 then Exit; + result := false; + pan := g_Map_PanelByGUID(PanelGUID); + if (pan = nil) or not pan.isGLift then exit; //!FIXME!TRIGANY! + PanelID := pan.arrIdx; - if (gLifts[PanelID].PanelType = PANEL_LIFTUP) or - (gLifts[PanelID].PanelType = PANEL_LIFTDOWN) then + if (gLifts[PanelID].PanelType = PANEL_LIFTUP) or (gLifts[PanelID].PanelType = PANEL_LIFTDOWN) then + begin case d of 0: t := 0; 1: t := 1; else t := IfThen(gLifts[PanelID].LiftType = 1, 0, 1); end - else if (gLifts[PanelID].PanelType = PANEL_LIFTLEFT) or - (gLifts[PanelID].PanelType = PANEL_LIFTRIGHT) then + end + else if (gLifts[PanelID].PanelType = PANEL_LIFTLEFT) or (gLifts[PanelID].PanelType = PANEL_LIFTRIGHT) then + begin case d of 0: t := 2; 1: t := 3; else t := IfThen(gLifts[PanelID].LiftType = 2, 3, 2); end; + end; if not d2d then begin with gLifts[PanelID] do - if LiftType <> t then + begin + if (LiftType <> t) then begin - g_Map_SetLift(PanelID, t); - - {if not NoSound then - g_Sound_PlayExAt('SOUND_GAME_SWITCH0', X, Y);} - Result := True; + g_Map_SetLiftGUID(PanelGUID, t); //??? + //if not NoSound then g_Sound_PlayExAt('SOUND_GAME_SWITCH0', X, Y); + result := true; end; + end; end else // Êàê â D2d begin - if gLiftMap = nil then Exit; + if (gLiftMap = nil) then exit; c := -1; for a := 0 to High(gLiftMap) do begin for b := 0 to High(gLiftMap[a]) do - if gLiftMap[a, b] = DWORD(PanelID) then + begin + if (gLiftMap[a, b] = DWORD(PanelID)) then begin c := a; - Break; + break; end; - - if c <> -1 then Break; + end; + if (c <> -1) then break; end; - if c = -1 then Exit; + if (c = -1) then exit; {if not NoSound then for b := 0 to High(gLiftMap[c]) do @@ -465,27 +505,32 @@ begin end;} for b := 0 to High(gLiftMap[c]) do + begin with gLifts[gLiftMap[c, b]] do - if LiftType <> t then + begin + if (LiftType <> t) then begin - g_Map_SetLift(gLiftMap[c, b], t); - - Result := True; + g_Map_SetLift_XXX(gLiftMap[c, b], t); + result := true; end; + end; + end; end; end; -function tr_SpawnShot(ShotType: Integer; wx, wy, dx, dy: Integer; ShotSound: Boolean; ShotTarget: Word): Integer; + +function tr_SpawnShot (ShotType: Integer; wx, wy, dx, dy: Integer; ShotSound: Boolean; ShotTarget: Word): Integer; var snd: string; Projectile: Boolean; TextureID: DWORD; Anim: TAnimation; begin - Result := -1; + result := -1; TextureID := DWORD(-1); snd := 'SOUND_WEAPON_FIREROCKET'; - Projectile := True; + Projectile := true; + case ShotType of TRIGGER_SHOT_PISTOL: begin @@ -495,8 +540,7 @@ begin if ShotSound then begin g_Player_CreateShell(wx, wy, 0, -2, SHELL_BULLET); - if g_Game_IsNet then - MH_SEND_Effect(wx, wy, 0, NET_GFX_SHELL1); + if g_Game_IsNet then MH_SEND_Effect(wx, wy, 0, NET_GFX_SHELL1); end; end; @@ -509,8 +553,7 @@ begin if ShotSound then begin g_Player_CreateShell(wx, wy, 0, -2, SHELL_BULLET); - if g_Game_IsNet then - MH_SEND_Effect(wx, wy, 0, NET_GFX_SHELL1); + if g_Game_IsNet then MH_SEND_Effect(wx, wy, 0, NET_GFX_SHELL1); end; end; @@ -522,8 +565,7 @@ begin if ShotSound then begin g_Player_CreateShell(wx, wy, 0, -2, SHELL_SHELL); - if g_Game_IsNet then - MH_SEND_Effect(wx, wy, 0, NET_GFX_SHELL2); + if g_Game_IsNet then MH_SEND_Effect(wx, wy, 0, NET_GFX_SHELL2); end; end; @@ -536,8 +578,7 @@ begin begin g_Player_CreateShell(wx, wy, 0, -2, SHELL_SHELL); g_Player_CreateShell(wx, wy, 0, -2, SHELL_SHELL); - if g_Game_IsNet then - MH_SEND_Effect(wx, wy, 0, NET_GFX_SHELL3); + if g_Game_IsNet then MH_SEND_Effect(wx, wy, 0, NET_GFX_SHELL3); end; end; @@ -627,125 +668,118 @@ begin end; if g_Game_IsNet and g_Game_IsServer then + begin case ShotType of - TRIGGER_SHOT_EXPL: - MH_SEND_Effect(wx, wy, Byte(ShotSound), NET_GFX_EXPLODE); - TRIGGER_SHOT_BFGEXPL: - MH_SEND_Effect(wx, wy, Byte(ShotSound), NET_GFX_BFGEXPL); + TRIGGER_SHOT_EXPL: MH_SEND_Effect(wx, wy, Byte(ShotSound), NET_GFX_EXPLODE); + TRIGGER_SHOT_BFGEXPL: MH_SEND_Effect(wx, wy, Byte(ShotSound), NET_GFX_BFGEXPL); else begin - if Projectile then - MH_SEND_CreateShot(LastShotID); - if ShotSound then - MH_SEND_Sound(wx, wy, snd); + if Projectile then MH_SEND_CreateShot(LastShotID); + if ShotSound then MH_SEND_Sound(wx, wy, snd); end; end; + end; - if ShotSound then - g_Sound_PlayExAt(snd, wx, wy); + if ShotSound then g_Sound_PlayExAt(snd, wx, wy); - if Projectile then - Result := LastShotID; + if Projectile then Result := LastShotID; end; -procedure MakeShot(var Trigger: TTrigger; wx, wy, dx, dy: Integer; TargetUID: Word); + +procedure MakeShot (var Trigger: TTrigger; wx, wy, dx, dy: Integer; TargetUID: Word); begin with Trigger do - if (trigData.trigShotAmmo = 0) or - ((trigData.trigShotAmmo > 0) and (ShotAmmoCount > 0)) then + begin + if (trigData.trigShotAmmo = 0) or ((trigData.trigShotAmmo > 0) and (ShotAmmoCount > 0)) then begin - if (trigShotPanelID <> -1) and (ShotPanelTime = 0) then + if (trigShotPanelGUID <> -1) and (ShotPanelTime = 0) then begin - g_Map_SwitchTexture(ShotPanelType, trigShotPanelID); + g_Map_SwitchTextureGUID(ShotPanelType, trigShotPanelGUID); ShotPanelTime := 4; // òèêîâ íà âñïûøêó âûñòðåëà end; - if trigData.trigShotIntSight > 0 then - ShotSightTimeout := 180; // ~= 5 ñåêóíä + if (trigData.trigShotIntSight > 0) then ShotSightTimeout := 180; // ~= 5 ñåêóíä - if ShotAmmoCount > 0 then Dec(ShotAmmoCount); + if (ShotAmmoCount > 0) then Dec(ShotAmmoCount); - dx := dx + Random(trigData.trigShotAccuracy) - Random(trigData.trigShotAccuracy); - dy := dy + Random(trigData.trigShotAccuracy) - Random(trigData.trigShotAccuracy); + dx += Random(trigData.trigShotAccuracy)-Random(trigData.trigShotAccuracy); + dy += Random(trigData.trigShotAccuracy)-Random(trigData.trigShotAccuracy); tr_SpawnShot(trigData.trigShotType, wx, wy, dx, dy, trigData.trigShotSound, TargetUID); end else + begin if (trigData.trigShotIntReload > 0) and (ShotReloadTime = 0) then + begin ShotReloadTime := trigData.trigShotIntReload; // òèêîâ íà ïåðåçàðÿäêó ïóøêè + end; + end; + end; end; -procedure tr_MakeEffect(X, Y, VX, VY: Integer; T, ST, CR, CG, CB: Byte; Silent, Send: Boolean); + +procedure tr_MakeEffect (X, Y, VX, VY: Integer; T, ST, CR, CG, CB: Byte; Silent, Send: Boolean); var FramesID: DWORD; Anim: TAnimation; begin if T = TRIGGER_EFFECT_PARTICLE then + begin case ST of TRIGGER_EFFECT_SLIQUID: begin - if (CR = 255) and (CG = 0) and (CB = 0) then - g_GFX_SimpleWater(X, Y, 1, VX, VY, 1, 0, 0, 0) - else if (CR = 0) and (CG = 255) and (CB = 0) then - g_GFX_SimpleWater(X, Y, 1, VX, VY, 2, 0, 0, 0) - else if (CR = 0) and (CG = 0) and (CB = 255) then - g_GFX_SimpleWater(X, Y, 1, VX, VY, 3, 0, 0, 0) - else - g_GFX_SimpleWater(X, Y, 1, VX, VY, 0, 0, 0, 0); + if (CR = 255) and (CG = 0) and (CB = 0) then g_GFX_SimpleWater(X, Y, 1, VX, VY, 1, 0, 0, 0) + else if (CR = 0) and (CG = 255) and (CB = 0) then g_GFX_SimpleWater(X, Y, 1, VX, VY, 2, 0, 0, 0) + else if (CR = 0) and (CG = 0) and (CB = 255) then g_GFX_SimpleWater(X, Y, 1, VX, VY, 3, 0, 0, 0) + else g_GFX_SimpleWater(X, Y, 1, VX, VY, 0, 0, 0, 0); end; - TRIGGER_EFFECT_LLIQUID: - g_GFX_SimpleWater(X, Y, 1, VX, VY, 4, CR, CG, CB); - TRIGGER_EFFECT_DLIQUID: - g_GFX_SimpleWater(X, Y, 1, VX, VY, 5, CR, CG, CB); - TRIGGER_EFFECT_BLOOD: - g_GFX_Blood(X, Y, 1, VX, VY, 0, 0, CR, CG, CB); - TRIGGER_EFFECT_SPARK: - g_GFX_Spark(X, Y, 1, GetAngle2(VX, VY), 0, 0); - TRIGGER_EFFECT_BUBBLE: - g_GFX_Bubbles(X, Y, 1, 0, 0); + TRIGGER_EFFECT_LLIQUID: g_GFX_SimpleWater(X, Y, 1, VX, VY, 4, CR, CG, CB); + TRIGGER_EFFECT_DLIQUID: g_GFX_SimpleWater(X, Y, 1, VX, VY, 5, CR, CG, CB); + TRIGGER_EFFECT_BLOOD: g_GFX_Blood(X, Y, 1, VX, VY, 0, 0, CR, CG, CB); + TRIGGER_EFFECT_SPARK: g_GFX_Spark(X, Y, 1, GetAngle2(VX, VY), 0, 0); + TRIGGER_EFFECT_BUBBLE: g_GFX_Bubbles(X, Y, 1, 0, 0); end; + end; + if T = TRIGGER_EFFECT_ANIMATION then + begin case ST of EFFECT_TELEPORT: begin if g_Frames_Get(FramesID, 'FRAMES_TELEPORT') then begin Anim := TAnimation.Create(FramesID, False, 3); - if not Silent then - g_Sound_PlayExAt('SOUND_GAME_TELEPORT', X, Y); + if not Silent then g_Sound_PlayExAt('SOUND_GAME_TELEPORT', X, Y); g_GFX_OnceAnim(X-32, Y-32, Anim); Anim.Free(); end; - if Send and g_Game_IsServer and g_Game_IsNet then - MH_SEND_Effect(X, Y, Byte(not Silent), NET_GFX_TELE); + if Send and g_Game_IsServer and g_Game_IsNet then MH_SEND_Effect(X, Y, Byte(not Silent), NET_GFX_TELE); end; EFFECT_RESPAWN: begin if g_Frames_Get(FramesID, 'FRAMES_ITEM_RESPAWN') then begin Anim := TAnimation.Create(FramesID, False, 4); - if not Silent then - g_Sound_PlayExAt('SOUND_ITEM_RESPAWNITEM', X, Y); + if not Silent then g_Sound_PlayExAt('SOUND_ITEM_RESPAWNITEM', X, Y); g_GFX_OnceAnim(X-16, Y-16, Anim); Anim.Free(); end; - if Send and g_Game_IsServer and g_Game_IsNet then - MH_SEND_Effect(X-16, Y-16, Byte(not Silent), NET_GFX_RESPAWN); + if Send and g_Game_IsServer and g_Game_IsNet then MH_SEND_Effect(X-16, Y-16, Byte(not Silent), NET_GFX_RESPAWN); end; EFFECT_FIRE: begin if g_Frames_Get(FramesID, 'FRAMES_FIRE') then begin Anim := TAnimation.Create(FramesID, False, 4); - if not Silent then - g_Sound_PlayExAt('SOUND_FIRE', X, Y); + if not Silent then g_Sound_PlayExAt('SOUND_FIRE', X, Y); g_GFX_OnceAnim(X-32, Y-128, Anim); Anim.Free(); end; - if Send and g_Game_IsServer and g_Game_IsNet then - MH_SEND_Effect(X-32, Y-128, Byte(not Silent), NET_GFX_FIRE); + if Send and g_Game_IsServer and g_Game_IsNet then MH_SEND_Effect(X-32, Y-128, Byte(not Silent), NET_GFX_FIRE); end; end; + end; end; -function tr_Teleport(ActivateUID: Integer; TX, TY: Integer; TDir: Integer; Silent: Boolean; D2D: Boolean): Boolean; + +function tr_Teleport (ActivateUID: Integer; TX, TY: Integer; TDir: Integer; Silent: Boolean; D2D: Boolean): Boolean; var p: TPlayer; m: TMonster; @@ -756,56 +790,45 @@ begin UID_PLAYER: begin p := g_Player_Get(ActivateUID); - if p = nil then - Exit; - + if p = nil then Exit; if D2D then - begin - if p.TeleportTo(TX-(p.Obj.Rect.Width div 2), - TY-p.Obj.Rect.Height, - Silent, - TDir) then - Result := True; - end + begin + if p.TeleportTo(TX-(p.Obj.Rect.Width div 2), TY-p.Obj.Rect.Height, Silent, TDir) then result := true; + end else - if p.TeleportTo(TX, TY, Silent, TDir) then - Result := True; + begin + if p.TeleportTo(TX, TY, Silent, TDir) then result := true; + end; end; - UID_MONSTER: begin m := g_Monsters_ByUID(ActivateUID); - if m = nil then - Exit; - + if m = nil then Exit; if D2D then - begin - if m.TeleportTo(TX-(m.Obj.Rect.Width div 2), - TY-m.Obj.Rect.Height, - Silent, - TDir) then - Result := True; - end + begin + if m.TeleportTo(TX-(m.Obj.Rect.Width div 2), TY-m.Obj.Rect.Height, Silent, TDir) then result := true; + end else - if m.TeleportTo(TX, TY, Silent, TDir) then - Result := True; + begin + if m.TeleportTo(TX, TY, Silent, TDir) then result := true; + end; end; end; end; -function tr_Push(ActivateUID: Integer; VX, VY: Integer; ResetVel: Boolean): Boolean; + +function tr_Push (ActivateUID: Integer; VX, VY: Integer; ResetVel: Boolean): Boolean; var p: TPlayer; m: TMonster; begin - Result := True; - if (ActivateUID < 0) or (ActivateUID > $FFFF) then Exit; + result := true; + if (ActivateUID < 0) or (ActivateUID > $FFFF) then exit; case g_GetUIDType(ActivateUID) of UID_PLAYER: begin p := g_Player_Get(ActivateUID); - if p = nil then - Exit; + if p = nil then Exit; if ResetVel then begin @@ -821,8 +844,7 @@ begin UID_MONSTER: begin m := g_Monsters_ByUID(ActivateUID); - if m = nil then - Exit; + if m = nil then Exit; if ResetVel then begin @@ -837,7 +859,8 @@ begin end; end; -function tr_Message(MKind: Integer; MText: string; MSendTo: Integer; MTime: Integer; ActivateUID: Integer): Boolean; + +function tr_Message (MKind: Integer; MText: string; MSendTo: Integer; MTime: Integer; ActivateUID: Integer): Boolean; var msg: string; p: TPlayer; @@ -853,19 +876,17 @@ begin begin if g_Game_IsWatchedPlayer(ActivateUID) then begin - if MKind = 0 then - g_Console_Add(msg, True) - else if MKind = 1 then - g_Game_Message(msg, MTime); + if MKind = 0 then g_Console_Add(msg, True) + else if MKind = 1 then g_Game_Message(msg, MTime); end else begin p := g_Player_Get(ActivateUID); if g_Game_IsNet and (p.FClientID >= 0) then - if MKind = 0 then - MH_SEND_Chat(msg, NET_CHAT_SYSTEM, p.FClientID) - else if MKind = 1 then - MH_SEND_GameEvent(NET_EV_BIGTEXT, MTime, msg, p.FClientID); + begin + if MKind = 0 then MH_SEND_Chat(msg, NET_CHAT_SYSTEM, p.FClientID) + else if MKind = 1 then MH_SEND_GameEvent(NET_EV_BIGTEXT, MTime, msg, p.FClientID); + end; end; end; end; @@ -876,19 +897,21 @@ begin begin p := g_Player_Get(ActivateUID); if g_Game_IsWatchedTeam(p.Team) then - if MKind = 0 then - g_Console_Add(msg, True) - else if MKind = 1 then - g_Game_Message(msg, MTime); + begin + if MKind = 0 then g_Console_Add(msg, True) + else if MKind = 1 then g_Game_Message(msg, MTime); + end; if g_Game_IsNet then begin for i := Low(gPlayers) to High(gPlayers) do + begin if (gPlayers[i].Team = p.Team) and (gPlayers[i].FClientID >= 0) then - if MKind = 0 then - MH_SEND_Chat(msg, NET_CHAT_SYSTEM, gPlayers[i].FClientID) - else if MKind = 1 then - MH_SEND_GameEvent(NET_EV_BIGTEXT, MTime, msg, gPlayers[i].FClientID); + begin + if MKind = 0 then MH_SEND_Chat(msg, NET_CHAT_SYSTEM, gPlayers[i].FClientID) + else if MKind = 1 then MH_SEND_GameEvent(NET_EV_BIGTEXT, MTime, msg, gPlayers[i].FClientID); + end; + end; end; end; end; @@ -899,19 +922,21 @@ begin begin p := g_Player_Get(ActivateUID); if g_Game_IsWatchedTeam(p.Team) then - if MKind = 0 then - g_Console_Add(msg, True) - else if MKind = 1 then - g_Game_Message(msg, MTime); + begin + if MKind = 0 then g_Console_Add(msg, True) + else if MKind = 1 then g_Game_Message(msg, MTime); + end; if g_Game_IsNet then begin for i := Low(gPlayers) to High(gPlayers) do + begin if (gPlayers[i].Team <> p.Team) and (gPlayers[i].FClientID >= 0) then - if MKind = 0 then - MH_SEND_Chat(msg, NET_CHAT_SYSTEM, gPlayers[i].FClientID) - else if MKind = 1 then - MH_SEND_GameEvent(NET_EV_BIGTEXT, MTime, msg, gPlayers[i].FClientID); + begin + if MKind = 0 then MH_SEND_Chat(msg, NET_CHAT_SYSTEM, gPlayers[i].FClientID) + else if MKind = 1 then MH_SEND_GameEvent(NET_EV_BIGTEXT, MTime, msg, gPlayers[i].FClientID); + end; + end; end; end; end; @@ -919,81 +944,84 @@ begin 3: // red team begin if g_Game_IsWatchedTeam(TEAM_RED) then - if MKind = 0 then - g_Console_Add(msg, True) - else if MKind = 1 then - g_Game_Message(msg, MTime); + begin + if MKind = 0 then g_Console_Add(msg, True) + else if MKind = 1 then g_Game_Message(msg, MTime); + end; if g_Game_IsNet then begin for i := Low(gPlayers) to High(gPlayers) do + begin if (gPlayers[i].Team = TEAM_RED) and (gPlayers[i].FClientID >= 0) then - if MKind = 0 then - MH_SEND_Chat(msg, NET_CHAT_SYSTEM, gPlayers[i].FClientID) - else if MKind = 1 then - MH_SEND_GameEvent(NET_EV_BIGTEXT, MTime, msg, gPlayers[i].FClientID); + begin + if MKind = 0 then MH_SEND_Chat(msg, NET_CHAT_SYSTEM, gPlayers[i].FClientID) + else if MKind = 1 then MH_SEND_GameEvent(NET_EV_BIGTEXT, MTime, msg, gPlayers[i].FClientID); + end; + end; end; end; 4: // blue team begin if g_Game_IsWatchedTeam(TEAM_BLUE) then - if MKind = 0 then - g_Console_Add(msg, True) - else if MKind = 1 then - g_Game_Message(msg, MTime); + begin + if MKind = 0 then g_Console_Add(msg, True) + else if MKind = 1 then g_Game_Message(msg, MTime); + end; if g_Game_IsNet then begin for i := Low(gPlayers) to High(gPlayers) do + begin if (gPlayers[i].Team = TEAM_BLUE) and (gPlayers[i].FClientID >= 0) then - if MKind = 0 then - MH_SEND_Chat(msg, NET_CHAT_SYSTEM, gPlayers[i].FClientID) - else if MKind = 1 then - MH_SEND_GameEvent(NET_EV_BIGTEXT, MTime, msg, gPlayers[i].FClientID); + begin + if MKind = 0 then MH_SEND_Chat(msg, NET_CHAT_SYSTEM, gPlayers[i].FClientID) + else if MKind = 1 then MH_SEND_GameEvent(NET_EV_BIGTEXT, MTime, msg, gPlayers[i].FClientID); + end; + end; end; end; 5: // everyone begin - if MKind = 0 then - g_Console_Add(msg, True) - else if MKind = 1 then - g_Game_Message(msg, MTime); + if MKind = 0 then g_Console_Add(msg, True) + else if MKind = 1 then g_Game_Message(msg, MTime); if g_Game_IsNet then begin - if MKind = 0 then - MH_SEND_Chat(msg, NET_CHAT_SYSTEM) - else if MKind = 1 then - MH_SEND_GameEvent(NET_EV_BIGTEXT, MTime, msg); + if MKind = 0 then MH_SEND_Chat(msg, NET_CHAT_SYSTEM) + else if MKind = 1 then MH_SEND_GameEvent(NET_EV_BIGTEXT, MTime, msg); end; end; end; end; -function tr_ShotAimCheck(var Trigger: TTrigger; Obj: PObj): Boolean; + +function tr_ShotAimCheck (var Trigger: TTrigger; Obj: PObj): Boolean; begin result := false; with Trigger do begin - if TriggerType <> TRIGGER_SHOT then - Exit; - Result := (trigData.trigShotAim and TRIGGER_SHOT_AIM_ALLMAP > 0) + if TriggerType <> TRIGGER_SHOT then Exit; + result := (trigData.trigShotAim and TRIGGER_SHOT_AIM_ALLMAP > 0) or g_Obj_Collide(X, Y, Width, Height, Obj); - if Result and (trigData.trigShotAim and TRIGGER_SHOT_AIM_TRACE > 0) then - Result := g_TraceVector(trigData.trigShotPos.X, - trigData.trigShotPos.Y, + if result and (trigData.trigShotAim and TRIGGER_SHOT_AIM_TRACE > 0) then + begin + result := g_TraceVector(trigData.trigShotPos.X, trigData.trigShotPos.Y, Obj^.X + Obj^.Rect.X + (Obj^.Rect.Width div 2), Obj^.Y + Obj^.Rect.Y + (Obj^.Rect.Height div 2)); + end; end; end; -function ActivateTrigger(var Trigger: TTrigger; actType: Byte): Boolean; + +function ActivateTrigger (var Trigger: TTrigger; actType: Byte): Boolean; var animonce: Boolean; p: TPlayer; m: TMonster; + pan: TPanel; idx, k, wx, wy, xd, yd: Integer; iid: LongWord; coolDown: Boolean; @@ -1042,16 +1070,12 @@ var end; begin - Result := False; - if g_Game_IsClient then - Exit; + result := false; + if g_Game_IsClient then exit; - if not Trigger.Enabled then - Exit; - if (Trigger.TimeOut <> 0) and (actType <> ACTIVATE_CUSTOM) then - Exit; - if gLMSRespawn = LMS_RESPAWN_WARMUP then - Exit; + if not Trigger.Enabled then exit; + if (Trigger.TimeOut <> 0) and (actType <> ACTIVATE_CUSTOM) then exit; + if gLMSRespawn = LMS_RESPAWN_WARMUP then exit; animonce := False; @@ -1083,38 +1107,38 @@ begin TRIGGER_OPENDOOR: begin - Result := tr_OpenDoor(trigPanelID, trigData.trigNoSound, trigData.trigd2d_doors); + Result := tr_OpenDoor(trigPanelGUID, trigData.trigNoSound, trigData.trigd2d_doors); TimeOut := 0; end; TRIGGER_CLOSEDOOR: begin - Result := tr_CloseDoor(trigPanelID, trigData.trigNoSound, trigData.trigd2d_doors); + Result := tr_CloseDoor(trigPanelGUID, trigData.trigNoSound, trigData.trigd2d_doors); TimeOut := 0; end; TRIGGER_DOOR, TRIGGER_DOOR5: begin - if trigPanelID <> -1 then + pan := g_Map_PanelByGUID(trigPanelGUID); + if (pan <> nil) and pan.isGWall then begin - if gWalls[trigPanelID].Enabled then - begin - Result := tr_OpenDoor(trigPanelID, trigData.trigNoSound, trigData.trigd2d_doors); - - if TriggerType = TRIGGER_DOOR5 then - DoorTime := 180; - end + if gWalls[{trigPanelID}pan.arrIdx].Enabled then + begin + result := tr_OpenDoor(trigPanelGUID, trigData.trigNoSound, trigData.trigd2d_doors); + if (TriggerType = TRIGGER_DOOR5) then DoorTime := 180; + end else - Result := tr_CloseDoor(trigPanelID, trigData.trigNoSound, trigData.trigd2d_doors); + begin + result := tr_CloseDoor(trigPanelGUID, trigData.trigNoSound, trigData.trigd2d_doors); + end; - if Result then - TimeOut := 18; + if result then TimeOut := 18; end; end; TRIGGER_CLOSETRAP, TRIGGER_TRAP: begin - tr_CloseTrap(trigPanelID, trigData.trigNoSound, trigData.trigd2d_doors); + tr_CloseTrap(trigPanelGUID, trigData.trigNoSound, trigData.trigd2d_doors); if TriggerType = TRIGGER_TRAP then begin @@ -1132,15 +1156,9 @@ begin TRIGGER_PRESS, TRIGGER_ON, TRIGGER_OFF, TRIGGER_ONOFF: begin - PressCount := PressCount + 1; - - if PressTime = -1 then - PressTime := trigData.trigWait; - - if coolDown then - TimeOut := 18 - else - TimeOut := 0; + PressCount += 1; + if PressTime = -1 then PressTime := trigData.trigWait; + if coolDown then TimeOut := 18 else TimeOut := 0; Result := True; end; @@ -1159,7 +1177,7 @@ begin TRIGGER_LIFTUP: begin - Result := tr_SetLift(trigPanelID, 0, trigData.trigNoSound, trigData.trigd2d_doors); + Result := tr_SetLift(trigPanelGUID, 0, trigData.trigNoSound, trigData.trigd2d_doors); TimeOut := 0; if (not trigData.trigNoSound) and Result then begin @@ -1175,7 +1193,7 @@ begin TRIGGER_LIFTDOWN: begin - Result := tr_SetLift(trigPanelID, 1, trigData.trigNoSound, trigData.trigd2d_doors); + Result := tr_SetLift(trigPanelGUID, 1, trigData.trigNoSound, trigData.trigd2d_doors); TimeOut := 0; if (not trigData.trigNoSound) and Result then begin @@ -1191,7 +1209,7 @@ begin TRIGGER_LIFT: begin - Result := tr_SetLift(trigPanelID, 3, trigData.trigNoSound, trigData.trigd2d_doors); + Result := tr_SetLift(trigPanelGUID, 3, trigData.trigNoSound, trigData.trigd2d_doors); if Result then begin @@ -2093,8 +2111,10 @@ begin end; end; - if Result and (Trigger.TexturePanel <> -1) then - g_Map_SwitchTexture(Trigger.TexturePanelType, Trigger.TexturePanel, IfThen(animonce, 2, 1)); + if Result {and (Trigger.TexturePanel <> -1)} then + begin + g_Map_SwitchTextureGUID(Trigger.TexturePanelType, Trigger.TexturePanelGUID, IfThen(animonce, 2, 1)); + end; end; @@ -2294,6 +2314,7 @@ var var mon: TMonster; + pan: TPanel; begin if (tgMonsList = nil) then tgMonsList := TSimpleMonsterList.Create(); @@ -2306,120 +2327,135 @@ begin // Åñòü òðèããåð: if TriggerType <> TRIGGER_NONE then begin - // Óìåíüøàåì âðåìÿ äî çàêðûòèÿ äâåðè (îòêðûòèÿ ëîâóøêè): - if DoorTime > 0 then - DoorTime := DoorTime - 1; - // Óìåíüøàåì âðåìÿ îæèäàíèÿ ïîñëå íàæàòèÿ: - if PressTime > 0 then - PressTime := PressTime - 1; - // Ïðîâåðÿåì èãðîêîâ è ìîíñòðîâ, êîòîðûõ ðàíåå çàïîìíèëè: + // Óìåíüøàåì âðåìÿ äî çàêðûòèÿ äâåðè (îòêðûòèÿ ëîâóøêè) + if DoorTime > 0 then DoorTime := DoorTime - 1; + // Óìåíüøàåì âðåìÿ îæèäàíèÿ ïîñëå íàæàòèÿ + if PressTime > 0 then PressTime := PressTime - 1; + // Ïðîâåðÿåì èãðîêîâ è ìîíñòðîâ, êîòîðûõ ðàíåå çàïîìíèëè: if (TriggerType = TRIGGER_DAMAGE) or (TriggerType = TRIGGER_HEALTH) then + begin for b := 0 to High(Activators) do begin // Óìåíüøàåì âðåìÿ äî ïîâòîðíîãî âîçäåéñòâèÿ: if Activators[b].TimeOut > 0 then - Dec(Activators[b].TimeOut) + begin + Dec(Activators[b].TimeOut); + end else - Continue; + begin + continue; + end; // Ñ÷èòàåì, ÷òî îáúåêò ïîêèíóë çîíó äåéñòâèÿ òðèããåðà - if (trigData.trigDamageInterval = 0) and (Activators[b].TimeOut < 65530) then - Activators[b].TimeOut := 0; + if (trigData.trigDamageInterval = 0) and (Activators[b].TimeOut < 65530) then Activators[b].TimeOut := 0; end; + end; - // Îáðàáàòûâàåì ñïàâíåðû: + // Îáðàáàòûâàåì ñïàâíåðû if Enabled and AutoSpawn then + begin if SpawnCooldown = 0 then begin - // Åñëè ïðèøëî âðåìÿ, ñïàâíèì ìîíñòðà: + // Åñëè ïðèøëî âðåìÿ, ñïàâíèì ìîíñòðà if (TriggerType = TRIGGER_SPAWNMONSTER) and (trigData.trigMonDelay > 0) then begin ActivateUID := 0; ActivateTrigger(gTriggers[a], ACTIVATE_CUSTOM); end; - // Åñëè ïðèøëî âðåìÿ, ñïàâíèì ïðåäìåò: + // Åñëè ïðèøëî âðåìÿ, ñïàâíèì ïðåäìåò if (TriggerType = TRIGGER_SPAWNITEM) and (trigData.trigItemDelay > 0) then begin ActivateUID := 0; ActivateTrigger(gTriggers[a], ACTIVATE_CUSTOM); end; - end else // Óìåíüøàåì âðåìÿ îæèäàíèÿ: + end + else + begin + // Óìåíüøàåì âðåìÿ îæèäàíèÿ Dec(SpawnCooldown); + end; + end; - // Îáðàáàòûâàåì ñîáûòèÿ òðèããåðà "Òóðåëü": + // Îáðàáàòûâàåì ñîáûòèÿ òðèããåðà "Òóðåëü" if TriggerType = TRIGGER_SHOT then begin if ShotPanelTime > 0 then begin Dec(ShotPanelTime); - if ShotPanelTime = 0 then - g_Map_SwitchTexture(ShotPanelType, trigShotPanelID); + if ShotPanelTime = 0 then g_Map_SwitchTextureGUID(ShotPanelType, trigShotPanelGUID); end; if ShotSightTime > 0 then begin Dec(ShotSightTime); - if ShotSightTime = 0 then - ShotSightTarget := ShotSightTargetN; + if ShotSightTime = 0 then ShotSightTarget := ShotSightTargetN; end; if ShotSightTimeout > 0 then begin Dec(ShotSightTimeout); - if ShotSightTimeout = 0 then - ShotSightTarget := 0; + if ShotSightTimeout = 0 then ShotSightTarget := 0; end; if ShotReloadTime > 0 then begin Dec(ShotReloadTime); - if ShotReloadTime = 0 then - ShotAmmoCount := trigData.trigShotAmmo; + if ShotReloadTime = 0 then ShotAmmoCount := trigData.trigShotAmmo; end; end; - // Òðèããåð "Çâóê" óæå îòûãðàë, åñëè íóæíî åùå - ïåðåçàïóñêàåì: + // Òðèããåð "Çâóê" óæå îòûãðàë, åñëè íóæíî åùå - ïåðåçàïóñêàåì if Enabled and (TriggerType = TRIGGER_SOUND) and (Sound <> nil) then + begin if (SoundPlayCount > 0) and (not Sound.IsPlaying()) then begin - if trigData.trigPlayCount > 0 then // Åñëè 0 - èãðàåì çâóê áåñêîíå÷íî - SoundPlayCount := SoundPlayCount - 1; + if trigData.trigPlayCount > 0 then SoundPlayCount -= 1; // Åñëè 0 - èãðàåì çâóê áåñêîíå÷íî if trigData.trigLocal then - Sound.PlayVolumeAt(X+(Width div 2), Y+(Height div 2), trigData.trigVolume/255.0) + begin + Sound.PlayVolumeAt(X+(Width div 2), Y+(Height div 2), trigData.trigVolume/255.0); + end else + begin Sound.PlayPanVolume((trigData.trigPan-127.0)/128.0, trigData.trigVolume/255.0); - if Sound.IsPlaying() and g_Game_IsNet and g_Game_IsServer then - MH_SEND_TriggerSound(gTriggers[a]); + end; + if Sound.IsPlaying() and g_Game_IsNet and g_Game_IsServer then MH_SEND_TriggerSound(gTriggers[a]); end; + end; - // Òðèããåð "Ëîâóøêà" - ïîðà îòêðûâàòü: - if (TriggerType = TRIGGER_TRAP) and (DoorTime = 0) and (trigPanelID <> -1) then + // Òðèããåð "Ëîâóøêà" - ïîðà îòêðûâàòü + if (TriggerType = TRIGGER_TRAP) and (DoorTime = 0) and (g_Map_PanelByGUID(trigPanelGUID) <> nil) then begin - tr_OpenDoor(trigPanelID, trigData.trigNoSound, trigData.trigd2d_doors); + tr_OpenDoor(trigPanelGUID, trigData.trigNoSound, trigData.trigd2d_doors); DoorTime := -1; end; - // Òðèããåð "Äâåðü 5 ñåê" - ïîðà çàêðûâàòü: - if (TriggerType = TRIGGER_DOOR5) and (DoorTime = 0) and (trigPanelID <> -1) then + // Òðèããåð "Äâåðü 5 ñåê" - ïîðà çàêðûâàòü + if (TriggerType = TRIGGER_DOOR5) and (DoorTime = 0) and (g_Map_PanelByGUID(trigPanelGUID) <> nil) then begin - // Óæå çàêðûòà: - if gWalls[trigPanelID].Enabled then - DoorTime := -1 - else // Ïîêà îòêðûòà - çàêðûâàåì - if tr_CloseDoor(trigPanelID, trigData.trigNoSound, trigData.trigd2d_doors) then + pan := g_Map_PanelByGUID(trigPanelGUID); + if (pan <> nil) and pan.isGWall then + begin + // Óæå çàêðûòà + if {gWalls[trigPanelID].Enabled} pan.Enabled then + begin DoorTime := -1; + end + else + begin + // Ïîêà îòêðûòà - çàêðûâàåì + if tr_CloseDoor(trigPanelGUID, trigData.trigNoSound, trigData.trigd2d_doors) then DoorTime := -1; + end; + end; end; // Òðèããåð - ðàñøèðèòåëü èëè ïåðåêëþ÷àòåëü, è ïðîøëà çàäåðæêà, è íàæàëè íóæíîå ÷èñëî ðàç: if (TriggerType in [TRIGGER_PRESS, TRIGGER_ON, TRIGGER_OFF, TRIGGER_ONOFF]) and (PressTime = 0) and (PressCount >= trigData.trigCount) then begin - // Ñáðàñûâàåì çàäåðæêó àêòèâàöèè: + // Ñáðàñûâàåì çàäåðæêó àêòèâàöèè: PressTime := -1; - // Ñáðàñûâàåì ñ÷åò÷èê íàæàòèé: - if trigData.trigCount > 0 then - PressCount := PressCount - trigData.trigCount - else - PressCount := 0; + // Ñáðàñûâàåì ñ÷åò÷èê íàæàòèé: + if trigData.trigCount > 0 then PressCount -= trigData.trigCount else PressCount := 0; - // Îïðåäåëÿåì èçìåíÿåìûå èì òðèããåðû: + // Îïðåäåëÿåì èçìåíÿåìûå èì òðèããåðû: for b := 0 to High(gTriggers) do + begin if g_Collide(trigData.trigtX, trigData.trigtY, trigData.trigtWidth, trigData.trigtHeight, gTriggers[b].X, gTriggers[b].Y, gTriggers[b].Width, gTriggers[b].Height) and ((b <> a) or (trigData.trigWait > 0)) then @@ -2430,7 +2466,14 @@ begin Affected[High(Affected)] := b; end; end; - // Âûáèðàåì îäèí èç òðèããåðîâ äëÿ ðàñøèðèòåëÿ, åñëè âêëþ÷åí ðàíäîì: + end; + + // if we have panelid, assume that it will switch the moving platform + if (trigPanelGUID >= 0) then + begin + end; + + // Âûáèðàåì îäèí èç òðèããåðîâ äëÿ ðàñøèðèòåëÿ, åñëè âêëþ÷åí ðàíäîì: if (TriggerType = TRIGGER_PRESS) and trigData.trigExtRandom then begin if (Length(Affected) > 0) then @@ -2441,6 +2484,7 @@ begin end; end else //  ïðîòèâíîì ñëó÷àå ðàáîòàåì êàê îáû÷íî: + begin for i := 0 to High(Affected) do begin b := Affected[i]; @@ -2479,6 +2523,7 @@ begin end; end; end; + end; SetLength(Affected, 0); end; @@ -2696,15 +2741,19 @@ begin b := False; for a := 0 to High(gTriggers) do + begin with gTriggers[a] do + begin if (TriggerType = TRIGGER_OPENDOOR) or (TriggerType = TRIGGER_DOOR5) or (TriggerType = TRIGGER_DOOR) then begin - tr_OpenDoor(trigPanelID, True, trigData.trigd2d_doors); + tr_OpenDoor(trigPanelGUID, True, trigData.trigd2d_doors); if TriggerType = TRIGGER_DOOR5 then DoorTime := 180; b := True; end; + end; + end; if b then g_Sound_PlayEx('SOUND_GAME_DOOROPEN'); end; @@ -2787,11 +2836,11 @@ begin // Êëþ÷è, íåîáõîäèìûå äëÿ àêòèâàöèè: Mem.WriteByte(gTriggers[i].Keys); // ID ïàíåëè, òåêñòóðà êîòîðîé èçìåíèòñÿ: - Mem.WriteInt(gTriggers[i].TexturePanel); + Mem.WriteInt(gTriggers[i].TexturePanelGUID); // Òèï ýòîé ïàíåëè: Mem.WriteWord(gTriggers[i].TexturePanelType); // Âíóòðåííèé íîìåð äðóãîé ïàíåëè (ïî ñ÷àñòëèâîé ñëó÷àéíîñòè îí áóäåò ñîâïàäàòü ñ òåì, ÷òî ñîçäàíî ïðè çàãðóçêå êàðòû) - Mem.WriteInt(gTriggers[i].trigPanelId); + Mem.WriteInt(gTriggers[i].trigPanelGUID); // Âðåìÿ äî âîçìîæíîñòè àêòèâàöèè: Mem.WriteWord(gTriggers[i].TimeOut); // UID òîãî, êòî àêòèâèðîâàë ýòîò òðèããåð: @@ -2914,11 +2963,11 @@ begin // Êëþ÷è, íåîáõîäèìûå äëÿ àêòèâàöèè: Mem.ReadByte(gTriggers[i].Keys); // ID ïàíåëè, òåêñòóðà êîòîðîé èçìåíèòñÿ: - Mem.ReadInt(gTriggers[i].TexturePanel); + Mem.ReadInt(gTriggers[i].TexturePanelGUID); // Òèï ýòîé ïàíåëè: Mem.ReadWord(gTriggers[i].TexturePanelType); // Âíóòðåííèé íîìåð äðóãîé ïàíåëè (ïî ñ÷àñòëèâîé ñëó÷àéíîñòè îí áóäåò ñîâïàäàòü ñ òåì, ÷òî ñîçäàíî ïðè çàãðóçêå êàðòû) - Mem.ReadInt(gTriggers[i].trigPanelId); + Mem.ReadInt(gTriggers[i].trigPanelGUID); // Âðåìÿ äî âîçìîæíîñòè àêòèâàöèè: Mem.ReadWord(gTriggers[i].TimeOut); // UID òîãî, êòî àêòèâèðîâàë ýòîò òðèããåð: diff --git a/src/mapdef/mapdef.txt b/src/mapdef/mapdef.txt index 9851afe..f30c218 100644 --- a/src/mapdef/mapdef.txt +++ b/src/mapdef/mapdef.txt @@ -404,8 +404,10 @@ TriggerData for (TRIGGER_PRESS, TRIGGER_ON, TRIGGER_OFF, TRIGGER_ONOFF) { Size is "size" type size offset 8 as twh; Wait is "wait" type ushort offset 12; Count is "count" type ushort offset 14; - MonsterID is "monsterid" type int offset 16 monster as monsterid; + MonsterID is "monsterid" type int offset 16 monster as monsterid default null; ExtRandom is "extrandom" type bool offset 20; + // this one is for moving platforms + PanelId is "panelid" type int panel default null omitdefault; } TriggerData for TRIGGER_SECRET { diff --git a/src/shared/MAPDEF.pas b/src/shared/MAPDEF.pas index 8f6a3ce..ad16025 100644 --- a/src/shared/MAPDEF.pas +++ b/src/shared/MAPDEF.pas @@ -122,6 +122,7 @@ type {$INCLUDE mapdef_help.inc} function trigMonsterId (): Integer; inline; + function trigPanelId (): Integer; inline; // panel index in list private // user fields @@ -279,6 +280,16 @@ begin end; +// panel index in list +function TDynRecordHelper.trigPanelId (): Integer; inline; +var + fld: TDynField; +begin + fld := getFieldWithType('panelid', TDynField.TType.TInt); + result := fld.recrefIndex; +end; + + // ////////////////////////////////////////////////////////////////////////// // function TDynRecordHelper.mapName (): AnsiString; inline; begin result := utf2win(getFieldWithType('name', TDynField.TType.TChar).sval); end; function TDynRecordHelper.mapAuthor (): AnsiString; inline; begin result := utf2win(getFieldWithType('author', TDynField.TType.TChar).sval); end; diff --git a/src/shared/hashtable.pas b/src/shared/hashtable.pas index 9f72e3a..ea71555 100644 --- a/src/shared/hashtable.pas +++ b/src/shared/hashtable.pas @@ -173,6 +173,11 @@ function joaatHash (constref buf; len: LongWord): LongWord; function nextPOT (x: LongWord): LongWord; inline; +// for integer keys +function hiiequ (constref a, b: Integer): Boolean; +function hiihash (constref k: Integer): LongWord; + + implementation uses @@ -204,7 +209,7 @@ function hsiequ (constref a, b: AnsiString): Boolean; begin result := (a = b); e {$RANGECHECKS OFF} function hiihash (constref k: Integer): LongWord; begin - result := k; + result := LongWord(k); result -= (result shl 6); result := result xor (result shr 17); result -= (result shl 9); diff --git a/src/shared/mapdef.inc b/src/shared/mapdef.inc index 6e3aa03..27888ed 100644 --- a/src/shared/mapdef.inc +++ b/src/shared/mapdef.inc @@ -797,6 +797,11 @@ const defaultMapDef: AnsiString = ''+ #32#97#115#32#109#111#110#115#116#101#114#105#100#59#10#32#32#69#120#116#82+ #97#110#100#111#109#32#105#115#32#34#101#120#116#114#97#110#100#111#109#34+ #32#116#121#112#101#32#98#111#111#108#32#111#102#102#115#101#116#32#50#48#59+ + #10#32#32#47#47#32#116#104#105#115#32#111#110#101#32#105#115#32#102#111#114+ + #32#109#111#118#105#110#103#32#112#108#97#116#102#111#114#109#115#10#32#32+ + #80#97#110#101#108#73#100#32#105#115#32#34#112#97#110#101#108#105#100#34#32+ + #116#121#112#101#32#105#110#116#32#112#97#110#101#108#32#100#101#102#97#117+ + #108#116#32#110#117#108#108#32#111#109#105#116#100#101#102#97#117#108#116#59+ #10#125#10#10#84#114#105#103#103#101#114#68#97#116#97#32#102#111#114#32#84+ #82#73#71#71#69#82#95#83#69#67#82#69#84#32#123#10#125#10#10#84#114#105#103+ #103#101#114#68#97#116#97#32#102#111#114#32#84#82#73#71#71#69#82#95#84#69#88+ -- 2.29.2