pr_cmds.c 32 KB

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