void Sky_DrawFace (int axis) { glpoly_t *p; MathVector3f_t verts[4]; int i, j, start; float di,qi,dj,qj; MathVector3f_t v_up, v_right, temp, temp2; Sky_SetBoxVert(-1.0f,-1.0f,axis,verts[0]); Sky_SetBoxVert(-1.0f,1.0f,axis,verts[1]); Sky_SetBoxVert(1.0f,1.0f,axis,verts[2]); Sky_SetBoxVert(1.0f,-1.0f,axis,verts[3]); start = Hunk_LowMark (); p = (glpoly_t*)Hunk_Alloc(sizeof(glpoly_t)); Math_VectorSubtract(verts[2],verts[3], v_up); Math_VectorSubtract(verts[2],verts[1], v_right); di = Math_Max((int)r_sky_quality.value,1); qi = 1.0f/di; dj = (axis < 4) ? di*2 : di; // Subdivide vertically more than horizontally on skybox sides qj = 1.0f/dj; for (i=0; i<di; i++) { for (j=0; j<dj; j++) { if (i*qi < skymins[0][axis]/2+0.5 - qi || i*qi > skymaxs[0][axis]/2+0.5 || j*qj < skymins[1][axis]/2+0.5 - qj || j*qj > skymaxs[1][axis]/2+0.5) continue; //if (i&1 ^ j&1) continue; //checkerboard test Math_VectorScale(v_right, qi*i, temp); Math_VectorScale(v_up, qj*j, temp2); Math_VectorAdd(temp,temp2,temp); Math_VectorAdd(verts[0],temp,p->verts[0]); Math_VectorScale(v_up, qj, temp); Math_VectorAdd(p->verts[0],temp,p->verts[1]); Math_VectorScale(v_right, qi, temp); Math_VectorAdd(p->verts[1],temp,p->verts[2]); Math_VectorAdd(p->verts[0],temp,p->verts[3]); Sky_DrawFaceQuad(p); } } Hunk_FreeToLowMark(start); }
void C4Vizatergo_Think(ServerEntity_t *ent) { #if 0 // TODO: Finish? float fDistance; vec3_t vDistance; ServerEntity_t *eDistantEnt = Game.Server_FindRadius(ent->v.origin,512.0f); if(eDistantEnt) { Math_VectorSubtract(eDistantEnt->v.origin,ent->v.origin,vDistance); fDistance = 512.0f-Math_Length(vDistance); Game.Con_Printf("Distance: %f\n",fDistance); if(fDistance > 0) Sound(ent,CHAN_AUTO,"weapons/c4/c4beep.wav",255,ATTN_NORM); } else fDistance = 0; ent->v.dNextThink = Server.dTime+(2.5f*(fDistance/100.0f)); #else Sound(ent, CHAN_AUTO, "weapons/c4/beep.wav", 130, ATTN_IDLE); if(!ent->local.eOwner && ent->local.hit) ent->v.movetype = MOVETYPE_BOUNCE; ent->v.dNextThink = Server.dTime+2.5; #endif }
void Select_AplyMatrix (void) { brush_t *b; face_t *f; int i, j; vec3_t temp; for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) { for (f=b->brush_faces ; f ; f=f->next) { for (i=0 ; i<3 ; i++) { Math_VectorSubtract(f->planepts[i],select_origin, temp); for (j=0 ; j<3 ; j++) f->planepts[i][j] = Math_DotProduct(temp,select_matrix[j]) + select_origin[j]; } if (select_fliporder) { Math_VectorCopy(f->planepts[0],temp); Math_VectorCopy(f->planepts[2],f->planepts[0]); Math_VectorCopy(temp,f->planepts[2]); } } Brush_Build( b ); } Sys_UpdateWindows (W_ALL); }
// TODO: stay at least 8 units away from all walls in this leaf void Chase_UpdateForDrawing (void) { int i; vec3_t forward, up, right; vec3_t ideal, crosshair, temp; Math_AngleVectors(cl.viewangles, forward, right, up); // calc ideal camera location before checking for walls for (i=0 ; i<3 ; i++) ideal[i] = cl.viewent.origin[i] - forward[i]*chase_back.value + right[i]*chase_right.value; //+ up[i]*chase_up.value; ideal[2] = cl.viewent.origin[2] + chase_up.value; // make sure camera is not in or behind a wall TraceLine(r_refdef.vieworg, ideal, temp); if(Math_Length(temp) != 0) Math_VectorCopy(temp, ideal); // place camera Math_VectorCopy(ideal, r_refdef.vieworg); // find the spot the player is looking at Math_VectorMA(cl.viewent.origin, 4096, forward, temp); TraceLine(cl.viewent.origin, temp, crosshair); // calculate camera angles to look at the same spot Math_VectorSubtract(crosshair,r_refdef.vieworg,temp); Math_VectorAngles (temp, r_refdef.viewangles); if (r_refdef.viewangles[PITCH] == 90 || r_refdef.viewangles[PITCH] == -90) r_refdef.viewangles[YAW] = cl.viewangles[YAW]; }
/* Returns the visible polygon on a face */ winding_t *MakeFaceWinding(brush_t *b,face_t *face) { winding_t *w; face_t *clip; plane_t plane; BOOL past; // get a poly that covers an effectively infinite area w = BasePolyForPlane (&face->plane); // chop the poly by all of the other faces past = FALSE; for (clip = b->brush_faces ; clip && w ; clip=clip->next) { if (clip == face) { past = TRUE; continue; } if(Math_DotProduct (face->plane.normal, clip->plane.normal) > 0.999 && fabs(face->plane.dist - clip->plane.dist) < 0.01 ) { // identical plane, use the later one if (past) { free (w); return NULL; } continue; } // flip the plane, because we want to keep the back side Math_VectorSubtract(vec3_origin,clip->plane.normal,plane.normal); plane.dist = -clip->plane.dist; w = ClipWinding(w,&plane,FALSE); if (!w) return w; } if (w->numpoints < 3) { free(w); w = NULL; } if (!w) printf ("unused plane\n"); return w; }
Waypoint_t *Waypoint_GetByType(MathVector3f_t position, WaypointType_t type, float distance) { Waypoint_t *point; MathVector3f_t vecdist; for (point = wWaypoints; point->number < waypoint_count; point++) if (point->wType == type) { Math_VectorSubtract(position, point->position, vecdist); if (Math_Length(vecdist) < distance) return point; } return NULL; }
/* Damage entities within a specific radius. */ void Entity_RadiusDamage(edict_t *eInflictor,float fRadius,int iDamage,int iDamageType) { int i; float fDistance; vec3_t vOrigin; edict_t *eTarget = Engine.Server_FindRadius(eInflictor->v.origin,fRadius); Engine.WriteByte(MSG_BROADCAST,SVC_TEMPENTITY); Engine.WriteByte(MSG_BROADCAST,CTE_EXPLOSION); for(i = 0; i < 3; i++) Engine.WriteCoord(MSG_BROADCAST,eInflictor->v.origin[i]); do { if(eTarget->v.bTakeDamage) { int i; for(i = 0; i < 3; i++) vOrigin[i] = eTarget->v.origin[i]+(eTarget->v.mins[i]+eTarget->v.maxs[i])*0.5f; Math_VectorSubtract(eInflictor->v.origin,vOrigin,vOrigin); fDistance = 0.5f*(float)Math_VectorLength(vOrigin); if(fDistance > 0) { Math_VectorInverse(vOrigin); Math_VectorAdd(eTarget->v.velocity,vOrigin,eTarget->v.velocity); // [15/7/2013] Reduce the damage by distance ~hogsy fDistance = (float)iDamage-(100.0f/fDistance); // [15/8/2013] Less damage for the inflictor ~hogsy if(eTarget == eInflictor) fDistance = fDistance/2.0f; if(fDistance > 0) if(Entity_CanDamage(eInflictor,eTarget, iDamageType)) MONSTER_Damage(eTarget,eInflictor,(int)fDistance,iDamageType); } } eTarget = eTarget->v.chain; } while(eTarget); }
// [20/9/2012] Lets us find a specific waypoint by name ~hogsy Waypoint_t *Waypoint_GetByName(ServerEntity_t *eMonster,char *cName,float fMaxDistance) { Waypoint_t *wPoint; vec3_t vDistance; for (wPoint = wWaypoints; wPoint->number < waypoint_count; wPoint++) if(strcmp(wPoint->cName,cName)) { // [20/9/2012] TODO: Needs testing :[ ~hogsy Math_VectorSubtract(eMonster->v.origin,wPoint->position,vDistance); if(Math_Length(vDistance) < fMaxDistance) return wPoint; } // [20/9/2012] Welp we didn't find anything, return null ~hogsy return NULL; }
/* Returns the range from an entity to a target. */ float MONSTER_GetRange(edict_t *ent,vec3_t target) { // [12/4/2012] Revised ~hogsy vec3_t spot,spot1,spot2; spot1[0] = ent->v.origin[0]+ent->v.view_ofs[0]; spot1[1] = ent->v.origin[1]+ent->v.view_ofs[1]; spot1[2] = ent->v.origin[2]+ent->v.view_ofs[2]; spot2[0] = target[0]; //+ target->v.view_ofs[0]; spot2[1] = target[1]; //+ target->v.view_ofs[1]; spot2[2] = target[2]; //+ target->v.view_ofs[2]; Math_VectorSubtract(spot1,spot2,spot); // [4/2/2013] Shouldn't this be a float rather than a double? Oh well, whatever you say, Carmack ~hogsy return (float)Math_VectorLength(spot); }
/* Itersects a ray with a brush Returns the face hit and the distance along the ray the intersection occured at Returns NULL and 0 if not hit at all */ face_t *Brush_Ray (vec3_t origin, vec3_t dir, brush_t *b, float *dist) { face_t *f, *firstface=NULL; vec3_t p1, p2; float frac, d1, d2; int i; Math_VectorCopy(origin,p1); for (i=0 ; i<3 ; i++) p2[i] = p1[i] + dir[i]*16384; for (f=b->brush_faces ; f ; f=f->next) { d1 = Math_DotProduct(p1,f->plane.normal)-f->plane.dist; d2 = Math_DotProduct(p2,f->plane.normal)-f->plane.dist; if (d1 >= 0 && d2 >= 0) { *dist = 0; return NULL; // ray is on front side of face } if (d1 <=0 && d2 <= 0) continue; // clip the ray to the plane frac = d1 / (d1 - d2); if (d1 > 0) { firstface = f; for (i=0 ; i<3 ; i++) p1[i] = p1[i] + frac *(p2[i] - p1[i]); } else { for (i=0 ; i<3 ; i++) p2[i] = p1[i] + frac *(p2[i] - p1[i]); } } // find distance p1 is along dir Math_VectorSubtract(p1,origin,p1); d1 = Math_DotProduct(p1,dir); *dist = d1; return firstface; }
void Sky_ProcessPoly (glpoly_t *p) { int i; MathVector3f_t verts[MAX_CLIP_VERTS]; // Draw it DrawGLPoly(p); rs_brushpasses++; // Update sky bounds if (!r_fastsky.value) { for (i=0 ; i<p->numverts ; i++) Math_VectorSubtract (p->verts[i], r_origin, verts[i]); Sky_ClipPoly (p->numverts, verts[0], 0); } }
void Sky_GetTexCoord(MathVector3f_t v,float speed,float *s,float *t) { MathVector3f_t vDirection; float fLength,fScroll; Math_VectorSubtract(v,r_origin,vDirection); vDirection[2] *= 3.0f; // Flatten the sphere fLength = vDirection[0]*vDirection[0]+vDirection[1]*vDirection[1]+vDirection[2]*vDirection[2]; fLength = sqrt(fLength); fLength = 6.0f*63.0f/fLength; fScroll = cl.time*speed; fScroll -= (int)fScroll & ~127; *s = (fScroll+vDirection[0]*fLength)*(1.0f/128.0f); *t = (fScroll+vDirection[1]*fLength)*(1.0f/128.0f); }
/* Alternative to SetSize. */ void Entity_SetSizeVector(edict_t *eEntity,vec3_t vMin,vec3_t vMax) { int i; // [13/9/2013] Check if the model is set yet, if not give us a little warning ~hogsy if(!eEntity->v.model) Engine.Con_Warning("Setting entity size before model! (%s)\n",eEntity->v.cClassname); for(i = 0; i < 3; i++) if(vMin[i] > vMax[i]) { Engine.Con_Warning("Backwards mins/maxs! (%s)\n",eEntity->v.cClassname); return; } Math_VectorCopy(vMin,eEntity->v.mins); Math_VectorCopy(vMax,eEntity->v.maxs); Math_VectorSubtract(vMax,vMin,eEntity->v.size); Engine.LinkEntity(eEntity,false); }
void SV_WallFriction (edict_t *ent, trace_t *trace) { vec3_t forward, right, up; float d, i; vec3_t into, side; Math_AngleVectors(ent->v.v_angle, forward, right, up); d = Math_DotProduct (trace->plane.normal, forward); d += 0.5; if (d >= 0) return; // Cut the tangential velocity i = Math_DotProduct (trace->plane.normal, ent->v.velocity); Math_VectorScale (trace->plane.normal, i, into); Math_VectorSubtract (ent->v.velocity, into, side); ent->v.velocity[0] = side[0] * (1 + d); ent->v.velocity[1] = side[1] * (1 + d); }
/* Sets the size of the given entity; requires that the model has been applied first. Alternative to SetSize. */ void Entity_SetSizeVector(ServerEntity_t *eEntity, MathVector3f_t vMin, MathVector3f_t vMax) { int i; // Check if the model is set yet, if not give us a little warning. if(!eEntity->v.model) Engine.Con_Warning("Setting entity size before model! (%s)\n",eEntity->v.cClassname); for(i = 0; i < 3; i++) if(vMin[i] > vMax[i]) { Engine.Con_Warning("Backwards mins/maxs! (%s)\n",eEntity->v.cClassname); return; } Math_VectorCopy(vMin,eEntity->v.mins); Math_VectorCopy(vMax,eEntity->v.maxs); Math_VectorSubtract(vMax,vMin,eEntity->v.size); Entity_Link(eEntity, false); }
void Physics_WallFriction(ServerEntity_t *eEntity, trace_t *trLine) { MathVector3f_t forward, right, up; float d, i; MathVector3f_t into, side; Math_AngleVectors(eEntity->v.v_angle, forward, right, up); d = Math_DotProduct(trLine->plane.normal, forward); d += 0.5; if (d >= 0) return; // Cut the tangential velocity. i = Math_DotProduct(trLine->plane.normal, eEntity->v.velocity); Math_VectorScale(trLine->plane.normal, i, into); Math_VectorSubtract(eEntity->v.velocity, into, side); eEntity->v.velocity[0] = side[0] * (1 + d); eEntity->v.velocity[1] = side[1] * (1 + d); }
/* Damage entities within a specific radius. */ void Entity_RadiusDamage(ServerEntity_t *eInflictor, float fRadius, int iDamage, int iDamageType) { int i; float fDistance; MathVector3f_t vOrigin; ServerEntity_t *eTarget = Engine.Server_FindRadius(eInflictor->v.origin, fRadius); do { if(eTarget->v.bTakeDamage) { for(i = 0; i < 3; i++) vOrigin[i] = eTarget->v.origin[i]+(eTarget->v.mins[i]+eTarget->v.maxs[i])*0.5f; Math_VectorSubtract(eInflictor->v.origin,vOrigin,vOrigin); fDistance = 0.5f*(float)Math_VectorLength(vOrigin); if(fDistance > 0) { Math_VectorInverse(vOrigin); Math_VectorAdd(eTarget->v.velocity,vOrigin,eTarget->v.velocity); // Reduce the damage by distance. fDistance = (float)iDamage-(100.0f/fDistance); // Less damage for the inflictor. if(eTarget == eInflictor) fDistance = fDistance/2.0f; if(fDistance > 0) Entity_Damage(eTarget,eInflictor,(int)fDistance,iDamageType); } } eTarget = eTarget->v.chain; } while(eTarget); }
void Waypoint_Spawn(MathVector3f_t vOrigin,WaypointType_t type) { #ifdef DEBUG_WAYPOINT char *cModelName = WAYPOINT_MODEL_BASE; #endif int iPointContents; Waypoint_t *wPoint; /* TODO If we're between two other waypoints and they can be seen then slot ourselves in so that we act as the last waypoint instead. */ iPointContents = Engine.Server_PointContents(vOrigin); // [17/6/2012] Check that this area is safe ~hogsy if(iPointContents == BSP_CONTENTS_SOLID) { Engine.Con_Warning("Failed to place waypoint, position is within a solid!\n"); return; } { Waypoint_t *wVisibleWaypoint = Waypoint_GetByVisibility(vOrigin); // [30/1/2013] Oops! Check we actually have a visible waypoint!! ~hogsy if(wVisibleWaypoint) { MathVector3f_t vDistance; Math_VectorSubtract(wVisibleWaypoint->position,vOrigin,vDistance); if(Math_VectorLength(vDistance) < MONSTER_RANGE_MEDIUM) { Engine.Con_Printf("Invalid waypoint position!\n"); return; } } } wPoint = Waypoint_Allocate(); if(!wPoint) { Engine.Con_Warning("Failed to allocate waypoint!\n"); return; } Math_VectorCopy(vOrigin,wPoint->position); wPoint->number = waypoint_count; wPoint->bOpen = false; wPoint->next = Waypoint_GetByNumber(wPoint->number+1); wPoint->last = Waypoint_GetByNumber(wPoint->number-1); wPoint->wType = type; switch(type) { case WAYPOINT_ITEM: wPoint->cName = "item"; #ifdef DEBUG_WAYPOINT cModelName = WAYPOINT_MODEL_ITEM; #endif break; case WAYPOINT_CLIMB: wPoint->cName = "climb"; // TODO: Check that there's a ladder nearby. #ifdef DEBUG_WAYPOINT cModelName = WAYPOINT_MODEL_CLIMB; #endif break; case WAYPOINT_COVER: wPoint->cName = "cover"; // [27/12/2012] TODO: Check that this is actually cover ~hogsy break; case WAYPOINT_TYPE_JUMP: wPoint->cName = "jump"; // [27/12/2012] TODO: Check if this is actually a jump by tracing out ahead ~hogsy #ifdef DEBUG_WAYPOINT cModelName = WAYPOINT_MODEL_JUMP; #endif break; case WAYPOINT_TYPE_SWIM: if(iPointContents != BSP_CONTENTS_WATER) { Engine.Con_Warning("Waypoint with type swim not within water contents (%i %i %i)!", (int)vOrigin[0], (int)vOrigin[1], (int)vOrigin[2]); Waypoint_Delete(wPoint); return; } wPoint->cName = "swim"; #ifdef DEBUG_WAYPOINT cModelName = WAYPOINT_MODEL_SWIM; #endif break; case WAYPOINT_TYPE_DEFAULT: wPoint->cName = "default"; break; case WAYPOINT_SPAWN: wPoint->cName = "spawn"; break; default: Engine.Con_Warning("Unknown waypoint type (%i)!\n",type); Waypoint_Delete(wPoint); return; } // [30/1/2013] Pathetic reordering... Ugh ~hogsy if(!wPoint->last) { wPoint->last = Waypoint_GetByVisibility(vOrigin); if(!wPoint->last) { Engine.Con_Warning("Failed to get another visible waypoint! (%i)\n",wPoint->number); return; } } else if(wPoint->last != wPoint && wPoint->last->next) wPoint->last->next = wPoint; #ifdef DEBUG_WAYPOINT wPoint->eDebug = Entity_Spawn(); if(wPoint->eDebug) { wPoint->eDebug->v.effects = EF_MOTION_ROTATE; Entity_SetModel(wPoint->eDebug,cModelName); Entity_SetSizeVector(wPoint->eDebug,g_mvOrigin3f,g_mvOrigin3f); Entity_SetOrigin(wPoint->eDebug,wPoint->position); } Engine.Con_DPrintf("Waypoint placed (%i %i %i)\n", (int)wPoint->position[0], (int)wPoint->position[1], (int)wPoint->position[2]); Engine.Con_DPrintf(" number: %i\n",wPoint->number); Engine.Con_DPrintf(" type: %i\n",wPoint->wType); #endif }
winding_t *BasePolyForPlane (plane_t *p) { int i, x; vec_t max, v; vec3_t org, vright, vup; winding_t *w; // find the major axis max = -BOGUS_RANGE; x = -1; for (i=0 ; i<3; i++) { v = fabs(p->normal[i]); if (v > max) { x = i; max = v; } } if (x==-1) Error("BasePolyForPlane: no axis found"); Math_VectorCopy(vec3_origin,vup); switch (x) { case 0: case 1: vup[2] = 1; break; case 2: vup[0] = 1; break; } v = Math_DotProduct(vup,p->normal); Math_VectorMA(vup,-v,p->normal,vup); Math_VectorNormalize(vup); Math_VectorScale(p->normal,p->dist,org); Math_CrossProduct(vup,p->normal,vright); Math_VectorScale(vup,8192,vup); Math_VectorScale(vright,8192,vright); // project a really big axis aligned box onto the plane w = NewWinding (4); Math_VectorSubtract(org,vright,w->points[0]); Math_VectorAdd(w->points[0],vup,w->points[0]); Math_VectorAdd(org,vright,w->points[1]); Math_VectorAdd(w->points[1],vup,w->points[1]); Math_VectorAdd(org,vright,w->points[2]); Math_VectorSubtract(w->points[2],vup,w->points[2]); Math_VectorSubtract(org,vright,w->points[3]); Math_VectorSubtract(w->points[3],vup,w->points[3]); w->numpoints = 4; return w; }
// [18/5/2013] TODO: Merge with SV_PushMove ~hogsy static void Server_PushRotate(edict_t *pusher,float movetime) { int i,e,num_moved,slaves_moved; edict_t *check,*block,*moved_edict[MAX_EDICTS],*ground,*slave,*master; vec3_t move,a,amove,entorig,pushorig,moved_from[MAX_EDICTS],org,org2,forward,right,up; bool bMoveIt; for (i = 0; i < 3; i++) amove[i] = pusher->v.avelocity[i] * movetime; Math_VectorNegate(amove,a); Math_AngleVectors(a,forward,right,up); Math_VectorCopy(pusher->v.angles,pushorig); // move the pusher to it's final position Math_VectorAdd(pusher->v.angles,amove,pusher->v.angles); pusher->v.ltime += movetime; SV_LinkEdict (pusher, false); slaves_moved = 0; master = pusher; while(master->v.aiment) { slave = PROG_TO_EDICT(master->v.aiment); slaves_moved++; Math_VectorCopy (slave->v.angles, moved_from[MAX_EDICTS - slaves_moved]); moved_edict[MAX_EDICTS - slaves_moved] = slave; if (slave->v.movedir[PITCH]) slave->v.angles[PITCH] = master->v.angles[PITCH]; else slave->v.angles[PITCH] += slave->v.avelocity[PITCH] * movetime; if (slave->v.movedir[YAW]) slave->v.angles[YAW] = master->v.angles[YAW]; else slave->v.angles[YAW] += slave->v.avelocity[YAW] * movetime; if (slave->v.movedir[ROLL]) slave->v.angles[ROLL] = master->v.angles[ROLL]; else slave->v.angles[ROLL] += slave->v.avelocity[ROLL] * movetime; slave->v.ltime = master->v.ltime; SV_LinkEdict(slave,false); master = slave; } // see if any solid entities are inside the final position num_moved = 0; check = NEXT_EDICT(sv.edicts); for (e = 1; e < sv.num_edicts; e++, check = NEXT_EDICT(check)) { if (check->free) continue; if (check->v.movetype == MOVETYPE_PUSH || check->v.movetype == MOVETYPE_NONE || check->v.movetype == MOVETYPE_NOCLIP) continue; // if the entity is standing on the pusher, it will definitely be moved bMoveIt = false; ground = check->v.groundentity; if(check->v.flags & FL_ONGROUND) { if (ground == pusher) bMoveIt = true; else { for (i = 0; i < slaves_moved; i++) { if (ground == moved_edict[MAX_EDICTS - i - 1]) { bMoveIt = true; break; } } } } if(!bMoveIt) { if( check->v.absmin[0] >= pusher->v.absmax[0] || check->v.absmin[1] >= pusher->v.absmax[1] || check->v.absmin[2] >= pusher->v.absmax[2] || check->v.absmax[0] <= pusher->v.absmin[0] || check->v.absmax[1] <= pusher->v.absmin[1] || check->v.absmax[2] <= pusher->v.absmin[2]) { for (i = 0; i < slaves_moved; i++) { slave = moved_edict[MAX_EDICTS-i-1]; if( check->v.absmin[0] >= slave->v.absmax[0] || check->v.absmin[1] >= slave->v.absmax[1] || check->v.absmin[2] >= slave->v.absmax[2] || check->v.absmax[0] <= slave->v.absmin[0] || check->v.absmax[1] <= slave->v.absmin[1] || check->v.absmax[2] <= slave->v.absmin[2] ) continue; } if (i == slaves_moved) continue; } // See if the ent's bbox is inside the pusher's final position if(!SV_TestEntityPosition(check)) continue; } // remove the onground flag for non-players if(check->v.movetype != MOVETYPE_WALK) check->v.flags = check->v.flags & ~FL_ONGROUND; Math_VectorCopy(check->v.origin,entorig); Math_VectorCopy(check->v.origin,moved_from[num_moved]); moved_edict[num_moved] = check; num_moved++; // calculate destination position Math_VectorSubtract(check->v.origin,pusher->v.origin,org); org2[0] = Math_DotProduct(org,forward); org2[1] = -Math_DotProduct(org,right); org2[2] = Math_DotProduct(org,up); Math_VectorSubtract (org2,org,move); // try moving the contacted entity pusher->Physics.iSolid = SOLID_NOT; SV_PushEntity (check, move); //@@TODO: do we ever want to do anybody's angles? maybe just yaw??? if(check->monster.iType != 1) { #if 0 vec3_t vYaw; vYaw[YAW] = Math_AngleMod(pusher->v.angles[YAW]+check->v.angles[YAW]); Con_Printf("%i %i\n",(int)check->v.angles[YAW],(int)vYaw[YAW]); //check->v.angles[YAW] = vYaw[YAW]; //check->v.angles[YAW] = Math_AngleMod(vYaw[YAW]); #endif // move back any entities we already moved for (i = 0; i < num_moved; i++) { Math_VectorAdd(moved_edict[i]->v.angles, amove, moved_edict[i]->v.angles); moved_edict[i]->v.angles[YAW] += amove[YAW]/2.0f; SV_LinkEdict(moved_edict[i],false); } } pusher->Physics.iSolid = SOLID_BSP; // If it is still inside the pusher, block block = SV_TestEntityPosition (check); if (block) { // fail the move if (check->v.mins[0] == check->v.maxs[0]) continue; if (check->Physics.iSolid == SOLID_NOT || check->Physics.iSolid == SOLID_TRIGGER) { // corpse check->v.mins[0] = check->v.mins[1] = 0; Math_VectorCopy(check->v.mins,check->v.maxs); continue; } Math_VectorCopy(entorig,check->v.origin); SV_LinkEdict(check,true); Math_VectorCopy(pushorig,pusher->v.angles); SV_LinkEdict(pusher,false); pusher->v.ltime -= movetime; for(i = 0; i < slaves_moved; i++) { slave = moved_edict[MAX_EDICTS - i - 1]; Math_VectorCopy(moved_from[MAX_EDICTS - i - 1], slave->v.angles); SV_LinkEdict(slave,false); slave->v.ltime -= movetime; } // if the pusher has a "blocked" function, call it // otherwise, just stay in place until the obstacle is gone if (pusher->v.blocked) pusher->v.blocked(pusher,check); // move back any entities we already moved for (i = 0; i < num_moved; i++) { Math_VectorCopy (moved_from[i], moved_edict[i]->v.origin); //@@TODO:: see above // if (!((int)moved_edict[i]->v.flags & (FL_CLIENT | FL_MONSTER))) Math_VectorSubtract (moved_edict[i]->v.angles, amove, moved_edict[i]->v.angles); moved_edict[i]->v.angles[YAW] -= amove[YAW]; SV_LinkEdict(moved_edict[i],false); } return; } } }
void Select_RotateAxis (int axis, float deg) { vec3_t temp; int i, j; vec_t c, s; if (deg == 0) return; Select_GetMid (select_origin); select_fliporder = FALSE; if (deg == 90) { for (i=0 ; i<3 ; i++) { Math_VectorCopy (vec3_origin, select_matrix[i]); select_matrix[i][i] = 1; } i = (axis+1)%3; j = (axis+2)%3; Math_VectorCopy(select_matrix[i],temp); Math_VectorCopy(select_matrix[j],select_matrix[i]); Math_VectorSubtract(vec3_origin,temp,select_matrix[j]); } else { deg = -deg; if (deg == -180) { c = -1; s = 0; } else if (deg == -270) { c = 0; s = -1; } else { c = cos(deg/180*3.14159); s = sin (deg/180*3.14159); } for (i=0 ; i<3 ; i++) { Math_VectorCopy (vec3_origin, select_matrix[i]); select_matrix[i][i] = 1; } switch (axis) { case 0: select_matrix[1][1] = c; select_matrix[1][2] = -s; select_matrix[2][1] = s; select_matrix[2][2] = c; break; case 1: select_matrix[0][0] = c; select_matrix[0][2] = s; select_matrix[2][0] = -s; select_matrix[2][2] = c; break; case 2: select_matrix[0][0] = c; select_matrix[0][1] = -s; select_matrix[1][0] = s; select_matrix[1][1] = c; break; } } Select_AplyMatrix (); }
void Sky_ProcessEntities(void) { int i,k,mark; unsigned int j; float dot; bool bRotated; ClientEntity_t *e; msurface_t *s; glpoly_t *p; MathVector3f_t vTemp, forward, right, up; if (!r_drawentities.value) return; for (i=0 ; i<cl_numvisedicts ; i++) { e = cl_visedicts[i]; if (e->model->type != MODEL_TYPE_LEVEL) continue; if(R_CullModelForEntity(e)) continue; if(e->alpha == ENTALPHA_ZERO) continue; Math_VectorSubtract (r_refdef.vieworg, e->origin, modelorg); if(e->angles[0] || e->angles[1] || e->angles[2]) { bRotated = true; Math_AngleVectors(e->angles, forward, right, up); Math_VectorCopy(modelorg,vTemp); modelorg[0] = Math_DotProduct(vTemp,forward); modelorg[1] = -Math_DotProduct(vTemp,right); modelorg[2] = Math_DotProduct(vTemp,up); } else bRotated = false; s = &e->model->surfaces[e->model->firstmodelsurface]; for (j=0 ; j<e->model->nummodelsurfaces ; j++, s++) { if (s->flags & SURF_DRAWSKY) { dot = Math_DotProduct (modelorg, s->plane->normal) - s->plane->dist; if (((s->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || (!(s->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { //copy the polygon and translate manually, since Sky_ProcessPoly needs it to be in world space mark = Hunk_LowMark(); p = (glpoly_t*)Hunk_Alloc (sizeof(*s->polys)); //FIXME: don't allocate for each poly p->numverts = s->polys->numverts; for (k=0; k<p->numverts; k++) { if(bRotated) { p->verts[k][0] = e->origin[0] + s->polys->verts[k][0] * forward[0] - s->polys->verts[k][1] * right[0] + s->polys->verts[k][2] * up[0]; p->verts[k][1] = e->origin[1] + s->polys->verts[k][0] * forward[1] - s->polys->verts[k][1] * right[1] + s->polys->verts[k][2] * up[1]; p->verts[k][2] = e->origin[2] + s->polys->verts[k][0] * forward[2] - s->polys->verts[k][1] * right[2] + s->polys->verts[k][2] * up[2]; } else Math_VectorAdd(s->polys->verts[k], e->origin, p->verts[k]); } Sky_ProcessPoly (p); Hunk_FreeToLowMark (mark); } } } } }
void Bot_Think(edict_t *eBot) { // If the bot isn't dead, then add animations. if(eBot->monster.iState != STATE_DEAD) { if(eBot->v.flags & FL_ONGROUND) { if(( (eBot->v.velocity[0] < -4.0f || eBot->v.velocity[0] > 4.0f) || (eBot->v.velocity[1] < -4.0f || eBot->v.velocity[1] > 4.0f)) && (!eBot->local.dAnimationTime || eBot->local.iAnimationEnd == 9)) Entity_Animate(eBot,PlayerAnimation_Walk); else if((eBot->v.velocity[0] == 0 || eBot->v.velocity[1] == 0) && (!eBot->local.dAnimationTime || eBot->local.iAnimationEnd > 9)) { #ifdef GAME_OPENKATANA if(eBot->v.iActiveWeapon == WEAPON_DAIKATANA) Entity_Animate(eBot,PlayerAnimation_KatanaIdle); else #endif Entity_Animate(eBot,PlayerAnimation_Idle); } } } switch(eBot->monster.iThink) { case THINK_IDLE: #if 1 // Add some random movement. ~hogsy if(rand()%120 == 0) { int iResult = rand()%3; if(iResult == 0) eBot->v.velocity[0] += BOT_MIN_SPEED; else if(iResult == 1) eBot->v.velocity[0] -= BOT_MIN_SPEED; iResult = rand()%3; if(iResult == 0) eBot->v.velocity[1] += BOT_MIN_SPEED; else if(iResult == 1) eBot->v.velocity[1] -= BOT_MIN_SPEED; eBot->v.angles[1] = Math_VectorToYaw(eBot->v.velocity); } else if(rand()%150 == 0) { Monster_Jump(eBot,200.0f); Entity_Animate(eBot,PlayerAnimation_Jump); } #endif break; case THINK_WANDERING: { edict_t *eTarget; Waypoint_t *wPoint; // Weapon_t *wMyWeapon; // vec3_t vAngle; eTarget = Monster_GetTarget(eBot); if(eTarget) { if(Monster_GetRelationship(eBot,eTarget) == RELATIONSHIP_HATE) { // [22/3/2013] Begin attacking next frame ~hogsy Monster_SetThink(eBot,THINK_ATTACKING); return; } } if(!eBot->monster.vTarget) { // [28/7/2012] TODO: Find specific waypoint such as an item ~hogsy wPoint = Waypoint_GetByVisibility(eBot->v.origin); if(wPoint) { if(wPoint->bOpen) { // [22/3/2013] TODO: Tell that current entity it's time to move... ~hogsy } Math_VectorCopy(wPoint->position,eBot->monster.vTarget); } } #if 0 wMyWeapon = Weapon_GetCurrentWeapon(eBot); if(MONSTER_GetRange(eBot,eBot->v.enemy->v.origin) > 4000) return; else if(wMyWeapon->iPrimaryType == AM_MELEE && MONSTER_GetRange(eBot,eBot->v.enemy->v.origin) > MONSTER_RANGE_MELEE) return; else if(Monster_IsVisible(eBot,eBot->v.enemy)) { // [5/8/2012] No ammo and it's not a melee weapon? ~hogsy if(!Weapon_CheckPrimaryAmmo(eBot) && wMyWeapon->iPrimaryType != AM_MELEE) { // [5/8/2012] Should probably flee ~hogsy Monster_SetThink(eBot,THINK_FLEEING); return; } Math_VectorSubtract(eBot->v.enemy->v.origin,eBot->v.origin,vAngle); // ent->v.ideal_yaw = VectorToAngles(vAngle); ChangeYaw(eBot); } #endif } break; } }