mirror of
https://github.com/nzp-team/dquakeplus.git
synced 2025-02-16 16:41:03 +00:00
Add Spike's SV_TouchLinks enhancement -- fixes touching mulptiple ents
This commit is contained in:
parent
6399b49edc
commit
b524455525
1 changed files with 69 additions and 38 deletions
107
source/world.c
107
source/world.c
|
@ -295,23 +295,83 @@ void SV_UnlinkEdict (edict_t *ent)
|
|||
ent->area.prev = ent->area.next = NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
SV_TouchLinks
|
||||
SV_AreaTriggerEdicts
|
||||
|
||||
Spike -- just builds a list of entities within the area, rather than walking
|
||||
them and risking the list getting corrupt.
|
||||
====================
|
||||
*/
|
||||
void SV_TouchLinks ( edict_t *ent, areanode_t *node )
|
||||
static void
|
||||
SV_AreaTriggerEdicts ( edict_t *ent, areanode_t *node, edict_t **list, int *listcount, const int listspace )
|
||||
{
|
||||
link_t *l, *next;
|
||||
edict_t *touch;
|
||||
int old_self, old_other;
|
||||
|
||||
// touch linked edicts
|
||||
for (l = node->trigger_edicts.next ; l != &node->trigger_edicts ; l = next)
|
||||
{
|
||||
next = l->next;
|
||||
touch = EDICT_FROM_AREA(l);
|
||||
if (touch == ent)
|
||||
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;
|
||||
|
||||
if (*listcount == listspace)
|
||||
return; // should never happen
|
||||
|
||||
list[*listcount] = touch;
|
||||
(*listcount)++;
|
||||
}
|
||||
|
||||
// recurse down both sides
|
||||
if (node->axis == -1)
|
||||
return;
|
||||
|
||||
if ( ent->v.absmax[node->axis] > node->dist )
|
||||
SV_AreaTriggerEdicts ( ent, node->children[0], list, listcount, listspace );
|
||||
if ( ent->v.absmin[node->axis] < node->dist )
|
||||
SV_AreaTriggerEdicts ( ent, node->children[1], list, listcount, listspace );
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
SV_TouchLinks
|
||||
|
||||
ericw -- copy the touching edicts to an array (on the hunk) so we can avoid
|
||||
iteating the trigger_edicts linked list while calling PR_ExecuteProgram
|
||||
which could potentially corrupt the list while it's being iterated.
|
||||
Based on code from Spike.
|
||||
====================
|
||||
*/
|
||||
void SV_TouchLinks (edict_t *ent)
|
||||
{
|
||||
edict_t **list;
|
||||
edict_t *touch;
|
||||
int old_self, old_other;
|
||||
int i, listcount;
|
||||
int mark;
|
||||
|
||||
mark = Hunk_LowMark ();
|
||||
list = (edict_t **) Hunk_Alloc (sv.num_edicts*sizeof(edict_t *));
|
||||
|
||||
listcount = 0;
|
||||
SV_AreaTriggerEdicts (ent, sv_areanodes, list, &listcount, sv.num_edicts);
|
||||
|
||||
for (i = 0; i < listcount; i++)
|
||||
{
|
||||
touch = list[i];
|
||||
// re-validate in case of PR_ExecuteProgram having side effects that make
|
||||
// edicts later in the list no longer touch
|
||||
if (touch == ent)
|
||||
continue;
|
||||
if (!touch->v.touch || touch->v.solid != SOLID_TRIGGER)
|
||||
|
@ -335,14 +395,8 @@ void SV_TouchLinks ( edict_t *ent, areanode_t *node )
|
|||
pr_global_struct->other = old_other;
|
||||
}
|
||||
|
||||
// recurse down both sides
|
||||
if (node->axis == -1)
|
||||
return;
|
||||
|
||||
if ( ent->v.absmax[node->axis] > node->dist )
|
||||
SV_TouchLinks ( ent, node->children[0] );
|
||||
if ( ent->v.absmin[node->axis] < node->dist )
|
||||
SV_TouchLinks ( ent, node->children[1] );
|
||||
// free hunk-allocated edicts array
|
||||
Hunk_FreeToLowMark (mark);
|
||||
}
|
||||
|
||||
|
||||
|
@ -410,31 +464,8 @@ void SV_LinkEdict (edict_t *ent, qboolean touch_triggers)
|
|||
return;
|
||||
|
||||
// set the abs box
|
||||
if (ent->v.solid == SOLID_BSP &&
|
||||
(ent->v.angles[0] || ent->v.angles[1] || ent->v.angles[2])&& ent != sv.edicts )//dr_mabuse1981: rotating fix added
|
||||
{ // expand for rotation
|
||||
float max, v;
|
||||
int i;
|
||||
|
||||
max = DotProduct(ent->v.mins, ent->v.mins);
|
||||
v = DotProduct(ent->v.maxs, ent->v.maxs);
|
||||
|
||||
if (max < v)
|
||||
max = v;
|
||||
|
||||
max = sqrt(max);
|
||||
|
||||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
ent->v.absmin[i] = ent->v.origin[i] - max;
|
||||
ent->v.absmax[i] = ent->v.origin[i] + max;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorAdd (ent->v.origin, ent->v.mins, ent->v.absmin);
|
||||
VectorAdd (ent->v.origin, ent->v.maxs, ent->v.absmax);
|
||||
}
|
||||
VectorAdd (ent->v.origin, ent->v.mins, ent->v.absmin);
|
||||
VectorAdd (ent->v.origin, ent->v.maxs, ent->v.absmax);
|
||||
|
||||
//
|
||||
// to make items easier to pick up and allow them to be grabbed off
|
||||
|
@ -489,7 +520,7 @@ void SV_LinkEdict (edict_t *ent, qboolean touch_triggers)
|
|||
|
||||
// if touch_triggers, touch all entities at this node and decend for more
|
||||
if (touch_triggers)
|
||||
SV_TouchLinks ( ent, sv_areanodes );
|
||||
SV_TouchLinks ( ent );
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue