The mysterious engine killing teleporter
Moderator: InsideQC Admins
19 posts
• Page 2 of 2 • 1, 2
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
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
We knew the words, we knew the score, we knew what we were fighting for
-

mh - Posts: 2292
- Joined: Sat Jan 12, 2008 1:38 am
I cursed like a pirate simply trying to get to that teleport, but porting mh's code above to makaqu (plus Q_malloc)
NOTE- this is not tested except for this specific case, and it didn't seem to break standard teleports in a quick run-through.
- 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.
-
qbism - Posts: 1236
- Joined: Thu Nov 04, 2004 5:51 am
19 posts
• Page 2 of 2 • 1, 2
Who is online
Users browsing this forum: No registered users and 1 guest