Forum

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

Discuss programming in the QuakeC language.

Moderator: InsideQC Admins

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

Postby skite2001 » Wed Nov 26, 2008 6:26 pm

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
User avatar
skite2001
 
Posts: 17
Joined: Mon Nov 17, 2008 5:40 pm

Return to QuakeC Programming

Who is online

Users browsing this forum: No registered users and 1 guest