subs.qc 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. /*
  2. subs.qc
  3. sub-functions, mostly movement related
  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. void() SUB_Null = {};
  20. void() SUB_Remove = {remove(self);};
  21. /*
  22. QuakeEd only writes a single float for angles (bad idea), so up and down are
  23. just constant angles.
  24. */
  25. vector() SetMovedir =
  26. {
  27. if (self.angles == '0 -1 0')
  28. self.movedir = '0 0 1';
  29. else if (self.angles == '0 -2 0')
  30. self.movedir = '0 0 -1';
  31. else
  32. {
  33. makevectors (self.angles);
  34. self.movedir = v_forward;
  35. }
  36. self.angles = '0 0 0';
  37. };
  38. /*
  39. ================
  40. InitTrigger
  41. ================
  42. */
  43. void() InitTrigger =
  44. {
  45. // trigger angles are used for one-way touches. An angle of 0 is assumed
  46. // to mean no restrictions, so use a yaw of 360 instead.
  47. if (self.angles != '0 0 0')
  48. SetMovedir ();
  49. self.solid = SOLID_TRIGGER;
  50. setmodel (self, self.model); // set size and link into world
  51. self.movetype = MOVETYPE_NONE;
  52. self.modelindex = 0;
  53. self.model = "";
  54. };
  55. /*
  56. =============
  57. SUB_CalcMove
  58. calculate self.velocity and self.nextthink to reach dest from
  59. self.origin traveling at speed
  60. ===============
  61. */
  62. void(entity ent, vector tdest, float tspeed, void() func) SUB_CalcMoveEnt =
  63. {
  64. local entity stemp;
  65. stemp = self;
  66. self = ent;
  67. SUB_CalcMove (tdest, tspeed, func);
  68. self = stemp;
  69. };
  70. void(vector tdest, float tspeed, void() func) SUB_CalcMove =
  71. {
  72. local vector vdestdelta;
  73. local float len, traveltime;
  74. if (!tspeed)
  75. objerror("No speed is defined!");
  76. self.think1 = func;
  77. self.finaldest = tdest;
  78. self.think = SUB_CalcMoveDone;
  79. if (tdest == self.origin)
  80. {
  81. self.velocity = '0 0 0';
  82. self.nextthink = self.ltime + 0.1;
  83. return;
  84. }
  85. // set destdelta to the vector needed to move
  86. vdestdelta = tdest - self.origin;
  87. // calculate length of vector
  88. len = vlen (vdestdelta);
  89. // divide by speed to get time to reach dest
  90. traveltime = len / tspeed;
  91. if (traveltime < 0.03)
  92. traveltime = 0.03;
  93. // set nextthink to trigger a think when dest is reached
  94. self.nextthink = self.ltime + traveltime;
  95. // scale the destdelta vector by the time spent traveling to get velocity
  96. self.velocity = vdestdelta * (1/traveltime); // qcc won't take vec/float
  97. };
  98. /*
  99. ============
  100. After moving, set origin to exact final destination
  101. ============
  102. */
  103. void() SUB_CalcMoveDone =
  104. {
  105. setorigin(self, self.finaldest);
  106. self.velocity = '0 0 0';
  107. self.nextthink = -1;
  108. if (self.think1)
  109. self.think1();
  110. };
  111. /*
  112. =============
  113. SUB_CalcAngleMove
  114. calculate self.avelocity and self.nextthink to reach destangle from
  115. self.angles rotating
  116. The calling function should make sure self.think is valid
  117. ===============
  118. */
  119. void(entity ent, vector destangle, float tspeed, void() func) SUB_CalcAngleMoveEnt =
  120. {
  121. local entity stemp;
  122. stemp = self;
  123. self = ent;
  124. SUB_CalcAngleMove (destangle, tspeed, func);
  125. self = stemp;
  126. };
  127. void(vector destangle, float tspeed, void() func) SUB_CalcAngleMove =
  128. {
  129. local vector destdelta;
  130. local float len, traveltime;
  131. if (!tspeed)
  132. objerror("No speed is defined!");
  133. // set destdelta to the vector needed to move
  134. destdelta = destangle - self.angles;
  135. // calculate length of vector
  136. len = vlen (destdelta);
  137. // divide by speed to get time to reach dest
  138. traveltime = len / tspeed;
  139. // set nextthink to trigger a think when dest is reached
  140. self.nextthink = self.ltime + traveltime;
  141. // scale the destdelta vector by the time spent traveling to get velocity
  142. self.avelocity = destdelta * (1 / traveltime);
  143. self.think1 = func;
  144. self.finalangle = destangle;
  145. self.think = SUB_CalcAngleMoveDone;
  146. };
  147. /*
  148. ============
  149. After rotating, set angle to exact final angle
  150. ============
  151. */
  152. void() SUB_CalcAngleMoveDone =
  153. {
  154. self.angles = self.finalangle;
  155. self.avelocity = '0 0 0';
  156. self.nextthink = -1;
  157. if (self.think1)
  158. self.think1();
  159. };
  160. //=============================================================================
  161. void() DelayThink =
  162. {
  163. activator = self.enemy;
  164. SUB_UseTargets ();
  165. remove(self);
  166. };
  167. /*
  168. ==============================
  169. SUB_UseTargets
  170. the global "activator" should be set to the entity that initiated the firing.
  171. If self.delay is set, a DelayedUse entity will be created that will actually
  172. do the SUB_UseTargets after that many seconds have passed.
  173. Centerprints any self.message to the activator.
  174. Removes all entities with a targetname that match self.killtarget,
  175. and removes them, so some events can remove other triggers.
  176. Search for (string)targetname in all entities that
  177. match (string)self.target and call their .use function
  178. ==============================
  179. */
  180. void() SUB_UseTargets =
  181. {
  182. local entity t, stemp, otemp, act;
  183. //
  184. // check for a delay
  185. //
  186. if (self.delay)
  187. {
  188. // create a temp object to fire at a later time
  189. t = spawn();
  190. t.classname = "DelayedUse";
  191. t.nextthink = time + self.delay;
  192. t.think = DelayThink;
  193. t.enemy = activator;
  194. t.message = self.message;
  195. t.killtarget = self.killtarget;
  196. t.target = self.target;
  197. return;
  198. }
  199. //
  200. // print the message
  201. //
  202. if (activator.classname == "player" && self.message != "")
  203. {
  204. centerprint (activator, self.message);
  205. if (!self.noise)
  206. sound (activator, CHAN_VOICE, "misc/talk.wav", 1, ATTN_NORM);
  207. }
  208. //
  209. // kill the killtagets
  210. //
  211. if (self.killtarget)
  212. {
  213. t = world;
  214. do
  215. {
  216. t = find (t, targetname, self.killtarget);
  217. if (!t)
  218. return;
  219. remove (t);
  220. } while ( 1 );
  221. }
  222. //
  223. // fire targets
  224. //
  225. if (self.target)
  226. {
  227. act = activator;
  228. t = world;
  229. do
  230. {
  231. t = find (t, targetname, self.target);
  232. if (!t)
  233. {
  234. return;
  235. }
  236. stemp = self;
  237. otemp = other;
  238. self = t;
  239. other = stemp;
  240. if (self.use != SUB_Null)
  241. {
  242. if (self.use)
  243. self.use ();
  244. }
  245. self = stemp;
  246. other = otemp;
  247. activator = act;
  248. } while ( 1 );
  249. }
  250. };