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

📄 g_spawn.pas

📁 雷神之锤2(Quake2)Delphi源码
💻 PAS
📖 第 1 页 / 共 3 页
字号:
    if lstrcmp(s.name,ent.classname)<>''then //if (!strcmp(s->name, ent->classname))
    begin
      (* found it*)
      s.spawn(ent); 
      exit;
    end;
  end;
  gi.dprintf('%s doesn'#39't have a spawn function'#13#10'',ent.classname); 
end;

(*
=============
ED_NewString
=============
*)

function ED_NewString(string: pchar): pchar; 
var
   newb: pchar; 
  new_p: pchar; 
      i: integer; 
      l: integer; 
begin
  
  l:= lstrlen(string)+1; 
  newb:= gi.TagMalloc(l,TAG_LEVEL); 
  new_p:= newb; 
  
  
  for i:=0 to Pred(l) do
  begin 
    if (string[i]=#92) and (i<l-1) then
    begin 
      inc(i); 
      if string[i]='n' then
      begin
        new_p^:=#13#10;  
        inc(new_p);
      end
      else
      begin
        new_p^:=#92; 
        inc(new_p); 
      end;
    end
    else
     begin
       new_p^:=string[i];
       inc(new_p); 
     end;
  end;
  result:= newb; 
end;


(*
===============
ED_ParseField

Takes a key/value pair and sets the binary values
in an edict
===============
*)

procedure ED_ParseField(key: pchar;  value: pchar;  ent: pedict_t); 
var
    f: pfield_t;
    b: pbyte;
    v: float;
  vec: vec3_t; 
begin
  
  for f:= fields to f.name do //for (f=fields ; f->name ; f++)
  begin
    if (not (f.flags and FFL_NOSPAWN)) and (not (Q_stricmp(f.name,key)) then
    //if (!(f->flags & FFL_NOSPAWN) && !Q_stricmp(f->name, key))
    begin
      (* found it*)
      if f.flags and FFL_SPAWNTEMP then
        b:= PByte(@st) //b = (byte *)&st;
      else
        b:= PByte(ent);//b = (byte *)ent;

      case f.type of
        F_LSTRING:
        begin
          PPChar(b+f.ofs)^:=ED_NewString(value); //*(char **)(b+f->ofs)
        end;
        F_VECTOR:
        begin
          sscanf(value, '%f %f %f', [@vec[0], @vec[1], @vec[2]]); 
          PFloat(b+f.ofs)[0]:=vec[0];
          PFloat(b+f.ofs)[1]:=vec[1];
          PFloat(b+f.ofs)[2]:=vec[2];
        end;
        F_INT:
        begin
          PInteger(b+f.ofs):=atoi(value);
        end;
        F_FLOAT:
        begin
          PFloat(b+f.ofs):=atof(value);
        end;
        F_ANGLEHACK:
        begin
          v:= atof(value);
          PFloat(b+f.ofs)[0]:=0; 
          PFloat(b+f.ofs)[1]:=v;
          PFloat(b+f.ofs)[2]:=0;
        end;
        F_IGNORE: ;
      end;{case?}
      exit;
    end;
  end;
  gi.dprintf('%s is not a field'#13#10'',key); 
end;

(*
====================
ED_ParseEdict

Parses an edict out of the given string, returning the new position
ed should be a properly initialized empty edict.
====================
*)

function ED_ParseEdict(data: pchar;  ent: pedict_t): pchar; 
var
       init: QBoolean;
    keyname: array [0..Pred(256)] of Char;
  com_token: PChar;
begin

  init:= false;
  RtlZeroMemory(@st,sizeof(st)); 
  
  (* go through all the dictionary pairs*)
  while True do
  begin
    (* parse key*)
    com_token:= COM_Parse( and data); 
    if com_token[0]='}' then break;
    if data<>nil then gi.error('ED_ParseEntity: EOF without closing brace');

    strncpy(keyname,com_token,sizeof(keyname)-1);

    com_token:= COM_Parse( and data); (* parse value *)
    if data<>nil then gi.error('ED_ParseEntity: EOF without closing brace');

    if com_token[0]='}' then gi.error('ED_ParseEntity: closing brace without data');
    init:= true;

    (* keynames with a leading underscore are used for utility comments,*)
    (* and are immediately discarded by quake*)
    //if keyname[0]='_' then continue
    ED_ParseField(keyname,com_token,ent);
  end;
  
  if not init then RtlZeroMemory(ent,sizeof(ent^));

  result:= data;
end;


(*
================
G_FindTeams

Chain together all entities with a matching team field.

All but the first will have the FL_TEAMSLAVE flag set.
All but the last will have the teamchain field set to the next one
================
*)

procedure G_FindTeams(); 
var
      e,
     e2,
  chain: pedict_t;
      i,
      j,
      c,
      c2: integer;
begin

  c:= 0;
  c2:= 0;
  i:= 1;
  e:= g_edicts+i;
  for i:= 1 to globals.num_edicts-1 do
  begin
    // if not e.inuse then continue;
    // if not e.team then continue;
    // if e.flags and FL_TEAMSLAVE then continue

    chain:= e;
    e.teammaster:= e;
    inc(c);
    inc(c2);
    e2:=e+1;
    for j:= i+1 to globals.num_edicts-2 do
    begin
      //if not e2.inuse then continue;
      //if not e2.team then continue;
      //if e2.flags and FL_TEAMSLAVE then continue;
      if not lstrcmp(e.team,e2.team) then
      begin
        inc(c2);
        chain.teamchain:= e2;
        e2.teammaster:= e;
        chain:= e2;
        e2.flags:= e2.flags or (FL_TEAMSLAVE);
      end;
      inc(e2);
    end;
    inc(e);
  end;
  gi.dprintf('%i teams with %i entities'#13#10'',c,c2);

end;

(*
==============
SpawnEntities

Creates a server's entity / program execution context by
parsing textual entity definitions out of an ent file.
==============
*)

procedure SpawnEntities(mapname: pchar;  entities: pchar;  spawnpoint: pchar); 
var
        ent: pedict_t;
    inhibit: integer;
  com_token: pchar;
          i: integer;
skill_level: float;
begin
  
  skill_level:= floor(skill.value); 
  if skill_level<0 then skill_level:= 0;
  if skill_level>3 then skill_level:= 3; 
  if skill.value<>skill_level then gi.cvar_forceset('skill',va('%f',skill_level));
  SaveClientData();

  gi.FreeTags(TAG_LEVEL);

  RtlZeroMemory(@level,sizeof(level));

  RtlZeroMemory(g_edicts,game.maxentities*sizeof(g_edicts[0]));

  strncpy(level.mapname,mapname,sizeof(level.mapname)-1);
  strncpy(game.spawnpoint,spawnpoint,sizeof(game.spawnpoint)-1);

  (* set client fields on player ents*)
  for i:=0 to Pred(game.maxclients) do
    g_edicts[i+1].client:= game.clients+i;
    
  ent:= 0;
  inhibit:= 0;

  (* parse ents*)
  while True do
  begin
    (* parse the opening brace *)
    com_token:= COM_Parse( and entities); 
    if not entities then break;  //if (!entities)

    if com_token[0]<>'{' then gi.error('ED_LoadFromFile: found %s when expecting {',com_token); 
    
    if not ent then ent:= g_edicts //if (!ent)
    else ent:= G_Spawn(); 
    entities:= ED_ParseEdict(entities,ent); 

    (* yet another map hack*)
    if not Q_stricmp(level.mapname,'command')) and (not Q_stricmp(ent.classname,'trigger_once')) and (not Q_stricmp(ent.model,'*27') then
      ent.spawnflags:= ent.spawnflags and (not SPAWNFLAG_NOT_HARD);
    (* remove things (except the world) from different skill levels or deathmatch*)
    if ent<>g_edicts then
    begin
      if deathmatch.value then //if (deathmatch->value)
      begin
        if ent.spawnflags and SPAWNFLAG_NOT_DEATHMATCH then
        begin 
          G_FreeEdict(ent); 
          inc(inhibit); 
        end;
      end;
      else
      begin 
        if ((skill.value=0) and (ent.spawnflags and SPAWNFLAG_NOT_EASY)) or
           ((skill.value=1) and (ent.spawnflags and SPAWNFLAG_NOT_MEDIUM)) or
           (((skill.value=2) or  (skill.value=3)) and (ent.spawnflags and SPAWNFLAG_NOT_HARD)) then
        begin 
          G_FreeEdict(ent); 
          inc(inhibit); 
        end;
      end;
      ent.spawnflags:= ent.spawnflags and (not(SPAWNFLAG_NOT_EASY or SPAWNFLAG_NOT_MEDIUM or SPAWNFLAG_NOT_HARD or SPAWNFLAG_NOT_COOP or SPAWNFLAG_NOT_DEATHMATCH)); 
      
    end;
    ED_CallSpawn(ent); 
    
  end;
  gi.dprintf('%i entities inhibited'#13#10'',inhibit); 
  
  
  {$ifdef DEBUG}
    i:= 1; 
    ent:= EDICT_NUM(i); 
    while i<globals.num_edicts do
    begin
      if ent.inuse<>0)or(ent.inuse<>1) then
        Com_DPrintf('Invalid entity %d'#13#10'',i);
      inc(i); ,
      inc(ent); 
    end;
  {$endif}
  G_FindTeams();
  
  PlayerTrail_Init(); 
  
end;


(*===================================================================*)
{$if 0}
   (* cursor positioning*)
   xl <value>
   xr <value>
   yb <value>
   yt <value>
   xv <value>
   yv<value>

⌨️ 快捷键说明

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