plugins/include/entity.inc
author David Anderson <dvander@alliedmods.net>
Mon Oct 15 04:06:57 2007 +0000 (2007-10-15)
changeset 1572 adbc41dc9cd0
parent 1330 ab94316bb52b
child 1837 652038bb27e6
permissions -rw-r--r--
fixed an overall deficiency where libraries did not include extensions. extensions can now mark themselves as libraries, and they thus become fully optional just as plugins do. additionally, a bug was fixed where plugins could be accidentally marked as required instead of optional. these changes resulted in a bcompat API bump to the extension/sharesys interface.
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved.
     5  * =============================================================================
     6  *
     7  * This file is part of the SourceMod/SourcePawn SDK.
     8  *
     9  * This program is free software; you can redistribute it and/or modify it under
    10  * the terms of the GNU General Public License, version 3.0, as published by the
    11  * Free Software Foundation.
    12  * 
    13  * This program is distributed in the hope that it will be useful, but WITHOUT
    14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    15  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    16  * details.
    17  *
    18  * You should have received a copy of the GNU General Public License along with
    19  * this program.  If not, see <http://www.gnu.org/licenses/>.
    20  *
    21  * As a special exception, AlliedModders LLC gives you permission to link the
    22  * code of this program (as well as its derivative works) to "Half-Life 2," the
    23  * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    24  * by the Valve Corporation.  You must obey the GNU General Public License in
    25  * all respects for all other code used.  Additionally, AlliedModders LLC grants
    26  * this exception to all derivative works.  AlliedModders LLC defines further
    27  * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    28  * or <http://www.sourcemod.net/license.php>.
    29  *
    30  * Version: $Id$
    31  */
    32  
    33 #if defined _entity_included
    34  #endinput
    35 #endif
    36 #define _entity_included
    37 
    38 /**
    39  * Property types for entities.
    40  */
    41 enum PropType
    42 {
    43 	Prop_Send = 0,	/**< This property is networked. */
    44 	Prop_Data = 1,	/**< This property is for saved game files. */
    45 };
    46 
    47 /**
    48  * @section For more information on these, see the HL2SDK (public/edict.h)
    49  */
    50 #define FL_EDICT_CHANGED		(1<<0)	/**< Game DLL sets this when the entity state changes
    51 										 Mutually exclusive with FL_EDICT_PARTIAL_CHANGE. */
    52 #define FL_EDICT_FREE			(1<<1)	/**< this edict if free for reuse */
    53 #define FL_EDICT_FULL			(1<<2)	/**< this is a full server entity */
    54 #define FL_EDICT_FULLCHECK		(0<<0)  /**< call ShouldTransmit() each time, this is a fake flag */
    55 #define FL_EDICT_ALWAYS			(1<<3)	/**< always transmit this entity */
    56 #define FL_EDICT_DONTSEND		(1<<4)	/**< don't transmit this entity */
    57 #define FL_EDICT_PVSCHECK		(1<<5)	/**< always transmit entity, but cull against PVS */
    58 #define FL_EDICT_PENDING_DORMANT_CHECK	(1<<6)
    59 #define FL_EDICT_DIRTY_PVS_INFORMATION	(1<<7)
    60 #define FL_FULL_EDICT_CHANGED		(1<<8)
    61 
    62 /**
    63  * @endsection
    64  */
    65 
    66 /**
    67  * Returns the maximum number of entities.
    68  *
    69  * @return				Maximum number of entities.
    70  */
    71 native GetMaxEntities();
    72 
    73 /**
    74  * Returns the number of entities in the server.
    75  *
    76  * @return				Number of entities in the server.
    77  */
    78 native GetEntityCount();
    79 
    80 /**
    81  * Returns whether or not an entity is valid.  Returns false
    82  * if there is no matching CBaseEntity for this edict index.
    83  *
    84  * @param edict			Index of the entity/edict.
    85  * @return				True if valid, false otherwise.
    86  */
    87 native bool:IsValidEntity(edict);
    88 
    89 /**
    90  * Returns whether or not an edict index is valid.
    91  *
    92  * @param edict			Index of the edict.
    93  * @return				True if valid, false otherwise.
    94  */
    95 native bool:IsValidEdict(edict);
    96 
    97 /**
    98  * Returns whether or not an entity is a valid networkable edict.
    99  *
   100  * @param edict			Index of the edict.
   101  * @return				True if networkable, false if invalid or not networkable.
   102  */
   103 native bool:IsEntNetworkable(edict);
   104 
   105 /**
   106  * Creates a new edict (the basis of a networkable entity)
   107  *
   108  * @return				Index of the edict, 0 on failure.
   109  */
   110 native CreateEdict();
   111 
   112 /** 
   113  * Removes an edict from the world.
   114  *
   115  * @param edict			Index of the edict.
   116  * @noreturn
   117  * @error				Invalid edict index.
   118  */
   119 native RemoveEdict(edict);
   120 
   121 /**
   122  * Returns the flags on an edict.  These are not the same as entity flags.
   123  *
   124  * @param edict			Index of the entity.
   125  * @return				Edict flags.
   126  * @error				Invalid edict index.
   127  */
   128 native GetEdictFlags(edict);
   129 
   130 /**
   131  * Sets the flags on an edict.  These are not the same as entity flags.
   132  *
   133  * @param edict			Index of the entity.
   134  * @param flags			Flags to set.
   135  * @noreturn
   136  * @error				Invalid edict index.
   137  */
   138 native SetEdictFlags(edict, flags);
   139 
   140 /**
   141  * Retrieves an edict classname.
   142  *
   143  * @param edict			Index of the entity.
   144  * @param clsname		Buffer to store the classname.
   145  * @param maxlength		Maximum length of the buffer.
   146  * @return				True on success, false if there is no classname set.
   147  */
   148 native bool:GetEdictClassname(edict, String:clsname[], maxlength);
   149 
   150 /**
   151  * Retrieves an entity's networkable serverclass name.
   152  * This is not the same as the classname and is used for networkable state changes.
   153  *
   154  * @param edict			Index of the entity.
   155  * @param clsname		Buffer to store the serverclass name.
   156  * @param maxlength		Maximum lnegth of the buffer.
   157  * @return				True on success, false if the edict is not networkable.
   158  * @error				Invalid edict index.
   159  */
   160 native bool:GetEntityNetClass(edict, String:clsname[], maxlength);
   161 
   162 /**
   163  * @section Entity offset functions
   164  *
   165  * Offsets should be specified in byte distance from the CBaseEntity 
   166  * structure, not short (double byte) or integer (four byte) multiples.  
   167  * It is somewhat common practice to use offsets aligned to their final 
   168  * type, and thus make sure you are not falling to this error in SourceMod.
   169  * For example, if your "integer-aligned" offset was 119, your byte-aligned
   170  * offset is 119*4, or 476.
   171  
   172  * Specifying incorrect offsets or the incorrect data type for an offset
   173  * can have fatal consequences.  If you are hardcoding offsets, and the 
   174  * layout of CBaseEntity does not match, you can easily crash the server.
   175  *
   176  * The reasonable bounds for offsets is greater than or equal to 0 and 
   177  * below 32768.  Offsets out of these bounds will throw an error.  However,
   178  * this does not represent any real range, it is simply a sanity check for
   179  * illegal values.  Any range outside of the CBaseEntity structure's private
   180  * size will cause undefined behaviour or even crash.
   181  */
   182  
   183 /**
   184  * Marks an entity as state changed.  This can be useful if you set an offset 
   185  * and wish for it to be immediately changed over the network.  By default this 
   186  * is not done for offset setting functions.  
   187  *
   188  * @param edict			Index to the edict.
   189  * @param offset		Offset to mark as changed.  If 0, 
   190  *						the entire edict is marked as changed.
   191  * @noreturn
   192  * @error				Invalid entity or offset out of bounds.
   193  */
   194 native ChangeEdictState(edict, offset = 0);
   195 
   196 /**
   197  * Peeks into an entity's object data and retrieves the integer value at 
   198  * the given offset.
   199  * 
   200  * @param entity		Edict index.
   201  * @param offset		Offset to use.
   202  * @param size			Number of bytes to read (valid values are 1, 2, or 4).
   203  * @return				Value at the given memory location.
   204  * @error				Invalid entity or offset out of reasonable bounds.
   205  */
   206 native GetEntData(entity, offset, size=4);
   207 
   208 /**
   209  * Peeks into an entity's object data and sets the integer value at 
   210  * the given offset.
   211  *
   212  * @param entity		Edict index.
   213  * @param offset		Offset to use.
   214  * @param size			Number of bytes to write (valid values are 1, 2, or 4).
   215  * @param changeState	If true, change will be sent over the network.
   216  * @return				Value at the given memory location.
   217  * @error				Invalid entity or offset out of reasonable bounds.
   218  * @noreturn
   219  */
   220 native SetEntData(entity, offset, value, size=4, bool:changeState=false);
   221 
   222 /**
   223  * Peeks into an entity's object data and retrieves the float value at 
   224  * the given offset.
   225  * 
   226  * @param entity		Edict index.
   227  * @param offset		Offset to use.
   228  * @return				Value at the given memory location.
   229  * @error				Invalid entity or offset out of reasonable bounds.
   230  */
   231 native Float:GetEntDataFloat(entity, offset);
   232 
   233 /**
   234  * Peeks into an entity's object data and sets the integer value at 
   235  * the given offset.
   236  *
   237  * @param entity		Edict index.
   238  * @param offset		Offset to use.
   239  * @param changeState	If true, change will be sent over the network.
   240  * @return				Value at the given memory location.
   241  * @error				Invalid entity or offset out of reasonable bounds.
   242  * @noreturn
   243  */
   244 native SetEntDataFloat(entity, offset, Float:value, bool:changeState=false);
   245 
   246 /**
   247  * Peeks into an entity's object data and retrieves the entity handle
   248  * info at the given offset.
   249  * 
   250  * @param entity		Edict index.
   251  * @param offset		Offset to use.
   252  * @return				Entity index at the given location, or 0 if none.
   253  * @error				Invalid entity or offset out of reasonable bounds.
   254  */
   255 native GetEntDataEnt(entity, offset);
   256 
   257 /**
   258  * Peeks into an entity's object data and sets the entity handle info
   259  * at the given offset.
   260  * 
   261  * @param entity		Edict index.
   262  * @param offset		Offset to use.
   263  * @param other			Entity index to set, or 0 to clear.
   264  * @param changeState	If true, change will be sent over the network.
   265  * @noreturn
   266  * @error				Invalid entity or offset out of reasonable bounds.
   267  */
   268 native SetEntDataEnt(entity, offset, other, bool:changeState=false);
   269 
   270 /**
   271  * Peeks into an entity's object data and retrieves the vector at the 
   272  * given offset.
   273  * @note Both a Vector and a QAngle are three floats.  This is a 
   274  * convenience function and will work with both types.
   275  * 
   276  * @param entity		Edict index.
   277  * @param offset		Offset to use.
   278  * @param vec			Vector buffer to store data in.
   279  * @noreturn
   280  * @error				Invalid entity or offset out of reasonable bounds.
   281  */
   282 native GetEntDataVector(entity, offset, Float:vec[3]);
   283 
   284 /**
   285  * Peeks into an entity's object data and sets the vector at the given 
   286  * offset.
   287  * @note Both a Vector and a QAngle are three floats.  This is a 
   288  * convenience function and will work with both types.
   289  * 
   290  * @param entity		Edict index.
   291  * @param offset		Offset to use.
   292  * @param vec			Vector to set.
   293  * @param changeState	If true, change will be sent over the network.
   294  * @noreturn
   295  * @error				Invalid entity or offset out of reasonable bounds.
   296  */
   297 native SetEntDataVector(entity, offset, const Float:vec[3], bool:changeState=false);
   298 
   299 /**
   300  * Peeks into an entity's object data and retrieves the string at 
   301  * the given offset.
   302  * 
   303  * @param entity		Edict index.
   304  * @param offset		Offset to use.
   305  * @param buffer		Destination string buffer.
   306  * @param maxlen		Maximum length of output string buffer.
   307  * @return			Number of non-null bytes written.
   308  * @error				Invalid entity or offset out of reasonable bounds.
   309  */
   310 native GetEntDataString(entity, offset, String:buffer[], maxlen);
   311 
   312 /**
   313  * Peeks into an entity's object data and sets the string at 
   314  * the given offset.
   315  * 
   316  * @param entity		Edict index.
   317  * @param offset		Offset to use.
   318  * @param buffer		String to set.
   319  * @param maxlen		Maximum length of bytes to write.
   320  * @param changeState	If true, change will be sent over the network.
   321  * @return			Number of non-null bytes written.
   322  * @error				Invalid entity or offset out of reasonable bounds.
   323  */
   324 native SetEntDataString(entity, offset, const String:buffer[], maxlen, bool:changeState=false);
   325 
   326 /**
   327  * @endsection
   328  */
   329 
   330 /**
   331  * Given a ServerClass name, finds a networkable send property offset.
   332  * This information is cached for future calls.
   333  *
   334  * @param cls			Classname.
   335  * @param prop			Property name.
   336  * @return				An offset, or -1 on failure.
   337  */
   338 native FindSendPropOffs(const String:cls[], const String:prop[]);
   339 
   340 /**
   341  * Given an entity, finds a datamap property offset.
   342  * This information is cached for future calls.
   343  *
   344  * @param entity		Entity index.
   345  * @param prop			Property name.
   346  * @return				An offset, or -1 on failure.
   347  */
   348 native FindDataMapOffs(entity, const String:prop[]);
   349 
   350 /**
   351  * Wrapper function for finding a send property for a particular entity.
   352  *
   353  * @param ent			Entity index.
   354  * @param prop			Property name.
   355  * @return				An offset, or -1 on failure.
   356  */
   357 stock GetEntSendPropOffs(ent, const String:prop[])
   358 {
   359 	decl String:cls[64];
   360 	
   361 	if (!GetEntityNetClass(ent, cls, sizeof(cls)))
   362 	{
   363 		return -1;
   364 	}
   365 	
   366 	return FindSendPropOffs(cls, prop);
   367 }
   368 
   369 /**
   370  * Gets a network property as an integer; wrapper around GetEntData().
   371  * 
   372  * @param entity		Edict index.
   373  * @param type			Property type.
   374  * @param prop			Property to use.
   375  * @param size			Number of bytes to read (valid values are 1, 2, or 4).
   376  * @return				Value at the given property offset.
   377  * @error				Invalid entity or property not found.
   378  */
   379 stock GetEntProp(entity, PropType:type, const String:prop[], size=4)
   380 {
   381 	new offs;
   382 
   383 	switch (type)
   384 	{
   385 		case Prop_Send:
   386 		{
   387 			offs = GetEntSendPropOffs(entity, prop);
   388 		}
   389 		case Prop_Data:
   390 		{
   391 			offs = FindDataMapOffs(entity, prop);
   392 		}
   393 		default:
   394 		{
   395 			ThrowError("Invalid Property type %d", type);
   396 		}
   397 	}
   398 
   399 	if (offs == -1)
   400 	{
   401 		ThrowError("Property \"%s\" not found for entity %d", prop, entity);
   402 	}
   403 
   404 	return GetEntData(entity, offs, size);
   405 }
   406 
   407 /**
   408  * Sets a network property as an integer; wrapper around GetEntData().
   409  *
   410  * @param entity		Edict index.
   411  * @param type			Property type.
   412  * @param prop			Property to use.
   413  * @param size			Number of bytes to write (valid values are 1, 2, or 4).
   414  * @error				Invalid entity or offset out of reasonable bounds.
   415  * @noreturn
   416  */
   417 stock SetEntProp(entity, PropType:type, const String:prop[], value, size=4)
   418 {
   419 	new offs;
   420 
   421 	switch (type)
   422 	{
   423 		case Prop_Send:
   424 		{
   425 			offs = GetEntSendPropOffs(entity, prop);
   426 		}
   427 		case Prop_Data:
   428 		{
   429 			offs = FindDataMapOffs(entity, prop);
   430 		}
   431 		default:
   432 		{
   433 			ThrowError("Invalid Property type %d", type);
   434 		}
   435 	}
   436 
   437 	if (offs == -1)
   438 	{
   439 		ThrowError("Property \"%s\" not found for entity %d", prop, entity);
   440 	}
   441 
   442 	return SetEntData(entity, offs, value, size, true);
   443 }
   444 
   445 /**
   446  * Gets a network property as a float; wrapper around GetEntDataFloat().
   447  * 
   448  * @param entity		Edict index.
   449  * @param type			Property type.
   450  * @param prop			Property to use.
   451  * @return				Value at the given property offset.
   452  * @error				Invalid entity or offset out of reasonable bounds.
   453  */
   454 stock Float:GetEntPropFloat(entity, PropType:type, const String:prop[])
   455 {
   456 	new offs;
   457 
   458 	switch (type)
   459 	{
   460 		case Prop_Send:
   461 		{
   462 			offs = GetEntSendPropOffs(entity, prop);
   463 		}
   464 		case Prop_Data:
   465 		{
   466 			offs = FindDataMapOffs(entity, prop);
   467 		}
   468 		default:
   469 		{
   470 			ThrowError("Invalid Property type %d", type);
   471 		}
   472 	}
   473 
   474 	if (offs == -1)
   475 	{
   476 		ThrowError("Property \"%s\" not found for entity %d", prop, entity);
   477 	}
   478 
   479 	return GetEntDataFloat(entity, offs);
   480 }
   481 
   482 /**
   483  * Sets a network property as a float; wrapper around SetEntDataFloat().
   484  * 
   485  * @param entity		Edict index.
   486  * @param type			Property type.
   487  * @param prop			Property to use.
   488  * @param value			Value to set.
   489  * @noreturn
   490  * @error				Invalid entity or offset out of reasonable bounds.
   491  */
   492 stock SetEntPropFloat(entity, PropType:type, const String:prop[], Float:value)
   493 {
   494 	new offs;
   495 
   496 	switch (type)
   497 	{
   498 		case Prop_Send:
   499 		{
   500 			offs = GetEntSendPropOffs(entity, prop);
   501 		}
   502 		case Prop_Data:
   503 		{
   504 			offs = FindDataMapOffs(entity, prop);
   505 		}
   506 		default:
   507 		{
   508 			ThrowError("Invalid Property type %d", type);
   509 		}
   510 	}
   511 
   512 	if (offs == -1)
   513 	{
   514 		ThrowError("Property \"%s\" not found for entity %d", prop, entity);
   515 	}
   516 
   517 	return SetEntDataFloat(entity, offs, value, true);
   518 }
   519 
   520 /**
   521  * Gets a network property as a handle entity; wrapper around GetEntDataEnt().
   522  * 
   523  * @param entity		Edict index.
   524  * @param type			Property type.
   525  * @param prop			Property to use.
   526  * @return				Entity index at the given property, or 0 if none.
   527  * @error				Invalid entity or offset out of reasonable bounds.
   528  */
   529 stock GetEntPropEnt(entity, PropType:type, const String:prop[])
   530 {
   531 	new offs;
   532 
   533 	switch (type)
   534 	{
   535 		case Prop_Send:
   536 		{
   537 			offs = GetEntSendPropOffs(entity, prop);
   538 		}
   539 		case Prop_Data:
   540 		{
   541 			offs = FindDataMapOffs(entity, prop);
   542 		}
   543 		default:
   544 		{
   545 			ThrowError("Invalid Property type %d", type);
   546 		}
   547 	}
   548 
   549 	if (offs == -1)
   550 	{
   551 		ThrowError("Property \"%s\" not found for entity %d", prop, entity);
   552 	}
   553 
   554 	return GetEntDataEnt(entity, offs);
   555 }
   556 
   557 /**
   558  * Sets a network property as a handle entity; wrapper around SetEntDataEnt().
   559  * 
   560  * @param entity		Edict index.
   561  * @param type			Property type.
   562  * @param prop			Property to use.
   563  * @param other			Entity index to set, or 0 to unset.
   564  * @noreturn
   565  * @error				Invalid entity or offset out of reasonable bounds.
   566  */
   567 stock SetEntPropEnt(entity, PropType:type, const String:prop[], other)
   568 {
   569 	new offs;
   570 
   571 	switch (type)
   572 	{
   573 		case Prop_Send:
   574 		{
   575 			offs = GetEntSendPropOffs(entity, prop);
   576 		}
   577 		case Prop_Data:
   578 		{
   579 			offs = FindDataMapOffs(entity, prop);
   580 		}
   581 		default:
   582 		{
   583 			ThrowError("Invalid Property type %d", type);
   584 		}
   585 	}
   586 
   587 	if (offs == -1)
   588 	{
   589 		ThrowError("Property \"%s\" not found for entity %d", prop, entity);
   590 	}
   591 
   592 	return SetEntDataEnt(entity, offs, other, true);
   593 }
   594 
   595 /**
   596  * Gets a network property as a vector; wrapper around GetEntDataVector().
   597  * @note Both a Vector and a QAngle are three floats.  This is a 
   598  * convenience function and will work with both types.
   599  * 
   600  * @param entity		Edict index.
   601  * @param type			Property type.
   602  * @param prop			Property to use.
   603  * @param vec			Vector buffer to store data in.
   604  * @noreturn
   605  * @error				Invalid entity or offset out of reasonable bounds.
   606  */
   607 stock GetEntPropVector(entity, PropType:type, const String:prop[], Float:vec[3])
   608 {
   609 	new offs;
   610 
   611 	switch (type)
   612 	{
   613 		case Prop_Send:
   614 		{
   615 			offs = GetEntSendPropOffs(entity, prop);
   616 		}
   617 		case Prop_Data:
   618 		{
   619 			offs = FindDataMapOffs(entity, prop);
   620 		}
   621 		default:
   622 		{
   623 			ThrowError("Invalid Property type %d", type);
   624 		}
   625 	}
   626 
   627 	if (offs == -1)
   628 	{
   629 		ThrowError("Property \"%s\" not found for entity %d", prop, entity);
   630 	}
   631 
   632 	return GetEntDataVector(entity, offs, vec);
   633 }
   634 
   635 /**
   636  * Sets a network property as a vector; wrapper around SetEntDataVector().
   637  * @note Both a Vector and a QAngle are three floats.  This is a 
   638  * convenience function and will work with both types.
   639  * 
   640  * @param entity		Edict index.
   641  * @param type			Property type.
   642  * @param prop			Property to use.
   643  * @param vec			Vector to set.
   644  * @noreturn
   645  * @error				Invalid entity or offset out of reasonable bounds.
   646  */
   647 stock SetEntPropVector(entity, PropType:type, const String:prop[], const Float:vec[3])
   648 {
   649 	new offs;
   650 
   651 	switch (type)
   652 	{
   653 		case Prop_Send:
   654 		{
   655 			offs = GetEntSendPropOffs(entity, prop);
   656 		}
   657 		case Prop_Data:
   658 		{
   659 			offs = FindDataMapOffs(entity, prop);
   660 		}
   661 		default:
   662 		{
   663 			ThrowError("Invalid Property type %d", type);
   664 		}
   665 	}
   666 
   667 	if (offs == -1)
   668 	{
   669 		ThrowError("Property \"%s\" not found for entity %d", prop, entity);
   670 	}
   671 
   672 	return SetEntDataVector(entity, offs, vec, true);
   673 }
   674 
   675 /**
   676  * Gets a network property as a string.
   677  * 
   678  * @param entity		Edict index.
   679  * @param type			Property type.
   680  * @param prop			Property to use.
   681  * @param buffer		Destination string buffer.
   682  * @param maxlen		Maximum length of output string buffer.		
   683  * @return				Number of non-null bytes written.
   684  * @error				Invalid entity, offset out of reasonable bounds, or property is not a valid string.
   685  */
   686 native GetEntPropString(entity, PropType:type, const String:prop[], String:buffer[], maxlen);
   687 
   688 /**
   689  * Sets a network property as a string.
   690  * 
   691  * @param entity		Edict index.
   692  * @param type			Property type.
   693  * @param prop			Property to use.
   694  * @param buffer		String to set.		
   695  * @return				Number of non-null bytes written.
   696  * @error				Invalid entity, offset out of reasonable bounds, or property is not a valid string.
   697  */
   698 native SetEntPropString(entity, PropType:type, const String:prop[], const String:buffer[]);
   699 
   700 /**
   701  * Copies an array of cells from an entity at a given offset.
   702  *
   703  * @param entity		Entity index.
   704  * @param offset		Offset to use.
   705  * @param array			Array to read into.
   706  * @param arraySize		Number of values to read.
   707  * @param dataSize		Size of each value in bytes (1, 2, or 4).
   708  * @noreturn
   709  * @error				Invalid entity or offset out of reasonable bounds.
   710  */
   711 stock GetEntDataArray(entity, offset, array[], arraySize, dataSize=4)
   712 {
   713 	for (new i=0; i<arraySize; i++)
   714 	{
   715 		array[i] = GetEntData(entity, offset + i*dataSize, dataSize)
   716 	}
   717 }
   718 
   719 
   720 /**
   721  * Copies an array of cells to an entity at a given offset.
   722  *
   723  * @param entity		Entity index.
   724  * @param offset		Offset to use.
   725  * @param array			Array of values to copy.
   726  * @param arraySize		Number of values to copy.
   727  * @param dataSize		Size of each value in bytes (1, 2, or 4).
   728  * @param changeState	True to set the network state as changed; false otherwise.
   729  * @noreturn
   730  * @error				Invalid entity or offset out of reasonable bounds.
   731  */
   732 stock SetEntDataArray(entity, offset, const array[], arraySize, dataSize=4, bool:changeState=false)
   733 {
   734 	for (new i=0; i<arraySize; i++)
   735 	{
   736 		SetEntData(entity, offset + i*dataSize, array[i], dataSize, changeState);
   737 	}
   738 }