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

📄 sv_world.pas

📁 delphi编的不错的贪吃蛇
💻 PAS
📖 第 1 页 / 共 2 页
字号:
  end;

  Inc(ent^.linkcount);

  if (ent^.solid = SOLID_NOT) then
    Exit;

  // find the first node that the ent's box crosses
  node := @sv_areanodes;
  while (True) do
  begin
    if (node^.axis = -1) then
      Break;
    if (ent^.absmin[node^.axis] > node^.dist) then
      node := node^.children[0]
    else if (ent^.absmax[node^.axis] < node^.dist) then
      node := node^.children[1]
    else
      Break;                            // crosses the node
  end;

  // link it in
  if (ent^.solid = SOLID_TRIGGER) then
    InsertLinkBefore(@ent^.area, @node^.trigger_edicts)
  else
    InsertLinkBefore(@ent^.area, @node^.solid_edicts);
end;

(*
====================
SV_AreaEdicts_r

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

procedure SV_AreaEdicts_r(node: areanode_p);
var
  l, next, start: link_p;
  check: edict_p;
  //  count: Integer;
begin
  //  count := 0;

    // touch linked edicts
  if (area_type = AREA_SOLID) then
    start := @node.solid_edicts
  else
    start := @node.trigger_edicts;

  l := start^.next;
  while l <> start do
  begin
    next := l^.next;
    check := EDICT_FROM_AREA(l);

    if (check^.solid = SOLID_NOT) then
    begin
      l := next;
      Continue;                         // deactivated
    end;
    if ((check^.absmin[0] > area_maxs^[0]) or
      (check^.absmin[1] > area_maxs^[1]) or
      (check^.absmin[2] > area_maxs^[2]) or
      (check^.absmax[0] < area_mins^[0]) or
      (check^.absmax[1] < area_mins^[1]) or
      (check^.absmax[2] < area_mins^[2])) then
    begin
      l := next;
      Continue;                         // not touching
    end;

    if (area_count = area_maxcount) then
    begin
      Com_Printf('SV_AreaEdicts: MAXCOUNT'#10, []);
      Exit;
    end;

    area_list^[area_count] := check;
    Inc(area_count);

    l := next;
  end;

  if (node^.axis = -1) then
    Exit;                               // terminal node

  // recurse down both sides
  if (area_maxs^[node^.axis] > node^.dist) then
    SV_AreaEdicts_r(node^.children[0]);

  if (area_mins^[node^.axis] < node^.dist) then
    SV_AreaEdicts_r(node^.children[1]);
end;

(*
================
SV_AreaEdicts
================
*)

function SV_AreaEdicts(mins, maxs: vec3_p; list: Parea_list;
  maxcount, areatype: Integer): Integer;
begin
  area_mins := PSingleArray(mins);
  area_maxs := PSingleArray(maxs);
  area_list := list;
  area_count := 0;
  area_maxcount := maxcount;
  area_type := areatype;

  SV_AreaEdicts_r(@sv_areanodes);

  Result := area_count;
end;

//===========================================================================

(*
=============
SV_PointContents
=============
*)
type
  TEdictArr = array[0..MAX_EDICTS - 1] of edict_p;
  PEdictArr = ^TEdictArr;

function SV_PointContents(const p: vec3_t): Integer;
var
  touch: TEdictArr;
  hit: edict_p;
  i, num: Integer;
  contents, c2: Integer;
  headnode: Integer;
  angles: PSingleArray;
begin
  // get base contents from world
  contents := CM_PointContents(p, sv.models[1].headnode);

  // or in contents from all the other entities
  num := SV_AreaEdicts(@p, @p, Parea_list(@touch), MAX_EDICTS, AREA_SOLID);

  for i := 0 to (num - 1) do
  begin
    hit := touch[i];

    // might intersect, so do an exact clip
    headnode := SV_HullForEntity(hit);
    angles := @hit^.s.angles;
    if (hit^.solid <> SOLID_BSP) then
      angles := @vec3_origin;           // boxes don't rotate

    c2 := CM_TransformedPointContents(p, headnode, hit^.s.origin, hit^.s.angles);

    contents := contents or c2;
  end;

  Result := contents;
end;

type
  moveclip_p = ^moveclip_t;
  moveclip_t = record
    boxmins, boxmaxs: vec3_t;           // enclose the test object along entire move
    mins, maxs: PSingleArray;           // size of the moving object
    mins2, maxs2: vec3_t;               // size when clipping against mosnters
    start, end_: PSingleArray;
    trace: trace_t;
    passedict: edict_p;
    contentmask: Integer;
  end;

  (*
  ================
  SV_HullForEntity

  Returns a headnode that can be used for testing or clipping an
  object of mins/maxs size.
  Offset is filled in to contain the adjustment that must be added to the
  testing object's origin to get a point to use with the returned hull.
  ================
  *)

function SV_HullForEntity(ent: edict_p): Integer;
var
  model: cmodel_p;
begin
  // decide which clipping hull to use, based on the size
  if (ent^.solid = SOLID_BSP) then
  begin
    // explicit hulls in the BSP model
    model := sv.models[ent^.s.modelindex];

    if (model = nil) then
      Com_Error(ERR_FATAL, 'MOVETYPE_PUSH with a non bsp model', []);

    Result := model^.headnode;
    Exit;
  end;

  // create a temp hull from bounding box sizes

  Result := CM_HeadnodeForBox(ent^.mins, ent^.maxs);
end;

//===========================================================================

(*
====================
SV_ClipMoveToEntities

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

procedure SV_ClipMoveToEntities(clip: moveclip_p);
var
  i, num: Integer;
  touchlist: TEdictArr;
  touch: edict_p;
  trace: trace_t;
  headnode: Integer;
  angles: PSingleArray;
begin
  num := SV_AreaEdicts(@clip.boxmins, @clip.boxmaxs, Parea_list(@touchlist), MAX_EDICTS,
    AREA_SOLID);

  // be careful, it is possible to have an entity in this
  // list removed before we get to it (killtriggered)
  for i := 0 to (num - 1) do
  begin
    touch := touchlist[i];
    if (touch^.solid = SOLID_NOT) then
      Continue;
    if (touch = clip^.passedict) then
      Continue;
    if (clip^.trace.allsolid) then
      Exit;
    if (clip^.passedict <> nil) then
    begin
      if (touch^.owner = clip^.passedict) then
        Continue;                       // don't clip against own missiles
      if (clip^.passedict^.owner = touch) then
        Continue;                       // don't clip against owner
    end;

    if ((clip^.contentmask and CONTENTS_DEADMONSTER = 0) and
      ((touch^.svflags and SVF_DEADMONSTER) <> 0)) then
      Continue;

    // might intersect, so do an exact clip
    headnode := SV_HullForEntity(touch);
    angles := @touch^.s.angles;
    if (touch^.solid <> SOLID_BSP) then
      angles := @vec3_origin;           // boxes don't rotate

    if (touch^.svflags and SVF_MONSTER) <> 0 then
      trace := CM_TransformedBoxTrace(vec3_p(clip^.start)^, vec3_p(clip^.end_)^,
        clip^.mins2, clip^.maxs2, headnode, clip^.contentmask,
        touch^.s.origin, vec3_p(angles)^)
    else
      trace := CM_TransformedBoxTrace(vec3_p(clip^.start)^, vec3_p(clip^.end_)^,
        vec3_p(clip^.mins)^, vec3_p(clip^.maxs)^, headnode, clip^.contentmask,
        touch^.s.origin, vec3_p(angles)^);

    if ((trace.allsolid) or (trace.startsolid) or
      (trace.fraction < clip^.trace.fraction)) then
    begin
      trace.ent := touch;
      if (clip^.trace.startsolid) then
      begin
        clip^.trace := trace;
        clip^.trace.startsolid := true;
      end
      else
        clip^.trace := trace;
    end
    else if (trace.startsolid) then
      clip^.trace.startsolid := true;
  end;
end;

(*
==================
SV_TraceBounds
==================
*)

procedure SV_TraceBounds(var start, mins, maxs, end_, boxmins, boxmaxs: vec3_t);
var
  i: Integer;
begin
  {
    // debug to test against everything
    boxmins[2] := -9999;
    boxmins[1] := boxmins[2];
    boxmins[0] := boxmins[1];

    boxmaxs[2] := 9999;
    boxmaxs[1] := boxmaxs[2];
    boxmaxs[0] := boxmaxs[1];
  }
  for i := 0 to 2 do
  begin
    if (end_[i] > start[i]) then
    begin
      boxmins[i] := start[i] + mins[i] - 1;
      boxmaxs[i] := end_[i] + maxs[i] + 1;
    end
    else
    begin
      boxmins[i] := end_[i] + mins[i] - 1;
      boxmaxs[i] := start[i] + maxs[i] + 1;
    end;
  end;
end;

(*
==================
SV_Trace

Moves the given mins/maxs volume through the world from start to end.

Passedict and edicts owned by passedict are explicitly not checked.

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

function SV_Trace(start, mins, maxs, end_: vec3_p; passedict: edict_p; contentmask: Integer): trace_t;
var
  clip: moveclip_t;
begin
  if (mins = nil) then
    mins := @vec3_origin;
  if (maxs = nil) then
    maxs := @vec3_origin;

  FillChar(clip, SizeOf(moveclip_t), 0);

  // clip to world
  clip.trace := CM_BoxTrace(start^, end_^, mins^, maxs^, 0, contentmask);
  clip.trace.ent := ge^.edicts;
  if (clip.trace.fraction = 0) then
  begin
    Result := clip.trace;               // blocked by the world
    Exit;
  end;

  clip.contentmask := contentmask;
  clip.start := PSingleArray(start);
  clip.end_ := PSingleArray(end_);
  clip.mins := PSingleArray(mins);
  clip.maxs := PSingleArray(maxs);
  clip.passedict := passedict;

  VectorCopy(mins^, clip.mins2);
  VectorCopy(maxs^, clip.maxs2);

  // create the bounding box of the entire move
  SV_TraceBounds(start^, clip.mins2, clip.maxs2, end_^, clip.boxmins, clip.boxmaxs);

  // clip to other solid entities
  SV_ClipMoveToEntities(@clip);

  Result := clip.trace;
end;

end.

⌨️ 快捷键说明

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