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