/* * ==================== * SV_AreaEdicts_r * * ==================== */ void SV_AreaEdicts_r(areanode_t *node) { link_t *l, *next, *start; edict_t *check; int count; count = 0; // touch linked edicts if (area_type == AREA_SOLID) { start = &node->solid_edicts; } else { start = &node->trigger_edicts; } for (l = start->next; l != start; l = next) { next = l->next; check = EDICT_FROM_AREA(l); if (check->solid == SOLID_NOT) { continue; // deactivated } if ((check->absmin[0] > area_maxs[0]) || (check->absmin[1] > area_maxs[1]) || (check->absmin[2] > area_maxs[2]) || (check->absmax[0] < area_mins[0]) || (check->absmax[1] < area_mins[1]) || (check->absmax[2] < area_mins[2])) { continue; // not touching } if (area_count == area_maxcount) { Com_Printf("SV_AreaEdicts: MAXCOUNT\n"); return; } area_list[area_count] = check; area_count++; } if (node->axis == -1) { return; // terminal node } // recurse down both sides if (area_maxs[node->axis] > node->dist) { SV_AreaEdicts_r(node->children[0]); } if (area_mins[node->axis] < node->dist) { SV_AreaEdicts_r(node->children[1]); } }
void AddLinksToPmove ( areanode_t *node ) { link_t *l, *next; edict_t *check; int pl; int i; physent_t *pe; pl = EDICT_TO_PROG(sv_player); // touch linked edicts for (l = node->solid_edicts.next ; l != &node->solid_edicts ; l = next) { next = l->next; check = EDICT_FROM_AREA(l); if (check->v.owner == pl) continue; // player's own missile if (check->v.solid == SOLID_BSP || check->v.solid == SOLID_BBOX || check->v.solid == SOLID_SLIDEBOX) { if (check == sv_player) continue; for (i=0 ; i<3 ; i++) if (check->v.absmin[i] > pmove_maxs[i] || check->v.absmax[i] < pmove_mins[i]) break; if (i != 3) continue; if (pmove.numphysent == MAX_PHYSENTS) return; pe = &pmove.physents[pmove.numphysent]; pmove.numphysent++; VectorCopy (check->v.origin, pe->origin); pe->info = NUM_FOR_EDICT(check); if (check->v.solid == SOLID_BSP) pe->model = sv.models[(int)(check->v.modelindex)]; else { pe->model = NULL; VectorCopy (check->v.mins, pe->mins); VectorCopy (check->v.maxs, pe->maxs); } } } // recurse down both sides if (node->axis == -1) return; if ( pmove_maxs[node->axis] > node->dist ) AddLinksToPmove ( node->children[0] ); if ( pmove_mins[node->axis] < node->dist ) AddLinksToPmove ( node->children[1] ); }
static void SV_AreaEdicts_r(areanode_t *node) { link_t *start; // touch linked edicts if (area_type == AREA_SOLID) { #if AREA_EDICTS_OPT if (!node->numSolidEdicts) return; #endif start = &node->solidEdicts; } else // AREA_TRIGGERS { #if AREA_EDICTS_OPT if (!node->numTrigEdicts) return; #endif start = &node->trigEdicts; } link_t *next; for (link_t *l = start->next; l != start; l = next) { next = l->next; edict_t *check = EDICT_FROM_AREA(l); if (check->solid == SOLID_NOT) continue; // deactivated if (check->absBounds.mins[2] > area_bounds.maxs[2] || check->absBounds.maxs[2] < area_bounds.mins[2] || check->absBounds.mins[0] > area_bounds.maxs[0] || check->absBounds.maxs[0] < area_bounds.mins[0] || check->absBounds.mins[1] > area_bounds.maxs[1] || check->absBounds.maxs[1] < area_bounds.mins[1]) continue; // not touching if (area_count == area_maxcount) { appWPrintf("SV_AreaEdicts: MAXCOUNT\n"); return; } area_list[area_count++] = check; } if (node->axis == -1) return; // terminal node if (area_bounds.maxs[node->axis] > node->dist) SV_AreaEdicts_r(node->children[0]); if (area_bounds.mins[node->axis] < node->dist) SV_AreaEdicts_r(node->children[1]); }
/* * Sv_AreaEdicts_r */ static void Sv_AreaEdicts_r(sv_area_node_t *node) { link_t *l, *next, *start; g_edict_t *check; // touch linked edicts if (sv_world.area_type == AREA_SOLID) start = &node->solid_edicts; else start = &node->trigger_edicts; for (l = start->next; l != start; l = next) { next = l->next; check = EDICT_FROM_AREA(l); if (check->solid == SOLID_NOT) continue; // skip it if (check->abs_mins[0] > sv_world.area_maxs[0] || check->abs_mins[1] > sv_world.area_maxs[1] || check->abs_mins[2] > sv_world.area_maxs[2] || check->abs_maxs[0] < sv_world.area_mins[0] || check->abs_maxs[1] < sv_world.area_mins[1] || check->abs_maxs[2] < sv_world.area_mins[2]) continue; // not touching if (sv_world.num_area_edicts == sv_world.max_area_edicts) { Com_Warn("Sv_AreaEdicts: MAXCOUNT\n"); return; } sv_world.area_edicts[sv_world.num_area_edicts] = check; sv_world.num_area_edicts++; } if (node->axis == -1) return; // terminal node // recurse down both sides if (sv_world.area_maxs[node->axis] > node->dist) Sv_AreaEdicts_r(node->children[0]); if (sv_world.area_mins[node->axis] < node->dist) Sv_AreaEdicts_r(node->children[1]); }
/* ==================== SV_AddLaddersToPmove ==================== */ void SV_AddLaddersToPmove( areanode_t *node, const vec3_t pmove_mins, const vec3_t pmove_maxs ) { link_t *l, *next; edict_t *check; physent_t *pe; // get water edicts for( l = node->water_edicts.next; l != &node->water_edicts; l = next ) { next = l->next; check = EDICT_FROM_AREA( l ); if( check->v.solid != SOLID_NOT ) // disabled ? continue; // only brushes can have special contents if( Mod_GetType( check->v.modelindex ) != mod_brush ) continue; if( !BoundsIntersect( pmove_mins, pmove_maxs, check->v.absmin, check->v.absmax )) continue; if( svgame.pmove->nummoveent == MAX_MOVEENTS ) return; pe = &svgame.pmove->moveents[svgame.pmove->nummoveent]; if( SV_CopyEdictToPhysEnt( pe, check )) svgame.pmove->nummoveent++; } // recurse down both sides if( node->axis == -1 ) return; if( pmove_maxs[node->axis] > node->dist ) SV_AddLaddersToPmove( node->children[0], pmove_mins, pmove_maxs ); if( pmove_mins[node->axis] < node->dist ) SV_AddLaddersToPmove( node->children[1], pmove_mins, pmove_maxs ); }
/* ==================== SV_AreaEdicts ==================== */ int SV_AreaEdicts (vec3_t mins, vec3_t maxs, edict_t **edicts, int max_edicts, int area) { link_t *l, *start; edict_t *touch; int stackdepth = 0, count = 0; areanode_t *localstack[AREA_NODES], *node = sv_areanodes; // touch linked edicts while (1) { if (area == AREA_SOLID) start = &node->solid_edicts; else start = &node->trigger_edicts; for (l = start->next ; l != start ; l = l->next) { touch = EDICT_FROM_AREA(l); if (touch->v.solid == SOLID_NOT) continue; if (mins[0] > touch->v.absmax[0] || mins[1] > touch->v.absmax[1] || mins[2] > touch->v.absmax[2] || maxs[0] < touch->v.absmin[0] || maxs[1] < touch->v.absmin[1] || maxs[2] < touch->v.absmin[2]) continue; if (count == max_edicts) return count; edicts[count++] = touch; } if (node->axis == -1) goto checkstack; // terminal node // recurse down both sides if (maxs[node->axis] > node->dist) { if (mins[node->axis] < node->dist) { localstack[stackdepth++] = node->children[0]; node = node->children[1]; continue; } node = node->children[0]; continue; } if (mins[node->axis] < node->dist) { node = node->children[1]; continue; } checkstack: if (!stackdepth) return count; node = localstack[--stackdepth]; } return count; }
/* ==================== SV_AddLinksToPmove collect solid entities ==================== */ void SV_AddLinksToPmove( areanode_t *node, const vec3_t pmove_mins, const vec3_t pmove_maxs ) { link_t *l, *next; edict_t *check, *pl; vec3_t mins, maxs; physent_t *pe; pl = EDICT_NUM( svgame.pmove->player_index + 1 ); //ASSERT( SV_IsValidEdict( pl )); if( !SV_IsValidEdict( pl ) ) { MsgDev( D_ERROR, "SV_AddLinksToPmove: you have broken clients!\n"); return; } // touch linked edicts for( l = node->solid_edicts.next; l != &node->solid_edicts; l = next ) { next = l->next; check = EDICT_FROM_AREA( l ); if( check->v.groupinfo != 0 ) { if(( !svs.groupop && (check->v.groupinfo & pl->v.groupinfo ) == 0) || ( svs.groupop == 1 && ( check->v.groupinfo & pl->v.groupinfo ) != 0 )) continue; } if( ( ( check->v.owner > 0) && check->v.owner == pl ) || check->v.solid == SOLID_TRIGGER ) continue; // player or player's own missile if( svgame.pmove->numvisent < MAX_PHYSENTS ) { pe = &svgame.pmove->visents[svgame.pmove->numvisent]; if( SV_CopyEdictToPhysEnt( pe, check )) svgame.pmove->numvisent++; } if( check->v.solid == SOLID_NOT && ( check->v.skin == CONTENTS_NONE || check->v.modelindex == 0 )) continue; // ignore monsterclip brushes if(( check->v.flags & FL_MONSTERCLIP ) && check->v.solid == SOLID_BSP ) continue; if( check == pl ) continue; // himself if( !sv_corpse_solid->value ) { if((( check->v.flags & FL_CLIENT ) && check->v.health <= 0 ) || check->v.deadflag == DEAD_DEAD ) continue; // dead body } if( VectorIsNull( check->v.size )) continue; VectorCopy( check->v.absmin, mins ); VectorCopy( check->v.absmax, maxs ); if( check->v.flags & FL_CLIENT ) { // trying to get interpolated values if( svs.currentPlayer ) SV_GetTrueMinMax( svs.currentPlayer, ( NUM_FOR_EDICT( check ) - 1), mins, maxs ); } if( !BoundsIntersect( pmove_mins, pmove_maxs, mins, maxs )) continue; if( svgame.pmove->numphysent < MAX_PHYSENTS ) { pe = &svgame.pmove->physents[svgame.pmove->numphysent]; if( SV_CopyEdictToPhysEnt( pe, check )) svgame.pmove->numphysent++; } } // recurse down both sides if( node->axis == -1 ) return; if( pmove_maxs[node->axis] > node->dist ) SV_AddLinksToPmove( node->children[0], pmove_mins, pmove_maxs ); if( pmove_mins[node->axis] < node->dist ) SV_AddLinksToPmove( node->children[1], pmove_mins, pmove_maxs ); }