p_tick.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. /* Emacs style mode select -*- C++ -*-
  2. *-----------------------------------------------------------------------------
  3. *
  4. *
  5. * PrBoom: a Doom port merged with LxDoom and LSDLDoom
  6. * based on BOOM, a modified and improved DOOM engine
  7. * Copyright (C) 1999 by
  8. * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
  9. * Copyright (C) 1999-2000,2002 by
  10. * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
  11. * Copyright 2005, 2006 by
  12. * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
  13. *
  14. * This program is free software; you can redistribute it and/or
  15. * modify it under the terms of the GNU General Public License
  16. * as published by the Free Software Foundation; either version 2
  17. * of the License, or (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with this program; if not, write to the Free Software
  26. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  27. * 02111-1307, USA.
  28. *
  29. * DESCRIPTION:
  30. * Thinker, Ticker.
  31. *
  32. *-----------------------------------------------------------------------------*/
  33. #include "doomstat.h"
  34. #include "p_user.h"
  35. #include "p_spec.h"
  36. #include "p_tick.h"
  37. #include "p_map.h"
  38. #include "r_fps.h"
  39. #include "e6y.h"
  40. #include "s_advsound.h"
  41. int leveltime;
  42. static dboolean newthinkerpresent;
  43. //
  44. // THINKERS
  45. // All thinkers should be allocated by Z_Malloc
  46. // so they can be operated on uniformly.
  47. // The actual structures will vary in size,
  48. // but the first element must be thinker_t.
  49. //
  50. // killough 8/29/98: we maintain several separate threads, each containing
  51. // a special class of thinkers, to allow more efficient searches.
  52. thinker_t thinkerclasscap[th_all+1];
  53. //
  54. // P_InitThinkers
  55. //
  56. void P_InitThinkers(void)
  57. {
  58. int i;
  59. for (i=0; i<NUMTHCLASS; i++) // killough 8/29/98: initialize threaded lists
  60. thinkerclasscap[i].cprev = thinkerclasscap[i].cnext = &thinkerclasscap[i];
  61. thinkercap.prev = thinkercap.next = &thinkercap;
  62. }
  63. //
  64. // killough 8/29/98:
  65. //
  66. // We maintain separate threads of friends and enemies, to permit more
  67. // efficient searches.
  68. //
  69. void P_UpdateThinker(thinker_t *thinker)
  70. {
  71. register thinker_t *th;
  72. // find the class the thinker belongs to
  73. int class =
  74. thinker->function == P_RemoveThinkerDelayed ? th_delete :
  75. thinker->function == P_MobjThinker &&
  76. ((mobj_t *) thinker)->health > 0 &&
  77. (((mobj_t *) thinker)->flags & MF_COUNTKILL ||
  78. ((mobj_t *) thinker)->type == MT_SKULL) ?
  79. ((mobj_t *) thinker)->flags & MF_FRIEND ?
  80. th_friends : th_enemies : th_misc;
  81. {
  82. /* Remove from current thread, if in one */
  83. if ((th = thinker->cnext)!= NULL)
  84. (th->cprev = thinker->cprev)->cnext = th;
  85. }
  86. // Add to appropriate thread
  87. th = &thinkerclasscap[class];
  88. th->cprev->cnext = thinker;
  89. thinker->cnext = th;
  90. thinker->cprev = th->cprev;
  91. th->cprev = thinker;
  92. }
  93. //
  94. // P_AddThinker
  95. // Adds a new thinker at the end of the list.
  96. //
  97. void P_AddThinker(thinker_t* thinker)
  98. {
  99. thinkercap.prev->next = thinker;
  100. thinker->next = &thinkercap;
  101. thinker->prev = thinkercap.prev;
  102. thinkercap.prev = thinker;
  103. thinker->references = 0; // killough 11/98: init reference counter to 0
  104. // killough 8/29/98: set sentinel pointers, and then add to appropriate list
  105. thinker->cnext = thinker->cprev = NULL;
  106. P_UpdateThinker(thinker);
  107. newthinkerpresent = true;
  108. }
  109. //
  110. // killough 11/98:
  111. //
  112. // Make currentthinker external, so that P_RemoveThinkerDelayed
  113. // can adjust currentthinker when thinkers self-remove.
  114. static thinker_t *currentthinker;
  115. //
  116. // P_RemoveThinkerDelayed()
  117. //
  118. // Called automatically as part of the thinker loop in P_RunThinkers(),
  119. // on nodes which are pending deletion.
  120. //
  121. // If this thinker has no more pointers referencing it indirectly,
  122. // remove it, and set currentthinker to one node preceeding it, so
  123. // that the next step in P_RunThinkers() will get its successor.
  124. //
  125. void P_RemoveThinkerDelayed(thinker_t *thinker)
  126. {
  127. if (!thinker->references)
  128. {
  129. { /* Remove from main thinker list */
  130. thinker_t *next = thinker->next;
  131. /* Note that currentthinker is guaranteed to point to us,
  132. * and since we're freeing our memory, we had better change that. So
  133. * point it to thinker->prev, so the iterator will correctly move on to
  134. * thinker->prev->next = thinker->next */
  135. (next->prev = currentthinker = thinker->prev)->next = next;
  136. }
  137. {
  138. /* Remove from current thinker class list */
  139. thinker_t *th = thinker->cnext;
  140. (th->cprev = thinker->cprev)->cnext = th;
  141. }
  142. Z_Free(thinker);
  143. }
  144. }
  145. //
  146. // P_RemoveThinker
  147. //
  148. // Deallocation is lazy -- it will not actually be freed
  149. // until its thinking turn comes up.
  150. //
  151. // killough 4/25/98:
  152. //
  153. // Instead of marking the function with -1 value cast to a function pointer,
  154. // set the function to P_RemoveThinkerDelayed(), so that later, it will be
  155. // removed automatically as part of the thinker process.
  156. //
  157. void P_RemoveThinker(thinker_t *thinker)
  158. {
  159. R_StopInterpolationIfNeeded(thinker);
  160. thinker->function = P_RemoveThinkerDelayed;
  161. P_UpdateThinker(thinker);
  162. }
  163. /* cph 2002/01/13 - iterator for thinker list
  164. * WARNING: Do not modify thinkers between calls to this functin
  165. */
  166. thinker_t* P_NextThinker(thinker_t* th, th_class cl)
  167. {
  168. thinker_t* top = &thinkerclasscap[cl];
  169. if (!th) th = top;
  170. th = cl == th_all ? th->next : th->cnext;
  171. return th == top ? NULL : th;
  172. }
  173. /*
  174. * P_SetTarget
  175. *
  176. * This function is used to keep track of pointer references to mobj thinkers.
  177. * In Doom, objects such as lost souls could sometimes be removed despite
  178. * their still being referenced. In Boom, 'target' mobj fields were tested
  179. * during each gametic, and any objects pointed to by them would be prevented
  180. * from being removed. But this was incomplete, and was slow (every mobj was
  181. * checked during every gametic). Now, we keep a count of the number of
  182. * references, and delay removal until the count is 0.
  183. */
  184. void P_SetTarget(mobj_t **mop, mobj_t *targ)
  185. {
  186. if (*mop) // If there was a target already, decrease its refcount
  187. (*mop)->thinker.references--;
  188. if ((*mop = targ)) // Set new target and if non-NULL, increase its counter
  189. targ->thinker.references++;
  190. }
  191. //
  192. // P_RunThinkers
  193. //
  194. // killough 4/25/98:
  195. //
  196. // Fix deallocator to stop using "next" pointer after node has been freed
  197. // (a Doom bug).
  198. //
  199. // Process each thinker. For thinkers which are marked deleted, we must
  200. // load the "next" pointer prior to freeing the node. In Doom, the "next"
  201. // pointer was loaded AFTER the thinker was freed, which could have caused
  202. // crashes.
  203. //
  204. // But if we are not deleting the thinker, we should reload the "next"
  205. // pointer after calling the function, in case additional thinkers are
  206. // added at the end of the list.
  207. //
  208. // killough 11/98:
  209. //
  210. // Rewritten to delete nodes implicitly, by making currentthinker
  211. // external and using P_RemoveThinkerDelayed() implicitly.
  212. //
  213. static void P_RunThinkers (void)
  214. {
  215. for (currentthinker = thinkercap.next;
  216. currentthinker != &thinkercap;
  217. currentthinker = currentthinker->next)
  218. {
  219. if (newthinkerpresent)
  220. R_ActivateThinkerInterpolations(currentthinker);
  221. if (currentthinker->function)
  222. currentthinker->function(currentthinker);
  223. }
  224. newthinkerpresent = false;
  225. // Dedicated thinkers
  226. T_MAPMusic();
  227. }
  228. //
  229. // P_Ticker
  230. //
  231. void P_Ticker (void)
  232. {
  233. int i;
  234. /* pause if in menu and at least one tic has been run
  235. *
  236. * killough 9/29/98: note that this ties in with basetic,
  237. * since G_Ticker does the pausing during recording or
  238. * playback, and compenates by incrementing basetic.
  239. *
  240. * All of this complicated mess is used to preserve demo sync.
  241. */
  242. if (paused || (menuactive && !demoplayback && !netgame &&
  243. players[consoleplayer].viewz != 1))
  244. {
  245. P_ResetWalkcam();
  246. return;
  247. }
  248. R_UpdateInterpolations ();
  249. P_MapStart();
  250. // not if this is an intermission screen
  251. if(gamestate==GS_LEVEL)
  252. for (i=0; i<MAXPLAYERS; i++)
  253. if (playeringame[i])
  254. P_PlayerThink(&players[i]);
  255. P_RunThinkers();
  256. P_UpdateSpecials();
  257. P_RespawnSpecials();
  258. P_MapEnd();
  259. leveltime++; // for par times
  260. }