Senior Member
Join Date: Mar 2011
Location: Chicago, IL, U.S.A.
|
02-16-2013
, 10:17
Re: spawn objects/entities [Code Revise REQ]
|
#19
|
Quote:
Originally Posted by striker07
its not that i can do like MAXPLAYERS or for Assign it an insanely high number to it? that would be way to intensive for the plugin
|
Actually, you can. The engine has a limit to the number of edicts that it can create. You can essentially use a static array and get rid of the overhead of using a dynamically allocated container. Moreover, since you are looking to create some sort of NPC plugin, I bet you will need a method to store data. Unfortunately, SourcePawn is not object oriented. The closest you can do is use an array with enumerators, as I show below. The nice thing about this is that you can easily expand the enumerator with more properties (e.g. destruction time, NPC status, health, mission, etc.) using getters and setters. Plus, it is more efficient than using a dynamic array and constantly pushing/popping elements. Using a larger array just allocates more bytes during load, and a few thousand more bytes in memory is absolutely no problem at all.
Spoiler
PHP Code:
#pragma semicolon 1
#include <sourcemod>
#include <sdktools>
// ===============================================================
// - CUSTOM DEFINES -
// ===============================================================
#define MAX_EDICTS 2048
#define TRUE 1
#define FALSE 0
#define NO_ACTIVATOR 0
#define FLAME_TIME 15.0
// ===============================================================
// - GLOBALS -
// ===============================================================
new LaserSprite, Halosprite;
enum TOUCH_DATA {
ACTIVATOR, // who/what did the touching?
TOUCH_FLAG // was this entity touched by a client?
}
new g_Touch[MAX_EDICTS+1][TOUCH_DATA];
// ===============================================================
// - STOCK FUNCTIONS -
// ===============================================================
// These are for you to use (if you need them).
// Resets an element of the array
stock ResetNPCVars(entity)
{
g_Touch[entity][TOUCH_DATA:ACTIVATOR] = NO_ACTIVATOR;
g_Touch[entity][TOUCH_DATA:TOUCH_FLAG] = FALSE;
}
// Returns true if an entity was touched by a client
stock bool:WasNPCTouchedByClient(entity, client)
{
return (g_Touch[entity][TOUCH_DATA:ACTIVATOR] == client);
}
// Returns the last activator to touch the entity
stock GetNPCActivator(entity)
{
return g_Touch[entity][TOUCH_DATA:ACTIVATOR];
}
// Returns true if the NPC was touched by a client at all in all of its touches
stock WasNPCTouchedAtAll(entity)
{
return (g_Touch[entity][TOUCH_DATA:ACTIVATOR] || g_Touch[entity][TOUCH_DATA:TOUCH_FLAG]);
}
// Sets entity touch data (see usage under Plugin Code section)
stock SetNPCTouchVars(entity, TOUCH_DATA:data, value)
{
g_Touch[entity][data] = value;
}
// ===============================================================
// - PLUGIN CODE -
// ===============================================================
public OnPluginStart()
{
LoadTranslations("common.phrases");
HookEvent("player_death", Event_PlayerDeath);
HookEvent("round_end", Event_RoundEnd);
}
public OnMapStart()
{
LaserSprite = PrecacheModel("materials/sprites/bluelaser1.vmt");
Halosprite = PrecacheModel("materials/sprites/halo01.vmt");
}
public Event_PlayerDeath(Handle:event, const String:name[], bool:dontBroadcast)
{
new victim = GetClientOfUserId(GetEventInt(event, "userid"));
decl Float:origin[3];
GetClientAbsOrigin(victim, origin);
CreateSomeEntity(origin);
}
CreateSomeEntity(Float:Origin[3])
{
new entity = CreateEntityByName("my_entity");
if (!entity) return;
TeleportEntity(entity, Origin, NULL_VECTOR, NULL_VECTOR);
SetEntityModel(entity, "models/somefolder/blah.mdl");
SetEntityRenderMode(entity, RENDER_TRANSCOLOR);
SetEntityRenderFx(entity, RENDERFX_PULSE_SLOW);
SetEntityRenderColor(entity, 31, 191, 36, 160);
new Float:SplashStartOrigin[3], Float:BeamStartOrigin[3], Float:BeamEndOrigin[3];
new BeamColor[4];
SplashStartOrigin = Origin;
BeamStartOrigin = Origin;
BeamEndOrigin = Origin;
SplashStartOrigin[2] = (Origin[2] - 5);
BeamStartOrigin[2] = (Origin[2] + 40);
BeamEndOrigin[2] = (Origin[2] - 5);
BeamColor[0] = 173; //r
BeamColor[1] = 156; //g
BeamColor[2] = 28; //b
BeamColor[3] = 210;//A
TE_SetupEnergySplash(Float:SplashStartOrigin, Float:Origin, false);
TE_SetupBeamPoints(BeamStartOrigin, BeamEndOrigin, LaserSprite, Halosprite, 0, 10, 0.8, 25.0, 20.0, 3, 5.0, BeamColor, 185);
DispatchSpawn(entity);
if (IsValidEntity(entity))
{
// Remove edict when touched
HookSingleEntityOutput(entity, "OnStartTouch", Entity_OnStartTouch);
// Change rendermode in 20.0 seconds
CreateTimer(20.0, Timer_SetRenderGlow, entity);
IgniteEntity(entity, FLAME_TIME, true);
}
}
public Entity_OnStartTouch(const String:output[], caller, activator, Float:delay)
{
// Something touched this entity
if (caller > 0)
SetNPCTouchVars(caller, ACTIVATOR, activator); // caller was touched by an ACTIVATOR of index: activator
// If you're going to use RemoveEdict, then you need to make sure that the edict is valid.
// In this case, the edict will be valid, but get into the habit of checking if an edict is valid before removing it.
//
// Secondly, sometimes the activator won't always be a player. Try throwing a prop_physics onto your NPC and see
// what happens. This callback will be fired, but IsPlayerAlive() will receive an index that does not belong
// to a player. Therefore, you need to check that the index belongs to a player.
if (activator >= 1 && activator <= MaxClients)
{
if (IsPlayerAlive(activator) && IsValidEdict(caller))
{
// This entity was touched by a client (alive player)
SetNPCTouchVars(caller, TOUCH_FLAG, TRUE);
RemoveEdict(caller);
}
}
}
public Action:Timer_SetRenderGlow(Handle:timer, any:entity)
{
if (IsValidEntity(entity))
{
SetEntityRenderMode(entity, RENDER_GLOW);
SetEntityRenderFx(entity, RENDERFX_PULSE_FAST_WIDER);
// Remove this entity 10 seconds from now (i.e. 30.0 after spawn)
CreateTimer(10.0, Timer_RemoveEntity, entity);
}
}
public Action:Timer_RemoveEntity(Handle:timer, any:entity)
{
if (IsValidEdict(entity))
RemoveEdict(entity);
}
public Event_RoundEnd(Handle:event, String:name[], bool:dontBroadcast)
{
// Reset variables after the round is over
for (new i = 0; i < MAX_EDICTS; i++)
ResetNPCVars(i);
}
public Plugin:MyInfo =
{
name = "CBase entity?",
author = "Sky-High",
description = "My first SM entity plugin",
version = "1.0",
url = "** AM Spam-Blocker V3.6 **"
};
|
|