Decal-Management-System...how to get it working

Discuss programming in the QuakeC language.
Post Reply
skite2001
Posts: 17
Joined: Mon Nov 17, 2008 5:40 pm

Decal-Management-System...how to get it working

Post by skite2001 »

Hello guys,
maybe everybody knows the problem with decal staytime, for example bulletholes, wallnails, shells.
The normal procedure would be something like:

Code: Select all

newmis.nextthink = time + 10 //remain 10 sec...
newmis.think = SUB_Remove //...then get removed
it looks really funny, if you got working wallnails, shoot em at a wall and after 10 sec it looks like "domino day"

after some checking of LordHavocs DP mod qc files i found something interesting:

he set a variable for maxdetails..lets say 1000 decals, that stay almost the whole time and don't get removed. After the 1001th decal, the oldest decors got removed each frame, to maintain a certain maximum decors (1000 for example).

i really like this idea and want to add this "feature" to my mod,
but it seems it isn't working, or i'm doing something wrong -.-*
I'm good at copy&paste and minor fixing, but i'm not a "got-no-live-quakec-coder" ^_-

here's the code i got:

Code: Select all

void(entity e) removedecor =
{
	if (e.classname != "decor")
	{
		// if this is not a decor, just make it invisible
		e.model = "";
		return;
	}
	numdecors = numdecors - 1;
	remove(e);
};

entity(entity e) newdecor =
{
	if (e == world)
	{
		e = spawn();
		e.classname = "decor";
	}
	if (e.classname == "decor")
		numdecors = numdecors + 1;
	// set up common defaults
	e.isdecor = TRUE;
	//e.createdtime = time;
	e.cnt = 10 * (0.5 + random());
	e.alpha = 1;
	e.effects = EF_LOWPRECISION;
	e.flags = e.flags - (e.flags & FL_ONGROUND);
	e.groundentity = world;
	e.movetype = MOVETYPE_NONE;
	e.solid = SOLID_NOT;
	e.frame = 0;
	e.havocattack = FALSE;
	e.touch = SUB_Null;
	return e;
};

//.float createdtime;

// removes the oldest decors each frame to maintain a certain maximum decors
void() decorframe =
{
	local entity estart, e;
	local float decay;
	//local entity b1, b2, b3, b4, b5, b6, b7, b8, b9, b10;
	//local float bt1, bt2, bt3, bt4, bt5, bt6, bt7, bt8, bt9, bt10, iterations;

	// different number of decors in multi-player (to avoid lag on modems)
	if (maxclients > 1)
		maxdecors = 32;
	else if (cvar("spawnmonsters"))
		maxdecors = 500;
	else
		maxdecors = 10000;
	if (cvar("ekg"))
		maxdecors = maxdecors * 5;
	// overridable by saved2 cvar on server console
	if (cvar("decors"))
		maxdecors = cvar("decors");
	maxdecors = bound(1, maxdecors, 16384);

	// numdecors is allowed to be bogus as long as it is >= the real number of decors
	// (but perfection is clearly preferable)
	if (numdecors <= maxdecors)
		return;

	// recount all the decors
	numdecors = 0;
	estart = e = findchain(classname, "decor");
	while(e)
	{
		numdecors = numdecors + 1;
		e = e.chain;
	}
	if (numdecors <= maxdecors)
		return; // nothing to do

	// changed decor removal policy to simply make them have timeouts that only apply when the decor limit has been reached
	// the timeout rate depends on how far over the limit it is, so this does adapt to sudden excess
	decay = frametime * (numdecors / maxdecors);
	e = estart;
	while(e)
	{
		if (e.cnt > 0)
			e.cnt = e.cnt - decay;
		else
			removedecor(e);
		e = e.chain;
	}
};

// used for various little bouncing debris to avoid getting stuck in the air
void() DecorThink =
{
	self.nextthink = time;
	self.flags = self.flags - (self.flags & FL_ONGROUND);
	if (pointcontents(self.origin) == CONTENT_SOLID)
		removedecor(self);
};


void(vector org, entity en, vector dir, string dmodel, float dskin, float dframe, float importance, float ismodel) newdecal =
{
	local vector dirangles;
	local entity e;
	if (cvar("temp1") & 2048)
		return;
	if (en.solid != SOLID_BSP || en.model == "")
		return;
	dir = normalize(dir);
	org = org + dir; // push it off the surface
	// to orient the bullet hole properly
	if (ismodel)
		dirangles = vectoangles(dir); // sprite bug
	else if (!ismodel)
	{
		dirangles = vectoangles('0 0 0' - dir); // sprite bug
		dirangles_x = 0 - dirangles_x; // sprite bug
	}

	e = findchain(classname, "decor");
	while (e != world)
	{
		if (e.angles == dirangles) // same surface
		if (e.model == dmodel) // same type of decal
		if (vlen(e.origin - org) < 4) // remove existing mark
			remove(e);
		e = e.chain;
	}

	if (importance >= 1000) // permanent
	{
		e = spawn();
		e.classname = "permanentdecal";
	}
	else
	{
		// if in danger of running out of entities, don't spawn any new ones
		if (numdecors >= 16384)
			return;
		e = newdecor(world);
		e.cnt = importance * (0.5 + random());
	}
	e.skin = dskin;
	e.frame = dframe;
	e.angles = dirangles;
	setmodel (e, dmodel);
	setsize (e, '0 0 0', '0 0 0');
	setorigin (e, org);
	if (en != world) // might be a mobile surface, follow it
	{
		e.aiment = en;
		e.view_ofs = org - en.origin;
		e.punchangle = en.angles; // base angles
		e.v_angle = e.angles - en.angles;
		e.movetype = MOVETYPE_FOLLOW;
	}
};
how can i add this to a shotgun shell script?

Code: Select all

float() crandom;
void() shell_touch;

/*
===============
eject_shell

Spews a spent shell casing from a shotgun
===============
*/
void(vector org,vector dir, float punch, vector spread) eject_shell =
{
        local float     flip; 
	local vector transform;
        // Spawn one shell
	newmis = spawn ();
	newmis.owner = self;
        newmis.movetype = MOVETYPE_BOUNCE;
	newmis.solid = SOLID_BBOX;

	newmis.angles = vectoangles(dir);

        newmis.touch = shell_touch;
        newmis.classname = "shellcasing";
	newmis.think = SUB_Remove;
        newmis.nextthink = time + 20;
        setmodel (newmis, "progs/shelcase.mdl");
	setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
	setorigin (newmis, org);

        // pick a random numbers
	flip = crandom();
	spread_x = spread_x * flip; 
	flip = crandom();
	spread_y = spread_y * flip; 
	flip = crandom();
	spread_z = spread_z * flip; 

      transform_x = dir_y + spread_x;
	transform_y = 0 - dir_x + spread_y;
	transform_z = dir_z + spread_z;  
        newmis.velocity = transform*punch;

        // pick a random number
        flip = random();

        // based on that rate, pick a rate at which to spin
        if (flip < 0.25)
        newmis.avelocity = '300 300 300';

        else if (flip < 0.5)
        newmis.avelocity = '150 300 100';

        else if (flip < 0.75)
        newmis.avelocity = '200 100 0';

        else
        newmis.avelocity = '400 200 100';
};

void() shell_touch =
{
     // DO NOT play the sound if we hit a door.
     if (other.classname == "door")
        return;

     sound (self, CHAN_WEAPON, "weapons/shellhit.wav", 1, ATTN_NORM);
};
help would be really appreciated!
thx and regrats
~skitey
Post Reply