📄 sv_world.java
字号:
ent.num_clusters = -1; ent.headnode = topnode; } else { ent.num_clusters = 0; for (int i = 0; i < num_leafs; i++) { if (SV_WORLD.clusters[i] == -1) continue; // not a visible leaf for (j = 0; j < i; j++) if (SV_WORLD.clusters[j] == SV_WORLD.clusters[i]) break; if (j == i) { if (ent.num_clusters == Defines.MAX_ENT_CLUSTERS) { // assume we missed some leafs, and mark by headnode ent.num_clusters = -1; ent.headnode = topnode; break; } ent.clusternums[ent.num_clusters++] = SV_WORLD.clusters[i]; } } } // if first time, make sure old_origin is valid if (0 == ent.linkcount) { Math3D.VectorCopy(ent.s.origin, ent.s.old_origin); } ent.linkcount++; if (ent.solid == Defines.SOLID_NOT) return; // find the first node that the ent's box crosses node = SV_WORLD.sv_areanodes[0]; while (true) { if (node.axis == -1) break; if (ent.absmin[node.axis] > node.dist) node = node.children[0]; else if (ent.absmax[node.axis] < node.dist) node = node.children[1]; else break; // crosses the node } // link it in if (ent.solid == Defines.SOLID_TRIGGER) InsertLinkBefore(ent.area, node.trigger_edicts); else InsertLinkBefore(ent.area, node.solid_edicts); } /* * ==================== SV_AreaEdicts_r * * ==================== */ public static void SV_AreaEdicts_r(areanode_t node) { link_t l, next, start; edict_t check; int count; count = 0; // touch linked edicts if (SV_WORLD.area_type == Defines.AREA_SOLID) start = node.solid_edicts; else start = node.trigger_edicts; for (l = start.next; l != start; l = next) { next = l.next; check = (edict_t) l.o; if (check.solid == Defines.SOLID_NOT) continue; // deactivated if (check.absmin[0] > SV_WORLD.area_maxs[0] || check.absmin[1] > SV_WORLD.area_maxs[1] || check.absmin[2] > SV_WORLD.area_maxs[2] || check.absmax[0] < SV_WORLD.area_mins[0] || check.absmax[1] < SV_WORLD.area_mins[1] || check.absmax[2] < SV_WORLD.area_mins[2]) continue; // not touching if (SV_WORLD.area_count == SV_WORLD.area_maxcount) { Com.Printf("SV_AreaEdicts: MAXCOUNT\n"); return; } SV_WORLD.area_list[SV_WORLD.area_count] = check; SV_WORLD.area_count++; } 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_AreaEdicts ================ */ public static int SV_AreaEdicts(float[] mins, float[] maxs, edict_t list[], int maxcount, int areatype) { SV_WORLD.area_mins = mins; SV_WORLD.area_maxs = maxs; SV_WORLD.area_list = list; SV_WORLD.area_count = 0; SV_WORLD.area_maxcount = maxcount; SV_WORLD.area_type = areatype; SV_AreaEdicts_r(SV_WORLD.sv_areanodes[0]); return SV_WORLD.area_count; } /* * ============= SV_PointContents ============= */ public static int SV_PointContents(float[] p) { edict_t hit; int i, num; int contents, c2; int headnode; float angles[]; // get base contents from world contents = CM.PointContents(p, SV_INIT.sv.models[1].headnode); // or in contents from all the other entities num = SV_AreaEdicts(p, p, SV_WORLD.touch, Defines.MAX_EDICTS, Defines.AREA_SOLID); for (i = 0; i < num; i++) { hit = SV_WORLD.touch[i]; // might intersect, so do an exact clip headnode = SV_HullForEntity(hit); angles = hit.s.angles; if (hit.solid != Defines.SOLID_BSP) angles = Globals.vec3_origin; // boxes don't rotate c2 = CM.TransformedPointContents(p, headnode, hit.s.origin, hit.s.angles); contents |= c2; } return contents; } /* * ================ SV_HullForEntity * * Returns a headnode that can be used for testing or clipping an object of * mins/maxs size. Offset is filled in to contain the adjustment that must * be added to the testing object's origin to get a point to use with the * returned hull. ================ */ public static int SV_HullForEntity(edict_t ent) { cmodel_t model; // decide which clipping hull to use, based on the size if (ent.solid == Defines.SOLID_BSP) { // explicit hulls in the BSP model model = SV_INIT.sv.models[ent.s.modelindex]; if (null == model) Com.Error(Defines.ERR_FATAL, "MOVETYPE_PUSH with a non bsp model"); return model.headnode; } // create a temp hull from bounding box sizes return CM.HeadnodeForBox(ent.mins, ent.maxs); } public static void SV_ClipMoveToEntities(moveclip_t clip) { int i, num; edict_t touch; trace_t trace; int headnode; float angles[]; num = SV_AreaEdicts(clip.boxmins, clip.boxmaxs, SV_WORLD.touchlist, Defines.MAX_EDICTS, Defines.AREA_SOLID); // be careful, it is possible to have an entity in this // list removed before we get to it (killtriggered) for (i = 0; i < num; i++) { touch = SV_WORLD.touchlist[i]; if (touch.solid == Defines.SOLID_NOT) continue; if (touch == clip.passedict) continue; if (clip.trace.allsolid) return; if (clip.passedict != null) { if (touch.owner == clip.passedict) continue; // don't clip against own missiles if (clip.passedict.owner == touch) continue; // don't clip against owner } if (0 == (clip.contentmask & Defines.CONTENTS_DEADMONSTER) && 0 != (touch.svflags & Defines.SVF_DEADMONSTER)) continue; // might intersect, so do an exact clip headnode = SV_HullForEntity(touch); angles = touch.s.angles; if (touch.solid != Defines.SOLID_BSP) angles = Globals.vec3_origin; // boxes don't rotate if ((touch.svflags & Defines.SVF_MONSTER) != 0) trace = CM.TransformedBoxTrace(clip.start, clip.end, clip.mins2, clip.maxs2, headnode, clip.contentmask, touch.s.origin, angles); else trace = CM.TransformedBoxTrace(clip.start, clip.end, clip.mins, clip.maxs, headnode, clip.contentmask, touch.s.origin, angles); if (trace.allsolid || trace.startsolid || trace.fraction < clip.trace.fraction) { trace.ent = touch; if (clip.trace.startsolid) { clip.trace = trace; clip.trace.startsolid = true; } else clip.trace.set(trace); } else if (trace.startsolid) clip.trace.startsolid = true; } } /* * ================== SV_TraceBounds ================== */ public static void SV_TraceBounds(float[] start, float[] mins, float[] maxs, float[] end, float[] boxmins, float[] boxmaxs) { int i; for (i = 0; i < 3; i++) { if (end[i] > start[i]) { boxmins[i] = start[i] + mins[i] - 1; boxmaxs[i] = end[i] + maxs[i] + 1; } else { boxmins[i] = end[i] + mins[i] - 1; boxmaxs[i] = start[i] + maxs[i] + 1; } } } /* * ================== SV_Trace * * Moves the given mins/maxs volume through the world from start to end. * * Passedict and edicts owned by passedict are explicitly not checked. * * ================== */ public static trace_t SV_Trace(float[] start, float[] mins, float[] maxs, float[] end, edict_t passedict, int contentmask) { moveclip_t clip = new moveclip_t(); if (mins == null) mins = Globals.vec3_origin; if (maxs == null) maxs = Globals.vec3_origin; // clip to world clip.trace = CM.BoxTrace(start, end, mins, maxs, 0, contentmask); clip.trace.ent = GameBase.g_edicts[0]; if (clip.trace.fraction == 0) return clip.trace; // blocked by the world clip.contentmask = contentmask; clip.start = start; clip.end = end; clip.mins = mins; clip.maxs = maxs; clip.passedict = passedict; Math3D.VectorCopy(mins, clip.mins2); Math3D.VectorCopy(maxs, clip.maxs2); // create the bounding box of the entire move SV_TraceBounds(start, clip.mins2, clip.maxs2, end, clip.boxmins, clip.boxmaxs); // clip to other solid entities SV_ClipMoveToEntities(clip); return clip.trace; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -