home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 14 / MA_Cover_14.iso / source / c / q1source_amy / qw / server / pr_cmds.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-21  |  31.9 KB  |  1,723 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20.  
  21. #include "qwsvdef.h"
  22.  
  23. #define    RETURN_EDICT(e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(e))
  24. #define    RETURN_STRING(s) (((int *)pr_globals)[OFS_RETURN] = PR_SetString(s))
  25.  
  26. /*
  27. ===============================================================================
  28.  
  29.                         BUILT-IN FUNCTIONS
  30.  
  31. ===============================================================================
  32. */
  33.  
  34. char *PF_VarString (int    first)
  35. {
  36.     int        i;
  37.     static char out[256];
  38.     
  39.     out[0] = 0;
  40.     for (i=first ; i<pr_argc ; i++)
  41.     {
  42.         strcat (out, G_STRING((OFS_PARM0+i*3)));
  43.     }
  44.     return out;
  45. }
  46.  
  47.  
  48. /*
  49. =================
  50. PF_errror
  51.  
  52. This is a TERMINAL error, which will kill off the entire server.
  53. Dumps self.
  54.  
  55. error(value)
  56. =================
  57. */
  58. void PF_error (void)
  59. {
  60.     char    *s;
  61.     edict_t    *ed;
  62.     
  63.     s = PF_VarString(0);
  64.     Con_Printf ("======SERVER ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name) ,s);
  65.     ed = PROG_TO_EDICT(pr_global_struct->self);
  66.     ED_Print (ed);
  67.  
  68.     SV_Error ("Program error");
  69. }
  70.  
  71. /*
  72. =================
  73. PF_objerror
  74.  
  75. Dumps out self, then an error message.  The program is aborted and self is
  76. removed, but the level can continue.
  77.  
  78. objerror(value)
  79. =================
  80. */
  81. void PF_objerror (void)
  82. {
  83.     char    *s;
  84.     edict_t    *ed;
  85.     
  86.     s = PF_VarString(0);
  87.     Con_Printf ("======OBJECT ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name),s);
  88.     ed = PROG_TO_EDICT(pr_global_struct->self);
  89.     ED_Print (ed);
  90.     ED_Free (ed);
  91.     
  92.     SV_Error ("Program error");
  93. }
  94.  
  95.  
  96.  
  97. /*
  98. ==============
  99. PF_makevectors
  100.  
  101. Writes new values for v_forward, v_up, and v_right based on angles
  102. makevectors(vector)
  103. ==============
  104. */
  105. void PF_makevectors (void)
  106. {
  107.     AngleVectors (G_VECTOR(OFS_PARM0), pr_global_struct->v_forward, pr_global_struct->v_right, pr_global_struct->v_up);
  108. }
  109.  
  110. /*
  111. =================
  112. PF_setorigin
  113.  
  114. This is the only valid way to move an object without using the physics of the world (setting velocity and waiting).  Directly changing origin will not set internal links correctly, so clipping would be messed up.  This should be called when an object is spawned, and then only if it is teleported.
  115.  
  116. setorigin (entity, origin)
  117. =================
  118. */
  119. void PF_setorigin (void)
  120. {
  121.     edict_t    *e;
  122.     float    *org;
  123.     
  124.     e = G_EDICT(OFS_PARM0);
  125.     org = G_VECTOR(OFS_PARM1);
  126.     VectorCopy (org, e->v.origin);
  127.     SV_LinkEdict (e, false);
  128. }
  129.  
  130.  
  131. /*
  132. =================
  133. PF_setsize
  134.  
  135. the size box is rotated by the current angle
  136.  
  137. setsize (entity, minvector, maxvector)
  138. =================
  139. */
  140. void PF_setsize (void)
  141. {
  142.     edict_t    *e;
  143.     float    *min, *max;
  144.     
  145.     e = G_EDICT(OFS_PARM0);
  146.     min = G_VECTOR(OFS_PARM1);
  147.     max = G_VECTOR(OFS_PARM2);
  148.     VectorCopy (min, e->v.mins);
  149.     VectorCopy (max, e->v.maxs);
  150.     VectorSubtract (max, min, e->v.size);
  151.     SV_LinkEdict (e, false);
  152. }
  153.  
  154.  
  155. /*
  156. =================
  157. PF_setmodel
  158.  
  159. setmodel(entity, model)
  160. Also sets size, mins, and maxs for inline bmodels
  161. =================
  162. */
  163. void PF_setmodel (void)
  164. {
  165.     edict_t    *e;
  166.     char    *m, **check;
  167.     int        i;
  168.     model_t    *mod;
  169.  
  170.     e = G_EDICT(OFS_PARM0);
  171.     m = G_STRING(OFS_PARM1);
  172.  
  173. // check to see if model was properly precached
  174.     for (i=0, check = sv.model_precache ; *check ; i++, check++)
  175.         if (!strcmp(*check, m))
  176.             break;
  177.  
  178.     if (!*check)
  179.         PR_RunError ("no precache: %s\n", m);
  180.         
  181.     e->v.model = PR_SetString(m);
  182.     e->v.modelindex = i;
  183.  
  184. // if it is an inline model, get the size information for it
  185.     if (m[0] == '*')
  186.     {
  187.         mod = Mod_ForName (m, true);
  188.         VectorCopy (mod->mins, e->v.mins);
  189.         VectorCopy (mod->maxs, e->v.maxs);
  190.         VectorSubtract (mod->maxs, mod->mins, e->v.size);
  191.         SV_LinkEdict (e, false);
  192.     }
  193.  
  194. }
  195.  
  196. /*
  197. =================
  198. PF_bprint
  199.  
  200. broadcast print to everyone on server
  201.  
  202. bprint(value)
  203. =================
  204. */
  205. void PF_bprint (void)
  206. {
  207.     char        *s;
  208.     int            level;
  209.     
  210.     level = G_FLOAT(OFS_PARM0);
  211.  
  212.     s = PF_VarString(1);
  213.     SV_BroadcastPrintf (level, "%s", s);
  214. }
  215.  
  216. /*
  217. =================
  218. PF_sprint
  219.  
  220. single print to a specific client
  221.  
  222. sprint(clientent, value)
  223. =================
  224. */
  225. void PF_sprint (void)
  226. {
  227.     char        *s;
  228.     client_t    *client;
  229.     int            entnum;
  230.     int            level;
  231.     
  232.     entnum = G_EDICTNUM(OFS_PARM0);
  233.     level = G_FLOAT(OFS_PARM1);
  234.  
  235.     s = PF_VarString(2);
  236.     
  237.     if (entnum < 1 || entnum > MAX_CLIENTS)
  238.     {
  239.         Con_Printf ("tried to sprint to a non-client\n");
  240.         return;
  241.     }
  242.         
  243.     client = &svs.clients[entnum-1];
  244.     
  245.     SV_ClientPrintf (client, level, "%s", s);
  246. }
  247.  
  248.  
  249. /*
  250. =================
  251. PF_centerprint
  252.  
  253. single print to a specific client
  254.  
  255. centerprint(clientent, value)
  256. =================
  257. */
  258. void PF_centerprint (void)
  259. {
  260.     char        *s;
  261.     int            entnum;
  262.     client_t    *cl;
  263.     
  264.     entnum = G_EDICTNUM(OFS_PARM0);
  265.     s = PF_VarString(1);
  266.     
  267.     if (entnum < 1 || entnum > MAX_CLIENTS)
  268.     {
  269.         Con_Printf ("tried to sprint to a non-client\n");
  270.         return;
  271.     }
  272.         
  273.     cl = &svs.clients[entnum-1];
  274.  
  275.     ClientReliableWrite_Begin (cl, svc_centerprint, 2 + strlen(s));
  276.     ClientReliableWrite_String (cl, s);
  277. }
  278.  
  279.  
  280. /*
  281. =================
  282. PF_normalize
  283.  
  284. vector normalize(vector)
  285. =================
  286. */
  287. void PF_normalize (void)
  288. {
  289.     float    *value1;
  290.     vec3_t    newvalue;
  291.     float    new;
  292.     
  293.     value1 = G_VECTOR(OFS_PARM0);
  294.  
  295.     new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
  296.     new = sqrt(new);
  297.     
  298.     if (new == 0)
  299.         newvalue[0] = newvalue[1] = newvalue[2] = 0;
  300.     else
  301.     {
  302.         new = 1/new;
  303.         newvalue[0] = value1[0] * new;
  304.         newvalue[1] = value1[1] * new;
  305.         newvalue[2] = value1[2] * new;
  306.     }
  307.     
  308.     VectorCopy (newvalue, G_VECTOR(OFS_RETURN));    
  309. }
  310.  
  311. /*
  312. =================
  313. PF_vlen
  314.  
  315. scalar vlen(vector)
  316. =================
  317. */
  318. void PF_vlen (void)
  319. {
  320.     float    *value1;
  321.     float    new;
  322.     
  323.     value1 = G_VECTOR(OFS_PARM0);
  324.  
  325.     new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2];
  326.     new = sqrt(new);
  327.     
  328.     G_FLOAT(OFS_RETURN) = new;
  329. }
  330.  
  331. /*
  332. =================
  333. PF_vectoyaw
  334.  
  335. float vectoyaw(vector)
  336. =================
  337. */
  338. void PF_vectoyaw (void)
  339. {
  340.     float    *value1;
  341.     float    yaw;
  342.     
  343.     value1 = G_VECTOR(OFS_PARM0);
  344.  
  345.     if (value1[1] == 0 && value1[0] == 0)
  346.         yaw = 0;
  347.     else
  348.     {
  349.         yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
  350.         if (yaw < 0)
  351.             yaw += 360;
  352.     }
  353.  
  354.     G_FLOAT(OFS_RETURN) = yaw;
  355. }
  356.  
  357.  
  358. /*
  359. =================
  360. PF_vectoangles
  361.  
  362. vector vectoangles(vector)
  363. =================
  364. */
  365. void PF_vectoangles (void)
  366. {
  367.     float    *value1;
  368.     float    forward;
  369.     float    yaw, pitch;
  370.     
  371.     value1 = G_VECTOR(OFS_PARM0);
  372.  
  373.     if (value1[1] == 0 && value1[0] == 0)
  374.     {
  375.         yaw = 0;
  376.         if (value1[2] > 0)
  377.             pitch = 90;
  378.         else
  379.             pitch = 270;
  380.     }
  381.     else
  382.     {
  383.         yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
  384.         if (yaw < 0)
  385.             yaw += 360;
  386.  
  387.         forward = sqrt (value1[0]*value1[0] + value1[1]*value1[1]);
  388.         pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
  389.         if (pitch < 0)
  390.             pitch += 360;
  391.     }
  392.  
  393.     G_FLOAT(OFS_RETURN+0) = pitch;
  394.     G_FLOAT(OFS_RETURN+1) = yaw;
  395.     G_FLOAT(OFS_RETURN+2) = 0;
  396. }
  397.  
  398. /*
  399. =================
  400. PF_Random
  401.  
  402. Returns a number from 0<= num < 1
  403.  
  404. random()
  405. =================
  406. */
  407. void PF_random (void)
  408. {
  409.     float        num;
  410.         
  411.     num = (rand ()&0x7fff) / ((float)0x7fff);
  412.     
  413.     G_FLOAT(OFS_RETURN) = num;
  414. }
  415.  
  416.  
  417. /*
  418. =================
  419. PF_ambientsound
  420.  
  421. =================
  422. */
  423. void PF_ambientsound (void)
  424. {
  425.     char        **check;
  426.     char        *samp;
  427.     float        *pos;
  428.     float         vol, attenuation;
  429.     int            i, soundnum;
  430.  
  431.     pos = G_VECTOR (OFS_PARM0);            
  432.     samp = G_STRING(OFS_PARM1);
  433.     vol = G_FLOAT(OFS_PARM2);
  434.     attenuation = G_FLOAT(OFS_PARM3);
  435.     
  436. // check to see if samp was properly precached
  437.     for (soundnum=0, check = sv.sound_precache ; *check ; check++, soundnum++)
  438.         if (!strcmp(*check,samp))
  439.             break;
  440.             
  441.     if (!*check)
  442.     {
  443.         Con_Printf ("no precache: %s\n", samp);
  444.         return;
  445.     }
  446.  
  447. // add an svc_spawnambient command to the level signon packet
  448.  
  449.     MSG_WriteByte (&sv.signon,svc_spawnstaticsound);
  450.     for (i=0 ; i<3 ; i++)
  451.         MSG_WriteCoord(&sv.signon, pos[i]);
  452.  
  453.     MSG_WriteByte (&sv.signon, soundnum);
  454.  
  455.     MSG_WriteByte (&sv.signon, vol*255);
  456.     MSG_WriteByte (&sv.signon, attenuation*64);
  457.  
  458. }
  459.  
  460. /*
  461. =================
  462. PF_sound
  463.  
  464. Each entity can have eight independant sound sources, like voice,
  465. weapon, feet, etc.
  466.  
  467. Channel 0 is an auto-allocate channel, the others override anything
  468. allready running on that entity/channel pair.
  469.  
  470. An attenuation of 0 will play full volume everywhere in the level.
  471. Larger attenuations will drop off.
  472.  
  473. =================
  474. */
  475. void PF_sound (void)
  476. {
  477.     char        *sample;
  478.     int            channel;
  479.     edict_t        *entity;
  480.     int         volume;
  481.     float attenuation;
  482.         
  483.     entity = G_EDICT(OFS_PARM0);
  484.     channel = G_FLOAT(OFS_PARM1);
  485.     sample = G_STRING(OFS_PARM2);
  486.     volume = G_FLOAT(OFS_PARM3) * 255;
  487.     attenuation = G_FLOAT(OFS_PARM4);
  488.     
  489.     SV_StartSound (entity, channel, sample, volume, attenuation);
  490. }
  491.  
  492. /*
  493. =================
  494. PF_break
  495.  
  496. break()
  497. =================
  498. */
  499. void PF_break (void)
  500. {
  501. Con_Printf ("break statement\n");
  502. *(int *)-4 = 0;    // dump to debugger
  503. //    PR_RunError ("break statement");
  504. }
  505.  
  506. /*
  507. =================
  508. PF_traceline
  509.  
  510. Used for use tracing and shot targeting
  511. Traces are blocked by bbox and exact bsp entityes, and also slide box entities
  512. if the tryents flag is set.
  513.  
  514. traceline (vector1, vector2, tryents)
  515. =================
  516. */
  517. void PF_traceline (void)
  518. {
  519.     float    *v1, *v2;
  520.     trace_t    trace;
  521.     int        nomonsters;
  522.     edict_t    *ent;
  523.  
  524.     v1 = G_VECTOR(OFS_PARM0);
  525.     v2 = G_VECTOR(OFS_PARM1);
  526.     nomonsters = G_FLOAT(OFS_PARM2);
  527.     ent = G_EDICT(OFS_PARM3);
  528.  
  529.     trace = SV_Move (v1, vec3_origin, vec3_origin, v2, nomonsters, ent);
  530.  
  531.     pr_global_struct->trace_allsolid = trace.allsolid;
  532.     pr_global_struct->trace_startsolid = trace.startsolid;
  533.     pr_global_struct->trace_fraction = trace.fraction;
  534.     pr_global_struct->trace_inwater = trace.inwater;
  535.     pr_global_struct->trace_inopen = trace.inopen;
  536.     VectorCopy (trace.endpos, pr_global_struct->trace_endpos);
  537.     VectorCopy (trace.plane.normal, pr_global_struct->trace_plane_normal);
  538.     pr_global_struct->trace_plane_dist =  trace.plane.dist;    
  539.     if (trace.ent)
  540.         pr_global_struct->trace_ent = EDICT_TO_PROG(trace.ent);
  541.     else
  542.         pr_global_struct->trace_ent = EDICT_TO_PROG(sv.edicts);
  543. }
  544.  
  545. /*
  546. =================
  547. PF_checkpos
  548.  
  549. Returns true if the given entity can move to the given position from it's
  550. current position by walking or rolling.
  551. FIXME: make work...
  552. scalar checkpos (entity, vector)
  553. =================
  554. */
  555. void PF_checkpos (void)
  556. {
  557. }
  558.  
  559. //============================================================================
  560.  
  561. byte    checkpvs[MAX_MAP_LEAFS/8];
  562.  
  563. int PF_newcheckclient (int check)
  564. {
  565.     int        i;
  566.     byte    *pvs;
  567.     edict_t    *ent;
  568.     mleaf_t    *leaf;
  569.     vec3_t    org;
  570.  
  571. // cycle to the next one
  572.  
  573.     if (check < 1)
  574.         check = 1;
  575.     if (check > MAX_CLIENTS)
  576.         check = MAX_CLIENTS;
  577.  
  578.     if (check == MAX_CLIENTS)
  579.         i = 1;
  580.     else
  581.         i = check + 1;
  582.  
  583.     for ( ;  ; i++)
  584.     {
  585.         if (i == MAX_CLIENTS+1)
  586.             i = 1;
  587.  
  588.         ent = EDICT_NUM(i);
  589.  
  590.         if (i == check)
  591.             break;    // didn't find anything else
  592.  
  593.         if (ent->free)
  594.             continue;
  595.         if (ent->v.health <= 0)
  596.             continue;
  597.         if ((int)ent->v.flags & FL_NOTARGET)
  598.             continue;
  599.  
  600.     // anything that is a client, or has a client as an enemy
  601.         break;
  602.     }
  603.  
  604. // get the PVS for the entity
  605.     VectorAdd (ent->v.origin, ent->v.view_ofs, org);
  606.     leaf = Mod_PointInLeaf (org, sv.worldmodel);
  607.     pvs = Mod_LeafPVS (leaf, sv.worldmodel);
  608.     memcpy (checkpvs, pvs, (sv.worldmodel->numleafs+7)>>3 );
  609.  
  610.     return i;
  611. }
  612.  
  613. /*
  614. =================
  615. PF_checkclient
  616.  
  617. Returns a client (or object that has a client enemy) that would be a
  618. valid target.
  619.  
  620. If there are more than one valid options, they are cycled each frame
  621.  
  622. If (self.origin + self.viewofs) is not in the PVS of the current target,
  623. it is not returned at all.
  624.  
  625. name checkclient ()
  626. =================
  627. */
  628. #define    MAX_CHECK    16
  629. int c_invis, c_notvis;
  630. void PF_checkclient (void)
  631. {
  632.     edict_t    *ent, *self;
  633.     mleaf_t    *leaf;
  634.     int        l;
  635.     vec3_t    view;
  636.     
  637. // find a new check if on a new frame
  638.     if (sv.time - sv.lastchecktime >= 0.1)
  639.     {
  640.         sv.lastcheck = PF_newcheckclient (sv.lastcheck);
  641.         sv.lastchecktime = sv.time;
  642.     }
  643.  
  644. // return check if it might be visible    
  645.     ent = EDICT_NUM(sv.lastcheck);
  646.     if (ent->free || ent->v.health <= 0)
  647.     {
  648.         RETURN_EDICT(sv.edicts);
  649.         return;
  650.     }
  651.  
  652. // if current entity can't possibly see the check entity, return 0
  653.     self = PROG_TO_EDICT(pr_global_struct->self);
  654.     VectorAdd (self->v.origin, self->v.view_ofs, view);
  655.     leaf = Mod_PointInLeaf (view, sv.worldmodel);
  656.     l = (leaf - sv.worldmodel->leafs) - 1;
  657.     if ( (l<0) || !(checkpvs[l>>3] & (1<<(l&7)) ) )
  658.     {
  659. c_notvis++;
  660.         RETURN_EDICT(sv.edicts);
  661.         return;
  662.     }
  663.  
  664. // might be able to see it
  665. c_invis++;
  666.     RETURN_EDICT(ent);
  667. }
  668.  
  669. //============================================================================
  670.  
  671.  
  672. /*
  673. =================
  674. PF_stuffcmd
  675.  
  676. Sends text over to the client's execution buffer
  677.  
  678. stuffcmd (clientent, value)
  679. =================
  680. */
  681. void PF_stuffcmd (void)
  682. {
  683.     int        entnum;
  684.     char    *str;
  685.     client_t    *cl;
  686.     
  687.     entnum = G_EDICTNUM(OFS_PARM0);
  688.     if (entnum < 1 || entnum > MAX_CLIENTS)
  689.         PR_RunError ("Parm 0 not a client");
  690.     str = G_STRING(OFS_PARM1);    
  691.     
  692.     cl = &svs.clients[entnum-1];
  693.  
  694.     if (strcmp(str, "disconnect\n") == 0) {
  695.         // so long and thanks for all the fish
  696.         cl->drop = true;
  697.         return;
  698.     }
  699.  
  700.     ClientReliableWrite_Begin (cl, svc_stufftext, 2+strlen(str));
  701.     ClientReliableWrite_String (cl, str);
  702. }
  703.  
  704. /*
  705. =================
  706. PF_localcmd
  707.  
  708. Sends text over to the client's execution buffer
  709.  
  710. localcmd (string)
  711. =================
  712. */
  713. void PF_localcmd (void)
  714. {
  715.     char    *str;
  716.     
  717.     str = G_STRING(OFS_PARM0);    
  718.     Cbuf_AddText (str);
  719. }
  720.  
  721. /*
  722. =================
  723. PF_cvar
  724.  
  725. float cvar (string)
  726. =================
  727. */
  728. void PF_cvar (void)
  729. {
  730.     char    *str;
  731.     
  732.     str = G_STRING(OFS_PARM0);
  733.     
  734.     G_FLOAT(OFS_RETURN) = Cvar_VariableValue (str);
  735. }
  736.  
  737. /*
  738. =================
  739. PF_cvar_set
  740.  
  741. float cvar (string)
  742. =================
  743. */
  744. void PF_cvar_set (void)
  745. {
  746.     char    *var, *val;
  747.     
  748.     var = G_STRING(OFS_PARM0);
  749.     val = G_STRING(OFS_PARM1);
  750.     
  751.     Cvar_Set (var, val);
  752. }
  753.  
  754. /*
  755. =================
  756. PF_findradius
  757.  
  758. Returns a chain of entities that have origins within a spherical area
  759.  
  760. findradius (origin, radius)
  761. =================
  762. */
  763. void PF_findradius (void)
  764. {
  765.     edict_t    *ent, *chain;
  766.     float    rad;
  767.     float    *org;
  768.     vec3_t    eorg;
  769.     int        i, j;
  770.  
  771.     chain = (edict_t *)sv.edicts;
  772.     
  773.     org = G_VECTOR(OFS_PARM0);
  774.     rad = G_FLOAT(OFS_PARM1);
  775.  
  776.     ent = NEXT_EDICT(sv.edicts);
  777.     for (i=1 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
  778.     {
  779.         if (ent->free)
  780.             continue;
  781.         if (ent->v.solid == SOLID_NOT)
  782.             continue;
  783.         for (j=0 ; j<3 ; j++)
  784.             eorg[j] = org[j] - (ent->v.origin[j] + (ent->v.mins[j] + ent->v.maxs[j])*0.5);            
  785.         if (Length(eorg) > rad)
  786.             continue;
  787.             
  788.         ent->v.chain = EDICT_TO_PROG(chain);
  789.         chain = ent;
  790.     }
  791.  
  792.     RETURN_EDICT(chain);
  793. }
  794.  
  795.  
  796. /*
  797. =========
  798. PF_dprint
  799. =========
  800. */
  801. void PF_dprint (void)
  802. {
  803.     Con_Printf ("%s",PF_VarString(0));
  804. }
  805.  
  806. char    pr_string_temp[128];
  807.  
  808. void PF_ftos (void)
  809. {
  810.     float    v;
  811.     v = G_FLOAT(OFS_PARM0);
  812.     
  813.     if (v == (int)v)
  814.         sprintf (pr_string_temp, "%d",(int)v);
  815.     else
  816.         sprintf (pr_string_temp, "%5.1f",v);
  817.     G_INT(OFS_RETURN) = PR_SetString(pr_string_temp);
  818. }
  819.  
  820. void PF_fabs (void)
  821. {
  822.     float    v;
  823.     v = G_FLOAT(OFS_PARM0);
  824.     G_FLOAT(OFS_RETURN) = fabs(v);
  825. }
  826.  
  827. void PF_vtos (void)
  828. {
  829.     sprintf (pr_string_temp, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]);
  830.     G_INT(OFS_RETURN) = PR_SetString(pr_string_temp);
  831. }
  832.  
  833. void PF_Spawn (void)
  834. {
  835.     edict_t    *ed;
  836.     ed = ED_Alloc();
  837.     RETURN_EDICT(ed);
  838. }
  839.  
  840. void PF_Remove (void)
  841. {
  842.     edict_t    *ed;
  843.     
  844.     ed = G_EDICT(OFS_PARM0);
  845.     ED_Free (ed);
  846. }
  847.  
  848.  
  849. // entity (entity start, .string field, string match) find = #5;
  850. void PF_Find (void)
  851. {
  852.     int        e;    
  853.     int        f;
  854.     char    *s, *t;
  855.     edict_t    *ed;
  856.     
  857.     e = G_EDICTNUM(OFS_PARM0);
  858.     f = G_INT(OFS_PARM1);
  859.     s = G_STRING(OFS_PARM2);
  860.     if (!s)
  861.         PR_RunError ("PF_Find: bad search string");
  862.         
  863.     for (e++ ; e < sv.num_edicts ; e++)
  864.     {
  865.         ed = EDICT_NUM(e);
  866.         if (ed->free)
  867.             continue;
  868.         t = E_STRING(ed,f);
  869.         if (!t)
  870.             continue;
  871.         if (!strcmp(t,s))
  872.         {
  873.             RETURN_EDICT(ed);
  874.             return;
  875.         }
  876.     }
  877.     
  878.     RETURN_EDICT(sv.edicts);
  879. }
  880.  
  881. void PR_CheckEmptyString (char *s)
  882. {
  883.     if (s[0] <= ' ')
  884.         PR_RunError ("Bad string");
  885. }
  886.  
  887. void PF_precache_file (void)
  888. {    // precache_file is only used to copy files with qcc, it does nothing
  889.     G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
  890. }
  891.  
  892. void PF_precache_sound (void)
  893. {
  894.     char    *s;
  895.     int        i;
  896.     
  897.     if (sv.state != ss_loading)
  898.         PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions");
  899.         
  900.     s = G_STRING(OFS_PARM0);
  901.     G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
  902.     PR_CheckEmptyString (s);
  903.     
  904.     for (i=0 ; i<MAX_SOUNDS ; i++)
  905.     {
  906.         if (!sv.sound_precache[i])
  907.         {
  908.             sv.sound_precache[i] = s;
  909.             return;
  910.         }
  911.         if (!strcmp(sv.sound_precache[i], s))
  912.             return;
  913.     }
  914.     PR_RunError ("PF_precache_sound: overflow");
  915. }
  916.  
  917. void PF_precache_model (void)
  918. {
  919.     char    *s;
  920.     int        i;
  921.     
  922.     if (sv.state != ss_loading)
  923.         PR_RunError ("PF_Precache_*: Precache can only be done in spawn functions");
  924.         
  925.     s = G_STRING(OFS_PARM0);
  926.     G_INT(OFS_RETURN) = G_INT(OFS_PARM0);
  927.     PR_CheckEmptyString (s);
  928.  
  929.     for (i=0 ; i<MAX_MODELS ; i++)
  930.     {
  931.         if (!sv.model_precache[i])
  932.         {
  933.             sv.model_precache[i] = s;
  934.             return;
  935.         }
  936.         if (!strcmp(sv.model_precache[i], s))
  937.             return;
  938.     }
  939.     PR_RunError ("PF_precache_model: overflow");
  940. }
  941.  
  942.  
  943. void PF_coredump (void)
  944. {
  945.     ED_PrintEdicts ();
  946. }
  947.  
  948. void PF_traceon (void)
  949. {
  950.     pr_trace = true;
  951. }
  952.  
  953. void PF_traceoff (void)
  954. {
  955.     pr_trace = false;
  956. }
  957.  
  958. void PF_eprint (void)
  959. {
  960.     ED_PrintNum (G_EDICTNUM(OFS_PARM0));
  961. }
  962.  
  963. /*
  964. ===============
  965. PF_walkmove
  966.  
  967. float(float yaw, float dist) walkmove
  968. ===============
  969. */
  970. void PF_walkmove (void)
  971. {
  972.     edict_t    *ent;
  973.     float    yaw, dist;
  974.     vec3_t    move;
  975.     dfunction_t    *oldf;
  976.     int     oldself;
  977.     
  978.     ent = PROG_TO_EDICT(pr_global_struct->self);
  979.     yaw = G_FLOAT(OFS_PARM0);
  980.     dist = G_FLOAT(OFS_PARM1);
  981.     
  982.     if ( !( (int)ent->v.flags & (FL_ONGROUND|FL_FLY|FL_SWIM) ) )
  983.     {
  984.         G_FLOAT(OFS_RETURN) = 0;
  985.         return;
  986.     }
  987.  
  988.     yaw = yaw*M_PI*2 / 360;
  989.     
  990.     move[0] = cos(yaw)*dist;
  991.     move[1] = sin(yaw)*dist;
  992.     move[2] = 0;
  993.  
  994. // save program state, because SV_movestep may call other progs
  995.     oldf = pr_xfunction;
  996.     oldself = pr_global_struct->self;
  997.     
  998.     G_FLOAT(OFS_RETURN) = SV_movestep(ent, move, true);
  999.     
  1000.     
  1001. // restore program state
  1002.     pr_xfunction = oldf;
  1003.     pr_global_struct->self = oldself;
  1004. }
  1005.  
  1006. /*
  1007. ===============
  1008. PF_droptofloor
  1009.  
  1010. void() droptofloor
  1011. ===============
  1012. */
  1013. void PF_droptofloor (void)
  1014. {
  1015.     edict_t        *ent;
  1016.     vec3_t        end;
  1017.     trace_t        trace;
  1018.     
  1019.     ent = PROG_TO_EDICT(pr_global_struct->self);
  1020.  
  1021.     VectorCopy (ent->v.origin, end);
  1022.     end[2] -= 256;
  1023.     
  1024.     trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent);
  1025.  
  1026.     if (trace.fraction == 1 || trace.allsolid)
  1027.         G_FLOAT(OFS_RETURN) = 0;
  1028.     else
  1029.     {
  1030.         VectorCopy (trace.endpos, ent->v.origin);
  1031.         SV_LinkEdict (ent, false);
  1032.         ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
  1033.         ent->v.groundentity = EDICT_TO_PROG(trace.ent);
  1034.         G_FLOAT(OFS_RETURN) = 1;
  1035.     }
  1036. }
  1037.  
  1038. /*
  1039. ===============
  1040. PF_lightstyle
  1041.  
  1042. void(float style, string value) lightstyle
  1043. ===============
  1044. */
  1045. void PF_lightstyle (void)
  1046. {
  1047.     int        style;
  1048.     char    *val;
  1049.     client_t    *client;
  1050.     int            j;
  1051.     
  1052.     style = G_FLOAT(OFS_PARM0);
  1053.     val = G_STRING(OFS_PARM1);
  1054.  
  1055. // change the string in sv
  1056.     sv.lightstyles[style] = val;
  1057.     
  1058. // send message to all clients on this server
  1059.     if (sv.state != ss_active)
  1060.         return;
  1061.     
  1062.     for (j=0, client = svs.clients ; j<MAX_CLIENTS ; j++, client++)
  1063.         if ( client->state == cs_spawned )
  1064.         {
  1065.             ClientReliableWrite_Begin (client, svc_lightstyle, strlen(val)+3);
  1066.             ClientReliableWrite_Char (client, style);
  1067.             ClientReliableWrite_String (client, val);
  1068.         }
  1069. }
  1070.  
  1071. void PF_rint (void)
  1072. {
  1073.     float    f;
  1074.     f = G_FLOAT(OFS_PARM0);
  1075.     if (f > 0)
  1076.         G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
  1077.     else
  1078.         G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
  1079. }
  1080. void PF_floor (void)
  1081. {
  1082.     G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0));
  1083. }
  1084. void PF_ceil (void)
  1085. {
  1086.     G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0));
  1087. }
  1088.  
  1089.  
  1090. /*
  1091. =============
  1092. PF_checkbottom
  1093. =============
  1094. */
  1095. void PF_checkbottom (void)
  1096. {
  1097.     edict_t    *ent;
  1098.     
  1099.     ent = G_EDICT(OFS_PARM0);
  1100.  
  1101.     G_FLOAT(OFS_RETURN) = SV_CheckBottom (ent);
  1102. }
  1103.  
  1104. /*
  1105. =============
  1106. PF_pointcontents
  1107. =============
  1108. */
  1109. void PF_pointcontents (void)
  1110. {
  1111.     float    *v;
  1112.     
  1113.     v = G_VECTOR(OFS_PARM0);
  1114.  
  1115.     G_FLOAT(OFS_RETURN) = SV_PointContents (v);    
  1116. }
  1117.  
  1118. /*
  1119. =============
  1120. PF_nextent
  1121.  
  1122. entity nextent(entity)
  1123. =============
  1124. */
  1125. void PF_nextent (void)
  1126. {
  1127.     int        i;
  1128.     edict_t    *ent;
  1129.     
  1130.     i = G_EDICTNUM(OFS_PARM0);
  1131.     while (1)
  1132.     {
  1133.         i++;
  1134.         if (i == sv.num_edicts)
  1135.         {
  1136.             RETURN_EDICT(sv.edicts);
  1137.             return;
  1138.         }
  1139.         ent = EDICT_NUM(i);
  1140.         if (!ent->free)
  1141.         {
  1142.             RETURN_EDICT(ent);
  1143.             return;
  1144.         }
  1145.     }
  1146. }
  1147.  
  1148. /*
  1149. =============
  1150. PF_aim
  1151.  
  1152. Pick a vector for the player to shoot along
  1153. vector aim(entity, missilespeed)
  1154. =============
  1155. */
  1156. //cvar_t    sv_aim = {"sv_aim", "0.93"};
  1157. cvar_t    sv_aim = {"sv_aim", "2"};
  1158. void PF_aim (void)
  1159. {
  1160.     edict_t    *ent, *check, *bestent;
  1161.     vec3_t    start, dir, end, bestdir;
  1162.     int        i, j;
  1163.     trace_t    tr;
  1164.     float    dist, bestdist;
  1165.     float    speed;
  1166.     char    *noaim;
  1167.  
  1168.     ent = G_EDICT(OFS_PARM0);
  1169.     speed = G_FLOAT(OFS_PARM1);
  1170.  
  1171.     VectorCopy (ent->v.origin, start);
  1172.     start[2] += 20;
  1173.  
  1174. // noaim option
  1175.     i = NUM_FOR_EDICT(ent);
  1176.     if (i>0 && i<MAX_CLIENTS)
  1177.     {
  1178.         noaim = Info_ValueForKey (svs.clients[i-1].userinfo, "noaim");
  1179.         if (atoi(noaim) > 0)
  1180.         {
  1181.             VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
  1182.             return;
  1183.         }
  1184.     }
  1185.  
  1186. // try sending a trace straight
  1187.     VectorCopy (pr_global_struct->v_forward, dir);
  1188.     VectorMA (start, 2048, dir, end);
  1189.     tr = SV_Move (start, vec3_origin, vec3_origin, end, false, ent);
  1190.     if (tr.ent && tr.ent->v.takedamage == DAMAGE_AIM
  1191.     && (!teamplay.value || ent->v.team <=0 || ent->v.team != tr.ent->v.team) )
  1192.     {
  1193.         VectorCopy (pr_global_struct->v_forward, G_VECTOR(OFS_RETURN));
  1194.         return;
  1195.     }
  1196.  
  1197.  
  1198. // try all possible entities
  1199.     VectorCopy (dir, bestdir);
  1200.     bestdist = sv_aim.value;
  1201.     bestent = NULL;
  1202.     
  1203.     check = NEXT_EDICT(sv.edicts);
  1204.     for (i=1 ; i<sv.num_edicts ; i++, check = NEXT_EDICT(check) )
  1205.     {
  1206.         if (check->v.takedamage != DAMAGE_AIM)
  1207.             continue;
  1208.         if (check == ent)
  1209.             continue;
  1210.         if (teamplay.value && ent->v.team > 0 && ent->v.team == check->v.team)
  1211.             continue;    // don't aim at teammate
  1212.         for (j=0 ; j<3 ; j++)
  1213.             end[j] = check->v.origin[j]
  1214.             + 0.5*(check->v.mins[j] + check->v.maxs[j]);
  1215.         VectorSubtract (end, start, dir);
  1216.         VectorNormalize (dir);
  1217.         dist = DotProduct (dir, pr_global_struct->v_forward);
  1218.         if (dist < bestdist)
  1219.             continue;    // to far to turn
  1220.         tr = SV_Move (start, vec3_origin, vec3_origin, end, false, ent);
  1221.         if (tr.ent == check)
  1222.         {    // can shoot at this one
  1223.             bestdist = dist;
  1224.             bestent = check;
  1225.         }
  1226.     }
  1227.     
  1228.     if (bestent)
  1229.     {
  1230.         VectorSubtract (bestent->v.origin, ent->v.origin, dir);
  1231.         dist = DotProduct (dir, pr_global_struct->v_forward);
  1232.         VectorScale (pr_global_struct->v_forward, dist, end);
  1233.         end[2] = dir[2];
  1234.         VectorNormalize (end);
  1235.         VectorCopy (end, G_VECTOR(OFS_RETURN));    
  1236.     }
  1237.     else
  1238.     {
  1239.         VectorCopy (bestdir, G_VECTOR(OFS_RETURN));
  1240.     }
  1241. }
  1242.  
  1243. /*
  1244. ==============
  1245. PF_changeyaw
  1246.  
  1247. This was a major timewaster in progs, so it was converted to C
  1248. ==============
  1249. */
  1250. void PF_changeyaw (void)
  1251. {
  1252.     edict_t        *ent;
  1253.     float        ideal, current, move, speed;
  1254.     
  1255.     ent = PROG_TO_EDICT(pr_global_struct->self);
  1256.     current = anglemod( ent->v.angles[1] );
  1257.     ideal = ent->v.ideal_yaw;
  1258.     speed = ent->v.yaw_speed;
  1259.     
  1260.     if (current == ideal)
  1261.         return;
  1262.     move = ideal - current;
  1263.     if (ideal > current)
  1264.     {
  1265.         if (move >= 180)
  1266.             move = move - 360;
  1267.     }
  1268.     else
  1269.     {
  1270.         if (move <= -180)
  1271.             move = move + 360;
  1272.     }
  1273.     if (move > 0)
  1274.     {
  1275.         if (move > speed)
  1276.             move = speed;
  1277.     }
  1278.     else
  1279.     {
  1280.         if (move < -speed)
  1281.             move = -speed;
  1282.     }
  1283.     
  1284.     ent->v.angles[1] = anglemod (current + move);
  1285. }
  1286.  
  1287. /*
  1288. ===============================================================================
  1289.  
  1290. MESSAGE WRITING
  1291.  
  1292. ===============================================================================
  1293. */
  1294.  
  1295. #define    MSG_BROADCAST    0        // unreliable to all
  1296. #define    MSG_ONE            1        // reliable to one (msg_entity)
  1297. #define    MSG_ALL            2        // reliable to all
  1298. #define    MSG_INIT        3        // write to the init string
  1299. #define    MSG_MULTICAST    4        // for multicast()
  1300.  
  1301. sizebuf_t *WriteDest (void)
  1302. {
  1303.     int        entnum;
  1304.     int        dest;
  1305.     edict_t    *ent;
  1306.  
  1307.     dest = G_FLOAT(OFS_PARM0);
  1308.     switch (dest)
  1309.     {
  1310.     case MSG_BROADCAST:
  1311.         return &sv.datagram;
  1312.     
  1313.     case MSG_ONE:
  1314.         SV_Error("Shouldn't be at MSG_ONE");
  1315. #if 0
  1316.         ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
  1317.         entnum = NUM_FOR_EDICT(ent);
  1318.         if (entnum < 1 || entnum > MAX_CLIENTS)
  1319.             PR_RunError ("WriteDest: not a client");
  1320.         return &svs.clients[entnum-1].netchan.message;
  1321. #endif
  1322.         
  1323.     case MSG_ALL:
  1324.         return &sv.reliable_datagram;
  1325.     
  1326.     case MSG_INIT:
  1327.         if (sv.state != ss_loading)
  1328.             PR_RunError ("PF_Write_*: MSG_INIT can only be written in spawn functions");
  1329.         return &sv.signon;
  1330.  
  1331.     case MSG_MULTICAST:
  1332.         return &sv.multicast;
  1333.  
  1334.     default:
  1335.         PR_RunError ("WriteDest: bad destination");
  1336.         break;
  1337.     }
  1338.     
  1339.     return NULL;
  1340. }
  1341.  
  1342. static client_t *Write_GetClient(void)
  1343. {
  1344.     int        entnum;
  1345.     edict_t    *ent;
  1346.  
  1347.     ent = PROG_TO_EDICT(pr_global_struct->msg_entity);
  1348.     entnum = NUM_FOR_EDICT(ent);
  1349.     if (entnum < 1 || entnum > MAX_CLIENTS)
  1350.         PR_RunError ("WriteDest: not a client");
  1351.     return &svs.clients[entnum-1];
  1352. }
  1353.  
  1354.  
  1355. void PF_WriteByte (void)
  1356. {
  1357.     if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
  1358.         client_t *cl = Write_GetClient();
  1359.         ClientReliableCheckBlock(cl, 1);
  1360.         ClientReliableWrite_Byte(cl, G_FLOAT(OFS_PARM1));
  1361.     } else
  1362.         MSG_WriteByte (WriteDest(), G_FLOAT(OFS_PARM1));
  1363. }
  1364.  
  1365. void PF_WriteChar (void)
  1366. {
  1367.     if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
  1368.         client_t *cl = Write_GetClient();
  1369.         ClientReliableCheckBlock(cl, 1);
  1370.         ClientReliableWrite_Char(cl, G_FLOAT(OFS_PARM1));
  1371.     } else
  1372.         MSG_WriteChar (WriteDest(), G_FLOAT(OFS_PARM1));
  1373. }
  1374.  
  1375. void PF_WriteShort (void)
  1376. {
  1377.     if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
  1378.         client_t *cl = Write_GetClient();
  1379.         ClientReliableCheckBlock(cl, 2);
  1380.         ClientReliableWrite_Short(cl, G_FLOAT(OFS_PARM1));
  1381.     } else
  1382.         MSG_WriteShort (WriteDest(), G_FLOAT(OFS_PARM1));
  1383. }
  1384.  
  1385. void PF_WriteLong (void)
  1386. {
  1387.     if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
  1388.         client_t *cl = Write_GetClient();
  1389.         ClientReliableCheckBlock(cl, 4);
  1390.         ClientReliableWrite_Long(cl, G_FLOAT(OFS_PARM1));
  1391.     } else
  1392.         MSG_WriteLong (WriteDest(), G_FLOAT(OFS_PARM1));
  1393. }
  1394.  
  1395. void PF_WriteAngle (void)
  1396. {
  1397.     if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
  1398.         client_t *cl = Write_GetClient();
  1399.         ClientReliableCheckBlock(cl, 1);
  1400.         ClientReliableWrite_Angle(cl, G_FLOAT(OFS_PARM1));
  1401.     } else
  1402.         MSG_WriteAngle (WriteDest(), G_FLOAT(OFS_PARM1));
  1403. }
  1404.  
  1405. void PF_WriteCoord (void)
  1406. {
  1407.     if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
  1408.         client_t *cl = Write_GetClient();
  1409.         ClientReliableCheckBlock(cl, 2);
  1410.         ClientReliableWrite_Coord(cl, G_FLOAT(OFS_PARM1));
  1411.     } else
  1412.         MSG_WriteCoord (WriteDest(), G_FLOAT(OFS_PARM1));
  1413. }
  1414.  
  1415. void PF_WriteString (void)
  1416. {
  1417.     if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
  1418.         client_t *cl = Write_GetClient();
  1419.         ClientReliableCheckBlock(cl, 1+strlen(G_STRING(OFS_PARM1)));
  1420.         ClientReliableWrite_String(cl, G_STRING(OFS_PARM1));
  1421.     } else
  1422.         MSG_WriteString (WriteDest(), G_STRING(OFS_PARM1));
  1423. }
  1424.  
  1425.  
  1426. void PF_WriteEntity (void)
  1427. {
  1428.     if (G_FLOAT(OFS_PARM0) == MSG_ONE) {
  1429.         client_t *cl = Write_GetClient();
  1430.         ClientReliableCheckBlock(cl, 2);
  1431.         ClientReliableWrite_Short(cl, G_EDICTNUM(OFS_PARM1));
  1432.     } else
  1433.         MSG_WriteShort (WriteDest(), G_EDICTNUM(OFS_PARM1));
  1434. }
  1435.  
  1436. //=============================================================================
  1437.  
  1438. int SV_ModelIndex (char *name);
  1439.  
  1440. void PF_makestatic (void)
  1441. {
  1442.     edict_t    *ent;
  1443.     int        i;
  1444.     
  1445.     ent = G_EDICT(OFS_PARM0);
  1446.  
  1447.     MSG_WriteByte (&sv.signon,svc_spawnstatic);
  1448.  
  1449.     MSG_WriteByte (&sv.signon, SV_ModelIndex(PR_GetString(ent->v.model)));
  1450.  
  1451.     MSG_WriteByte (&sv.signon, ent->v.frame);
  1452.     MSG_WriteByte (&sv.signon, ent->v.colormap);
  1453.     MSG_WriteByte (&sv.signon, ent->v.skin);
  1454.     for (i=0 ; i<3 ; i++)
  1455.     {
  1456.         MSG_WriteCoord(&sv.signon, ent->v.origin[i]);
  1457.         MSG_WriteAngle(&sv.signon, ent->v.angles[i]);
  1458.     }
  1459.  
  1460. // throw the entity away now
  1461.     ED_Free (ent);
  1462. }
  1463.  
  1464. //=============================================================================
  1465.  
  1466. /*
  1467. ==============
  1468. PF_setspawnparms
  1469. ==============
  1470. */
  1471. void PF_setspawnparms (void)
  1472. {
  1473.     edict_t    *ent;
  1474.     int        i;
  1475.     client_t    *client;
  1476.  
  1477.     ent = G_EDICT(OFS_PARM0);
  1478.     i = NUM_FOR_EDICT(ent);
  1479.     if (i < 1 || i > MAX_CLIENTS)
  1480.         PR_RunError ("Entity is not a client");
  1481.  
  1482.     // copy spawn parms out of the client_t
  1483.     client = svs.clients + (i-1);
  1484.  
  1485.     for (i=0 ; i< NUM_SPAWN_PARMS ; i++)
  1486.         (&pr_global_struct->parm1)[i] = client->spawn_parms[i];
  1487. }
  1488.  
  1489. /*
  1490. ==============
  1491. PF_changelevel
  1492. ==============
  1493. */
  1494. void PF_changelevel (void)
  1495. {
  1496.     char    *s;
  1497.     static    int    last_spawncount;
  1498.  
  1499. // make sure we don't issue two changelevels
  1500.     if (svs.spawncount == last_spawncount)
  1501.         return;
  1502.     last_spawncount = svs.spawncount;
  1503.     
  1504.     s = G_STRING(OFS_PARM0);
  1505.     Cbuf_AddText (va("map %s\n",s));
  1506. }
  1507.  
  1508.  
  1509. /*
  1510. ==============
  1511. PF_logfrag
  1512.  
  1513. logfrag (killer, killee)
  1514. ==============
  1515. */
  1516. void PF_logfrag (void)
  1517. {
  1518.     edict_t    *ent1, *ent2;
  1519.     int        e1, e2;
  1520.     char    *s;
  1521.  
  1522.     ent1 = G_EDICT(OFS_PARM0);
  1523.     ent2 = G_EDICT(OFS_PARM1);
  1524.  
  1525.     e1 = NUM_FOR_EDICT(ent1);
  1526.     e2 = NUM_FOR_EDICT(ent2);
  1527.     
  1528.     if (e1 < 1 || e1 > MAX_CLIENTS
  1529.     || e2 < 1 || e2 > MAX_CLIENTS)
  1530.         return;
  1531.     
  1532.     s = va("\\%s\\%s\\\n",svs.clients[e1-1].name, svs.clients[e2-1].name);
  1533.  
  1534.     SZ_Print (&svs.log[svs.logsequence&1], s);
  1535.     if (sv_fraglogfile) {
  1536.         fprintf (sv_fraglogfile, s);
  1537.         fflush (sv_fraglogfile);
  1538.     }
  1539. }
  1540.  
  1541.  
  1542. /*
  1543. ==============
  1544. PF_infokey
  1545.  
  1546. string(entity e, string key) infokey
  1547. ==============
  1548. */
  1549. void PF_infokey (void)
  1550. {
  1551.     edict_t    *e;
  1552.     int        e1;
  1553.     char    *value;
  1554.     char    *key;
  1555.     static    char ov[256];
  1556.  
  1557.     e = G_EDICT(OFS_PARM0);
  1558.     e1 = NUM_FOR_EDICT(e);
  1559.     key = G_STRING(OFS_PARM1);
  1560.  
  1561.     if (e1 == 0) {
  1562.         if ((value = Info_ValueForKey (svs.info, key)) == NULL ||
  1563.             !*value)
  1564.             value = Info_ValueForKey(localinfo, key);
  1565.     } else if (e1 <= MAX_CLIENTS) {
  1566.         if (!strcmp(key, "ip"))
  1567.             value = strcpy(ov, NET_BaseAdrToString (svs.clients[e1-1].netchan.remote_address));
  1568.         else if (!strcmp(key, "ping")) {
  1569.             int ping = SV_CalcPing (&svs.clients[e1-1]);
  1570.             sprintf(ov, "%d", ping);
  1571.             value = ov;
  1572.         } else
  1573.             value = Info_ValueForKey (svs.clients[e1-1].userinfo, key);
  1574.     } else
  1575.         value = "";
  1576.  
  1577.     RETURN_STRING(value);
  1578. }
  1579.  
  1580. /*
  1581. ==============
  1582. PF_stof
  1583.  
  1584. float(string s) stof
  1585. ==============
  1586. */
  1587. void PF_stof (void)
  1588. {
  1589.     char    *s;
  1590.  
  1591.     s = G_STRING(OFS_PARM0);
  1592.  
  1593.     G_FLOAT(OFS_RETURN) = atof(s);
  1594. }
  1595.  
  1596.  
  1597. /*
  1598. ==============
  1599. PF_multicast
  1600.  
  1601. void(vector where, float set) multicast
  1602. ==============
  1603. */
  1604. void PF_multicast (void)
  1605. {
  1606.     float    *o;
  1607.     int        to;
  1608.  
  1609.     o = G_VECTOR(OFS_PARM0);
  1610.     to = G_FLOAT(OFS_PARM1);
  1611.  
  1612.     SV_Multicast (o, to);
  1613. }
  1614.  
  1615.  
  1616. void PF_Fixme (void)
  1617. {
  1618.     PR_RunError ("unimplemented bulitin");
  1619. }
  1620.  
  1621.  
  1622.  
  1623. builtin_t pr_builtin[] =
  1624. {
  1625.     PF_Fixme,
  1626. PF_makevectors,    // void(entity e)    makevectors         = #1;
  1627. PF_setorigin,    // void(entity e, vector o) setorigin    = #2;
  1628. PF_setmodel,    // void(entity e, string m) setmodel    = #3;
  1629. PF_setsize,    // void(entity e, vector min, vector max) setsize = #4;
  1630. PF_Fixme,    // void(entity e, vector min, vector max) setabssize = #5;
  1631. PF_break,    // void() break                        = #6;
  1632. PF_random,    // float() random                        = #7;
  1633. PF_sound,    // void(entity e, float chan, string samp) sound = #8;
  1634. PF_normalize,    // vector(vector v) normalize            = #9;
  1635. PF_error,    // void(string e) error                = #10;
  1636. PF_objerror,    // void(string e) objerror                = #11;
  1637. PF_vlen,    // float(vector v) vlen                = #12;
  1638. PF_vectoyaw,    // float(vector v) vectoyaw        = #13;
  1639. PF_Spawn,    // entity() spawn                        = #14;
  1640. PF_Remove,    // void(entity e) remove                = #15;
  1641. PF_traceline,    // float(vector v1, vector v2, float tryents) traceline = #16;
  1642. PF_checkclient,    // entity() clientlist                    = #17;
  1643. PF_Find,    // entity(entity start, .string fld, string match) find = #18;
  1644. PF_precache_sound,    // void(string s) precache_sound        = #19;
  1645. PF_precache_model,    // void(string s) precache_model        = #20;
  1646. PF_stuffcmd,    // void(entity client, string s)stuffcmd = #21;
  1647. PF_findradius,    // entity(vector org, float rad) findradius = #22;
  1648. PF_bprint,    // void(string s) bprint                = #23;
  1649. PF_sprint,    // void(entity client, string s) sprint = #24;
  1650. PF_dprint,    // void(string s) dprint                = #25;
  1651. PF_ftos,    // void(string s) ftos                = #26;
  1652. PF_vtos,    // void(string s) vtos                = #27;
  1653. PF_coredump,
  1654. PF_traceon,
  1655. PF_traceoff,
  1656. PF_eprint,    // void(entity e) debug print an entire entity
  1657. PF_walkmove, // float(float yaw, float dist) walkmove
  1658. PF_Fixme, // float(float yaw, float dist) walkmove
  1659. PF_droptofloor,
  1660. PF_lightstyle,
  1661. PF_rint,
  1662. PF_floor,
  1663. PF_ceil,
  1664. PF_Fixme,
  1665. PF_checkbottom,
  1666. PF_pointcontents,
  1667. PF_Fixme,
  1668. PF_fabs,
  1669. PF_aim,
  1670. PF_cvar,
  1671. PF_localcmd,
  1672. PF_nextent,
  1673. PF_Fixme,
  1674. PF_changeyaw,
  1675. PF_Fixme,
  1676. PF_vectoangles,
  1677.  
  1678. PF_WriteByte,
  1679. PF_WriteChar,
  1680. PF_WriteShort,
  1681. PF_WriteLong,
  1682. PF_WriteCoord,
  1683. PF_WriteAngle,
  1684. PF_WriteString,
  1685. PF_WriteEntity,
  1686.  
  1687. PF_Fixme,
  1688. PF_Fixme,
  1689. PF_Fixme,
  1690. PF_Fixme,
  1691. PF_Fixme,
  1692. PF_Fixme,
  1693. PF_Fixme,
  1694.  
  1695. SV_MoveToGoal,
  1696. PF_precache_file,
  1697. PF_makestatic,
  1698.  
  1699. PF_changelevel,
  1700. PF_Fixme,
  1701.  
  1702. PF_cvar_set,
  1703. PF_centerprint,
  1704.  
  1705. PF_ambientsound,
  1706.  
  1707. PF_precache_model,
  1708. PF_precache_sound,        // precache_sound2 is different only for qcc
  1709. PF_precache_file,
  1710.  
  1711. PF_setspawnparms,
  1712.  
  1713. PF_logfrag,
  1714.  
  1715. PF_infokey,
  1716. PF_stof,
  1717. PF_multicast
  1718. };
  1719.  
  1720. builtin_t *pr_builtins = pr_builtin;
  1721. int pr_numbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]);
  1722.  
  1723.