The mysterious engine killing teleporter
Moderator: Inside3D Admins
19 posts
• Page 2 of 2 • 1, 2
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:
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;
}
}
}
Like the fifth day of playing 24-hour Scrabble when you don't want to use any letters because each one means a world to you because you're so deranged.
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:
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.
19 posts
• Page 2 of 2 • 1, 2
Who is online
Users browsing this forum: No registered users and 0 guests
