SHOW:
|
|
- or go back to the newest paste.
1 | /*----------------------------------------------------------------------------*\ | |
2 | - | =========================== |
2 | + | =========================== |
3 | - | foreach efficient looping |
3 | + | foreach efficient looping |
4 | - | =========================== |
4 | + | =========================== |
5 | Description: | |
6 | - | Provides efficient looping through sparse data sets, such as connected |
6 | + | Provides efficient looping through sparse data sets, such as connected |
7 | - | players. Significantly improved from the original version to be a generic |
7 | + | players. Significantly improved from the original version to be a generic |
8 | - | loop system, rather then purely a player loop system. When used for |
8 | + | loop system, rather then purely a player loop system. When used for |
9 | - | players this has constant time O(n) for number of connected players (n), |
9 | + | players this has constant time O(n) for number of connected players (n), |
10 | - | unlike standard player loops which are O(MAX_PLAYERS), regardless of the |
10 | + | unlike standard player loops which are O(MAX_PLAYERS), regardless of the |
11 | - | actual number of connected players. Even when n is MAX_PLAYERS this is |
11 | + | actual number of connected players. Even when n is MAX_PLAYERS this is |
12 | - | still faster. |
12 | + | still faster. |
13 | Legal: | |
14 | - | Version: MPL 1.1 |
14 | + | Version: MPL 1.1 |
15 | - | |
15 | + | |
16 | - | The contents of this file are subject to the Mozilla Public License Version |
16 | + | The contents of this file are subject to the Mozilla Public License Version |
17 | - | 1.1 (the "License"); you may not use this file except in compliance with |
17 | + | 1.1 (the "License"); you may not use this file except in compliance with |
18 | - | the License. You may obtain a copy of the License at |
18 | + | the License. You may obtain a copy of the License at |
19 | - | http://www.mozilla.org/MPL/ |
19 | + | [url]http://www.mozilla.org/MPL/[/url] |
20 | - | |
20 | + | |
21 | - | Software distributed under the License is distributed on an "AS IS" basis, |
21 | + | Software distributed under the License is distributed on an "AS IS" basis, |
22 | - | WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
22 | + | WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
23 | - | for the specific language governing rights and limitations under the |
23 | + | for the specific language governing rights and limitations under the |
24 | - | License. |
24 | + | License. |
25 | - | |
25 | + | |
26 | - | The Original Code is the YSI foreach include. |
26 | + | The Original Code is the YSI foreach include. |
27 | - | |
27 | + | |
28 | - | The Initial Developer of the Original Code is Alex "Y_Less" Cole. |
28 | + | The Initial Developer of the Original Code is Alex "Y_Less" Cole. |
29 | - | Portions created by the Initial Developer are Copyright (C) 2011 |
29 | + | Portions created by the Initial Developer are Copyright (C) 2011 |
30 | - | the Initial Developer. All Rights Reserved. |
30 | + | the Initial Developer. All Rights Reserved. |
31 | - | |
31 | + | |
32 | - | Contributors: |
32 | + | Contributors: |
33 | - | ZeeX, koolk, JoeBullet/Google63, g_aSlice/Slice |
33 | + | ZeeX, koolk, JoeBullet/Google63, g_aSlice/Slice |
34 | - | |
34 | + | |
35 | - | Thanks: |
35 | + | Thanks: |
36 | - | JoeBullet/Google63 - Handy arbitrary ASM jump code using SCTRL. |
36 | + | JoeBullet/Google63 - Handy arbitrary ASM jump code using SCTRL. |
37 | - | ZeeX - Very productive conversations. |
37 | + | ZeeX - Very productive conversations. |
38 | - | koolk - IsPlayerinAreaEx code. |
38 | + | koolk - IsPlayerinAreaEx code. |
39 | - | TheAlpha - Danish translation. |
39 | + | TheAlpha - Danish translation. |
40 | - | breadfish - German translation. |
40 | + | breadfish - German translation. |
41 | - | Fireburn - Dutch translation. |
41 | + | Fireburn - Dutch translation. |
42 | - | yom - French translation. |
42 | + | yom - French translation. |
43 | - | 50p - Polish translation. |
43 | + | 50p - Polish translation. |
44 | - | Zamaroht - Spanish translation. |
44 | + | Zamaroht - Spanish translation. |
45 | - | Dracoblue, sintax, mabako, Xtreme, other coders - Producing other modes |
45 | + | Dracoblue, sintax, mabako, Xtreme, other coders - Producing other modes |
46 | - | for me to strive to better. |
46 | + | for me to strive to better. |
47 | - | Pixels^ - Running XScripters where the idea was born. |
47 | + | Pixels^ - Running XScripters where the idea was born. |
48 | - | Matite - Pestering me to release it and using it. |
48 | + | Matite - Pestering me to release it and using it. |
49 | - | |
49 | + | |
50 | - | Very special thanks to: |
50 | + | Very special thanks to: |
51 | - | Thiadmer - PAWN, whose limits continue to amaze me! |
51 | + | Thiadmer - PAWN, whose limits continue to amaze me! |
52 | - | Kye/Kalcor - SA:MP. |
52 | + | Kye/Kalcor - SA:MP. |
53 | - | SA:MP Team past, present and future - SA:MP. |
53 | + | SA:MP Team past, present and future - SA:MP. |
54 | - | |
54 | + | |
55 | Version: | |
56 | - | 0.4 |
56 | + | 0.4 |
57 | Changelog: | |
58 | - | 05/01/12: |
58 | + | 17/10/12: |
59 | - | Fixed multi-dimensional iterators. |
59 | + | Fixed a bug that was here but not in "foreach.inc". |
60 | - | Fixed "FOREACH_NO_BOTS". |
60 | + | 04/10/12: |
61 | - | Made "Iterator:" support multi-dimensional arrays. |
61 | + | Added a tiny tweak to detect tag-returning iterator functions. |
62 | - | 07/12/11: |
62 | + | Added Iter_InternalSize. |
63 | - | Underlying implementation tweak for more consistent code. |
63 | + | 13/01/12: |
64 | - | Added Iter_Contains. |
64 | + | Fixed the count thanks to AndreT. |
65 | - | 06/12/11: |
65 | + | 05/01/12: |
66 | - | Minor fixes. |
66 | + | Fixed multi-dimensional iterators. |
67 | - | 31/10/11: |
67 | + | Fixed "FOREACH_NO_BOTS". |
68 | - | Changed the underlying loop code to be slightly faster. |
68 | + | Made "Iterator:" support multi-dimensional arrays. |
69 | - | Added support for Iter_SafeRemove, prompting refactoring. |
69 | + | 24/12/11: |
70 | - | 17/09/11: |
70 | + | Added _YSI_SPECIAL_DEBUG support. |
71 | - | Fixed arrays under the new syntax. |
71 | + | Added fix for function iterators. |
72 | - | 28/04/11: |
72 | + | Ported back to YSI. |
73 | - | Moved iterator identifiers to end of variables. |
73 | + | Changed to use internal YSI "__" natives. |
74 | - | Rewrote "foreach" to accept two syntaxes for "foreach (new i : Iter)". |
74 | + | Fixed calls order by using ALS. |
75 | - | 16/08/10: |
75 | + | 31/10/11: |
76 | - | Removed all the "2" versions of the functions. |
76 | + | Changed the underlying loop code to be slightly faster. |
77 | - | 14/08/10: |
77 | + | Added support for Iter_SafeRemove, prompting refactoring. |
78 | - | Added Iter_Clear to reset an array. |
78 | + | 17/09/11: |
79 | - | 06/08/10: |
79 | + | Fixed arrays under the new syntax. |
80 | - | Added special array declaration format. |
80 | + | 28/04/11: |
81 | - | 18/12/09: |
81 | + | Moved iterator identifiers to end of variables. |
82 | - | Added Itter_Func2 functions for multi-dimensional iterators. |
82 | + | Rewrote "foreach" to accept two syntaxes for "foreach (new i : Iter)". |
83 | - | Renamed foreact et al as keywords in the documentation. |
83 | + | 16/08/10: |
84 | - | Changed licensing from GPL to MPL. |
84 | + | Removed all the "2" versions of the functions. |
85 | - | 02/09/09: |
85 | + | 14/08/10: |
86 | - | Fixed (again) for 0.3. |
86 | + | Added Iter_Clear to reset an array. |
87 | - | Added free slot finding. |
87 | + | 06/08/10: |
88 | - | 21/08/09: |
88 | + | Added special array declaration format. |
89 | - | Updated to include random functions. |
89 | + | 18/12/09: |
90 | - | Made entirely stand alone. |
90 | + | Added Itter_Func2 functions for multi-dimensional iterators. |
91 | - | Ported to 0.3 (separate version). |
91 | + | Renamed foreact et al as keywords in the documentation. |
92 | - | Added automatic callback hook code. |
92 | + | Changed licensing from GPL to MPL. |
93 | - | Removed debug information from stand alone version. |
93 | + | 02/09/09: |
94 | - | 06/01/08: |
94 | + | Fixed (again) for 0.3. |
95 | - | Added debug information. |
95 | + | Added free slot finding. |
96 | - | 09/10/07: |
96 | + | 21/08/09: |
97 | - | Moved to system. |
97 | + | Updated to include random functions. |
98 | - | 16/09/07: |
98 | + | Made entirely stand alone. |
99 | - | Added list sorting. |
99 | + | Ported to 0.3 (separate version). |
100 | - | Made this part of Y SeRver Includes, not Y Sever Includes. |
100 | + | Added automatic callback hook code. |
101 | - | Made list sorting optional. |
101 | + | Removed debug information from stand alone version. |
102 | - | Fixed version number. |
102 | + | 06/01/08: |
103 | - | 08/09/07: |
103 | + | Added debug information. |
104 | - | First version. |
104 | + | 09/10/07: |
105 | Moved to system. | |
106 | - | Public: |
106 | + | 16/09/07: |
107 | - | OnPlayerDisconnect - Called when a player leaves to remove them. |
107 | + | Added list sorting. |
108 | - | OnPlayerConnect - Called when a player connects to add them. |
108 | + | Made this part of Y SeRver Includes, not Y Sever Includes. |
109 | - | Core: |
109 | + | Made list sorting optional. |
110 | - | - |
110 | + | Fixed version number. |
111 | - | Stock: |
111 | + | 08/09/07: |
112 | - | Itter_ShowArray - Displays the contents of the array. |
112 | + | First version. |
113 | - | Itter_AddInternal - Add a value to an itterator. |
113 | + | |
114 | - | Itter_RemoveInternal - Remove a value from an itterator. |
114 | + | Public: |
115 | - | Itter_RandomInternal - Get a random item from an itterator. |
115 | + | OnPlayerDisconnect - Called when a player leaves to remove them. |
116 | - | Itter_FreeInternal - Gets the first free slot in the itterator. |
116 | + | OnPlayerConnect - Called when a player connects to add them. |
117 | - | Itter_InitInternal - Initialises a multi-dimensional itterator. |
117 | + | Core: |
118 | - | Itter_ContainsInternal - Checks if a value is in an iterator. |
118 | + | - |
119 | - | Static: |
119 | + | Stock: |
120 | - | - |
120 | + | Itter_ShowArray - Displays the contents of the array. |
121 | - | Inline: |
121 | + | Itter_AddInternal - Add a value to an itterator. |
122 | - | Itter_Create - Create a new itterator value set. |
122 | + | Itter_RemoveInternal - Remove a value from an itterator. |
123 | - | Itter_Add - Wraps Itter_AddInternal. |
123 | + | Itter_RandomInternal - Get a random item from an itterator. |
124 | - | Itter_SafeRemove - Wraps Itter_SafeRemoveInternal. |
124 | + | Itter_FreeInternal - Gets the first free slot in the itterator. |
125 | - | Itter_Remove - Wraps Itter_RemoveInternal. |
125 | + | Itter_InitInternal - Initialises a multi-dimensional itterator. |
126 | - | Itter_Random - Wraps Itter_RandomInternal. |
126 | + | Static: |
127 | - | Itter_Count - Gets the number of items in an itterator. |
127 | + | - |
128 | - | Itter_Debug - Wraps around Itter_ShowArray. |
128 | + | Inline: |
129 | - | Itter_Free - Wraps around Itter_FreeInternal. |
129 | + | Itter_Create - Create a new itterator value set. |
130 | - | Itter_Contains - Wraps around Itter_ContainsInternal. |
130 | + | Itter_Add - Wraps Itter_AddInternal. |
131 | - | API: |
131 | + | Itter_Remove - Wraps Itter_RemoveInternal. |
132 | - | - |
132 | + | Itter_Random - Wraps Itter_RandomInternal. |
133 | Itter_Count - Gets the number of items in an itterator. | |
134 | - | - |
134 | + | Itter_Debug - Wraps around Itter_ShowArray. |
135 | Itter_Free - Wraps around Itter_FreeInternal. | |
136 | - | Itter_OnPlayerConnect - Hook for the OnPlayerConnect callback. |
136 | + | Itter_Create2 - Create a new itterator array value set. |
137 | - | Itter_OnPlayerDisconnect - Hook for the OnPlayerDisconnect callback. |
137 | + | Itter_Add2 - Wraps Itter_AddInternal for arrays. |
138 | - | Itter_OnGameModeInit - Only exists to make the code compile correctly... |
138 | + | Itter_Remove2 - Wraps Itter_RemoveInternal for arrays. |
139 | Itter_Random2 - Wraps Itter_RandomInternal for arrays. | |
140 | - | - |
140 | + | Itter_Count2 - Gets the number of items in an itterator array. |
141 | Itter_Debug2 - Wraps around Itter_ShowArray for arrays. | |
142 | - | - |
142 | + | Itter_Free2 - Wraps around Itter_FreeInternal for arrays. |
143 | API: | |
144 | - | - |
144 | + | - |
145 | Callbacks: | |
146 | - | foreach - Command to loop an iterator. |
146 | + | - |
147 | - | foreachex - Like foreach but without a new variable. |
147 | + | |
148 | - | foreach2 - Command to loop through an iterator array. |
148 | + | Itter_OnPlayerConnect - Hook for the OnPlayerConnect callback. |
149 | - | foreachex - Like foreach2 but without a new variable. |
149 | + | Itter_OnPlayerDisconnect - Hook for the OnPlayerDisconnect callback. |
150 | Itter_OnGameModeInit - Only exists to make the code compile correctly... | |
151 | - | Iterator - Declare an iterator. |
151 | + | |
152 | - | |
153 | - | Global: |
153 | + | |
154 | - | - |
154 | + | - |
155 | - | Static: |
155 | + | |
156 | - | YSI_g_OPC - Records wether Itter_OnPlayerConnect exists for speed. |
156 | + | - |
157 | - | YSI_g_OPDC - Records wether Itter_OnPlayerDisconnect exists for speed. |
157 | + | |
158 | foreach - Command to loop an iterator. | |
159 | - | - |
159 | + | foreachex - Like foreach but without a new variable. |
160 | foreach2 - Command to loop through an iterator array. | |
161 | - | YSI_ITTER_NO_SORT - Removed. |
161 | + | foreachex - Like foreach2 but without a new variable. |
162 | - | FOREACH_NO_BOTS - Remove the bot iterators for smaller code. |
162 | + | |
163 | - | FOREACH_NO_PLAYERS - Remove all default code for player itteration. |
163 | + | Iterator - Declare an iterator. |
164 | Variables: | |
165 | - | - |
165 | + | Global: |
166 | - | |
167 | - | Player - List of all players connected. |
167 | + | Static: |
168 | - | Bot - List of all bots (npcs) connected. |
168 | + | YSI_g_OPC - Records wether Itter_OnPlayerConnect exists for speed. |
169 | - | NPC - Alias of Bot. |
169 | + | YSI_g_OPDC - Records wether Itter_OnPlayerDisconnect exists for speed. |
170 | - | Character - All players and bots. |
170 | + | |
171 | - | |
172 | Compile options: | |
173 | - | #define _FOREACH_LOCAL_VERSION 13 |
173 | + | YSI_ITTER_NO_SORT - Removed. |
174 | FOREACH_NO_BOTS - Remove the bot iterators for smaller code. | |
175 | FOREACH_NO_PLAYERS - Remove all default code for player itteration. | |
176 | Operators: | |
177 | - | #define _FOREACH_CUR_VERSION _FOREACH_LOCAL_VERSION |
177 | + | - |
178 | - | #endinput |
178 | + | |
179 | Player - List of all players connected. | |
180 | Bot - List of all bots (npcs) connected. | |
181 | - | #define _FOREACH_INC_TEST |
181 | + | NPC - Alias of Bot. |
182 | - | #tryinclude <YSI\y_iterate> |
182 | + | Character - All players and bots. |
183 | - | #undef _FOREACH_INC_TEST |
183 | + | |
184 | - | // <foreach> exists - test which is newer. |
184 | + | |
185 | - | #if defined _inc_y_iterate |
185 | + | // "y_iterate" is always higher than "foreach". |
186 | - | #if _FOREACH_CUR_VERSION > _FOREACH_LOCAL_VERSION |
186 | + | #define _FOREACH_LOCAL_VERSION 19 |
187 | - | // Foreach is newer. |
187 | + | |
188 | - | #undef _inc_y_iterate |
188 | + | |
189 | - | #define _FOREACH_NO_TEST |
189 | + | |
190 | - | #include <YSI\y_iterate> |
190 | + | #define _FOREACH_CUR_VERSION _FOREACH_LOCAL_VERSION |
191 | - | #endinput |
191 | + | #endinput |
192 | - | #endif |
192 | + | |
193 | - | #endif |
193 | + | |
194 | #define _FOREACH_INC_TEST | |
195 | #tryinclude <YSI\y_iterate> | |
196 | #undef _FOREACH_INC_TEST | |
197 | - | #error "Please include a_samp or a_npc before foreach" |
197 | + | // <foreach> exists - test which is newer. |
198 | #if defined _inc_y_iterate | |
199 | #if !defined _FOREACH_CUR_VERSION | |
200 | - | //#include <YSI\y_debug> |
200 | + | // Foreach exists, but it's an old version - don't try use this |
201 | - | //#include <YSI\y_hooks> |
201 | + | // system or the variables will conflict. |
202 | #error "Old foreach.inc files are no longer compatible with YSI." | |
203 | #endinput | |
204 | - | #define BOTSYNC_IS_BOT (true) |
204 | + | #endif |
205 | #if _FOREACH_CUR_VERSION > _FOREACH_LOCAL_VERSION | |
206 | // Foreach is newer. | |
207 | #undef _inc_y_iterate | |
208 | - | #define _FOREACH_BOT |
208 | + | #define _FOREACH_NO_TEST |
209 | #include <YSI\y_iterate> | |
210 | #endinput | |
211 | #endif | |
212 | - | #error YSI_ITTER_NO_SORT is no longer supported by foreach. |
212 | + | #endif |
213 | #endif | |
214 | ||
215 | #if !defined _samp_included | |
216 | #error "Please include a_samp or a_npc before foreach" | |
217 | #endif | |
218 | ||
219 | #if defined _YSI_SPECIAL_DEBUG | |
220 | - | #define _Y_ITER_C2:sizeof%0(%1)@YSII_Ag-1;_:(%2=_Y_ITER_ARRAY:%3(%4)@YSII_Ag[%5])!=_Y_ITER_ARRAY_SIZE(%6);) -1;_:(%2=%3@YSII_Ag(%4,%5))!=-1;) |
220 | + | #define PS_IS_PLAYER_CONNECTED(%0) (%0 != INVALID_PLAYER_ID) |
221 | #else | |
222 | #define PS_IS_PLAYER_CONNECTED IsPlayerConnected | |
223 | #endif | |
224 | ||
225 | - | static stock |
225 | + | //#include "y_debug" |
226 | - | YSI_g_sCallbacks = 0; |
226 | + | //#include "y_hooks" |
227 | ||
228 | #include <YSI\internal\y_natives> | |
229 | #include <YSI\y_debug> | |
230 | ||
231 | - | Itter_Create2 |
231 | + | |
232 | #define BOTSYNC_IS_BOT (true) | |
233 | - | name - Itterator identifier. |
233 | + | |
234 | - | size0 - Number of iterators. |
234 | + | |
235 | - | size1 - Number of items per iterator. |
235 | + | |
236 | #define _FOREACH_BOT | |
237 | - | - |
237 | + | |
238 | ||
239 | - | Creates a new array of itterator start/array pair. |
239 | + | |
240 | #error YSI_ITTER_NO_SORT is no longer supported by foreach. | |
241 | #endif | |
242 | ||
243 | #define _Y_ITER_ARRAY: _:_Y_ITER_C0: | |
244 | #define _Y_ITER_ARRAY_SIZE(%1) _:_Y_ITER_C1:_Y_ITER_C2:sizeof %1@YSII_Ag-1 | |
245 | - | new \ |
245 | + | |
246 | - | %1@YSII_Sg[%2] = {-1, ...}, \ |
246 | + | |
247 | - | %1@YSII_Cg[%2] = {0}, \ |
247 | + | |
248 | - | %1@YSII_Ag[%2][%3]*/ |
248 | + | #define _Y_ITER_C2:sizeof%0(%1)@YSII_Ag-1;_:(%2=_Y_ITER_ARRAY:%3(%4)@YSII_Ag[%5])!=%9_Y_ITER_ARRAY_SIZE(%6);) -1;_:(%2=%3@YSII_Ag(%4,%5))!=-1;) |
249 | ||
250 | #define _Y_ITER_C3:%0[%1]@YSII_Cg,%2[%3]@YSII_Ag[%4]={%5} _Y_ITER_C3:%0@YSII_Cg[%4-1],%0@YSII_Ag[%1][%4] | |
251 | ||
252 | #if !defined BOTSYNC_IS_BOT | |
253 | static stock | |
254 | - | Iterator |
254 | + | YSI_g_sCallbacks = 0; |
255 | #endif | |
256 | - | Creates a new itterator start/array pair. |
256 | + | |
257 | #if !defined BOTSYNC_IS_BOT | |
258 | forward Itter_OPDCInternal(playerid); | |
259 | #endif | |
260 | ||
261 | /*----------------------------------------------------------------------------*\ | |
262 | Function: | |
263 | Itter_Create2 | |
264 | - | Itter_Init2 |
264 | + | |
265 | name - Itterator identifier. | |
266 | - | itter - Name of the itterator array to initialise. |
266 | + | size0 - Number of iterators. |
267 | size1 - Number of items per iterator. | |
268 | - | - |
268 | + | |
269 | - | |
270 | - | Wrapper for Itter_InitInternal. |
270 | + | |
271 | Creates a new array of itterator start/array pair. | |
272 | \*----------------------------------------------------------------------------*/ | |
273 | ||
274 | // If this ever changes, update the size reference in y_users. | |
275 | /*#define Iter_Create2 Itter_Create2 | |
276 | #define Itter_Create2(%1,%2,%3) \ | |
277 | new \ | |
278 | - | Itter_InitInternal(%1@YSII_Ag,sizeof %1@YSII_Ag,sizeof %1@YSII_Ag[]) |
278 | + | %1@YSII_Sg[%2] = {-1, ...}, \ |
279 | %1@YSII_Cg[%2] = {0}, \ | |
280 | %1@YSII_Ag[%2][%3]*/ | |
281 | ||
282 | - | Itter_Create |
282 | + | |
283 | ||
284 | - | name - Itterator identifier. |
284 | + | |
285 | - | size - Number of values. |
285 | + | |
286 | Iterator | |
287 | - | - |
287 | + | |
288 | Creates a new itterator start/array pair. | |
289 | - | Creates a new itterator start/array pair. |
289 | + | |
290 | ||
291 | #define Iterator:%1<%2> _Y_ITER_C3:%1@YSII_Cg,%1@YSII_Ag[(%2)+1]={(%2)*2,(%2)*2-1,...} | |
292 | #define iterator%0<%1> Iterator:%0<%1> | |
293 | ||
294 | /*----------------------------------------------------------------------------*\ | |
295 | - | new \ |
295 | + | |
296 | - | %1@YSII_Sg = -1, \ |
296 | + | Itter_Init2 |
297 | - | %1@YSII_Cg = 0, \ |
297 | + | |
298 | - | %1@YSII_Ag[%2] = {-1, ...}*/ |
298 | + | itter - Name of the itterator array to initialise. |
299 | Return: | |
300 | - | |
301 | Notes: | |
302 | - | Itter_Add |
302 | + | Wrapper for Itter_InitInternal. |
303 | ||
304 | - | itter - Name of the itterator to add the data to. |
304 | + | |
305 | - | value - Value to add to the itterator. |
305 | + | |
306 | \*----------------------------------------------------------------------------*/ | |
307 | - | - |
307 | + | |
308 | #define Iter_Init Itter_Init | |
309 | - | Wrapper for Itter_AddInternal. |
309 | + | |
310 | Itter_InitInternal(%1@YSII_Ag,sizeof %1@YSII_Ag,sizeof %1@YSII_Ag[]-1) | |
311 | ||
312 | /*----------------------------------------------------------------------------*\ | |
313 | Function: | |
314 | Itter_Create | |
315 | Params: | |
316 | name - Itterator identifier. | |
317 | size - Number of values. | |
318 | Return: | |
319 | - | |
320 | - | Itter_AddSafeInternal(%1@YSII_Sg, %1@YSII_Cg, %1@YSII_Ag, %1@YSII_Rg, %2)*/ |
320 | + | |
321 | Creates a new itterator start/array pair. | |
322 | \*----------------------------------------------------------------------------*/ | |
323 | ||
324 | - | Itter_Free |
324 | + | |
325 | /*#define Iter_Create Itter_Create | |
326 | - | itter - Name of the itterator to get the first free slot in. |
326 | + | |
327 | new \ | |
328 | - | - |
328 | + | %1@YSII_Sg = -1, \ |
329 | %1@YSII_Cg = 0, \ | |
330 | - | Wrapper for Itter_FreeInternal. |
330 | + | %1@YSII_Ag[%2] = {-1, ...}*/ |
331 | ||
332 | /*----------------------------------------------------------------------------*\ | |
333 | Function: | |
334 | Itter_Add | |
335 | Params: | |
336 | itter - Name of the itterator to add the data to. | |
337 | value - Value to add to the itterator. | |
338 | Return: | |
339 | - | |
340 | Notes: | |
341 | - | Itter_Remove |
341 | + | Wrapper for Itter_AddInternal. |
342 | ||
343 | - | itter - Name of the itterator to remove data from. |
343 | + | |
344 | - | value - Data to remove. |
344 | + | |
345 | \*----------------------------------------------------------------------------*/ | |
346 | - | - |
346 | + | |
347 | #define Iter_Add Itter_Add | |
348 | - | Wrapper for Itter_RemoveInternal. |
348 | + | |
349 | ||
350 | /*#define Iter_AddSafe Itter_AddSafe | |
351 | #define Itter_AddSafe(%1,%2) \ | |
352 | Itter_AddSafeInternal(%1@YSII_Sg, %1@YSII_Cg, %1@YSII_Ag, %1@YSII_Rg, %2)*/ | |
353 | ||
354 | /*----------------------------------------------------------------------------*\ | |
355 | Function: | |
356 | Itter_Free | |
357 | Params: | |
358 | itter - Name of the itterator to get the first free slot in. | |
359 | - | Itter_Contains |
359 | + | |
360 | - | |
361 | - | itter - Name of the itterator to check membership of. |
361 | + | |
362 | - | value - Value to check. |
362 | + | Wrapper for Itter_FreeInternal. |
363 | ||
364 | - | - |
364 | + | |
365 | ||
366 | - | Checks if the given value is in the given iterator. |
366 | + | |
367 | ||
368 | #define Iter_Free Itter_Free | |
369 | #define Itter_Free(%1) Itter_FreeInternal(_Y_ITER_ARRAY:%1@YSII_Ag,_Y_ITER_ARRAY_SIZE(%1)) | |
370 | ||
371 | /*----------------------------------------------------------------------------*\ | |
372 | Function: | |
373 | Itter_Remove | |
374 | Params: | |
375 | itter - Name of the itterator to remove data from. | |
376 | value - Data to remove. | |
377 | - | Itter_SafeRemove |
377 | + | |
378 | - | |
379 | - | itter - Name of the itterator to remove data from. |
379 | + | |
380 | - | value - Data to remove. |
380 | + | Wrapper for Itter_RemoveInternal. |
381 | - | next - Container for the pointer to the next element. |
381 | + | |
382 | native Iter_Remove(Iterator:Name<>, value); | |
383 | - | - |
383 | + | |
384 | \*----------------------------------------------------------------------------*/ | |
385 | - | Wrapper for Itter_SafeRemoveInternal. Common use: |
385 | + | |
386 | - | |
386 | + | |
387 | - | Iter_SafeRemove(iter, i, i); |
387 | + | |
388 | ||
389 | /*----------------------------------------------------------------------------*\ | |
390 | Function: | |
391 | Itter_Contains | |
392 | Params: | |
393 | itter - Name of the itterator to check membership of. | |
394 | value - Value to check. | |
395 | Return: | |
396 | - | |
397 | Notes: | |
398 | - | Itter_Random |
398 | + | Checks if the given value is in the given iterator. |
399 | ||
400 | - | itter - Name of the itterator to get a random slot from. |
400 | + | |
401 | ||
402 | - | - |
402 | + | |
403 | ||
404 | - | Wrapper for Itter_RandomInternal. |
404 | + | |
405 | #define Itter_Contains(%1,%2) Itter_ContainsInternal(_Y_ITER_ARRAY:%1@YSII_Ag,%2,_Y_ITER_ARRAY_SIZE(%1)) | |
406 | ||
407 | /*----------------------------------------------------------------------------*\ | |
408 | Function: | |
409 | Itter_SafeRemove | |
410 | Params: | |
411 | itter - Name of the itterator to remove data from. | |
412 | value - Data to remove. | |
413 | next - Container for the pointer to the next element. | |
414 | Return: | |
415 | - | Itter_Debug |
415 | + | - |
416 | Notes: | |
417 | - | itter - Name of the itterator to output debug information from. |
417 | + | Wrapper for Itter_SafeRemoveInternal. Common use: |
418 | ||
419 | - | - |
419 | + | Iter_SafeRemove(iter, i, i); |
420 | ||
421 | - | Wrapper for Itter_ShowArray. |
421 | + | |
422 | ||
423 | \*----------------------------------------------------------------------------*/ | |
424 | ||
425 | #define Iter_SafeRemove Itter_SafeRemove | |
426 | #define Itter_SafeRemove(%1,%2,%3) Itter_SafeRemoveInternal(_Y_ITER_ARRAY:%1@YSII_Cg,_Y_ITER_ARRAY:%1@YSII_Ag,%2,%3,_Y_ITER_ARRAY_SIZE(%1)) | |
427 | ||
428 | /*----------------------------------------------------------------------------*\ | |
429 | - | Itter_Count |
429 | + | |
430 | Itter_Random | |
431 | - | itter - Name of the itterator to get a random slot from4. |
431 | + | |
432 | itter - Name of the itterator to get a random slot from. | |
433 | - | - |
433 | + | |
434 | - | |
435 | - | Returns the number of items in this itterator. |
435 | + | |
436 | Wrapper for Itter_RandomInternal. | |
437 | ||
438 | native Iter_Random(Iterator:Name<>); | |
439 | ||
440 | \*----------------------------------------------------------------------------*/ | |
441 | ||
442 | #define Iter_Random Itter_Random | |
443 | #define Itter_Random(%1) Itter_RandomInternal(_Y_ITER_ARRAY:%1@YSII_Cg,_Y_ITER_ARRAY:%1@YSII_Ag,_Y_ITER_ARRAY_SIZE(%1)) | |
444 | ||
445 | /*----------------------------------------------------------------------------*\ | |
446 | - | Itter_Clear |
446 | + | |
447 | Itter_Debug | |
448 | - | itter - Name of the itterator empty. |
448 | + | |
449 | itter - Name of the itterator to output debug information from. | |
450 | - | - |
450 | + | |
451 | - | |
452 | - | Wrapper for Itter_ClearInternal. |
452 | + | |
453 | Wrapper for Itter_ShowArray. | |
454 | \*----------------------------------------------------------------------------*/ | |
455 | ||
456 | //#define Iter_Debug Itter_Debug | |
457 | //#define Itter_Debug(%1) Itter_ShowArray(_Y_ITER_ARRAY:%1@YSII_Cg,_Y_ITER_ARRAY:%1@YSII_Ag) | |
458 | ||
459 | /*----------------------------------------------------------------------------*\ | |
460 | Function: | |
461 | Itter_Count | |
462 | Params: | |
463 | itter - Name of the itterator to get a random slot from4. | |
464 | Return: | |
465 | - | |
466 | - | new |
466 | + | |
467 | - | Iterator:Player<MAX_PLAYERS>; |
467 | + | Returns the number of items in this itterator. |
468 | - | |
468 | + | |
469 | - | #if defined _FOREACH_BOT && !defined FOREACH_NO_BOTS |
469 | + | |
470 | - | new |
470 | + | |
471 | - | Iterator:Bot<MAX_PLAYERS>, |
471 | + | |
472 | - | Iterator:Character<MAX_PLAYERS>; |
472 | + | |
473 | - | |
473 | + | |
474 | - | //#define NPC@YSII_Sg Bot@YSII_Sg |
474 | + | |
475 | - | #define NPC@YSII_Cg Bot@YSII_Cg |
475 | + | |
476 | - | #define NPC@YSII_Ag Bot@YSII_Ag |
476 | + | |
477 | - | //#define NPC@YSII_Eg Bot@YSII_Eg |
477 | + | |
478 | - | //#define NPC@YSII_Rg Bot@YSII_Rg |
478 | + | Itter_Clear |
479 | - | #endif |
479 | + | |
480 | itter - Name of the itterator empty. | |
481 | Return: | |
482 | - | |
483 | Notes: | |
484 | - | foreach |
484 | + | Wrapper for Itter_ClearInternal. |
485 | ||
486 | - | data - Data to itterate through. |
486 | + | |
487 | - | as - Variable to set value to. |
487 | + | |
488 | \*----------------------------------------------------------------------------*/ | |
489 | - | - |
489 | + | |
490 | #define Iter_Clear Itter_Clear | |
491 | - | Not exactly the same as PHP foreach, just itterates through a list and |
491 | + | |
492 | - | returns the value of the current slot but uses that slot as the next index |
492 | + | |
493 | - | too. Variables must be in the form @YSII_<gname>S for the start index and |
493 | + | |
494 | - | @YSII_<gname>A for the data array where <name> is what's entered in data. |
494 | + | |
495 | \*----------------------------------------------------------------------------*/ | |
496 | ||
497 | #if !defined BOTSYNC_IS_BOT | |
498 | - | // for (new %2 = %1@YSII_Sg; _:%2 != -1; %2 = %1@YSII_Ag[%2]) |
498 | + | new |
499 | Iterator:Player<MAX_PLAYERS>; | |
500 | ||
501 | #if defined _FOREACH_BOT && !defined FOREACH_NO_BOTS | |
502 | new | |
503 | Iterator:Bot<MAX_PLAYERS>, | |
504 | Iterator:Character<MAX_PLAYERS>; | |
505 | ||
506 | //#define NPC@YSII_Sg Bot@YSII_Sg | |
507 | #define NPC@YSII_Cg Bot@YSII_Cg | |
508 | #define NPC@YSII_Ag Bot@YSII_Ag | |
509 | //#define NPC@YSII_Eg Bot@YSII_Eg | |
510 | //#define NPC@YSII_Rg Bot@YSII_Rg | |
511 | #endif | |
512 | #endif | |
513 | - | #define Y_FOREACH_SEVENTH|||%9Y_FOREACH_SIXTH;%0|||%1|||%2||| new %0:%1=%0:_Y_ITER_ARRAY_SIZE(%2);_:(%1=_Y_ITER_ARRAY:%2@YSII_Ag[%1])!=_Y_ITER_ARRAY_SIZE(%2); |
513 | + | |
514 | /*----------------------------------------------------------------------------*\ | |
515 | Variables to optimise memory usage by only having one copy of each string. | |
516 | Note that only strings used more than once are put here because only they | |
517 | have any gain to being located in only one place. | |
518 | \*----------------------------------------------------------------------------*/ | |
519 | ||
520 | static stock | |
521 | YSI_gsOnPlayerConnect[] = "Itter_OnPlayerConnect", | |
522 | YSI_gsOnPlayerDisconnect[] = "Itter_OnPlayerDisconnect", | |
523 | YSI_gsOnGameModeInit[] = "Itter_OnGameModeInit", | |
524 | YSI_gsSpecifier@i[] = "i", | |
525 | YSI_gsSpecifier@[] = ""; | |
526 | ||
527 | /*----------------------------------------------------------------------------*\ | |
528 | Function: | |
529 | foreach | |
530 | Params: | |
531 | data - Data to itterate through. | |
532 | as - Variable to set value to. | |
533 | Return: | |
534 | - | |
535 | Notes: | |
536 | - | foreachex |
536 | + | Not exactly the same as PHP foreach, just itterates through a list and |
537 | returns the value of the current slot but uses that slot as the next index | |
538 | - | data - Data to itterate through. |
538 | + | too. Variables must be in the form @YSII_<gname>S for the start index and |
539 | - | as - Variable to set value to. |
539 | + | @YSII_<gname>A for the data array where <name> is what's entered in data. |
540 | \*----------------------------------------------------------------------------*/ | |
541 | - | - |
541 | + | |
542 | //#define foreach(%1,%2) | |
543 | - | Similar to foreach but doesn't declare a new variable for the itterator. |
543 | + | // for (new %2 = %1@YSII_Sg; _:%2 != -1; %2 = %1@YSII_Ag[%2]) |
544 | #define foreach%1(%0) for(new Y_FOREACH_SECOND|||Y_FOREACH_THIRD|||%0|||) | |
545 | // This allows us to use "new" multiple times - stripping off ONLY whole words. | |
546 | #define new%0|||%9|||%1:%2||| %9|||%0|||%1|||%2||| | |
547 | - | //for (%2=_Y_ITER_ARRAY_SIZE(%1);(%2=_Y_ITER_ARRAY:%1@YSII_Ag[%2])!=_Y_ITER_ARRAY_SIZE(%1);) |
547 | + | |
548 | // This one is called if the new syntax is required, but the state of "new" is | |
549 | // as-yet unknown. This attempts to call "%1" as a macro, if it starts with | |
550 | // "new" as a whole word then it will (and will also helpfully strip off the | |
551 | - | Itter_OnPlayerConnect |
551 | + | |
552 | #define Y_FOREACH_THIRD|||%0|||%1|||%2||| %1=Y_FOREACH_FIFTH|||Y_FOREACH_FOURTH|||%1:%2||| | |
553 | - | playerid - Player who joined. |
553 | + | |
554 | // This is called if the "new" macro is called for a second time. | |
555 | - | - |
555 | + | |
556 | ||
557 | - | Adds a player to the loop data. Now sorts the list too. Note that I found |
557 | + | |
558 | - | the most bizzare bug ever (I *think* it may be a compiler but, but it |
558 | + | #define Y_FOREACH_SEVENTH|||%9Y_FOREACH_SIXTH;%0|||%1|||%2||| new %0:%1=%0:_Y_ITER_ARRAY_SIZE(%2);_:(%1=_Y_ITER_ARRAY:%2@YSII_Ag[%1])!=%0:_Y_ITER_ARRAY_SIZE(%2); |
559 | - | requires further investigation), basically it seems that multiple variables |
559 | + | |
560 | - | were being treated as the same variable (namely @YSII_EgotS and |
560 | + | |
561 | - | @YSII_CgharacterS were the same and @YSII_EgotC and @YSII_CgharacterC were the |
561 | + | |
562 | - | same). Adding print statements which reference these variables seem to fix |
562 | + | |
563 | - | the problem, and I've tried to make sure that the values will never actually |
563 | + | |
564 | - | get printed. |
564 | + | |
565 | // Move any tags from the second half to the first half. | |
566 | //#define hta:%0=hta:%1:%2;_:%3!=-1;%4=hta:%5:%6[%7] %0:%1=%2;_:%1!=-1;%1=%6[%1] | |
567 | ||
568 | - | public OnPlayerConnect(playerid) |
568 | + | |
569 | - | { |
569 | + | |
570 | - | #if defined _FOREACH_BOT |
570 | + | |
571 | - | if (!IsPlayerNPC(playerid)) |
571 | + | |
572 | - | { |
572 | + | |
573 | - | Itter_Add(Player, playerid); |
573 | + | |
574 | - | } |
574 | + | |
575 | - | #if !defined FOREACH_NO_BOTS |
575 | + | |
576 | - | else |
576 | + | |
577 | - | { |
577 | + | |
578 | - | Itter_Add(Bot, playerid); |
578 | + | |
579 | - | } |
579 | + | |
580 | - | #pragma tabsize 4 |
580 | + | |
581 | - | Itter_Add(Character, playerid); |
581 | + | foreachex |
582 | - | #endif |
582 | + | |
583 | - | #else |
583 | + | data - Data to itterate through. |
584 | - | Itter_Add(Player, playerid); |
584 | + | as - Variable to set value to. |
585 | - | #endif |
585 | + | |
586 | - | if (YSI_g_sCallbacks & 2) |
586 | + | - |
587 | - | { |
587 | + | |
588 | - | CallLocalFunction("Itter_OnPlayerConnect", "i", playerid); |
588 | + | Similar to foreach but doesn't declare a new variable for the itterator. |
589 | - | } |
589 | + | |
590 | - | return 1; |
590 | + | |
591 | - | } |
591 | + | |
592 | - | |
592 | + | //for (%2=_Y_ITER_ARRAY_SIZE(%1);(%2=_Y_ITER_ARRAY:%1@YSII_Ag[%2])!=_Y_ITER_ARRAY_SIZE(%1);) |
593 | - | #if defined _ALS_OnPlayerConnect |
593 | + | |
594 | - | #undef OnPlayerConnect |
594 | + | |
595 | - | #else |
595 | + | |
596 | - | #define _ALS_OnPlayerConnect |
596 | + | Itter_OnPlayerConnect |
597 | - | #endif |
597 | + | |
598 | - | #define OnPlayerConnect Itter_OnPlayerConnect |
598 | + | playerid - Player who joined. |
599 | - | forward OnPlayerConnect(playerid); |
599 | + | |
600 | - | |
601 | Notes: | |
602 | Adds a player to the loop data. Now sorts the list too. Note that I found | |
603 | the most bizzare bug ever (I *think* it may be a compiler but, but it | |
604 | - | Itter_OnGameModeInit |
604 | + | requires further investigation), basically it seems that multiple variables |
605 | were being treated as the same variable (namely @YSII_EgotS and | |
606 | - | - |
606 | + | @YSII_CgharacterS were the same and @YSII_EgotC and @YSII_CgharacterC were the |
607 | same). Adding print statements which reference these variables seem to fix | |
608 | - | - |
608 | + | the problem, and I've tried to make sure that the values will never actually |
609 | get printed. | |
610 | - | There are WIERD bugs in this script, seemingly caused by the compiler, so |
610 | + | |
611 | - | this hopefully fixes them. The OnFilterScriptInit code is written to be |
611 | + | |
612 | - | very fast by utilising the internal array structure instead of the regular |
612 | + | |
613 | - | Add functions. |
613 | + | public OnPlayerConnect(playerid) |
614 | { | |
615 | P:0("Iter_OnPlayerConnect: %d", playerid); | |
616 | #if defined _FOREACH_BOT | |
617 | - | public OnGameModeInit() |
617 | + | if (!IsPlayerNPC(playerid)) |
618 | - | { |
618 | + | { |
619 | - | // Clear everything. |
619 | + | Itter_Add(Player, playerid); |
620 | - | if (funcidx("Itter_OnPlayerDisconnect") != -1) |
620 | + | } |
621 | - | { |
621 | + | #if !defined FOREACH_NO_BOTS |
622 | - | YSI_g_sCallbacks |= 1; |
622 | + | else |
623 | - | } |
623 | + | { |
624 | - | if (funcidx("Itter_OnPlayerConnect") != -1) |
624 | + | Itter_Add(Bot, playerid); |
625 | - | { |
625 | + | } |
626 | - | YSI_g_sCallbacks |= 2; |
626 | + | #pragma tabsize 4 |
627 | - | } |
627 | + | Itter_Add(Character, playerid); |
628 | - | if (!Player@YSII_Cg) |
628 | + | #endif |
629 | - | { |
629 | + | #else |
630 | - | #if defined _FOREACH_BOT && !defined FOREACH_NO_BOTS |
630 | + | Itter_Add(Player, playerid); |
631 | - | CallLocalFunction("Itter_OnGameModeInit", "", Bot@YSII_Cg, Character@YSII_Cg, Player@YSII_Cg); |
631 | + | #endif |
632 | - | #else |
632 | + | if (YSI_g_sCallbacks & 2) |
633 | - | CallLocalFunction("Itter_OnGameModeInit", "", Player@YSII_Cg); |
633 | + | { |
634 | - | #endif |
634 | + | CallLocalFunction(YSI_gsOnPlayerConnect, YSI_gsSpecifier@i, playerid); |
635 | - | return 1; |
635 | + | } |
636 | - | } |
636 | + | P:0("Iter_OnPlayerConnect end"); |
637 | - | // Do the forward iterator list. |
637 | + | return 1; |
638 | - | #if defined _FOREACH_BOT && !defined FOREACH_NO_BOTS |
638 | + | } |
639 | - | Bot@YSII_Cg = _Y_ITER_C3:0; |
639 | + | |
640 | - | Bot@YSII_Ag[MAX_PLAYERS] = MAX_PLAYERS; |
640 | + | #if defined _ALS_OnPlayerConnect |
641 | - | Character@YSII_Ag[MAX_PLAYERS] = MAX_PLAYERS; |
641 | + | #undef OnPlayerConnect |
642 | - | Character@YSII_Cg = _Y_ITER_C3:0; |
642 | + | #else |
643 | - | new |
643 | + | #define _ALS_OnPlayerConnect |
644 | - | lastBot = MAX_PLAYERS, |
644 | + | #endif |
645 | - | lastCharacter = MAX_PLAYERS; |
645 | + | #define OnPlayerConnect Itter_OnPlayerConnect |
646 | - | #endif |
646 | + | forward OnPlayerConnect(playerid); |
647 | - | Player@YSII_Cg = _Y_ITER_C3:0; |
647 | + | |
648 | - | Player@YSII_Ag[MAX_PLAYERS] = MAX_PLAYERS; |
648 | + | |
649 | - | new |
649 | + | |
650 | - | lastPlayer = MAX_PLAYERS; |
650 | + | |
651 | - | for (new i = 0; i != MAX_PLAYERS; ++i) |
651 | + | Itter_OnFilterScriptInit |
652 | - | { |
652 | + | |
653 | - | if (IsPlayerConnected(i)) |
653 | + | - |
654 | - | { |
654 | + | |
655 | - | #if defined _FOREACH_BOT |
655 | + | - |
656 | - | // Had to do "if ! else" due to compile options. |
656 | + | |
657 | - | if (!IsPlayerNPC(i)) |
657 | + | Fixes a bug where callbacks are not detected when "loadfs" is used after the |
658 | - | { |
658 | + | GM has already started. If this is a GM this is just never used called. |
659 | - | Player@YSII_Ag[lastPlayer] = i; |
659 | + | |
660 | - | ++Player@YSII_Cg; |
660 | + | |
661 | - | lastPlayer = i; |
661 | + | |
662 | - | } |
662 | + | public OnFilterScriptInit() |
663 | - | #if !defined FOREACH_NO_BOTS |
663 | + | { |
664 | - | else |
664 | + | P:0("Iter_OnFilterScriptInit start: %d", MAX_PLAYERS); |
665 | - | { |
665 | + | if (funcidx(YSI_gsOnPlayerDisconnect) != -1) |
666 | - | Bot@YSII_Ag[lastBot] = i; |
666 | + | { |
667 | - | ++Bot@YSII_Cg; |
667 | + | YSI_g_sCallbacks |= 1; |
668 | - | lastBot = i; |
668 | + | } |
669 | - | } |
669 | + | if (funcidx(YSI_gsOnPlayerConnect) != -1) |
670 | - | #pragma tabsize 4 |
670 | + | { |
671 | - | Character@YSII_Ag[lastCharacter] = i; |
671 | + | YSI_g_sCallbacks |= 2; |
672 | - | ++Character@YSII_Cg; |
672 | + | } |
673 | - | lastCharacter = i; |
673 | + | #if defined _FOREACH_BOT && !defined FOREACH_NO_BOTS |
674 | - | #endif |
674 | + | Bot@YSII_Cg = _Y_ITER_C3:0; |
675 | - | #else |
675 | + | Character@YSII_Cg = _Y_ITER_C3:0; |
676 | - | Player@YSII_Ag[lastPlayer] = i; |
676 | + | new |
677 | - | ++Player@YSII_Cg; |
677 | + | lastBot = MAX_PLAYERS, |
678 | - | lastPlayer = i; |
678 | + | lastCharacter = MAX_PLAYERS; |
679 | - | #endif |
679 | + | #endif |
680 | - | } |
680 | + | Player@YSII_Cg = _Y_ITER_C3:0; |
681 | - | else |
681 | + | new |
682 | - | { |
682 | + | lastPlayer = MAX_PLAYERS; |
683 | - | #if defined _FOREACH_BOT && !defined FOREACH_NO_BOTS |
683 | + | for (new i = 0; i != MAX_PLAYERS; ++i) |
684 | - | Bot@YSII_Ag[i] = MAX_PLAYERS + 1; |
684 | + | { |
685 | - | //Bot@YSII_Rg[i] = -1; |
685 | + | if (IsPlayerConnected(i)) |
686 | - | Character@YSII_Ag[i] = MAX_PLAYERS + 1; |
686 | + | { |
687 | - | //Character@YSII_Rg[i] = -1; |
687 | + | #if defined _FOREACH_BOT |
688 | - | #endif |
688 | + | // Had to do "if ! else" due to compile options. |
689 | - | Player@YSII_Ag[i] = MAX_PLAYERS + 1; |
689 | + | if (!IsPlayerNPC(i)) |
690 | - | //Player@YSII_Rg[i] = -1; |
690 | + | { |
691 | - | } |
691 | + | Player@YSII_Ag[lastPlayer] = i; |
692 | - | } |
692 | + | ++Player@YSII_Cg; |
693 | - | #if defined _FOREACH_BOT && !defined FOREACH_NO_BOTS |
693 | + | lastPlayer = i; |
694 | - | Bot@YSII_Ag[lastPlayer] = MAX_PLAYERS; |
694 | + | } |
695 | - | Character@YSII_Ag[lastPlayer] = MAX_PLAYERS; |
695 | + | #if !defined FOREACH_NO_BOTS |
696 | - | #endif |
696 | + | else |
697 | - | Player@YSII_Ag[lastPlayer] = MAX_PLAYERS; |
697 | + | { |
698 | - | CallLocalFunction("Itter_OnGameModeInit", ""); |
698 | + | Bot@YSII_Ag[lastBot] = i; |
699 | - | return 1; |
699 | + | ++Bot@YSII_Cg; |
700 | - | } |
700 | + | lastBot = i; |
701 | - | |
701 | + | } |
702 | - | #if defined _ALS_OnGameModeInit |
702 | + | #pragma tabsize 4 |
703 | - | #undef OnGameModeInit |
703 | + | Character@YSII_Ag[lastCharacter] = i; |
704 | - | #else |
704 | + | ++Character@YSII_Cg; |
705 | - | #define _ALS_OnGameModeInit |
705 | + | lastCharacter = i; |
706 | - | #endif |
706 | + | #endif |
707 | - | #define OnGameModeInit Itter_OnGameModeInit |
707 | + | #else |
708 | - | forward OnGameModeInit(); |
708 | + | Player@YSII_Ag[lastPlayer] = i; |
709 | ++Player@YSII_Cg; | |
710 | lastPlayer = i; | |
711 | #endif | |
712 | } | |
713 | - | Itter_OnPlayerDisconnect |
713 | + | else |
714 | { | |
715 | - | playerid - Player who left. |
715 | + | #if defined _FOREACH_BOT && !defined FOREACH_NO_BOTS |
716 | Bot@YSII_Ag[i] = MAX_PLAYERS + 1; | |
717 | - | - |
717 | + | //Bot@YSII_Rg[i] = -1; |
718 | Character@YSII_Ag[i] = MAX_PLAYERS + 1; | |
719 | - | Removes a player from the loop data. No longer uses "hook" to ENSURE that |
719 | + | //Character@YSII_Rg[i] = -1; |
720 | - | this is always last. Previously I think that the order of evaluation in |
720 | + | #endif |
721 | - | y_hooks meant that this got called before the user "OnPlayerDisconnect". |
721 | + | Player@YSII_Ag[i] = MAX_PLAYERS + 1; |
722 | //Player@YSII_Rg[i] = -1; | |
723 | } | |
724 | } | |
725 | - | public OnPlayerDisconnect(playerid, reason) |
725 | + | #if defined _FOREACH_BOT && !defined FOREACH_NO_BOTS |
726 | - | { |
726 | + | Bot@YSII_Ag[lastPlayer] = MAX_PLAYERS; |
727 | - | if (YSI_g_sCallbacks & 1) |
727 | + | Character@YSII_Ag[lastPlayer] = MAX_PLAYERS; |
728 | - | { |
728 | + | #endif |
729 | - | CallLocalFunction("Itter_OnPlayerDisconnect", "ii", playerid, reason); |
729 | + | Player@YSII_Ag[lastPlayer] = MAX_PLAYERS; |
730 | - | } |
730 | + | CallLocalFunction("Itter_OnFilterScriptInit", YSI_gsSpecifier@); |
731 | - | #if defined _FOREACH_BOT |
731 | + | P:0("Iter_OnFilterScriptInit end"); |
732 | - | if (!IsPlayerNPC(playerid)) |
732 | + | return 1; |
733 | - | { |
733 | + | } |
734 | - | Itter_Remove(Player, playerid); |
734 | + | |
735 | - | } |
735 | + | #if defined _ALS_OnFilterScriptInit |
736 | - | #if !defined FOREACH_NO_BOTS |
736 | + | #undef OnFilterScriptInit |
737 | - | else |
737 | + | #else |
738 | - | { |
738 | + | #define _ALS_OnFilterScriptInit |
739 | - | Itter_Remove(Bot, playerid); |
739 | + | #endif |
740 | - | } |
740 | + | #define OnFilterScriptInit Itter_OnFilterScriptInit |
741 | - | #pragma tabsize 4 |
741 | + | forward OnFilterScriptInit(); |
742 | - | Itter_Remove(Character, playerid); |
742 | + | |
743 | - | #endif |
743 | + | |
744 | - | #else |
744 | + | |
745 | - | Itter_Remove(Player, playerid); |
745 | + | |
746 | - | #endif |
746 | + | Itter_OnGameModeInit |
747 | - | return 1; |
747 | + | |
748 | - | } |
748 | + | - |
749 | - | |
749 | + | |
750 | - | #if defined _ALS_OnPlayerDisconnect |
750 | + | - |
751 | - | #undef OnPlayerDisconnect |
751 | + | |
752 | - | #else |
752 | + | There are WIERD bugs in this script, seemingly caused by the compiler, so |
753 | - | #define _ALS_OnPlayerDisconnect |
753 | + | this hopefully fixes them. The OnFilterScriptInit code is written to be |
754 | - | #endif |
754 | + | very fast by utilising the internal array structure instead of the regular |
755 | - | #define OnPlayerDisconnect Itter_OnPlayerDisconnect |
755 | + | Add functions. |
756 | - | forward OnPlayerDisconnect(playerid, reason); |
756 | + | |
757 | ||
758 | #if !defined BOTSYNC_IS_BOT | |
759 | public OnGameModeInit() | |
760 | { | |
761 | - | Itter_ShowArray |
761 | + | P:0("Iter_OnGameModeInit start: %d", MAX_PLAYERS); |
762 | // Clear everything. | |
763 | - | start - Itterator start point. |
763 | + | if (funcidx(YSI_gsOnPlayerDisconnect) != -1) |
764 | - | members[] - Itterator contents. |
764 | + | { |
765 | - | size - Number of itterator values |
765 | + | YSI_g_sCallbacks |= 1; |
766 | } | |
767 | - | - |
767 | + | if (funcidx(YSI_gsOnPlayerConnect) != -1) |
768 | { | |
769 | - | Pure debug function. Has regular prints not debug prints |
769 | + | YSI_g_sCallbacks |= 2; |
770 | - | as it's only called when debug is on. |
770 | + | } |
771 | if (!Player@YSII_Cg) | |
772 | { | |
773 | #if defined _FOREACH_BOT && !defined FOREACH_NO_BOTS | |
774 | - | Itter_ShowArray(size, members[]) |
774 | + | CallLocalFunction(YSI_gsOnGameModeInit, YSI_gsSpecifier@, Bot@YSII_Cg, Character@YSII_Cg, Player@YSII_Cg); |
775 | #else | |
776 | - | static |
776 | + | CallLocalFunction(YSI_gsOnGameModeInit, YSI_gsSpecifier@, Player@YSII_Cg); |
777 | - | sString[61]; |
777 | + | #endif |
778 | - | new |
778 | + | #if defined _YSI_SPECIAL_DEBUG |
779 | - | i, |
779 | + | for (new i = 0; i != MAX_PLAYERS; ++i) |
780 | - | j = 10; |
780 | + | { |
781 | - | printf("Start: %d", start); |
781 | + | Player@YSII_Ag[i] = i + 1; |
782 | - | printf("Size: %d", size); |
782 | + | } |
783 | - | while (i < size) |
783 | + | Player@YSII_Ag[MAX_PLAYERS] = 0; |
784 | - | { |
784 | + | Player@YSII_Cg = _Y_ITER_C3:MAX_PLAYERS; |
785 | - | sString[0] = '\0'; |
785 | + | #endif |
786 | - | while (i < j && i < size) |
786 | + | P:0("Iter_OnGameModeInit: first"); |
787 | - | { |
787 | + | return 1; |
788 | - | format(sString, sizeof (sString), "%s, %d", sString, members[i]); |
788 | + | } |
789 | - | i++; |
789 | + | // Do the forward iterator list. |
790 | - | } |
790 | + | #if defined _FOREACH_BOT && !defined FOREACH_NO_BOTS |
791 | - | printf("Array (%d): %s", j, sString); |
791 | + | Bot@YSII_Cg = _Y_ITER_C3:0; |
792 | - | j += 10; |
792 | + | Bot@YSII_Ag[MAX_PLAYERS] = MAX_PLAYERS; |
793 | - | } |
793 | + | Character@YSII_Ag[MAX_PLAYERS] = MAX_PLAYERS; |
794 | Character@YSII_Cg = _Y_ITER_C3:0; | |
795 | new | |
796 | lastBot = MAX_PLAYERS, | |
797 | lastCharacter = MAX_PLAYERS; | |
798 | - | Itter_RandomInternal |
798 | + | #endif |
799 | Player@YSII_Cg = _Y_ITER_C3:0; | |
800 | - | count - Number of items in the itterator. |
800 | + | Player@YSII_Ag[MAX_PLAYERS] = MAX_PLAYERS; |
801 | - | array[] - Itterator data. |
801 | + | new |
802 | - | size - Size of the iterator. |
802 | + | lastPlayer = MAX_PLAYERS; |
803 | for (new i = 0; i != MAX_PLAYERS; ++i) | |
804 | - | - |
804 | + | { |
805 | if (IsPlayerConnected(i)) | |
806 | - | Returns a random value from an iterator. |
806 | + | { |
807 | #if defined _FOREACH_BOT | |
808 | // Had to do "if ! else" due to compile options. | |
809 | if (!IsPlayerNPC(i)) | |
810 | - | Itter_RandomInternal(count, array[], size) |
810 | + | { |
811 | Player@YSII_Ag[lastPlayer] = i; | |
812 | - | if (count == 0) |
812 | + | ++Player@YSII_Cg; |
813 | - | { |
813 | + | lastPlayer = i; |
814 | - | return -1; |
814 | + | } |
815 | - | } |
815 | + | #if !defined FOREACH_NO_BOTS |
816 | - | new |
816 | + | else |
817 | - | rnd = random(count), |
817 | + | { |
818 | - | cur = array[size]; |
818 | + | Bot@YSII_Ag[lastBot] = i; |
819 | - | while (cur != size) |
819 | + | ++Bot@YSII_Cg; |
820 | - | { |
820 | + | lastBot = i; |
821 | - | if (rnd-- == 0) |
821 | + | } |
822 | - | { |
822 | + | #pragma tabsize 4 |
823 | - | return cur; |
823 | + | Character@YSII_Ag[lastCharacter] = i; |
824 | - | } |
824 | + | ++Character@YSII_Cg; |
825 | - | cur = array[cur]; |
825 | + | lastCharacter = i; |
826 | - | } |
826 | + | #endif |
827 | - | return -1; |
827 | + | #else |
828 | Player@YSII_Ag[lastPlayer] = i; | |
829 | ++Player@YSII_Cg; | |
830 | lastPlayer = i; | |
831 | #endif | |
832 | - | Itter_FreeInternal |
832 | + | } |
833 | else | |
834 | - | count - Number of items in the itterator. |
834 | + | { |
835 | - | array[] - Itterator data. |
835 | + | #if defined _FOREACH_BOT && !defined FOREACH_NO_BOTS |
836 | - | size - Size of the itterator. |
836 | + | Bot@YSII_Ag[i] = MAX_PLAYERS + 1; |
837 | //Bot@YSII_Rg[i] = -1; | |
838 | - | - |
838 | + | Character@YSII_Ag[i] = MAX_PLAYERS + 1; |
839 | //Character@YSII_Rg[i] = -1; | |
840 | - | Finds the first free slot in the itterator. Itterators now HAVE to be |
840 | + | #endif |
841 | - | sorted for this function to work correctly as it uses that fact to decide |
841 | + | Player@YSII_Ag[i] = MAX_PLAYERS + 1; |
842 | - | wether a slot is unused or the last one. If you want to use the slot |
842 | + | //Player@YSII_Rg[i] = -1; |
843 | - | straight after finding it the itterator will need to re-find it to add in |
843 | + | } |
844 | - | the data. |
844 | + | } |
845 | #if defined _FOREACH_BOT && !defined FOREACH_NO_BOTS | |
846 | Bot@YSII_Ag[lastPlayer] = MAX_PLAYERS; | |
847 | Character@YSII_Ag[lastPlayer] = MAX_PLAYERS; | |
848 | - | Itter_FreeInternal(array[], size) |
848 | + | #endif |
849 | Player@YSII_Ag[lastPlayer] = MAX_PLAYERS; | |
850 | - | for (new i = 0; i != size; ++i) |
850 | + | P:0("Iter_OnGameModeInit: lastplayer = %d", lastPlayer); |
851 | - | { |
851 | + | CallLocalFunction(YSI_gsOnGameModeInit, YSI_gsSpecifier@); |
852 | - | if (array[i] > size) |
852 | + | #if defined _YSI_SPECIAL_DEBUG |
853 | - | { |
853 | + | for (new i = 0; i != MAX_PLAYERS; ++i) |
854 | - | return i; |
854 | + | { |
855 | - | } |
855 | + | Player@YSII_Ag[i] = i + 1; |
856 | - | } |
856 | + | } |
857 | - | return -1; |
857 | + | Player@YSII_Ag[MAX_PLAYERS] = 0; |
858 | Player@YSII_Cg = _Y_ITER_C3:MAX_PLAYERS; | |
859 | #endif | |
860 | return 1; | |
861 | } | |
862 | - | Itter_AddInternal |
862 | + | |
863 | #if defined _ALS_OnGameModeInit | |
864 | - | &start - Array start index. |
864 | + | #undef OnGameModeInit |
865 | - | &count - Number of items in the itterator. |
865 | + | #else |
866 | - | array[] - Itterator data. |
866 | + | #define _ALS_OnGameModeInit |
867 | - | value - Item to add. |
867 | + | #endif |
868 | #define OnGameModeInit Itter_OnGameModeInit | |
869 | - | - |
869 | + | forward OnGameModeInit(); |
870 | #endif | |
871 | - | Adds a value to a given itterator set. Now detects when you try and add the |
871 | + | |
872 | - | last item multiple times, as well as all the other items. Now simplified even |
872 | + | |
873 | - | further with the new internal representation. |
873 | + | |
874 | Itter_OnPlayerDisconnect | |
875 | Params: | |
876 | playerid - Player who left. | |
877 | - | Itter_AddInternal(&count, array[], value, size) |
877 | + | |
878 | - | |
879 | - | if (0 <= value < size && array[value] > size) |
879 | + | |
880 | - | { |
880 | + | Removes a player from the loop data. No longer uses "hook" to ENSURE that |
881 | - | new |
881 | + | this is always last. Previously I think that the order of evaluation in |
882 | - | last = size, |
882 | + | y_hooks meant that this got called before the user "OnPlayerDisconnect". |
883 | - | next = array[last]; |
883 | + | |
884 | - | while (next < value) |
884 | + | |
885 | - | { |
885 | + | |
886 | - | last = next; |
886 | + | public OnPlayerDisconnect(playerid, reason) |
887 | - | next = array[last]; |
887 | + | { |
888 | - | } |
888 | + | if (YSI_g_sCallbacks & 1) |
889 | - | array[last] = value; |
889 | + | { |
890 | - | array[value] = next; |
890 | + | CallLocalFunction(YSI_gsOnPlayerDisconnect, "ii", playerid, reason); |
891 | - | ++count; |
891 | + | } |
892 | - | return 1; |
892 | + | SetTimerEx("Itter_OPDCInternal", 0, false, YSI_gsSpecifier@i, playerid); |
893 | - | } |
893 | + | return 1; |
894 | - | return 0; |
894 | + | } |
895 | ||
896 | #if defined _ALS_OnPlayerDisconnect | |
897 | #undef OnPlayerDisconnect | |
898 | #else | |
899 | - | Itter_RemoveInternal |
899 | + | #define _ALS_OnPlayerDisconnect |
900 | #endif | |
901 | - | &count - Number of items in the itterator. |
901 | + | #define OnPlayerDisconnect Itter_OnPlayerDisconnect |
902 | - | array[] - Itterator data. |
902 | + | forward OnPlayerDisconnect(playerid, reason); |
903 | - | value - Item to remove. |
903 | + | |
904 | ||
905 | - | - |
905 | + | |
906 | Function: | |
907 | - | Removes a value from an itterator. |
907 | + | Itter_OPDCInternal |
908 | Params: | |
909 | playerid - Player who left. | |
910 | Return: | |
911 | - | Itter_RemoveInternal(&count, array[], value, size) |
911 | + | - |
912 | Notes: | |
913 | - | new |
913 | + | Called AFTER "OnPlayerDisconnect" so that using "Kick" inside a "foreach" |
914 | - | last; |
914 | + | loop doesn't crash the server due to an OOB error. |
915 | - | return Itter_SafeRemoveInternal(count, array, value, last, size); |
915 | + | |
916 | ||
917 | #if !defined BOTSYNC_IS_BOT | |
918 | public Itter_OPDCInternal(playerid) | |
919 | { | |
920 | - | Itter_SafeRemoveInternal |
920 | + | if (IsPlayerConnected(playerid)) |
921 | { | |
922 | - | &count - Number of items in the itterator. |
922 | + | return; |
923 | - | array[] - Iterator data. |
923 | + | } |
924 | - | back[] - Reverse iterator data. |
924 | + | #if defined _FOREACH_BOT |
925 | - | value - Item to remove. |
925 | + | if (!IsPlayerNPC(playerid)) |
926 | - | &last - Pointer in which to store the last pointer. |
926 | + | { |
927 | Itter_Remove(Player, playerid); | |
928 | - | - |
928 | + | } |
929 | #if !defined FOREACH_NO_BOTS | |
930 | - | Removes a value from an itterator safely. |
930 | + | else |
931 | { | |
932 | Itter_Remove(Bot, playerid); | |
933 | } | |
934 | - | Itter_SafeRemoveInternal(&count, array[], value, &last, size) |
934 | + | #pragma tabsize 4 |
935 | Itter_Remove(Character, playerid); | |
936 | - | if (0 <= value < size && array[value] <= size) |
936 | + | #endif |
937 | - | { |
937 | + | #else |
938 | - | last = size; |
938 | + | Itter_Remove(Player, playerid); |
939 | - | new |
939 | + | #endif |
940 | - | next = array[last]; |
940 | + | } |
941 | - | while (next != value) |
941 | + | |
942 | - | { |
942 | + | |
943 | - | last = next; |
943 | + | |
944 | - | next = array[last]; |
944 | + | |
945 | - | } |
945 | + | Itter_ShowArray |
946 | - | array[last] = array[value]; |
946 | + | |
947 | - | array[value] = size + 1; |
947 | + | start - Itterator start point. |
948 | - | --count; |
948 | + | members[] - Itterator contents. |
949 | - | return 1; |
949 | + | size - Number of itterator values |
950 | - | } |
950 | + | |
951 | - | return 0; |
951 | + | - |
952 | Notes: | |
953 | Pure debug function. Has regular prints not debug prints | |
954 | as it's only called when debug is on. | |
955 | \*----------------------------------------------------------------------------*/ | |
956 | - | Itter_ContainsInternal |
956 | + | |
957 | /*stock | |
958 | - | array[] - Itterator data. |
958 | + | Itter_ShowArray(size, members[]) |
959 | - | value - Item to check. |
959 | + | |
960 | - | size - Size of the iterator. |
960 | + | static |
961 | sString[61]; | |
962 | - | - |
962 | + | new |
963 | i, | |
964 | - | Checks if this item is in the iterator. |
964 | + | j = 10; |
965 | printf("Start: %d", start); | |
966 | printf("Size: %d", size); | |
967 | while (i < size) | |
968 | - | Itter_ContainsInternal(array[], value, size) |
968 | + | { |
969 | sString[0] = '\0'; | |
970 | - | return 0 <= value < size && array[value] <= size; |
970 | + | while (i < j && i < size) |
971 | { | |
972 | format(sString, sizeof (sString), "%s, %d", sString, members[i]); | |
973 | i++; | |
974 | } | |
975 | - | Itter_ClearInternal |
975 | + | printf("Array (%d): %s", j, sString); |
976 | j += 10; | |
977 | - | &count - Number of items in the itterator. |
977 | + | } |
978 | - | array[] - Itterator data. |
978 | + | |
979 | - | back[] - Reverse data. |
979 | + | |
980 | - | size - Size of the iterator. |
980 | + | |
981 | Function: | |
982 | - | - |
982 | + | Itter_RandomInternal |
983 | Params: | |
984 | - | Resets an iterator. |
984 | + | count - Number of items in the itterator. |
985 | array[] - Itterator data. | |
986 | size - Size of the iterator. | |
987 | Return: | |
988 | - | Itter_ClearInternal(&count, array[], size) |
988 | + | - |
989 | Notes: | |
990 | - | for (new i = 0, t = size + 1; i < size; ++i) |
990 | + | Returns a random value from an iterator. |
991 | - | { |
991 | + | |
992 | - | array[i] = t; |
992 | + | |
993 | - | } |
993 | + | |
994 | - | array[size] = size; |
994 | + | Itter_RandomInternal(count, array[], size) |
995 | - | count = 0; |
995 | + | |
996 | if (count == 0) | |
997 | { | |
998 | return -1; | |
999 | } | |
1000 | - | Itter_InitInternal |
1000 | + | new |
1001 | rnd = random(count), | |
1002 | - | array[][] - Itterator array to initialise. |
1002 | + | cur = array[size]; |
1003 | - | s0 - Size of first dimension. |
1003 | + | while (cur != size) |
1004 | - | s1 - Size of second dimension. |
1004 | + | { |
1005 | if (rnd-- == 0) | |
1006 | - | - |
1006 | + | { |
1007 | return cur; | |
1008 | - | Multi-dimensional arrays can't be initialised at compile time, so need to be |
1008 | + | } |
1009 | - | done at run time, which is slightly annoying. |
1009 | + | cur = array[cur]; |
1010 | } | |
1011 | return -1; | |
1012 | } | |
1013 | - | Itter_InitInternal(arr[][], s0, s1) |
1013 | + | |
1014 | /*----------------------------------------------------------------------------*\ | |
1015 | - | for (new i = 0, t = s1 + 1; i < s0; ++i) |
1015 | + | |
1016 | - | { |
1016 | + | Itter_FreeInternal |
1017 | - | for (new j = 0; j < s1; ++j) |
1017 | + | |
1018 | - | { |
1018 | + | count - Number of items in the itterator. |
1019 | - | arr[i][j] = t; |
1019 | + | array[] - Itterator data. |
1020 | - | } |
1020 | + | size - Size of the itterator. |
1021 | - | arr[i][s1] = s1; |
1021 | + | |
1022 | - | } |
1022 | + | - |
1023 | - | } |
1023 | + | |
1024 | Finds the first free slot in the itterator. Itterators now HAVE to be | |
1025 | sorted for this function to work correctly as it uses that fact to decide | |
1026 | wether a slot is unused or the last one. If you want to use the slot | |
1027 | straight after finding it the itterator will need to re-find it to add in | |
1028 | the data. | |
1029 | \*----------------------------------------------------------------------------*/ | |
1030 | ||
1031 | stock | |
1032 | Itter_FreeInternal(array[], size) | |
1033 | { | |
1034 | for (new i = 0; i != size; ++i) | |
1035 | { | |
1036 | if (array[i] > size) | |
1037 | { | |
1038 | return i; | |
1039 | } | |
1040 | } | |
1041 | return -1; | |
1042 | } | |
1043 | ||
1044 | /*----------------------------------------------------------------------------*\ | |
1045 | Function: | |
1046 | Itter_AddInternal | |
1047 | Params: | |
1048 | &start - Array start index. | |
1049 | &count - Number of items in the itterator. | |
1050 | array[] - Itterator data. | |
1051 | value - Item to add. | |
1052 | Return: | |
1053 | - | |
1054 | Notes: | |
1055 | Adds a value to a given itterator set. Now detects when you try and add the | |
1056 | last item multiple times, as well as all the other items. Now simplified even | |
1057 | further with the new internal representation. | |
1058 | \*----------------------------------------------------------------------------*/ | |
1059 | ||
1060 | stock | |
1061 | Itter_AddInternal(&count, array[], value, size) | |
1062 | { | |
1063 | if (0 <= value < size && array[value] > size) | |
1064 | { | |
1065 | new | |
1066 | last = size, | |
1067 | next = array[last]; | |
1068 | while (next < value) | |
1069 | { | |
1070 | last = next; | |
1071 | next = array[last]; | |
1072 | } | |
1073 | array[last] = value; | |
1074 | array[value] = next; | |
1075 | ++count; | |
1076 | return 1; | |
1077 | } | |
1078 | return 0; | |
1079 | } | |
1080 | ||
1081 | /*----------------------------------------------------------------------------*\ | |
1082 | Function: | |
1083 | Itter_RemoveInternal | |
1084 | Params: | |
1085 | &count - Number of items in the itterator. | |
1086 | array[] - Itterator data. | |
1087 | value - Item to remove. | |
1088 | Return: | |
1089 | - | |
1090 | Notes: | |
1091 | Removes a value from an itterator. | |
1092 | \*----------------------------------------------------------------------------*/ | |
1093 | ||
1094 | stock | |
1095 | Itter_RemoveInternal(&count, array[], value, size) | |
1096 | { | |
1097 | new | |
1098 | last; | |
1099 | return Itter_SafeRemoveInternal(count, array, value, last, size); | |
1100 | } | |
1101 | ||
1102 | /*----------------------------------------------------------------------------*\ | |
1103 | Function: | |
1104 | Itter_SafeRemoveInternal | |
1105 | Params: | |
1106 | &count - Number of items in the itterator. | |
1107 | array[] - Iterator data. | |
1108 | back[] - Reverse iterator data. | |
1109 | value - Item to remove. | |
1110 | &last - Pointer in which to store the last pointer. | |
1111 | Return: | |
1112 | - | |
1113 | Notes: | |
1114 | Removes a value from an itterator safely. | |
1115 | \*----------------------------------------------------------------------------*/ | |
1116 | ||
1117 | stock | |
1118 | Itter_SafeRemoveInternal(&count, array[], value, &last, size) | |
1119 | { | |
1120 | if (0 <= value < size && array[value] <= size) | |
1121 | { | |
1122 | last = size; | |
1123 | new | |
1124 | next = array[last]; | |
1125 | while (next != value) | |
1126 | { | |
1127 | last = next; | |
1128 | next = array[last]; | |
1129 | } | |
1130 | array[last] = array[value]; | |
1131 | array[value] = size + 1; | |
1132 | --count; | |
1133 | return 1; | |
1134 | } | |
1135 | return 0; | |
1136 | } | |
1137 | ||
1138 | /*----------------------------------------------------------------------------*\ | |
1139 | Function: | |
1140 | Itter_ContainsInternal | |
1141 | Params: | |
1142 | array[] - Itterator data. | |
1143 | value - Item to check. | |
1144 | size - Size of the iterator. | |
1145 | Return: | |
1146 | - | |
1147 | Notes: | |
1148 | Checks if this item is in the iterator. | |
1149 | \*----------------------------------------------------------------------------*/ | |
1150 | ||
1151 | stock | |
1152 | Itter_ContainsInternal(array[], value, size) | |
1153 | { | |
1154 | return 0 <= value < size && array[value] <= size; | |
1155 | } | |
1156 | ||
1157 | /*----------------------------------------------------------------------------*\ | |
1158 | Function: | |
1159 | Itter_ClearInternal | |
1160 | Params: | |
1161 | &count - Number of items in the itterator. | |
1162 | array[] - Itterator data. | |
1163 | back[] - Reverse data. | |
1164 | size - Size of the iterator. | |
1165 | Return: | |
1166 | - | |
1167 | Notes: | |
1168 | Resets an iterator. | |
1169 | \*----------------------------------------------------------------------------*/ | |
1170 | ||
1171 | stock | |
1172 | Itter_ClearInternal(&count, array[], size) | |
1173 | { | |
1174 | for (new i = 0, t = size + 1; i < size; ++i) | |
1175 | { | |
1176 | array[i] = t; | |
1177 | } | |
1178 | array[size] = size; | |
1179 | count = 0; | |
1180 | } | |
1181 | ||
1182 | /*----------------------------------------------------------------------------*\ | |
1183 | Function: | |
1184 | Itter_InitInternal | |
1185 | Params: | |
1186 | array[][] - Itterator array to initialise. | |
1187 | s0 - Size of first dimension. | |
1188 | s1 - Size of second dimension. | |
1189 | Return: | |
1190 | - | |
1191 | Notes: | |
1192 | Multi-dimensional arrays can't be initialised at compile time, so need to be | |
1193 | done at run time, which is slightly annoying. | |
1194 | \*----------------------------------------------------------------------------*/ | |
1195 | ||
1196 | stock | |
1197 | Itter_InitInternal(arr[][], s0, s1) | |
1198 | { | |
1199 | for (new i = 0, t = s1 + 1; i < s0; ++i) | |
1200 | { | |
1201 | for (new j = 0; j < s1; ++j) | |
1202 | { | |
1203 | arr[i][j] = t; | |
1204 | } | |
1205 | arr[i][s1] = s1; | |
1206 | } | |
1207 | } | |
1208 | ||
1209 | /*----------------------------------------------------------------------------*\ | |
1210 | Function: | |
1211 | Itter_PrevInternal | |
1212 | Params: | |
1213 | array[] - Itterator data. | |
1214 | size - Size of the iterator. | |
1215 | slot - The current slot. | |
1216 | Return: | |
1217 | - | |
1218 | Notes: | |
1219 | Gets the element in an iterator that points to the current element. | |
1220 | \*----------------------------------------------------------------------------*/ | |
1221 | ||
1222 | stock | |
1223 | Itter_PrevInternal(array[], size, slot) | |
1224 | { | |
1225 | if (0 <= slot <= size && array[slot] <= size) | |
1226 | { | |
1227 | for (new last = slot; last--; ) | |
1228 | { | |
1229 | if (array[last] == slot) | |
1230 | { | |
1231 | return last; | |
1232 | } | |
1233 | } | |
1234 | } | |
1235 | return size; | |
1236 | } | |
1237 | ||
1238 | /*----------------------------------------------------------------------------*\ | |
1239 | Function: | |
1240 | Iter_Begin | |
1241 | Params: | |
1242 | iter - Name of the iterator to get the start of. | |
1243 | Return: | |
1244 | - | |
1245 | Notes: | |
1246 | Gets a point BEFORE the start of the iterator (the theoretical beginning). | |
1247 | \*----------------------------------------------------------------------------*/ | |
1248 | ||
1249 | #define Iter_Begin(%1) (_Y_ITER_ARRAY_SIZE(%1)) | |
1250 | #define Itter_Begin(%1) (_Y_ITER_ARRAY_SIZE(%1)) | |
1251 | ||
1252 | /*----------------------------------------------------------------------------*\ | |
1253 | Function: | |
1254 | Iter_End | |
1255 | Params: | |
1256 | iter - Name of the iterator to get the end of. | |
1257 | Return: | |
1258 | - | |
1259 | Notes: | |
1260 | Gets a point AFTER the end of the iterator (think "MAX_PLAYERS"). | |
1261 | \*----------------------------------------------------------------------------*/ | |
1262 | ||
1263 | #define Iter_End(%1) (_Y_ITER_ARRAY_SIZE(%1)) | |
1264 | #define Itter_End(%1) (_Y_ITER_ARRAY_SIZE(%1)) | |
1265 | ||
1266 | /*----------------------------------------------------------------------------*\ | |
1267 | Function: | |
1268 | Iter_First | |
1269 | Params: | |
1270 | iter - Name of the iterator to get the first valid element in. | |
1271 | Return: | |
1272 | - | |
1273 | Notes: | |
1274 | Gets the first element in an iterator. | |
1275 | \*----------------------------------------------------------------------------*/ | |
1276 | ||
1277 | #define Iter_First(%1) (_Y_ITER_ARRAY:%1@YSII_Ag[_Y_ITER_ARRAY_SIZE(%1)]) | |
1278 | #define Itter_First(%1) (_Y_ITER_ARRAY:%1@YSII_Ag[_Y_ITER_ARRAY_SIZE(%1)]) | |
1279 | ||
1280 | /*----------------------------------------------------------------------------*\ | |
1281 | Function: | |
1282 | Iter_Last | |
1283 | Params: | |
1284 | iter - Name of the iterator to | |
1285 | Return: | |
1286 | - | |
1287 | Notes: | |
1288 | Gets the last element in an iterator. | |
1289 | \*----------------------------------------------------------------------------*/ | |
1290 | ||
1291 | #define Iter_Last(%1) Itter_PrevInternal(_Y_ITER_ARRAY:%1@YSII_Ag,_Y_ITER_ARRAY_SIZE(%1),_Y_ITER_ARRAY_SIZE(%1)) | |
1292 | #define Itter_Last(%1) Itter_PrevInternal(_Y_ITER_ARRAY:%1@YSII_Ag,_Y_ITER_ARRAY_SIZE(%1),_Y_ITER_ARRAY_SIZE(%1)) | |
1293 | ||
1294 | /*----------------------------------------------------------------------------*\ | |
1295 | Function: | |
1296 | Iter_Next | |
1297 | Params: | |
1298 | iter - Name of the iterator to get the next element in. | |
1299 | cur - The current element. | |
1300 | Return: | |
1301 | - | |
1302 | Notes: | |
1303 | Gets the element in an interator after the current one. | |
1304 | \*----------------------------------------------------------------------------*/ | |
1305 | ||
1306 | #define Iter_Next(%1,%2) (_Y_ITER_ARRAY:%1@YSII_Ag[(%2)]) | |
1307 | #define Itter_Next(%1,%2) (_Y_ITER_ARRAY:%1@YSII_Ag[(%2)]) | |
1308 | ||
1309 | /*----------------------------------------------------------------------------*\ | |
1310 | Function: | |
1311 | Iter_Prev | |
1312 | Params: | |
1313 | iter - Name of the iterator to get the previous element in. | |
1314 | cur - The current element. | |
1315 | Return: | |
1316 | - | |
1317 | Notes: | |
1318 | Gets the element in an iterator before the current one. Slow. | |
1319 | \*----------------------------------------------------------------------------*/ | |
1320 | ||
1321 | #define Iter_Prev(%1,%2) Itter_PrevInternal(_Y_ITER_ARRAY:%1@YSII_Ag,_Y_ITER_ARRAY_SIZE(%1),(%2)) | |
1322 | #define Itter_Prev(%1,%2) Itter_PrevInternal(_Y_ITER_ARRAY:%1@YSII_Ag,_Y_ITER_ARRAY_SIZE(%1),(%2)) | |
1323 | ||
1324 | /*----------------------------------------------------------------------------*\ | |
1325 | Function: | |
1326 | Iter_InternalArray | |
1327 | Params: | |
1328 | iter - Name of the iterator to get the true name of. | |
1329 | Return: | |
1330 | - | |
1331 | Notes: | |
1332 | Accesses the internal array of an iterator. | |
1333 | \*----------------------------------------------------------------------------*/ | |
1334 | ||
1335 | #define Iter_InternalArray(%1) (_Y_ITER_ARRAY:%1@YSII_Ag) | |
1336 | #define Itter_InternalArray(%1) (_Y_ITER_ARRAY:%1@YSII_Ag) | |
1337 | ||
1338 | /*----------------------------------------------------------------------------*\ | |
1339 | Function: | |
1340 | Iter_InternalSize | |
1341 | Params: | |
1342 | iter - Name of the iterator to get the true size of. | |
1343 | Return: | |
1344 | - | |
1345 | Notes: | |
1346 | Accesses the internal size of an iterator. | |
1347 | \*----------------------------------------------------------------------------*/ | |
1348 | ||
1349 | #define _Y_ITER_INT_SIZE:%0(%2[%1]@YSII_Ag)) %0(%2@YSII_Ag[])) | |
1350 | ||
1351 | #define Iter_InternalSize(%1) (_:_Y_ITER_INT_SIZE:sizeof (%1@YSII_Ag)) | |
1352 | #define Itter_InternalSize(%1) (_:_Y_ITER_INT_SIZE:sizeof (%1@YSII_Ag)) |