Move c/h files implementing/defining standard library stuff into a new libc directory...
[kugel-rb.git] / apps / plugins / doom / p_tick.c
blob4bf8feaf7e96886c66932068245701d11e424a7f
1 /* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
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 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
27 * DESCRIPTION:
28 * Thinker, Ticker.
30 *-----------------------------------------------------------------------------*/
32 #include "doomstat.h"
33 #include "p_user.h"
34 #include "p_spec.h"
35 #include "p_tick.h"
36 #include "p_map.h"
37 #include "rockmacros.h"
38 int leveltime;
41 // THINKERS
42 // All thinkers should be allocated by Z_Malloc
43 // so they can be operated on uniformly.
44 // The actual structures will vary in size,
45 // but the first element must be thinker_t.
48 // Both the head and tail of the thinker list.
49 thinker_t thinkercap;
51 // killough 8/29/98: we maintain several separate threads, each containing
52 // a special class of thinkers, to allow more efficient searches.
54 thinker_t thinkerclasscap[NUMTHCLASS];
57 // P_InitThinkers
60 void P_InitThinkers(void)
62 int i;
64 for (i=0; i<NUMTHCLASS; i++) // killough 8/29/98: initialize threaded lists
65 thinkerclasscap[i].cprev = thinkerclasscap[i].cnext = &thinkerclasscap[i];
67 thinkercap.prev = thinkercap.next = &thinkercap;
71 // killough 8/29/98:
73 // We maintain separate threads of friends and enemies, to permit more
74 // efficient searches.
77 void P_UpdateThinker(thinker_t *thinker)
79 // find the class the thinker belongs to
81 int class = thinker->function == P_MobjThinker &&
82 ((mobj_t *) thinker)->health > 0 &&
83 (((mobj_t *) thinker)->flags & MF_COUNTKILL ||
84 ((mobj_t *) thinker)->type == MT_SKULL) ?
85 ((mobj_t *) thinker)->flags & MF_FRIEND ?
86 th_friends : th_enemies : th_misc;
88 // Remove from current thread
89 thinker_t *th = thinker->cnext;
90 (th->cprev = thinker->cprev)->cnext = th;
92 // Add to appropriate thread
93 th = &thinkerclasscap[class];
94 th->cprev->cnext = thinker;
95 thinker->cnext = th;
96 thinker->cprev = th->cprev;
97 th->cprev = thinker;
101 // P_AddThinker
102 // Adds a new thinker at the end of the list.
105 void P_AddThinker(thinker_t* thinker)
107 thinkercap.prev->next = thinker;
108 thinker->next = &thinkercap;
109 thinker->prev = thinkercap.prev;
110 thinkercap.prev = thinker;
112 thinker->references = 0; // killough 11/98: init reference counter to 0
114 // killough 8/29/98: set sentinel pointers, and then add to appropriate list
115 thinker->cnext = thinker->cprev = thinker;
116 P_UpdateThinker(thinker);
120 // killough 11/98:
122 // Make currentthinker external, so that P_RemoveThinkerDelayed
123 // can adjust currentthinker when thinkers self-remove.
125 static thinker_t *currentthinker;
128 // P_RemoveThinkerDelayed()
130 // Called automatically as part of the thinker loop in P_RunThinkers(),
131 // on nodes which are pending deletion.
133 // If this thinker has no more pointers referencing it indirectly,
134 // remove it, and set currentthinker to one node preceeding it, so
135 // that the next step in P_RunThinkers() will get its successor.
138 void P_RemoveThinkerDelayed(thinker_t *thinker)
140 if (!thinker->references)
142 thinker_t *next = thinker->next;
143 (next->prev = currentthinker = thinker->prev)->next = next;
144 Z_Free(thinker);
149 // P_RemoveThinker
151 // Deallocation is lazy -- it will not actually be freed
152 // until its thinking turn comes up.
154 // killough 4/25/98:
156 // Instead of marking the function with -1 value cast to a function pointer,
157 // set the function to P_RemoveThinkerDelayed(), so that later, it will be
158 // removed automatically as part of the thinker process.
161 void P_RemoveThinker(thinker_t *thinker)
163 thinker->function = P_RemoveThinkerDelayed;
165 // killough 8/29/98: remove immediately from threaded list
166 (thinker->cnext->cprev = thinker->cprev)->cnext = thinker->cnext;
170 * P_SetTarget
172 * This function is used to keep track of pointer references to mobj thinkers.
173 * In Doom, objects such as lost souls could sometimes be removed despite
174 * their still being referenced. In Boom, 'target' mobj fields were tested
175 * during each gametic, and any objects pointed to by them would be prevented
176 * from being removed. But this was incomplete, and was slow (every mobj was
177 * checked during every gametic). Now, we keep a count of the number of
178 * references, and delay removal until the count is 0.
181 void P_SetTarget(mobj_t **mop, mobj_t *targ)
183 if (*mop) // If there was a target already, decrease its refcount
184 (*mop)->thinker.references--;
185 if ((*mop = targ)) // Set new target and if non-NULL, increase its counter
186 targ->thinker.references++;
190 // P_RunThinkers
192 // killough 4/25/98:
194 // Fix deallocator to stop using "next" pointer after node has been freed
195 // (a Doom bug).
197 // Process each thinker. For thinkers which are marked deleted, we must
198 // load the "next" pointer prior to freeing the node. In Doom, the "next"
199 // pointer was loaded AFTER the thinker was freed, which could have caused
200 // crashes.
202 // But if we are not deleting the thinker, we should reload the "next"
203 // pointer after calling the function, in case additional thinkers are
204 // added at the end of the list.
206 // killough 11/98:
208 // Rewritten to delete nodes implicitly, by making currentthinker
209 // external and using P_RemoveThinkerDelayed() implicitly.
212 static void P_RunThinkers (void)
214 for (currentthinker = thinkercap.next;
215 currentthinker != &thinkercap;
216 currentthinker = currentthinker->next)
217 if (currentthinker->function)
218 currentthinker->function(currentthinker);
222 // P_Ticker
225 void P_Ticker (void)
227 int i;
229 /* pause if in menu and at least one tic has been run
231 * killough 9/29/98: note that this ties in with basetic,
232 * since G_Ticker does the pausing during recording or
233 * playback, and compenates by incrementing basetic.
235 * All of this complicated mess is used to preserve demo sync.
238 if (paused || (menuactive && !demoplayback && !netgame &&
239 players[consoleplayer].viewz != 1))
240 return;
242 P_MapStart();
243 // not if this is an intermission screen
244 if(gamestate==GS_LEVEL)
245 for (i=0; i<MAXPLAYERS; i++)
246 if (playeringame[i])
247 P_PlayerThink(&players[i]);
249 P_RunThinkers();
250 P_UpdateSpecials();
251 P_RespawnSpecials();
252 P_MapEnd();
253 leveltime++; // for par times