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