PageRenderTime 79ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/quakeforge/trunk/libs/gamecode/builtins/pr_cmds.c

#
C | 672 lines | 457 code | 91 blank | 124 comment | 59 complexity | 51f2c81591646e5a23492c8dfee8f186 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, AGPL-3.0, AGPL-1.0, Unlicense
  1. /*
  2. pr_cmds.c
  3. (description)
  4. Copyright (C) 1996-1997 Id Software, Inc.
  5. This program is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License
  7. as published by the Free Software Foundation; either version 2
  8. of the License, or (at your option) any later version.
  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. See the GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to:
  15. Free Software Foundation, Inc.
  16. 59 Temple Place - Suite 330
  17. Boston, MA 02111-1307, USA
  18. */
  19. #ifdef HAVE_CONFIG_H
  20. # include "config.h"
  21. #endif
  22. static __attribute__ ((used)) const char rcsid[] =
  23. "$Id: pr_cmds.c 11716 2007-06-09 09:43:21Z taniwha $";
  24. #ifdef HAVE_ERRNO_H
  25. # include <errno.h>
  26. #endif
  27. #ifdef HAVE_STRING_H
  28. # include <string.h>
  29. #endif
  30. #ifdef HAVE_STRINGS_H
  31. # include <strings.h>
  32. #endif
  33. #include <stdlib.h>
  34. #include "QF/cvar.h"
  35. #include "QF/dstring.h"
  36. #include "QF/mathlib.h"
  37. #include "QF/progs.h"
  38. #include "QF/sys.h"
  39. #include "QF/zone.h"
  40. #include "compat.h"
  41. #include "QF/csqc.h"
  42. #define U __attribute__ ((used))
  43. static U void (*const gib_progs_init)(progs_t *) = GIB_Progs_Init;
  44. #undef U
  45. VISIBLE const char *pr_gametype = "";
  46. /* BUILT-IN FUNCTIONS */
  47. VISIBLE char *
  48. PF_VarString (progs_t *pr, int first)
  49. {
  50. char *out, *dst;
  51. const char *src;
  52. int len, i;
  53. for (len = 0, i = first; i < pr->pr_argc; i++)
  54. len += strlen (P_GSTRING (pr, i));
  55. dst = out = Hunk_TempAlloc (len + 1);
  56. for (i = first; i < pr->pr_argc; i++) {
  57. src = P_GSTRING (pr, i);
  58. while (*src)
  59. *dst++ = *src++;
  60. }
  61. *dst = 0;
  62. return out;
  63. }
  64. /*
  65. vector (vector v) normalize
  66. */
  67. static void
  68. PF_normalize (progs_t *pr)
  69. {
  70. float new;
  71. float *value1;
  72. vec3_t newvalue;
  73. value1 = P_VECTOR (pr, 0);
  74. new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2] *
  75. value1[2];
  76. new = sqrt (new);
  77. if (new == 0)
  78. newvalue[0] = newvalue[1] = newvalue[2] = 0;
  79. else {
  80. new = 1 / new;
  81. newvalue[0] = value1[0] * new;
  82. newvalue[1] = value1[1] * new;
  83. newvalue[2] = value1[2] * new;
  84. }
  85. VectorCopy (newvalue, R_VECTOR (pr));
  86. }
  87. /*
  88. float (vector v) vlen
  89. */
  90. static void
  91. PF_vlen (progs_t *pr)
  92. {
  93. float new;
  94. float *value1;
  95. value1 = P_VECTOR (pr, 0);
  96. new = value1[0] * value1[0] + value1[1] * value1[1] + value1[2] *
  97. value1[2];
  98. new = sqrt (new);
  99. R_FLOAT (pr) = new;
  100. }
  101. /*
  102. float (vector v) vectoyaw
  103. */
  104. static void
  105. PF_vectoyaw (progs_t *pr)
  106. {
  107. float yaw;
  108. float *value1;
  109. value1 = P_VECTOR (pr, 0);
  110. if (value1[1] == 0 && value1[0] == 0)
  111. yaw = 0;
  112. else {
  113. yaw = (int) (atan2 (value1[1], value1[0]) * 180 / M_PI);
  114. if (yaw < 0)
  115. yaw += 360;
  116. }
  117. R_FLOAT (pr) = yaw;
  118. }
  119. /*
  120. vector (vector v) vectoangles
  121. */
  122. static void
  123. PF_vectoangles (progs_t *pr)
  124. {
  125. float forward, pitch, yaw;
  126. float *value1;
  127. value1 = P_VECTOR (pr, 0);
  128. if (value1[1] == 0 && value1[0] == 0) {
  129. yaw = 0;
  130. if (value1[2] > 0)
  131. pitch = 90;
  132. else
  133. pitch = 270;
  134. } else {
  135. yaw = (int) (atan2 (value1[1], value1[0]) * 180 / M_PI);
  136. if (yaw < 0)
  137. yaw += 360;
  138. forward = sqrt (value1[0] * value1[0] + value1[1] * value1[1]);
  139. pitch = (int) (atan2 (value1[2], forward) * 180 / M_PI);
  140. if (pitch < 0)
  141. pitch += 360;
  142. }
  143. R_VECTOR (pr)[0] = pitch;
  144. R_VECTOR (pr)[1] = yaw;
  145. R_VECTOR (pr)[2] = 0;
  146. }
  147. /*
  148. float () random
  149. Returns a number from 0<= num < 1
  150. */
  151. static void
  152. PF_random (progs_t *pr)
  153. {
  154. float num;
  155. num = (rand () & 0x7fff) / ((float) 0x7fff);
  156. R_FLOAT (pr) = num;
  157. }
  158. /*
  159. void () break
  160. */
  161. static void
  162. PF_break (progs_t *pr)
  163. {
  164. Sys_Printf ("break statement\n");
  165. PR_DumpState (pr);
  166. }
  167. /*
  168. float (string s) cvar
  169. */
  170. static void
  171. PF_cvar (progs_t *pr)
  172. {
  173. const char *str;
  174. str = P_GSTRING (pr, 0);
  175. R_FLOAT (pr) = Cvar_VariableValue (str);
  176. }
  177. /*
  178. void (string var, string val) cvar_set
  179. */
  180. static void
  181. PF_cvar_set (progs_t *pr)
  182. {
  183. const char *var_name, *val;
  184. cvar_t *var;
  185. var_name = P_GSTRING (pr, 0);
  186. val = P_GSTRING (pr, 1);
  187. var = Cvar_FindVar (var_name);
  188. if (!var)
  189. var = Cvar_FindAlias (var_name);
  190. if (!var) {
  191. Sys_Printf ("PF_cvar_set: variable %s not found\n", var_name);
  192. return;
  193. }
  194. Cvar_Set (var, val);
  195. }
  196. /*
  197. float (float f) fabs
  198. */
  199. static void
  200. PF_fabs (progs_t *pr)
  201. {
  202. float v;
  203. v = P_FLOAT (pr, 0);
  204. R_FLOAT (pr) = fabs (v);
  205. }
  206. /*
  207. entity (entity start, .(...) fld, ... match) find
  208. */
  209. static void
  210. PF_Find (progs_t *pr)
  211. {
  212. const char *s = 0, *t; // ev_string
  213. int i; // ev_vector
  214. int e, f;
  215. etype_t type;
  216. ddef_t *field_def;
  217. edict_t *ed;
  218. e = P_EDICTNUM (pr, 0);
  219. f = P_INT (pr, 1);
  220. field_def = PR_FieldAtOfs (pr, f);
  221. if (!field_def)
  222. PR_RunError (pr, "PF_Find: bad search field: %d", f);
  223. type = field_def->type & ~DEF_SAVEGLOBAL;
  224. if (type == ev_string) {
  225. s = P_GSTRING (pr, 2);
  226. if (!s)
  227. PR_RunError (pr, "PF_Find: bad search string");
  228. }
  229. for (e++; e < *pr->num_edicts; e++) {
  230. ed = EDICT_NUM (pr, e);
  231. if (ed->free)
  232. continue;
  233. switch (type) {
  234. case ev_string:
  235. t = E_GSTRING (pr, ed, f);
  236. if (!t)
  237. continue;
  238. if (strcmp (t, s))
  239. continue;
  240. RETURN_EDICT (pr, ed);
  241. return;
  242. case ev_float:
  243. if (P_FLOAT (pr, 2) != E_FLOAT (ed, f))
  244. continue;
  245. RETURN_EDICT (pr, ed);
  246. return;
  247. case ev_vector:
  248. for (i = 0; i <= 2; i++)
  249. if (P_FLOAT (pr, 2 + i) != E_FLOAT (ed, f + i))
  250. continue;
  251. RETURN_EDICT (pr, ed);
  252. return;
  253. case ev_integer:
  254. case ev_entity:
  255. if (P_INT (pr, 2) != E_INT (ed, f))
  256. continue;
  257. RETURN_EDICT (pr, ed);
  258. return;
  259. default:
  260. PR_Error (pr, "PF_Find: unsupported search field");
  261. }
  262. }
  263. RETURN_EDICT (pr, *pr->edicts);
  264. }
  265. /*
  266. void () coredump
  267. */
  268. static void
  269. PF_coredump (progs_t *pr)
  270. {
  271. ED_PrintEdicts (pr, "");
  272. }
  273. /*
  274. void () traceon
  275. */
  276. static void
  277. PF_traceon (progs_t *pr)
  278. {
  279. pr->pr_trace = true;
  280. pr->pr_trace_depth = pr->pr_depth;
  281. }
  282. /*
  283. void () traceoff
  284. */
  285. static void
  286. PF_traceoff (progs_t *pr)
  287. {
  288. pr->pr_trace = false;
  289. }
  290. /*
  291. void (entity e) eprint
  292. */
  293. static void
  294. PF_eprint (progs_t *pr)
  295. {
  296. ED_PrintNum (pr, P_EDICTNUM (pr, 0));
  297. }
  298. /*
  299. void (string s) dprint
  300. */
  301. static void
  302. PF_dprint (progs_t *pr)
  303. {
  304. Sys_Printf ("%s", PF_VarString (pr, 0));
  305. }
  306. /*
  307. float (float v) rint
  308. */
  309. static void
  310. PF_rint (progs_t *pr)
  311. {
  312. float f;
  313. f = P_FLOAT (pr, 0);
  314. if (f > 0)
  315. R_FLOAT (pr) = (int) (f + 0.5);
  316. else
  317. R_FLOAT (pr) = (int) (f - 0.5);
  318. }
  319. /*
  320. float (float v) floor
  321. */
  322. static void
  323. PF_floor (progs_t *pr)
  324. {
  325. R_FLOAT (pr) = floor (P_FLOAT (pr, 0));
  326. }
  327. /*
  328. float (float v) ceil
  329. */
  330. static void
  331. PF_ceil (progs_t *pr)
  332. {
  333. R_FLOAT (pr) = ceil (P_FLOAT (pr, 0));
  334. }
  335. /*
  336. entity (entity e) nextent
  337. */
  338. static void
  339. PF_nextent (progs_t *pr)
  340. {
  341. int i;
  342. edict_t *ent;
  343. i = P_EDICTNUM (pr, 0);
  344. while (1) {
  345. i++;
  346. if (i == *pr->num_edicts) {
  347. RETURN_EDICT (pr, *pr->edicts);
  348. return;
  349. }
  350. ent = EDICT_NUM (pr, i);
  351. if (!ent->free) {
  352. RETURN_EDICT (pr, ent);
  353. return;
  354. }
  355. }
  356. }
  357. // we assume that ints are smaller than floats
  358. #ifdef FLT_MAX_10_EXP
  359. # define STRING_BUF (FLT_MAX_10_EXP + 8)
  360. #else
  361. # define STRING_BUF 128
  362. #endif
  363. /*
  364. integer (float f) ftoi
  365. */
  366. static void
  367. PF_ftoi (progs_t *pr)
  368. {
  369. R_INT (pr) = P_FLOAT (pr, 0);
  370. }
  371. /*
  372. string (float f) ftos
  373. */
  374. static void
  375. PF_ftos (progs_t *pr)
  376. {
  377. char string[STRING_BUF];
  378. int i;
  379. // trimming 0s idea thanks to Maddes
  380. i = snprintf (string, sizeof (string), "%1.6f", P_FLOAT (pr, 0)) - 1;
  381. for (; i > 0; i--) {
  382. if (string[i] == '0')
  383. string[i] = '\0';
  384. else if (string[i] == '.') {
  385. string[i] = '\0';
  386. break;
  387. } else
  388. break;
  389. }
  390. RETURN_STRING (pr, string);
  391. }
  392. /*
  393. float (integer i) itof
  394. */
  395. static void
  396. PF_itof (progs_t *pr)
  397. {
  398. R_FLOAT (pr) = P_INT (pr, 0);
  399. }
  400. /*
  401. string (integer i) itos
  402. */
  403. static void
  404. PF_itos (progs_t *pr)
  405. {
  406. char string[STRING_BUF];
  407. snprintf (string, sizeof (string), "%d", P_INT (pr, 0));
  408. RETURN_STRING (pr, string);
  409. }
  410. /*
  411. float (string s) stof
  412. */
  413. static void
  414. PF_stof (progs_t *pr)
  415. {
  416. R_FLOAT (pr) = atof (P_GSTRING (pr, 0));
  417. }
  418. /*
  419. integer (string s) stoi
  420. */
  421. static void
  422. PF_stoi (progs_t *pr)
  423. {
  424. R_INT (pr) = atoi (P_GSTRING (pr, 0));
  425. }
  426. /*
  427. vector (string s) stov
  428. */
  429. static void
  430. PF_stov (progs_t *pr)
  431. {
  432. float v[3] = {0, 0, 0};
  433. sscanf (P_GSTRING (pr, 0), "'%f %f %f'", v, v + 1, v + 2);
  434. RETURN_VECTOR (pr, v);
  435. }
  436. /*
  437. string (vector v) vtos
  438. */
  439. static void
  440. PF_vtos (progs_t *pr)
  441. {
  442. char string[STRING_BUF * 3 + 5];
  443. snprintf (string, sizeof (string), "'%5.1f %5.1f %5.1f'",
  444. P_VECTOR (pr, 0)[0],
  445. P_VECTOR (pr, 0)[1],
  446. P_VECTOR (pr, 0)[2]);
  447. RETURN_STRING (pr, string);
  448. }
  449. /*
  450. float (string s) strlen
  451. */
  452. static void
  453. PF_strlen (progs_t *pr)
  454. {
  455. const char *s;
  456. s = P_GSTRING (pr, 0);
  457. R_FLOAT (pr) = strlen(s);
  458. }
  459. /*
  460. float (string char, string s) charcount
  461. */
  462. static void
  463. PF_charcount (progs_t *pr)
  464. {
  465. char goal;
  466. const char *s;
  467. int count;
  468. goal = (P_GSTRING (pr, 0))[0];
  469. if (goal == '\0') {
  470. R_FLOAT (pr) = 0;
  471. return;
  472. }
  473. count = 0;
  474. s = P_GSTRING (pr, 1);
  475. while (*s) {
  476. if (*s == goal)
  477. count++;
  478. s++;
  479. }
  480. R_FLOAT (pr) = count;
  481. }
  482. #if (INT_MAX == 2147483647) && (INT_MIN == -2147483648)
  483. # define INT_WIDTH 11
  484. #else /* I hope... */
  485. # define INT_WIDTH 20
  486. #endif
  487. #define MAX_ARG 7
  488. /*
  489. string (...) sprintf
  490. */
  491. static void
  492. PF_sprintf (progs_t *pr)
  493. {
  494. const char *fmt = P_GSTRING (pr, 0);
  495. int count = pr->pr_argc - 1;
  496. pr_type_t **args = pr->pr_params + 1;
  497. dstring_t *dstr;
  498. int str;
  499. str = PR_NewMutableString (pr);
  500. dstr = PR_GetMutableString (pr, str);
  501. PR_Sprintf (pr, dstr, "PF_sprintf", fmt, count, args);
  502. RETURN_STRING (pr, dstr->str);
  503. dstring_delete (dstr);
  504. }
  505. /*
  506. string () gametype
  507. */
  508. static void
  509. PR_gametype (progs_t *pr)
  510. {
  511. RETURN_STRING (pr, pr_gametype);
  512. }
  513. static void
  514. PF_PR_SetField (progs_t *pr)
  515. {
  516. edict_t *ent = P_EDICT (pr, 0);
  517. ddef_t *field = PR_FindField (pr, P_GSTRING (pr, 1));
  518. const char *value = P_GSTRING (pr, 2);
  519. R_INT (pr) = 0;
  520. if (field)
  521. R_INT (pr) = ED_ParseEpair (pr, ent->v, field, value);
  522. }
  523. static void
  524. PF_PR_FindFunction (progs_t *pr)
  525. {
  526. dfunction_t *func = PR_FindFunction (pr, P_GSTRING (pr, 0));
  527. R_FUNCTION (pr) = 0;
  528. if (func)
  529. R_FUNCTION (pr) = func - pr->pr_functions;
  530. }
  531. #define QF (PR_RANGE_QF << PR_RANGE_SHIFT) |
  532. static builtin_t builtins[] = {
  533. {"break", PF_break, 6},
  534. {"random", PF_random, 7},
  535. {"normalize", PF_normalize, 9},
  536. {"vlen", PF_vlen, 12},
  537. {"vectoyaw", PF_vectoyaw, 13},
  538. {"find", PF_Find, 18},
  539. {"dprint", PF_dprint, 25},
  540. {"ftos", PF_ftos, 26},
  541. {"vtos", PF_vtos, 27},
  542. {"coredump", PF_coredump, 28},
  543. {"traceon", PF_traceon, 29},
  544. {"traceoff", PF_traceoff, 30},
  545. {"eprint", PF_eprint, 31},
  546. {"rint", PF_rint, 36},
  547. {"floor", PF_floor, 37},
  548. {"ceil", PF_ceil, 38},
  549. {"fabs", PF_fabs, 43},
  550. {"cvar", PF_cvar, 45},
  551. {"nextent", PF_nextent, 47},
  552. {"vectoangles", PF_vectoangles, 51},
  553. {"cvar_set", PF_cvar_set, 72},
  554. {"stof", PF_stof, 81},
  555. {"strlen", PF_strlen, QF 100},
  556. {"charcount", PF_charcount, QF 101},
  557. {"sprintf", PF_sprintf, QF 109},
  558. {"ftoi", PF_ftoi, QF 110},
  559. {"itof", PF_itof, QF 111},
  560. {"itos", PF_itos, QF 112},
  561. {"stoi", PF_stoi, QF 113},
  562. {"stov", PF_stov, QF 114},
  563. {"gametype", PR_gametype, QF 115},
  564. {"PR_SetField", PF_PR_SetField, -1},
  565. {"PR_FindFunction", PF_PR_FindFunction, -1},
  566. {0}
  567. };
  568. VISIBLE void
  569. PR_Cmds_Init (progs_t *pr)
  570. {
  571. PR_RegisterBuiltins (pr, builtins);
  572. }