⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sv_world.pas

📁 delphi编的不错的贪吃蛇
💻 PAS
📖 第 1 页 / 共 2 页
字号:
{$ALIGN ON}{$MINENUMSIZE 4}
{----------------------------------------------------------------------------}
{                                                                            }
{ File(s): server\sv_world.c                                                 }
{                                                                            }
{ Initial conversion by : Juha Hartikainen (juha@linearteam.org)             }
{ Initial conversion on : 02-Jun-2002                                        }
{                                                                            }
{ This File contains part of convertion of Quake2 source to ObjectPascal.    }
{ More information about this project can be found at:                       }
{ http://www.sulaco.co.za/quake2/                                            }
{                                                                            }
{ Copyright (C) 1997-2001 Id Software, Inc.                                  }
{                                                                            }
{ 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 the Free Software Foundation; either version 2             }
{ of the License, or (at your option) any later version.                     }
{                                                                            }
{ This program is distributed in the hope that it will be useful,            }
{ but WITHOUT ANY WARRANTY; without even the implied warranty of             }
{ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                       }
{                                                                            }
{ See the GNU General Public License for more details.                       }
{                                                                            }
{----------------------------------------------------------------------------}
unit sv_world;

// world.c -- world query functions

interface

uses
  DelphiTypes,
  SysUtils,
  Common,
  GameUnit,
  q_shared,
  Server;

type
  areanode_p = ^areanode_t;
  areanode_t = record
    axis: Integer;                      // -1 = leaf node
    dist: Single;
    children: array[0..1] of areanode_p; // to areanode_t;
    trigger_edicts: link_t;
    solid_edicts: link_t;
  end;

function SV_HullForEntity(ent: edict_p): Integer; cdecl;
procedure SV_ClearWorld; cdecl;
procedure SV_LinkEdict(ent: edict_p); cdecl;
procedure SV_UnlinkEdict(ent: edict_p); cdecl;
function SV_AreaEdicts(mins, maxs: vec3_p; list: Parea_list;
  maxcount, areatype: Integer): Integer; cdecl;

function SV_Trace(start, mins, maxs, end_: vec3_p; passedict: edict_p; contentmask: Integer): trace_t; cdecl;
function SV_PointContents(const p: vec3_t): Integer; cdecl;

const
  AREA_DEPTH = 4;
  AREA_NODES = 32;

var
  sv_areanodes: array[0..AREA_NODES - 1] of areanode_t;
  sv_numareanodes: Integer;

  area_mins, area_maxs: PSingleArray;
  area_list: Parea_list;
  area_count, area_maxcount: Integer;
  area_type: Integer;

implementation

uses
  game_add,
  CModel,
  sv_game,
  sv_init;

function EDICT_FROM_AREA(l: pointer): edict_p;
begin
  Result := edict_p(Integer(l) - Integer(@edict_p(0)^.area));
end;

// ClearLink is used for new headnodes

procedure ClearLink(l: link_p);
begin
  l^.next := l;
  l^.prev := l^.next;
end;

procedure RemoveLink(l: link_p);
begin
  l^.next^.prev := l^.prev;
  l^.prev^.next := l^.next;
end;

procedure InsertLinkBefore(l: link_p; before: link_p);
begin
  l^.next := before;
  l^.prev := before^.prev;
  l^.prev^.next := l;
  l^.next^.prev := l;
end;

(*
===============
SV_CreateAreaNode

Builds a uniformly subdivided tree for the given world size
===============
*)

function SV_CreateAreaNode(depth: Integer; mins, maxs: vec3_p): areanode_p;
var
  anode: areanode_p;
  size, mins1, maxs1, mins2, maxs2: vec3_t;
begin
  anode := @sv_areanodes[sv_numareanodes];
  Inc(sv_numareanodes);

  ClearLink(@anode^.trigger_edicts);
  ClearLink(@anode^.solid_edicts);

  if (depth = AREA_DEPTH) then
  begin
    anode^.axis := -1;
    anode^.children[1] := nil;
    anode^.children[0] := anode^.children[1];
    Result := anode;
    Exit;
  end;

  VectorSubtract(maxs^, mins^, size);
  if (size[0] > size[1]) then
    anode^.axis := 0
  else
    anode^.axis := 1;

  anode^.dist := 0.5 * (maxs[anode^.axis] + mins[anode^.axis]);
  VectorCopy(mins^, mins1);
  VectorCopy(mins^, mins2);
  VectorCopy(maxs^, maxs1);
  VectorCopy(maxs^, maxs2);

  mins2[anode^.axis] := anode^.dist;
  maxs1[anode^.axis] := mins2[anode^.axis];

  anode^.children[0] := SV_CreateAreaNode(depth + 1, @mins2, @maxs2);
  anode^.children[1] := SV_CreateAreaNode(depth + 1, @mins1, @maxs1);

  Result := anode;
end;

(*
===============
SV_ClearWorld

===============
*)

procedure SV_ClearWorld;
begin
  FillChar(sv_areanodes, SizeOf(sv_areanodes), 0);
  sv_numareanodes := 0;
  SV_CreateAreaNode(0, @sv.models[1].mins, @sv.models[1].maxs);
end;

(*
===============
SV_UnlinkEdict

===============
*)

procedure SV_UnlinkEdict(ent: edict_p); cdecl;
begin
  if (ent^.area.prev = nil) then
    Exit;                               // not linked in anywhere
  RemoveLink(@ent^.area);
  ent^.area.next := nil;
  ent^.area.prev := ent^.area.next;
end;

(*
===============
SV_LinkEdict

===============
*)
const
  MAX_TOTAL_ENT_LEAFS = 128;

type
  TMaxLeafsArray = array[0..MAX_TOTAL_ENT_LEAFS - 1] of Integer;

procedure SV_LinkEdict(ent: edict_p);
var
  node: areanode_p;
  leafs: TMaxLeafsArray;
  clusters: TMaxLeafsArray;
  num_leafs: Integer;
  i, j, k: Integer;
  area: Integer;
  topnode: Integer;
  max, v: Single;
begin
  if (ent.area.prev <> nil) then
    SV_UnlinkEdict(ent);                // unlink from old position

  if (ent = ge^.edicts) then
    Exit;                               // don't add the world

  if (not ent^.inuse) then
    Exit;

  // set the size
  VectorSubtract(ent^.maxs, ent^.mins, ent^.size);

  // encode the size into the entity_state for client prediction
  if (ent^.solid = SOLID_BBOX) and ((ent^.svflags and SVF_DEADMONSTER) = 0) then
  begin
    // assume that x/y are equal and symetric
    i := Trunc(ent^.maxs[0] / 8);
    if (i < 1) then
      i := 1;

    if (i > 31) then
      i := 31;

    // z is not symetric
    j := Trunc((-ent^.mins[2]) / 8);
    if (j < 1) then
      j := 1;

    if (j > 31) then
      j := 31;

    // and z maxs can be negative...
    k := Trunc((ent^.maxs[2] + 32) / 8);
    if (k < 1) then
      k := 1;

    if (k > 63) then
      k := 63;

    ent^.s.solid := (k shl 10) or (j shl 5) or i;
  end
  else if (ent^.solid = SOLID_BSP) then
  begin
    ent^.s.solid := 31;                 // a solid_bbox will never create this value
  end
  else
    ent^.s.solid := 0;

  // set the abs box
  if ((ent^.solid = SOLID_BSP) and
    ((ent^.s.angles[0] <> 0) or (ent^.s.angles[1] <> 0) or (ent^.s.angles[2] <> 0))) then
  begin
    // expand for rotation
    max := 0;
    for i := 0 to 2 do
    begin
      v := fabs(ent^.mins[i]);
      if (v > max) then
        max := v;
      v := fabs(ent^.maxs[i]);
      if (v > max) then
        max := v;
    end;
    for i := 0 to 2 do
    begin
      ent^.absmin[i] := ent^.s.origin[i] - max;
      ent^.absmax[i] := ent^.s.origin[i] + max;
    end;
  end
  else
  begin
    // normal
    VectorAdd(ent^.s.origin, ent^.mins, ent^.absmin);
    VectorAdd(ent^.s.origin, ent^.maxs, ent^.absmax);
  end;

  // because movement is clipped an epsilon away from an actual edge,
  // we must fully check even when bounding boxes don't quite touch
  ent^.absmin[0] := ent^.absmin[0] - 1;
  ent^.absmin[1] := ent^.absmin[1] - 1;
  ent^.absmin[2] := ent^.absmin[2] - 1;
  ent^.absmax[0] := ent^.absmax[0] + 1;
  ent^.absmax[1] := ent^.absmax[1] + 1;
  ent^.absmax[2] := ent^.absmax[2] + 1;

  // link to PVS leafs
  ent^.num_clusters := 0;
  ent^.areanum := 0;
  ent^.areanum2 := 0;

  //get all leafs, including solids
  num_leafs := CM_BoxLeafnums(ent^.absmin, ent^.absmax, @leafs,
    MAX_TOTAL_ENT_LEAFS, @topnode);

  // set areas
  for i := 0 to (num_leafs - 1) do
  begin
    clusters[i] := CM_LeafCluster(leafs[i]);
    area := CM_LeafArea(leafs[i]);
    if (area <> 0) then
    begin
      // doors may legally straggle two areas,
      // but nothing should evern need more than that
      if (ent^.areanum <> 0) and (ent^.areanum <> area) then
      begin
        if (ent^.areanum2 <> 0) and (ent^.areanum2 <> area) and (sv.state = ss_loading) then
          Com_DPrintf('Object touching 3 areas at %f %f %f'#10, [
            ent^.absmin[0], ent^.absmin[1], ent^.absmin[2]]);

        ent^.areanum2 := area;
      end
      else
        ent^.areanum := area;
    end;
  end;

  if (num_leafs >= MAX_TOTAL_ENT_LEAFS) then
  begin
    // assume we missed some leafs, and mark by headnode
    ent^.num_clusters := -1;
    ent^.headnode := topnode;
  end
  else
  begin
    ent^.num_clusters := 0;
    for i := 0 to (num_leafs - 1) do
    begin
      if (clusters[i] = -1) then
        Continue;                       // not a visible leaf

      j := 0;
      while j < i do
      begin
        if (clusters[j] = clusters[i]) then
          Break;
        Inc(j);
      end;

      if (j = i) then
      begin
        if (ent^.num_clusters = MAX_ENT_CLUSTERS) then
        begin
          // assume we missed some leafs, and mark by headnode
          ent^.num_clusters := -1;
          ent^.headnode := topnode;
          Break;
        end;

        ent^.clusternums[ent^.num_clusters] := clusters[i];
        Inc(ent^.num_clusters);
      end;
    end;
  end;

  // if first time, make sure old_origin is valid
  if (ent^.linkcount = 0) then
  begin
    VectorCopy(ent^.s.origin, ent^.s.old_origin);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -