Forum

The mysterious engine killing teleporter

Discuss programming topics for the various GPL'd game engine sources.

Moderator: InsideQC Admins

Postby metlslime » Sat Mar 28, 2009 4:33 am

note, tyr-glquake does not break on White Room, so Tyrann must have more to his fix than the code snippet from above.
metlslime
 
Posts: 316
Joined: Tue Feb 05, 2008 11:03 pm

Postby MeTcHsteekle » Sat Mar 28, 2009 12:56 pm

metlslime wrote:So I guess the more robust method of FTE and DP is the way to go.


Damn, the tough way around eh?
bah
MeTcHsteekle
 
Posts: 399
Joined: Thu May 15, 2008 10:46 pm
Location: its a secret

Postby mh » Thu Apr 08, 2010 7:56 pm

Here's the more robust version as it's currently coded in DirectQ. Any other engine's allocators are going to be different of course, and the C++ stuff won't be usable, but it should nonetheless be straightforward to port.
Code: Select all
void SV_TouchLinks (edict_t *ent, areanode_t *node)
{
   link_t          *l, *next;
   edict_t          *touch;
   int          old_self, old_other, touched = 0, i;

   // Static due to recursive function
   static edict_t **list = NULL;

   if (!list)
   {
      // alloc first time (to keep it off the stack - 256K - ouch!)
      list = (edict_t **) Pool_Permanent->Alloc (MAX_EDICTS * sizeof (edict_t *));
   }

loc0:;
   // ensure
   touched = 0;

   // Build a list of touched edicts since linked list may change during touch
   for (l = node->trigger_edicts.next; l != &node->trigger_edicts; l = l->next)
   {
      touch = EDICT_FROM_AREA(l);

      if (touch == ent) continue;
      if (touch->free) continue;
      if (!touch->v.touch || touch->v.solid != SOLID_TRIGGER) continue;

      if (ent->v.absmin[0] > touch->v.absmax[0] || ent->v.absmin[1] > touch->v.absmax[1] || ent->v.absmin[2] > touch->v.absmax[2] ||
         ent->v.absmax[0] < touch->v.absmin[0] || ent->v.absmax[1] < touch->v.absmin[1] || ent->v.absmax[2] < touch->v.absmin[2])
         continue;

      list[touched++] = touch;

      if (touched == MAX_EDICTS)
      {
         Con_DPrintf ("SV_TouchLinks: ");
         Con_DPrintf ("too many touched trigger_edicts (max = %d)\n", MAX_EDICTS);
         break;
      }
   }

   // touch linked edicts
   for (i = 0; i < touched; ++i)
   {
      int ednum;

      touch = list[i];

      ednum = GetNumberForEdict(touch);

      old_self = SVProgs->GlobalStruct->self;
      old_other = SVProgs->GlobalStruct->other;

      SVProgs->GlobalStruct->self = EDICT_TO_PROG(touch);
      SVProgs->GlobalStruct->other = EDICT_TO_PROG(ent);
      SVProgs->GlobalStruct->time = SV_TIME;
      SVProgs->ExecuteProgram (touch->v.touch);

      SVProgs->GlobalStruct->self = old_self;
      SVProgs->GlobalStruct->other = old_other;
   }

   // recurse down both sides
   if (node->axis == -1)
      return;

   if (ent->v.absmax[node->axis] > node->dist)
   {
      // order reversed to reduce code
      if (ent->v.absmin[node->axis] < node->dist) SV_TouchLinks(ent, node->children[1]);
      node = node->children[0];
      goto loc0;
   }
   else
   {
      if (ent->v.absmin[node->axis] < node->dist)
      {
         node = node->children[1];
         goto loc0;
      }
   }
}
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
User avatar
mh
 
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Postby qbism » Fri Apr 09, 2010 4:03 am

I cursed like a pirate simply trying to get to that teleport, but porting mh's code above to makaqu (plus Q_malloc)
Code: Select all
void SV_TouchLinks ( edict_t *ent, areanode_t *node )
{
   link_t      *l, *next;
   edict_t      *touch;
   int         old_self, old_other, touched = 0, i;

   // Static due to recursive function
   static edict_t **list = NULL;

   if (!list)
   {
      // alloc first time (to keep it off the stack - 256K - ouch!)
      list = (edict_t **) Q_malloc (MAX_EDICTS * sizeof (edict_t *));
   }
loc0:;
   // ensure
   touched = 0;

   // Build a list of touched edicts since linked list may change during touch
   for (l = node->trigger_edicts.next; l != &node->trigger_edicts; l = l->next)
   {
      touch = EDICT_FROM_AREA(l);

      if (touch == ent) continue;
      if (touch->free) continue;
      if (!touch->v.touch || touch->v.solid != SOLID_TRIGGER) continue;

      if (ent->v.absmin[0] > touch->v.absmax[0] || ent->v.absmin[1] > touch->v.absmax[1] || ent->v.absmin[2] > touch->v.absmax[2] ||
         ent->v.absmax[0] < touch->v.absmin[0] || ent->v.absmax[1] < touch->v.absmin[1] || ent->v.absmax[2] < touch->v.absmin[2])
         continue;

      list[touched++] = touch;

      if (touched == MAX_EDICTS)
      {
         Con_DPrintf ("SV_TouchLinks: ");
         Con_DPrintf ("too many touched trigger_edicts (max = %d)\n", MAX_EDICTS);
         break;
      }
   }

   // touch linked edicts
   for (i = 0; i < touched; ++i)
   {
      int ednum;

      touch = list[i];

      ednum = NUM_FOR_EDICT(touch);

       old_self = pr_global_struct->self;
      old_other = pr_global_struct->other;

      pr_global_struct->self = EDICT_TO_PROG(touch);
      pr_global_struct->other = EDICT_TO_PROG(ent);
      pr_global_struct->time = sv.time;
      PR_ExecuteProgram (touch->v.touch);

      pr_global_struct->self = old_self;
      pr_global_struct->other = old_other;
   }

   // recurse down both sides
   if (node->axis == -1)
      return;

   if (ent->v.absmax[node->axis] > node->dist)
   {
      // order reversed to reduce code
      if (ent->v.absmin[node->axis] < node->dist) SV_TouchLinks(ent, node->children[1]);
      node = node->children[0];
      goto loc0;
   }
   else
   {
      if (ent->v.absmin[node->axis] < node->dist)
      {
         node = node->children[1];
         goto loc0;
      }
   }
}

NOTE- this is not tested except for this specific case, and it didn't seem to break standard teleports in a quick run-through.
User avatar
qbism
 
Posts: 1236
Joined: Thu Nov 04, 2004 5:51 am

Previous

Return to Engine Programming

Who is online

Users browsing this forum: No registered users and 1 guest