/* ================ DialogAFConstraintHinge::SaveConstraint ================ */ void DialogAFConstraintHinge::SaveConstraint( void ) { int s1, s2; CString str; if ( !file || !constraint ) { return; } UpdateData( TRUE ); // save anchor to the current idDeclAF_Constraint GetSafeComboBoxSelection( &m_comboAnchorJoint, str, -1 ); constraint->anchor.joint1 = str; constraint->anchor.ToVec3().x = m_anchor_x; constraint->anchor.ToVec3().y = m_anchor_y; constraint->anchor.ToVec3().z = m_anchor_z; // hinge axis if ( constraint->axis.type == idAFVector::VEC_BONEDIR ) { s1 = GetSafeComboBoxSelection( &m_comboAxisJoint1, str, -1 ); constraint->axis.joint1 = str; s2 = GetSafeComboBoxSelection( &m_comboAxisJoint2, str, s1 ); constraint->axis.joint2 = str; } else { constraint->axis.ToVec3() = idAngles( m_axisPitch, m_axisYaw, 0.0f ).ToForward(); } // hinge limit constraint->limitAngles[0] = m_limitAngle1; constraint->limitAngles[1] = m_limitAngle2; constraint->limitAngles[2] = m_limitAngle3; AFDialogSetFileModified(); }
/* ============ idAASBuild::AddBrushesForMapEntity ============ */ idBrushList idAASBuild::AddBrushesForMapEntity( const idMapEntity *mapEnt, int entityNum, idBrushList brushList ) { int i; idVec3 origin; idMat3 axis; if( mapEnt->GetNumPrimitives() < 1 ) { return brushList; } mapEnt->epairs.GetVector( "origin", "0 0 0", origin ); if( !mapEnt->epairs.GetMatrix( "rotation", "1 0 0 0 1 0 0 0 1", axis ) ) { float angle = mapEnt->epairs.GetFloat( "angle" ); if( angle != 0.0f ) { axis = idAngles( 0.0f, angle, 0.0f ).ToMat3(); } else { axis.Identity(); } } for( i = 0; i < mapEnt->GetNumPrimitives(); i++ ) { idMapPrimitive *mapPrim; mapPrim = mapEnt->GetPrimitive( i ); if( mapPrim->GetType() == idMapPrimitive::TYPE_BRUSH ) { brushList = AddBrushesForMapBrush( static_cast<idMapBrush *>( mapPrim ), origin, axis, entityNum, i, brushList ); continue; } if( mapPrim->GetType() == idMapPrimitive::TYPE_PATCH ) { if( aasSettings->usePatches ) { brushList = AddBrushesForMapPatch( static_cast<idMapPatch *>( mapPrim ), origin, axis, entityNum, i, brushList ); } continue; } } return brushList; }
/* ============= idVec3::ToAngles ============= */ idAngles idVec3::ToAngles( void ) const { float forward; float yaw; float pitch; if ( ( x == 0.0f ) && ( y == 0.0f ) ) { yaw = 0.0f; if ( z > 0.0f ) { pitch = 90.0f; } else { pitch = 270.0f; } } else { yaw = RAD2DEG( idMath::ATan( y, x ) ); if ( yaw < 0.0f ) { yaw += 360.0f; } forward = ( float )idMath::Sqrt( x * x + y * y ); pitch = RAD2DEG( idMath::ATan( z, forward ) ); if ( pitch < 0.0f ) { pitch += 360.0f; } } return idAngles( -pitch, yaw, 0.0f ); }
/* ================ idTarget_EndLevel::Draw ================ */ void idTarget_EndLevel::Draw() { if (noGui) { return; } renderView_t renderView; memset( &renderView, 0, sizeof( renderView ) ); renderView.width = SCREEN_WIDTH; renderView.height = SCREEN_HEIGHT; renderView.x = 0; renderView.y = 0; renderView.fov_x = 90; renderView.fov_y = gameLocal.CalcFovY( renderView.fov_x ); renderView.time = gameLocal.time; #if 0 renderView.vieworg = initialViewOrg; renderView.viewaxis = idAngles(initialViewAngles).toMat3(); #else renderView.vieworg = renderEntity.origin; renderView.viewaxis = renderEntity.axis; #endif gameRenderWorld->RenderScene( &renderView ); // draw the gui on top of the 3D view gui->Redraw(gameLocal.time); }
void CDialogSound::OnBtnDrop() { idStr classname; idStr key; idStr value; idVec3 org; idDict args; idAngles viewAngles; gameEdit->PlayerGetViewAngles( viewAngles ); gameEdit->PlayerGetEyePosition( org ); org += idAngles( 0, viewAngles.yaw, 0 ).ToForward() * 80 + idVec3( 0, 0, 1 ); args.Set("origin", org.ToString()); args.Set("classname", "speaker"); args.Set("angle", va( "%f", viewAngles.yaw + 180 )); args.Set("s_shader", strShader); args.Set("s_looping", "1" ); args.Set("s_shakes", "0" ); idStr name = gameEdit->GetUniqueEntityName( "speaker" ); bool nameValid = false; while (!nameValid) { DialogName dlg("Name Speaker", this); dlg.m_strName = name; if (dlg.DoModal() == IDOK) { idEntity *gameEnt = gameEdit->FindEntity(dlg.m_strName); if (gameEnt) { if (MessageBox("Please choose another name", "Duplicate Entity Name!", MB_OKCANCEL) == IDCANCEL) { return; } } else { nameValid = true; name = dlg.m_strName; } } } args.Set("name", name.c_str()); idEntity *ent = NULL; gameEdit->SpawnEntityDef( args, &ent ); if (ent) { gameEdit->EntityUpdateChangeableSpawnArgs( ent, NULL ); gameEdit->ClearEntitySelection(); gameEdit->AddSelectedEntity( ent ); } gameEdit->MapAddEntity( &args ); const idDict *dict = gameEdit->MapGetEntityDict( args.GetString( "name" ) ); Set( dict ); AddGroups(); AddSpeakers(); }
idAngles Aimbot::Main( float fov, float ping, bool humanize, float smoothMultiplier, float smoothTransposition ) { #define FRAME_TIME_SECONDS 0.008f Ping = ping; FOV = fov; _Muzzle = ImportExport::User->EyePosition() + ImportExport::User->ViewAngles().ToMat3()[0]*14.0f + EvaluatePath(idVec3(0,0,0), ImportExport::User->Velocity(), FRAME_TIME_SECONDS); if ( ScanForTarget() ) { idAngles angles = AimAt( TargetOrigin() ); return humanize ? Humanize( smoothMultiplier, smoothTransposition, angles ) : angles; } return idAngles(0, 0, 0); }
/* ================ DialogAFConstraintBallAndSocket::SaveConstraint ================ */ void DialogAFConstraintBallAndSocket::SaveConstraint( void ) { int s1, s2; CString str; idAngles angles; if ( !file || !constraint ) { return; } UpdateData( TRUE ); // anchor GetSafeComboBoxSelection( &m_comboAnchorJoint, str, -1 ); constraint->anchor.joint1 = str; constraint->anchor.ToVec3().x = m_anchor_x; constraint->anchor.ToVec3().y = m_anchor_y; constraint->anchor.ToVec3().z = m_anchor_z; // limit if ( constraint->limit == idDeclAF_Constraint::LIMIT_CONE ) { constraint->limitAngles[0] = m_coneAngle; } else { constraint->limitAngles[0] = m_pyramidAngle1; } constraint->limitAngles[1] = m_pyramidAngle2; constraint->limitAngles[2] = m_limitRoll; angles.pitch = m_limitPitch; angles.yaw = m_limitYaw; angles.roll = 0.0f; constraint->limitAxis.ToVec3() = angles.ToForward(); s1 = GetSafeComboBoxSelection( &m_comboLimitJoint1, str, -1 ); constraint->limitAxis.joint1 = str; s2 = GetSafeComboBoxSelection( &m_comboLimitJoint2, str, s1 ); constraint->limitAxis.joint2 = str; // limit axis if ( constraint->shaft[0].type == idAFVector::VEC_BONEDIR ) { s1 = GetSafeComboBoxSelection( &m_comboLimitAxisJoint1, str, -1 ); constraint->shaft[0].joint1 = str; s2 = GetSafeComboBoxSelection( &m_comboLimitAxisJoint2, str, s1 ); constraint->shaft[0].joint2 = str; } else { constraint->shaft[0].ToVec3() = idAngles( m_limitAxisPitch, m_limitAxisYaw, 0.0f ).ToForward(); } AFDialogSetFileModified(); }
void idRenderWindow::Render( int time ) { rLight.origin = lightOrigin.ToVec3(); rLight.shaderParms[SHADERPARM_RED] = lightColor.x(); rLight.shaderParms[SHADERPARM_GREEN] = lightColor.y(); rLight.shaderParms[SHADERPARM_BLUE] = lightColor.z(); world->UpdateLightDef(lightDef, &rLight); if ( worldEntity.hModel ) { if (updateAnimation) { BuildAnimation(time); } if (modelAnim) { if (time > animEndTime) { animEndTime = time + animLength; } gameEdit->ANIM_CreateAnimFrame(worldEntity.hModel, modelAnim, worldEntity.numJoints, worldEntity.joints, animLength - (animEndTime - time), vec3_origin, false ); } worldEntity.axis = idAngles(modelRotate.x(), modelRotate.y(), modelRotate.z()).ToMat3(); world->UpdateEntityDef(modelDef, &worldEntity); } }
END_CLASS void idEntity_Leaf::Spawn() { liveTime = spawnArgs.GetFloat( "leaf_liveTime" ); // in seconds. Keep this low to prevent too many leaves in the map at a time. each leaf is an entity! Try to make each leaf live at least until it touches the ground. Some leaves will slide along the ground if they live long enough. default: 8 moveSpeed = spawnArgs.GetFloat( "leaf_moveSpeed" ); // from 1-10. How fast the leaves move regardless of wind. Keep this high. default: 10 spread = spawnArgs.GetFloat( "leaf_spread" ); // from 1-10. Affects how far apart leafs speread apart when falling. default: 10 windPower = spawnArgs.GetFloat( "leaf_windPower" ); // from 1-10. How strong the wind is on the leaves. default: 1 windDir = spawnArgs.GetVector( "leaf_windDir" ); // Wind direction. default: '0 1 0' gravity = spawnArgs.GetVector( "leaf_gravity" ); // Gravity of the leaf. Keep this pretty low, or accept the default. default: '0 0 -20' origin = spawnArgs.GetVector( "leaf_origin" ); ang = GetAngles(); dieTime = gameLocal.time + liveTime * 1000; if( moveSpeed == 0 ) { moveSpeed = 1; } if( origin != idVec3( 0, 0, 0 ) ) { SetOrigin( origin ); } spread = spread / 20; //max spread is 0.5 dir = gameLocal.random.RandomInt( 3 ); if( dir < 1 ) { spreadX = spread; } else if( dir < 2 && dir > 1 ) { spreadX = 0; } else { spreadX = -spread; } dir = gameLocal.random.RandomInt( 3 ); if( dir < 1 ) { spreadY = spread; } else if( dir < 2 && dir > 1 ) { spreadY = 0; } else { spreadY = -spread; } SetAngles( idAngles( gameLocal.random.CRandomFloat() * 360, gameLocal.random.CRandomFloat() * 360, gameLocal.random.CRandomFloat() * 360 ) ); GetPhysics()->SetLinearVelocity( idVec3( 0, 0, 0 ) ); GetPhysics()->SetGravity( idVec3( 0, 0, 0 ) ); //gravity - if we set zero gravity, the leaves stop when they hit the ground. dont know why, but it's cool! curVel = GetPhysics()->GetLinearVelocity(); nextAngles = 0; }
/* ============ idAASLocal::ShowFloorTrace ============ */ void idAASLocal::ShowFloorTrace( const idVec3 &origin ) const { idPlayer *player; player = gameLocal.GetLocalPlayer(); if ( !player ) { return; } idMat3 playerAxis = idAngles( 0.0f, player->GetViewAngles().yaw, 0.0f ).ToMat3(); idVec3 org = origin; int areaNum = PointReachableAreaNum( org, DefaultSearchBounds(), AAS_AREA_REACHABLE_WALK, TravelFlagInvalidForTeam() ); PushPointIntoArea( areaNum, org ); aasTraceFloor_t trace; TraceFloor( trace, org, areaNum, origin + playerAxis[0] * 1024, TFL_WALK|TFL_AIR ); gameRenderWorld->DebugArrow( colorCyan, org, trace.endpos, 1, 0 ); idVec3 up = trace.endpos + playerAxis[2] * 64; const idVec4 &color = ( trace.fraction >= 1.0f ) ? colorGreen : colorRed; gameRenderWorld->DebugArrow( color, trace.endpos, up + playerAxis[1] * 32, 1, 0, true ); gameRenderWorld->DebugArrow( color, trace.endpos, up - playerAxis[1] * 32, 1, 0, true ); }
/* ================ DialogAFConstraintSlider::SaveConstraint ================ */ void DialogAFConstraintSlider::SaveConstraint( void ) { int s1, s2; CString str; if ( !file || !constraint ) { return; } UpdateData( TRUE ); // slider axis if ( constraint->axis.type == idAFVector::VEC_BONEDIR ) { s1 = GetSafeComboBoxSelection( &m_comboAxisJoint1, str, -1 ); constraint->axis.joint1 = str; s2 = GetSafeComboBoxSelection( &m_comboAxisJoint2, str, s1 ); constraint->axis.joint2 = str; } else { constraint->axis.ToVec3() = idAngles( m_axisPitch, m_axisYaw, 0.0f ).ToForward(); } AFDialogSetFileModified(); }
void idGLDrawableModel::draw(int x, int y, int w, int h) { if ( !worldModel ) { return; } if ( worldModel->IsDynamicModel() != DM_STATIC ) { //return; } rect.Set( x, y, w, h ); qglViewport(x, y, w, h); qglScissor(x, y, w, h); qglMatrixMode(GL_PROJECTION); qglClearColor( 0.1f, 0.1f, 0.1f, 0.0f ); qglClear(GL_COLOR_BUFFER_BIT); if (worldDirty) { //InitWorld(); world->InitFromMap( NULL ); renderLight_t parms; idDict spawnArgs; spawnArgs.Set("classname", "light"); spawnArgs.Set("name", "light_1"); spawnArgs.Set("origin", "-128 0 0"); idStr str; sprintf(str, "%f %f %f", light, light, light); spawnArgs.Set("_color", str); gameEdit->ParseSpawnArgsToRenderLight( &spawnArgs, &parms ); lightDef = world->AddLightDef( &parms ); renderEntity_t worldEntity; memset( &worldEntity, 0, sizeof( worldEntity ) ); spawnArgs.Clear(); spawnArgs.Set("classname", "func_static"); spawnArgs.Set("name", spawnArgs.GetString("model")); spawnArgs.Set("origin", "0 0 0"); if ( skinStr.Length() ) { spawnArgs.Set( "skin", skinStr ); } gameEdit->ParseSpawnArgsToRenderEntity(&spawnArgs, &worldEntity); worldEntity.hModel = worldModel; worldEntity.axis = rotation.ToMat3(); worldEntity.shaderParms[0] = 1; worldEntity.shaderParms[1] = 1; worldEntity.shaderParms[2] = 1; worldEntity.shaderParms[3] = 1; modelDef = world->AddEntityDef( &worldEntity ); worldDirty = false; } renderView_t refdef; // render it renderSystem->BeginFrame(w, h); memset( &refdef, 0, sizeof( refdef ) ); refdef.vieworg.Set(zOffset, xOffset, -yOffset); refdef.viewaxis = idAngles(0,0,0).ToMat3(); refdef.shaderParms[0] = 1; refdef.shaderParms[1] = 1; refdef.shaderParms[2] = 1; refdef.shaderParms[3] = 1; refdef.width = SCREEN_WIDTH; refdef.height = SCREEN_HEIGHT; refdef.fov_x = 90; refdef.fov_y = 2 * atan((float)h / w) * idMath::M_RAD2DEG; refdef.time = eventLoop->Milliseconds(); world->RenderScene( &refdef ); int frontEnd, backEnd; renderSystem->EndFrame( &frontEnd, &backEnd ); qglMatrixMode( GL_MODELVIEW ); qglLoadIdentity(); }
void idGLDrawableMaterial::draw(int x, int y, int w, int h) { const idMaterial *mat = material; if (mat) { qglViewport(x, y, w, h); qglScissor(x, y, w, h); qglMatrixMode(GL_PROJECTION); qglClearColor( 0.1f, 0.1f, 0.1f, 0.0f ); qglClear(GL_COLOR_BUFFER_BIT); if (worldDirty) { InitWorld(); renderLight_t parms; idDict spawnArgs; spawnArgs.Set("classname", "light"); spawnArgs.Set("name", "light_1"); spawnArgs.Set("origin", "0 0 0"); idStr str; sprintf(str, "%f %f %f", light, light, light); spawnArgs.Set("_color", str); gameEdit->ParseSpawnArgsToRenderLight( &spawnArgs, &parms ); lightDef = world->AddLightDef( &parms ); idImage *img = (mat->GetNumStages() > 0) ? mat->GetStage(0)->texture.image : mat->GetEditorImage(); if (img == NULL) { common->Warning("Unable to load image for preview for %s", mat->GetName()); return; } int width = img->uploadWidth; int height = img->uploadHeight; width *= scale; height *= scale; srfTriangles_t *tris = worldModel->AllocSurfaceTriangles( 4, 6 ); tris->numVerts = 4; tris->numIndexes = 6; tris->indexes[0] = 0; tris->indexes[1] = 1; tris->indexes[2] = 2; tris->indexes[3] = 3; tris->indexes[4] = 1; tris->indexes[5] = 0; tris->verts[0].xyz.x = 64; tris->verts[0].xyz.y = -xOffset + 0 - width / 2; tris->verts[0].xyz.z = yOffset + 0 - height / 2; tris->verts[0].st.x = 1; tris->verts[0].st.y = 1; tris->verts[1].xyz.x = 64; tris->verts[1].xyz.y = -xOffset + width / 2; tris->verts[1].xyz.z = yOffset + height / 2; tris->verts[1].st.x = 0; tris->verts[1].st.y = 0; tris->verts[2].xyz.x = 64; tris->verts[2].xyz.y = -xOffset + 0 - width / 2; tris->verts[2].xyz.z = yOffset + height / 2; tris->verts[2].st.x = 1; tris->verts[2].st.y = 0; tris->verts[3].xyz.x = 64; tris->verts[3].xyz.y = -xOffset + width / 2; tris->verts[3].xyz.z = yOffset + 0 - height / 2; tris->verts[3].st.x = 0; tris->verts[3].st.y = 1; tris->verts[0].normal = tris->verts[1].xyz.Cross(tris->verts[3].xyz); tris->verts[1].normal = tris->verts[2].normal = tris->verts[3].normal = tris->verts[0].normal; AddTris(tris, mat); worldModel->FinishSurfaces(); renderEntity_t worldEntity; memset( &worldEntity, 0, sizeof( worldEntity ) ); if ( mat->HasGui() ) { worldEntity.gui[ 0 ] = mat->GlobalGui(); } worldEntity.hModel = worldModel; worldEntity.axis = mat3_default; worldEntity.shaderParms[0] = 1; worldEntity.shaderParms[1] = 1; worldEntity.shaderParms[2] = 1; worldEntity.shaderParms[3] = 1; modelDef = world->AddEntityDef( &worldEntity ); worldDirty = false; } renderView_t refdef; // render it renderSystem->BeginFrame(w, h); memset( &refdef, 0, sizeof( refdef ) ); refdef.vieworg.Set(viewAngle, 0, 0); refdef.viewaxis = idAngles(0,0,0).ToMat3(); refdef.shaderParms[0] = 1; refdef.shaderParms[1] = 1; refdef.shaderParms[2] = 1; refdef.shaderParms[3] = 1; refdef.width = SCREEN_WIDTH; refdef.height = SCREEN_HEIGHT; refdef.fov_x = 90; refdef.fov_y = 2 * atan((float)h / w) * idMath::M_RAD2DEG; refdef.time = eventLoop->Milliseconds(); world->RenderScene( &refdef ); int frontEnd, backEnd; renderSystem->EndFrame( &frontEnd, &backEnd ); qglMatrixMode( GL_MODELVIEW ); qglLoadIdentity(); } }
/* ================== FixGlobalTjunctions ================== */ void FixGlobalTjunctions( uEntity_t *e ) { mapTri_t *a; int vert; int i; optimizeGroup_t *group; int areaNum; common->Printf( "----- FixGlobalTjunctions -----\n" ); // clear the hash tables memset( hashVerts, 0, sizeof( hashVerts ) ); numHashVerts = 0; numTotalVerts = 0; // bound all the triangles to determine the bucket size hashBounds.Clear(); for ( areaNum = 0 ; areaNum < e->numAreas ; areaNum++ ) { for ( group = e->areas[areaNum].groups ; group ; group = group->nextGroup ) { for ( a = group->triList ; a ; a = a->next ) { hashBounds.AddPoint( a->v[0].xyz ); hashBounds.AddPoint( a->v[1].xyz ); hashBounds.AddPoint( a->v[2].xyz ); } } } // spread the bounds so it will never have a zero size for ( i = 0 ; i < 3 ; i++ ) { hashBounds[0][i] = floor( hashBounds[0][i] - 1 ); hashBounds[1][i] = ceil( hashBounds[1][i] + 1 ); hashIntMins[i] = hashBounds[0][i] * SNAP_FRACTIONS; hashScale[i] = ( hashBounds[1][i] - hashBounds[0][i] ) / HASH_BINS; hashIntScale[i] = hashScale[i] * SNAP_FRACTIONS; if ( hashIntScale[i] < 1 ) { hashIntScale[i] = 1; } } // add all the points to the hash buckets for ( areaNum = 0 ; areaNum < e->numAreas ; areaNum++ ) { for ( group = e->areas[areaNum].groups ; group ; group = group->nextGroup ) { // don't touch discrete surfaces if ( group->material != NULL && group->material->IsDiscrete() ) { continue; } for ( a = group->triList ; a ; a = a->next ) { for ( vert = 0 ; vert < 3 ; vert++ ) { a->hashVert[vert] = GetHashVert( a->v[vert].xyz ); } } } } // add all the func_static model vertexes to the hash buckets // optionally inline some of the func_static models if ( dmapGlobals.entityNum == 0 ) { for ( int eNum = 1 ; eNum < dmapGlobals.num_entities ; eNum++ ) { uEntity_t *entity = &dmapGlobals.uEntities[eNum]; const char *className = entity->mapEntity->epairs.GetString( "classname" ); if ( idStr::Icmp( className, "func_static" ) ) { continue; } const char *modelName = entity->mapEntity->epairs.GetString( "model" ); if ( !modelName ) { continue; } if ( !strstr( modelName, ".lwo" ) && !strstr( modelName, ".ase" ) && !strstr( modelName, ".ma" ) ) { continue; } idRenderModel *model = renderModelManager->FindModel( modelName ); // common->Printf( "adding T junction verts for %s.\n", entity->mapEntity->epairs.GetString( "name" ) ); idMat3 axis; // get the rotation matrix in either full form, or single angle form if ( !entity->mapEntity->epairs.GetMatrix( "rotation", "1 0 0 0 1 0 0 0 1", axis ) ) { float angle = entity->mapEntity->epairs.GetFloat( "angle" ); if ( angle != 0.0f ) { axis = idAngles( 0.0f, angle, 0.0f ).ToMat3(); } else { axis.Identity(); } } idVec3 origin = entity->mapEntity->epairs.GetVector( "origin" ); for ( i = 0 ; i < model->NumSurfaces() ; i++ ) { const modelSurface_t *surface = model->Surface( i ); const srfTriangles_t *tri = surface->geometry; mapTri_t mapTri; memset( &mapTri, 0, sizeof( mapTri ) ); mapTri.material = surface->shader; // don't let discretes (autosprites, etc) merge together if ( mapTri.material->IsDiscrete() ) { mapTri.mergeGroup = (void *)surface; } for ( int j = 0 ; j < tri->numVerts ; j += 3 ) { idVec3 v = tri->verts[j].xyz * axis + origin; GetHashVert( v ); } } } } // now fix each area for ( areaNum = 0 ; areaNum < e->numAreas ; areaNum++ ) { for ( group = e->areas[areaNum].groups ; group ; group = group->nextGroup ) { // don't touch discrete surfaces if ( group->material != NULL && group->material->IsDiscrete() ) { continue; } mapTri_t *newList = NULL; for ( mapTri_t *tri = group->triList ; tri ; tri = tri->next ) { mapTri_t *fixed = FixTriangleAgainstHash( tri ); newList = MergeTriLists( newList, fixed ); } FreeTriList( group->triList ); group->triList = newList; } } // done FreeTJunctionHash(); }
stateResult_t rvMonsterStroggHover::State_DeathSpiral ( const stateParms_t& parms ) { enum { STAGE_INIT, STAGE_SPIRAL }; switch ( parms.stage ) { case STAGE_INIT: { disablePain = true; // Make sure all animation and attack states stop StopAnimState ( ANIMCHANNEL_TORSO ); StopAnimState ( ANIMCHANNEL_LEGS ); // Start the crash & burn effects for ( int i = 0; i < numHoverJoints; i++ ) { if ( jointHover[i] != INVALID_JOINT ) { PlayEffect ( "fx_hurt", jointHover[i], false ); effectHover[i] = PlayEffect ( "fx_crash", jointHover[i], true ); } } deathPitch = viewAxis.ToAngles()[0]; deathRoll = viewAxis.ToAngles()[2]; deathPitchRate = gameLocal.random.RandomFloat()*0.3f + 0.1f; deathYawRate = gameLocal.random.RandomFloat()*2.0f + 1.5f; deathRollRate = gameLocal.random.RandomFloat()*3.0f + 1.0f; deathSpeed = gameLocal.random.RandomFloat()*300.0f + 500.0f; deathGrav = gameLocal.random.RandomFloat()*6.0f + 6.0f; strafeRight = (gameLocal.random.RandomFloat()>0.5f); StopSound( SND_CHANNEL_HEART, false ); StartSound ( "snd_crash", SND_CHANNEL_HEART, 0, false, NULL ); } return SRESULT_STAGE ( STAGE_SPIRAL ); case STAGE_SPIRAL: { move.current_yaw += (strafeRight?-deathYawRate:deathYawRate); deathPitch = idMath::ClampFloat( -90.0f, 90.0f, deathPitch+deathPitchRate ); deathRoll += (strafeRight?deathRollRate:-deathRollRate); viewAxis = idAngles( deathPitch, move.current_yaw, deathRoll ).ToMat3(); idVec3 vel = GetPhysics()->GetLinearVelocity(); idVec3 strafeVel = viewAxis[0] * deathSpeed; strafeVel.z = 0; vel += strafeVel; vel.Normalize(); vel *= deathSpeed; vel += GetPhysics()->GetGravity()/deathGrav; physicsObj.UseVelocityMove( true ); physicsObj.SetLinearVelocity( vel ); idSoundEmitter *emitter = soundSystem->EmitterForIndex( SOUNDWORLD_GAME, refSound.referenceSoundHandle ); if( emitter ) { refSound.parms.frequencyShift += 0.025f; emitter->ModifySound ( SND_CHANNEL_HEART, &refSound.parms ); } } return SRESULT_WAIT; } return SRESULT_ERROR; }
/* ================ idTestModel::Think ================ */ void idTestModel::Think() { idVec3 pos; idMat3 axis; idAngles ang; int i; if( thinkFlags & TH_THINK ) { if( anim && ( gameLocal.testmodel == this ) && ( mode != g_testModelAnimate.GetInteger() ) ) { StopSound( SND_CHANNEL_ANY, false ); if( head.GetEntity() ) { head.GetEntity()->StopSound( SND_CHANNEL_ANY, false ); } switch( g_testModelAnimate.GetInteger() ) { default: case 0: // cycle anim with origin reset if( animator.NumFrames( anim ) <= 1 ) { // single frame animations end immediately, so just cycle it since it's the same result animator.CycleAnim( ANIMCHANNEL_ALL, anim, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) ); if( headAnim ) { headAnimator->CycleAnim( ANIMCHANNEL_ALL, headAnim, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) ); } } else { animator.PlayAnim( ANIMCHANNEL_ALL, anim, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) ); if( headAnim ) { headAnimator->PlayAnim( ANIMCHANNEL_ALL, headAnim, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) ); if( headAnimator->AnimLength( headAnim ) > animator.AnimLength( anim ) ) { // loop the body anim when the head anim is longer animator.CurrentAnim( ANIMCHANNEL_ALL )->SetCycleCount( -1 ); } } } animator.RemoveOriginOffset( false ); break; case 1: // cycle anim with fixed origin animator.CycleAnim( ANIMCHANNEL_ALL, anim, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) ); animator.RemoveOriginOffset( true ); if( headAnim ) { headAnimator->CycleAnim( ANIMCHANNEL_ALL, headAnim, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) ); } break; case 2: // cycle anim with continuous origin animator.CycleAnim( ANIMCHANNEL_ALL, anim, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) ); animator.RemoveOriginOffset( false ); if( headAnim ) { headAnimator->CycleAnim( ANIMCHANNEL_ALL, headAnim, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) ); } break; case 3: // frame by frame with continuous origin animator.SetFrame( ANIMCHANNEL_ALL, anim, frame, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) ); animator.RemoveOriginOffset( false ); if( headAnim ) { headAnimator->SetFrame( ANIMCHANNEL_ALL, headAnim, frame, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) ); } break; case 4: // play anim once animator.PlayAnim( ANIMCHANNEL_ALL, anim, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) ); animator.RemoveOriginOffset( false ); if( headAnim ) { headAnimator->PlayAnim( ANIMCHANNEL_ALL, headAnim, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) ); } break; case 5: // frame by frame with fixed origin animator.SetFrame( ANIMCHANNEL_ALL, anim, frame, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) ); animator.RemoveOriginOffset( true ); if( headAnim ) { headAnimator->SetFrame( ANIMCHANNEL_ALL, headAnim, frame, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) ); } break; } mode = g_testModelAnimate.GetInteger(); } if( ( mode == 0 ) && ( gameLocal.time >= starttime + animtime ) ) { starttime = gameLocal.time; StopSound( SND_CHANNEL_ANY, false ); animator.PlayAnim( ANIMCHANNEL_ALL, anim, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) ); if( headAnim ) { headAnimator->PlayAnim( ANIMCHANNEL_ALL, headAnim, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) ); if( headAnimator->AnimLength( headAnim ) > animator.AnimLength( anim ) ) { // loop the body anim when the head anim is longer animator.CurrentAnim( ANIMCHANNEL_ALL )->SetCycleCount( -1 ); } } } if( headAnimator ) { // copy the animation from the body to the head for( i = 0; i < copyJoints.Num(); i++ ) { if( copyJoints[ i ].mod == JOINTMOD_WORLD_OVERRIDE ) { idMat3 mat = head.GetEntity()->GetPhysics()->GetAxis().Transpose(); GetJointWorldTransform( copyJoints[ i ].from, gameLocal.time, pos, axis ); pos -= head.GetEntity()->GetPhysics()->GetOrigin(); headAnimator->SetJointPos( copyJoints[ i ].to, copyJoints[ i ].mod, pos * mat ); headAnimator->SetJointAxis( copyJoints[ i ].to, copyJoints[ i ].mod, axis * mat ); } else { animator.GetJointLocalTransform( copyJoints[ i ].from, gameLocal.time, pos, axis ); headAnimator->SetJointPos( copyJoints[ i ].to, copyJoints[ i ].mod, pos ); headAnimator->SetJointAxis( copyJoints[ i ].to, copyJoints[ i ].mod, axis ); } } } // update rotation RunPhysics(); physicsObj.GetAngles( ang ); physicsObj.SetAngularExtrapolation( extrapolation_t( EXTRAPOLATION_LINEAR | EXTRAPOLATION_NOSTOP ), gameLocal.time, 0, ang, idAngles( 0, g_testModelRotate.GetFloat() * 360.0f / 60.0f, 0 ), ang_zero ); idClipModel* clip = physicsObj.GetClipModel(); if( clip != NULL && animator.ModelDef() ) { idVec3 neworigin; idMat3 axis; jointHandle_t joint; joint = animator.GetJointHandle( "origin" ); animator.GetJointTransform( joint, gameLocal.time, neworigin, axis ); neworigin = ( ( neworigin - animator.ModelDef()->GetVisualOffset() ) * physicsObj.GetAxis() ) + GetPhysics()->GetOrigin(); clip->Link( gameLocal.clip, this, 0, neworigin, clip->GetAxis() ); } } UpdateAnimation(); Present(); if( ( gameLocal.testmodel == this ) && g_showTestModelFrame.GetInteger() && anim ) { gameLocal.Printf( "^5 Anim: ^7%s ^5Frame: ^7%d/%d Time: %.3f\n", animator.AnimFullName( anim ), animator.CurrentAnim( ANIMCHANNEL_ALL )->GetFrameNumber( gameLocal.time ), animator.CurrentAnim( ANIMCHANNEL_ALL )->NumFrames(), MS2SEC( gameLocal.time - animator.CurrentAnim( ANIMCHANNEL_ALL )->GetStartTime() ) ); if( headAnim ) { gameLocal.Printf( "^5 Head: ^7%s ^5Frame: ^7%d/%d Time: %.3f\n\n", headAnimator->AnimFullName( headAnim ), headAnimator->CurrentAnim( ANIMCHANNEL_ALL )->GetFrameNumber( gameLocal.time ), headAnimator->CurrentAnim( ANIMCHANNEL_ALL )->NumFrames(), MS2SEC( gameLocal.time - headAnimator->CurrentAnim( ANIMCHANNEL_ALL )->GetStartTime() ) ); } else { gameLocal.Printf( "\n\n" ); } } }
/* ================ idDeclAF::ParseBody ================ */ bool idDeclAF::ParseBody( idLexer &src ) { bool hasJoint = false; idToken token; idAFVector angles; idDeclAF_Body *body = new idDeclAF_Body; bodies.Alloc() = body; body->SetDefault( this ); if ( !src.ExpectTokenType( TT_STRING, 0, &token ) || !src.ExpectTokenString( "{" ) ) { return false; } body->name = token; if ( !body->name.Icmp( "origin" ) || !body->name.Icmp( "world" ) ) { src.Error( "a body may not be named \"origin\" or \"world\"" ); return false; } while( src.ReadToken( &token ) ) { if ( !token.Icmp( "model" ) ) { if ( !src.ExpectTokenType( TT_NAME, 0, &token ) ) { return false; } if ( !token.Icmp( "box" ) ) { body->modelType = TRM_BOX; if ( !src.ExpectTokenString( "(" ) || !body->v1.Parse( src ) || !src.ExpectTokenString( "," ) || !body->v2.Parse( src ) || !src.ExpectTokenString( ")" ) ) { return false; } } else if ( !token.Icmp( "octahedron" ) ) { body->modelType = TRM_OCTAHEDRON; if ( !src.ExpectTokenString( "(" ) || !body->v1.Parse( src ) || !src.ExpectTokenString( "," ) || !body->v2.Parse( src ) || !src.ExpectTokenString( ")" ) ) { return false; } } else if ( !token.Icmp( "dodecahedron" ) ) { body->modelType = TRM_DODECAHEDRON; if ( !src.ExpectTokenString( "(" ) || !body->v1.Parse( src ) || !src.ExpectTokenString( "," ) || !body->v2.Parse( src ) || !src.ExpectTokenString( ")" ) ) { return false; } } else if ( !token.Icmp( "cylinder" ) ) { body->modelType = TRM_CYLINDER; if ( !src.ExpectTokenString( "(" ) || !body->v1.Parse( src ) || !src.ExpectTokenString( "," ) || !body->v2.Parse( src ) || !src.ExpectTokenString( "," ) ) { return false; } body->numSides = src.ParseInt(); if ( !src.ExpectTokenString( ")" ) ) { return false; } } else if ( !token.Icmp( "cone" ) ) { body->modelType = TRM_CONE; if ( !src.ExpectTokenString( "(" ) || !body->v1.Parse( src ) || !src.ExpectTokenString( "," ) || !body->v2.Parse( src ) || !src.ExpectTokenString( "," ) ) { return false; } body->numSides = src.ParseInt(); if ( !src.ExpectTokenString( ")" ) ) { return false; } } else if ( !token.Icmp( "bone" ) ) { body->modelType = TRM_BONE; if ( !src.ExpectTokenString( "(" ) || !body->v1.Parse( src ) || !src.ExpectTokenString( "," ) || !body->v2.Parse( src ) || !src.ExpectTokenString( "," ) ) { return false; } body->width = src.ParseFloat(); if ( !src.ExpectTokenString( ")" ) ) { return false; } } else if ( !token.Icmp( "custom" ) ) { src.Error( "custom models not yet implemented" ); return false; } else { src.Error( "unkown model type %s", token.c_str() ); return false; } } else if ( !token.Icmp( "origin" ) ) { if ( !body->origin.Parse( src ) ) { return false; } } else if ( !token.Icmp( "angles" ) ) { if ( !angles.Parse( src ) ) { return false; } body->angles = idAngles( angles.ToVec3().x, angles.ToVec3().y, angles.ToVec3().z ); } else if ( !token.Icmp( "joint" ) ) { if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ) { return false; } body->jointName = token; hasJoint = true; } else if ( !token.Icmp( "mod" ) ) { if ( !src.ExpectAnyToken( &token ) ) { return false; } body->jointMod = JointModFromString( token.c_str() ); } else if ( !token.Icmp( "density" ) ) { body->density = src.ParseFloat(); } else if ( !token.Icmp( "inertiaScale" ) ) { src.Parse1DMatrix( 9, body->inertiaScale[0].ToFloatPtr() ); } else if ( !token.Icmp( "friction" ) ) { body->linearFriction = src.ParseFloat(); src.ExpectTokenString( "," ); body->angularFriction = src.ParseFloat(); src.ExpectTokenString( "," ); body->contactFriction = src.ParseFloat(); } else if ( !token.Icmp( "contents" ) ) { ParseContents( src, body->contents ); } else if ( !token.Icmp( "clipMask" ) ) { ParseContents( src, body->clipMask ); } else if ( !token.Icmp( "selfCollision" ) ) { body->selfCollision = src.ParseBool(); } else if ( !token.Icmp( "containedjoints" ) ) { if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ) { return false; } body->containedJoints = token; } else if ( !token.Icmp( "frictionDirection" ) ) { if ( !body->frictionDirection.Parse( src ) ) { return false; } } else if ( !token.Icmp( "contactMotorDirection" ) ) { if ( !body->contactMotorDirection.Parse( src ) ) { return false; } } else if ( token == "}" ) { break; } else { src.Error( "unknown token %s in body", token.c_str() ); return false; } } if ( body->modelType == TRM_INVALID ) { src.Error( "no model set for body" ); return false; } if ( !hasJoint ) { src.Error( "no joint set for body" ); return false; } body->clipMask |= CONTENTS_MOVEABLECLIP; return true; }
void idWorldManager::UpdatePlay( int idx ) { int currentIndex = records[idx].index; if (currentIndex > records[idx].events.Num() - 1) { return; } if (records[idx].events[currentIndex].timestamp < gameLocal.time - recordStarttime) { if (!records[idx].events[currentIndex].frobcommand.IsEmpty() && !records[idx].events[currentIndex].done) { //FROB EVENT. idEntity *frobEnt; frobEnt = gameLocal.FindEntity( records[idx].events[currentIndex].frobcommand ); if (frobEnt) { if (frobEnt->IsType(idTrigger_Multi::Type)) { static_cast<idTrigger_Multi *>( frobEnt )->TriggerAction(NULL); } else { gameLocal.GetLocalPlayer()->DoFrob(frobEnt); //common->Printf("frobbing! %d\n", gameLocal.time); } } else { gameLocal.Warning("WorldManager couldn't find frob ent: %s\n", gameLocal.FindEntity( records[idx].events[currentIndex].frobcommand.c_str())); } records[idx].events[currentIndex].done = true; } else if (records[idx].events[currentIndex].recordtype == RECORD_LAUNCHAIM && !records[idx].events[currentIndex].done) { //event: change launcher aim. //find the launcher with this id. int i; int targetEnt = -1; for ( i = 0; i < gameLocal.num_entities; i++ ) { if ( !gameLocal.entities[ i ] ) continue; int kk = records[idx].events[currentIndex].entID; if (gameLocal.entities[i]->spawnArgs.GetInt("id") != records[idx].events[currentIndex].entID) { continue; } targetEnt = i; break; } if (developer.GetBool()) { common->Printf("worldmanager: aiming launcher entity ID %d \n", records[idx].events[currentIndex].entID); } if (targetEnt >= 0) { //legacy. gameLocal.entities[targetEnt]->spawnArgs.SetVector("new_launchdir", records[idx].events[currentIndex].position); gameLocal.entities[targetEnt]->spawnArgs.SetInt("new_force", records[idx].events[currentIndex].yaw); gameLocal.entities[targetEnt]->spawnArgs.SetInt("new_update", 1); static_cast<idLauncher *>( gameLocal.entities[i] )->SetLaunchDir(records[idx].events[currentIndex].position, records[idx].events[currentIndex].yaw); } records[idx].events[currentIndex].done = true; } else if (!records[idx].events[currentIndex].deckcommand.IsEmpty() && !records[idx].events[currentIndex].done) { //DECK EVENT. gameLocal.RunDeckCommand(records[idx].events[currentIndex].deckcommand.c_str()); records[idx].events[currentIndex].done = true; } else if (records[idx].events[currentIndex].recordtype == RECORD_UNSPAWN && !records[idx].events[currentIndex].done) { //UNSPAWN EVENT. //find the ent with this id. int i; int targetEnt = -1; for ( i = 0; i < gameLocal.num_entities; i++ ) { if ( !gameLocal.entities[ i ] ) continue; int kk = records[idx].events[currentIndex].entID; if (gameLocal.entities[i]->spawnArgs.GetInt("id") != records[idx].events[currentIndex].entID) { continue; } targetEnt = i; break; } if (targetEnt >= 0) { gameLocal.entities[targetEnt]->PostEventMS( &EV_Remove, 0 ); //gameLocal.entities[targetEnt]->Event_CallFunction("onPick"); } records[idx].events[currentIndex].done = true; } else if (records[idx].events[currentIndex].recordtype == RECORD_SPAWN && !records[idx].events[currentIndex].done) { //SPAWN EVENT. idEntity *ent; idDict args; idAngles ang; int id = gameLocal.time - recordStarttime; if (developer.GetBool()) { common->Printf("worldmanager: spawning entity ID %d classname %s \n", records[idx].events[currentIndex].entID, records[idx].events[currentIndex].spawncommand.c_str()); } args.Set( "classname", records[idx].events[currentIndex].spawncommand ); args.SetVector( "origin", records[idx].events[currentIndex].position ); args.SetInt( "id", records[idx].events[currentIndex].entID); bool bSpawn = gameLocal.SpawnEntityDef( args, &ent ); if (ent) { ent->spawnArgs.SetInt("id", records[idx].events[currentIndex].entID); //BC 7-21-2016 was crashing here. ang.pitch = 0; ang.yaw = records[idx].events[currentIndex].yaw; ang.roll = 0; ent->SetAngles( ang ); } if (developer.GetBool()) { common->Printf("worldmanager: spawning success:%d\n", bSpawn); } records[idx].events[currentIndex].done = true; } else { //MOVE EVENT. float moveTime = (float)RECORDRATE / 1000; records[idx].ghost->Event_SetMoveTime(moveTime); records[idx].ghost->Event_MoveToPos(records[idx].events[currentIndex].position); idAngles newAng = idAngles(0, records[idx].events[currentIndex].yaw, 0); records[idx].ghost->SetAxis(newAng.ToMat3()); if (index == -1) { int lastLineIndex = recordlines[idx].lines.Num() - 1; recordline_t newLine; newLine.position1 = recordlines[idx].lines[lastLineIndex].position2; newLine.position2 = records[idx].events[currentIndex].position; recordlines[idx].lines.Append(newLine); } records[idx].events[currentIndex].done = true; } records[idx].index++; } }
/* ================ idForce_Field::Evaluate ================ */ void idForce_Field::Evaluate( int time ) { int numClipModels, i; idBounds bounds; idVec3 force, torque, angularVelocity; idClipModel *cm, *clipModelList[ MAX_GENTITIES ]; assert( clipModel ); bounds.FromTransformedBounds( clipModel->GetBounds(), clipModel->GetOrigin(), clipModel->GetAxis() ); numClipModels = gameLocal.clip.ClipModelsTouchingBounds( bounds, -1, clipModelList, MAX_GENTITIES ); for ( i = 0; i < numClipModels; i++ ) { cm = clipModelList[ i ]; if ( !cm->IsTraceModel() ) { continue; } idEntity *entity = cm->GetEntity(); if ( !entity ) { continue; } //bc ignore things. if (entity->IsType( idMoveableItem::Type )) { //int ignoreNum = static_cast<idMoveableItem *>( entity)->forcefieldIgnore.GetEntityNum(); //int myOwnerNum = this->owner.GetEntityNum(); if (static_cast<idMoveableItem *>( entity)->forcefieldIgnore.GetEntityNum() == this->owner.GetEntityNum()) { continue; } } idPhysics *physics = entity->GetPhysics(); //bc /* if (this->owner.IsValid()) { if (gameLocal.GetLocalPlayer()->pickerState >= 2) { if (gameLocal.GetLocalPlayer()->pickerWeapon.dragEnt.IsValid()) { if( gameLocal.GetLocalPlayer()->pickerWeapon.dragEnt.GetEntity()->IsGrabbed() && physics->IsType( idPhysics_Player::Type )) { continue; } } } } */ if ( playerOnly ) { if ( !physics->IsType( idPhysics_Player::Type ) ) { continue; } } else if ( monsterOnly ) { if ( !physics->IsType( idPhysics_Monster::Type ) ) { continue; } } if ( !gameLocal.clip.ContentsModel( cm->GetOrigin(), cm, cm->GetAxis(), -1, clipModel->Handle(), clipModel->GetOrigin(), clipModel->GetAxis() ) ) { continue; } switch( type ) { case FORCEFIELD_UNIFORM: { force = dir; break; } case FORCEFIELD_EXPLOSION: { force = cm->GetOrigin() - clipModel->GetOrigin(); force.Normalize(); break; } case FORCEFIELD_IMPLOSION: { force = clipModel->GetOrigin() - cm->GetOrigin(); force.Normalize(); break; } default: { gameLocal.Error( "idForce_Field: invalid type" ); break; } } if ( randomTorque != 0.0f ) { torque[0] = gameLocal.random.CRandomFloat(); torque[1] = gameLocal.random.CRandomFloat(); torque[2] = gameLocal.random.CRandomFloat(); if ( torque.Normalize() == 0.0f ) { torque[2] = 1.0f; } } switch( applyType ) { case FORCEFIELD_APPLY_FORCE: { if ( randomTorque != 0.0f ) { entity->AddForce( gameLocal.world, cm->GetId(), cm->GetOrigin() + torque.Cross( dir ) * randomTorque, dir * magnitude ); } else { entity->AddForce( gameLocal.world, cm->GetId(), cm->GetOrigin(), force * magnitude ); } break; } case FORCEFIELD_APPLY_VELOCITY: { //triggered by jumppad. LAUNCHER. //ignore objects that are being held by the player. if (gameLocal.GetLocalPlayer()->pickerWeapon.dragEnt.IsValid()) { //player is holding onto an object. if (gameLocal.GetLocalPlayer()->pickerWeapon.dragEnt.GetEntity() == entity) { //the thrown object equals the carried object. abort. continue; } } if ( entity->IsType( idDoor::Type ) ) continue; if ( entity->IsType( idAFEntity_Generic::Type )) { physics->SetLinearVelocity( force * magnitude, cm->GetId() ); continue; } //BC hack. only launch players when they're reeeaally close, to lessen accidental launches when //launch is plopped down near player's feet. if ( entity->IsType( idPlayer::Type ) ) { idVec3 playerPos = entity->GetPhysics()->GetOrigin(); playerPos.z = clipModel->GetOrigin().z; idVec3 rawDist = playerPos - clipModel->GetOrigin(); float finalDist = rawDist.LengthFast(); if (finalDist > 24) continue; //force *= 0.98f; //BC hack. reduce player boost. static_cast<idPlayer *>( entity )->physicsObj.inJump = true; } else { force *= g_launchermultiplier.GetFloat(); //BC hack. give non-players an extra boost. //TODO: figure out why/how physics treats players and objects differently. //force *= 1.1f; //was 1.43 //force *= 1.9f; //was 1.43 //force *= forceMultiplier; } //common->Printf("thrown mass is %f\n", entity->GetPhysics()->GetMass()); //bc hack: snap the object to the center of the jumppad so jump arc is more consistent. if (jumppadTimer < time) { jumppadTimer = time + 400; idVec3 jumppadOrigin = clipModel->GetOrigin(); //jumppadOrigin.z = physics->GetOrigin().z; //retain objects' original vertical (z) axis, so that things don't get stuck in the ground. //jumppadOrigin.z //gameRenderWorld->DebugCircle( colorWhite, jumppadOrigin, idVec3(0,0,1), 32, 12, 5000 ); //physics->GetAbsBounds() jumppadOrigin.z += 5; physics->SetOrigin( jumppadOrigin ); //BC 10-13-2015 reset object angle to 0,0,0. idAngles snapAngle = idAngles(0,0,0); physics->SetAxis(snapAngle.ToMat3()); //common->Printf("tele hack\n"); //gameRenderWorld->DebugBounds( colorMagenta, physics->GetBounds(), physics->GetOrigin(), 5000 ); //gameRenderWorld->DebugCircle( colorOrange, physics->GetOrigin(), idVec3(0,0,1), 16, 12, 5000 ); //gameRenderWorld->DebugCircle( colorWhite, clipModel->GetOrigin(), idVec3(0,0,1), 32, 12, 5000 ); physics->SetLinearVelocity( force * magnitude, cm->GetId() ); } /* if ( randomTorque != 0.0f ) { angularVelocity = physics->GetAngularVelocity( cm->GetId() ); physics->SetAngularVelocity( 0.5f * (angularVelocity + torque * randomTorque), cm->GetId() ); } */ //Raven if ( !physics->IsType( idPhysics_AF::Type )) lastApplyTime = time; break; } case FORCEFIELD_APPLY_IMPULSE: { if ( randomTorque != 0.0f ) { entity->ApplyImpulse( gameLocal.world, cm->GetId(), cm->GetOrigin() + torque.Cross( dir ) * randomTorque, dir * magnitude ); } else { entity->ApplyImpulse( gameLocal.world, cm->GetId(), cm->GetOrigin(), force * magnitude ); } break; } default: { gameLocal.Error( "idForce_Field: invalid apply type" ); break; } } } }
/* ============ TestMath ============ */ void TestMath() { int i; TIME_TYPE start, end, bestClocks; idLib::common->Printf("====================================\n" ); float tst = -1.0f; float tst2 = 1.0f; float testvar = 1.0f; idRandom rnd; bestClocks = 0; tst = rnd.CRandomFloat(); for ( i = 0; i < NUMTESTS; i++ ) { StartRecordTime( start ); tst = fabs( tst ); StopRecordTime( end ); GetBest( start, end, bestClocks ); testvar = ( testvar + tst ) * tst; tst = rnd.CRandomFloat(); } PrintClocks( " fabs( tst )", 1, bestClocks ); bestClocks = 0; tst = rnd.CRandomFloat(); for ( i = 0; i < NUMTESTS; i++ ) { StartRecordTime( start ); int tmp = * ( int * ) &tst; tmp &= 0x7FFFFFFF; tst = * ( float * ) &tmp; StopRecordTime( end ); GetBest( start, end, bestClocks ); testvar = ( testvar + tst ) * tst; tst = rnd.CRandomFloat(); } PrintClocks( " idMath::Fabs( tst )", 1, bestClocks ); bestClocks = 0; tst = 10.0f + 100.0f * rnd.RandomFloat(); for ( i = 0; i < NUMTESTS; i++ ) { StartRecordTime( start ); tst = sqrt( tst ); StopRecordTime( end ); GetBest( start, end, bestClocks ); testvar = ( testvar + tst ) * tst * 0.01f; tst = 10.0f + 100.0f * rnd.RandomFloat(); } PrintClocks( " sqrt( tst )", 1, bestClocks ); bestClocks = 0; tst = rnd.RandomFloat(); for ( i = 0; i < NUMTESTS; i++ ) { StartRecordTime( start ); tst = idMath::Sqrt( tst ); StopRecordTime( end ); GetBest( start, end, bestClocks ); testvar = ( testvar + tst ) * tst; tst = rnd.RandomFloat(); } PrintClocks( " idMath::Sqrt( tst )", 1, bestClocks ); bestClocks = 0; tst = rnd.RandomFloat(); for ( i = 0; i < NUMTESTS; i++ ) { StartRecordTime( start ); tst = idMath::Sqrt16( tst ); StopRecordTime( end ); GetBest( start, end, bestClocks ); testvar = ( testvar + tst ) * tst; tst = rnd.RandomFloat(); } PrintClocks( " idMath::Sqrt16( tst )", 1, bestClocks ); bestClocks = 0; tst = rnd.CRandomFloat(); for ( i = 0; i < NUMTESTS; i++ ) { StartRecordTime( start ); tst = idMath::Sin( tst ); StopRecordTime( end ); GetBest( start, end, bestClocks ); testvar = ( testvar + tst ) * tst; tst = rnd.CRandomFloat(); } PrintClocks( " idMath::Sin( tst )", 1, bestClocks ); bestClocks = 0; tst = rnd.CRandomFloat(); for ( i = 0; i < NUMTESTS; i++ ) { StartRecordTime( start ); tst = idMath::Sin16( tst ); StopRecordTime( end ); GetBest( start, end, bestClocks ); testvar = ( testvar + tst ) * tst; tst = rnd.CRandomFloat(); } PrintClocks( " idMath::Sin16( tst )", 1, bestClocks ); bestClocks = 0; tst = rnd.CRandomFloat(); for ( i = 0; i < NUMTESTS; i++ ) { StartRecordTime( start ); tst = idMath::Cos( tst ); StopRecordTime( end ); GetBest( start, end, bestClocks ); testvar = ( testvar + tst ) * tst; tst = rnd.CRandomFloat(); } PrintClocks( " idMath::Cos( tst )", 1, bestClocks ); bestClocks = 0; tst = rnd.CRandomFloat(); for ( i = 0; i < NUMTESTS; i++ ) { StartRecordTime( start ); tst = idMath::Cos16( tst ); StopRecordTime( end ); GetBest( start, end, bestClocks ); testvar = ( testvar + tst ) * tst; tst = rnd.CRandomFloat(); } PrintClocks( " idMath::Cos16( tst )", 1, bestClocks ); bestClocks = 0; tst = rnd.CRandomFloat(); for ( i = 0; i < NUMTESTS; i++ ) { StartRecordTime( start ); idMath::SinCos( tst, tst, tst2 ); StopRecordTime( end ); GetBest( start, end, bestClocks ); testvar = ( testvar + tst ) * tst; tst = rnd.CRandomFloat(); } PrintClocks( " idMath::SinCos( tst )", 1, bestClocks ); bestClocks = 0; tst = rnd.CRandomFloat(); for ( i = 0; i < NUMTESTS; i++ ) { StartRecordTime( start ); idMath::SinCos16( tst, tst, tst2 ); StopRecordTime( end ); GetBest( start, end, bestClocks ); testvar = ( testvar + tst ) * tst; tst = rnd.CRandomFloat(); } PrintClocks( "idMath::SinCos16( tst )", 1, bestClocks ); bestClocks = 0; tst = rnd.CRandomFloat(); for ( i = 0; i < NUMTESTS; i++ ) { StartRecordTime( start ); tst = idMath::Tan( tst ); StopRecordTime( end ); GetBest( start, end, bestClocks ); testvar = ( testvar + tst ) * tst; tst = rnd.CRandomFloat(); } PrintClocks( " idMath::Tan( tst )", 1, bestClocks ); bestClocks = 0; tst = rnd.CRandomFloat(); for ( i = 0; i < NUMTESTS; i++ ) { StartRecordTime( start ); tst = idMath::Tan16( tst ); StopRecordTime( end ); GetBest( start, end, bestClocks ); testvar = ( testvar + tst ) * tst; tst = rnd.CRandomFloat(); } PrintClocks( " idMath::Tan16( tst )", 1, bestClocks ); bestClocks = 0; tst = rnd.CRandomFloat(); for ( i = 0; i < NUMTESTS; i++ ) { StartRecordTime( start ); tst = idMath::ASin( tst ); StopRecordTime( end ); GetBest( start, end, bestClocks ); testvar = ( testvar + tst ) * tst * ( 1.0f / idMath::PI ); tst = rnd.CRandomFloat(); } PrintClocks( " idMath::ASin( tst )", 1, bestClocks ); bestClocks = 0; tst = rnd.CRandomFloat(); for ( i = 0; i < NUMTESTS; i++ ) { StartRecordTime( start ); tst = idMath::ASin16( tst ); StopRecordTime( end ); GetBest( start, end, bestClocks ); testvar = ( testvar + tst ) * tst * ( 1.0f / idMath::PI ); tst = rnd.CRandomFloat(); } PrintClocks( " idMath::ASin16( tst )", 1, bestClocks ); bestClocks = 0; tst = rnd.CRandomFloat(); for ( i = 0; i < NUMTESTS; i++ ) { StartRecordTime( start ); tst = idMath::ACos( tst ); StopRecordTime( end ); GetBest( start, end, bestClocks ); testvar = ( testvar + tst ) * tst * ( 1.0f / idMath::PI ); tst = rnd.CRandomFloat(); } PrintClocks( " idMath::ACos( tst )", 1, bestClocks ); bestClocks = 0; tst = rnd.CRandomFloat(); for ( i = 0; i < NUMTESTS; i++ ) { StartRecordTime( start ); tst = idMath::ACos16( tst ); StopRecordTime( end ); GetBest( start, end, bestClocks ); testvar = ( testvar + tst ) * tst * ( 1.0f / idMath::PI ); tst = rnd.CRandomFloat(); } PrintClocks( " idMath::ACos16( tst )", 1, bestClocks ); bestClocks = 0; tst = rnd.CRandomFloat(); for ( i = 0; i < NUMTESTS; i++ ) { StartRecordTime( start ); tst = idMath::ATan( tst ); StopRecordTime( end ); GetBest( start, end, bestClocks ); testvar = ( testvar + tst ) * tst; tst = rnd.CRandomFloat(); } PrintClocks( " idMath::ATan( tst )", 1, bestClocks ); bestClocks = 0; tst = rnd.CRandomFloat(); for ( i = 0; i < NUMTESTS; i++ ) { StartRecordTime( start ); tst = idMath::ATan16( tst ); StopRecordTime( end ); GetBest( start, end, bestClocks ); testvar = ( testvar + tst ) * tst; tst = rnd.CRandomFloat(); } PrintClocks( " idMath::ATan16( tst )", 1, bestClocks ); bestClocks = 0; tst = rnd.CRandomFloat(); for ( i = 0; i < NUMTESTS; i++ ) { StartRecordTime( start ); tst = idMath::Pow( 2.7f, tst ); StopRecordTime( end ); GetBest( start, end, bestClocks ); testvar = ( testvar + tst ) * tst * 0.1f; tst = rnd.CRandomFloat(); } PrintClocks( " idMath::Pow( tst )", 1, bestClocks ); bestClocks = 0; tst = rnd.CRandomFloat(); for ( i = 0; i < NUMTESTS; i++ ) { StartRecordTime( start ); tst = idMath::Pow16( 2.7f, tst ); StopRecordTime( end ); GetBest( start, end, bestClocks ); testvar = ( testvar + tst ) * tst * 0.1f; tst = rnd.CRandomFloat(); } PrintClocks( " idMath::Pow16( tst )", 1, bestClocks ); bestClocks = 0; tst = rnd.CRandomFloat(); for ( i = 0; i < NUMTESTS; i++ ) { StartRecordTime( start ); tst = idMath::Exp( tst ); StopRecordTime( end ); GetBest( start, end, bestClocks ); testvar = ( testvar + tst ) * tst * 0.1f; tst = rnd.CRandomFloat(); } PrintClocks( " idMath::Exp( tst )", 1, bestClocks ); bestClocks = 0; tst = rnd.CRandomFloat(); for ( i = 0; i < NUMTESTS; i++ ) { StartRecordTime( start ); tst = idMath::Exp16( tst ); StopRecordTime( end ); GetBest( start, end, bestClocks ); testvar = ( testvar + tst ) * tst * 0.1f; tst = rnd.CRandomFloat(); } PrintClocks( " idMath::Exp16( tst )", 1, bestClocks ); bestClocks = 0; tst = rnd.CRandomFloat(); for ( i = 0; i < NUMTESTS; i++ ) { tst = fabs( tst ) + 1.0f; StartRecordTime( start ); tst = idMath::Log( tst ); StopRecordTime( end ); GetBest( start, end, bestClocks ); testvar = ( testvar + tst ) * tst; tst = rnd.CRandomFloat(); } PrintClocks( " idMath::Log( tst )", 1, bestClocks ); bestClocks = 0; tst = rnd.CRandomFloat(); for ( i = 0; i < NUMTESTS; i++ ) { tst = fabs( tst ) + 1.0f; StartRecordTime( start ); tst = idMath::Log16( tst ); StopRecordTime( end ); GetBest( start, end, bestClocks ); testvar = ( testvar + tst ) * tst; tst = rnd.CRandomFloat(); } PrintClocks( " idMath::Log16( tst )", 1, bestClocks ); idLib::common->Printf( "testvar = %f\n", testvar ); idMat3 resultMat3; idQuat fromQuat, toQuat, resultQuat; idCQuat cq; idAngles ang; fromQuat = idAngles( 30, 45, 0 ).ToQuat(); toQuat = idAngles( 45, 0, 0 ).ToQuat(); cq = idAngles( 30, 45, 0 ).ToQuat().ToCQuat(); ang = idAngles( 30, 40, 50 ); bestClocks = 0; for ( i = 0; i < NUMTESTS; i++ ) { StartRecordTime( start ); resultMat3 = fromQuat.ToMat3(); StopRecordTime( end ); GetBest( start, end, bestClocks ); } PrintClocks( " idQuat::ToMat3()", 1, bestClocks ); bestClocks = 0; for ( i = 0; i < NUMTESTS; i++ ) { StartRecordTime( start ); resultQuat.Slerp( fromQuat, toQuat, 0.3f ); StopRecordTime( end ); GetBest( start, end, bestClocks ); } PrintClocks( " idQuat::Slerp()", 1, bestClocks ); bestClocks = 0; for ( i = 0; i < NUMTESTS; i++ ) { StartRecordTime( start ); resultQuat = cq.ToQuat(); StopRecordTime( end ); GetBest( start, end, bestClocks ); } PrintClocks( " idCQuat::ToQuat()", 1, bestClocks ); bestClocks = 0; for ( i = 0; i < NUMTESTS; i++ ) { StartRecordTime( start ); resultQuat = ang.ToQuat(); StopRecordTime( end ); GetBest( start, end, bestClocks ); } PrintClocks( " idAngles::ToQuat()", 1, bestClocks ); bestClocks = 0; for ( i = 0; i < NUMTESTS; i++ ) { StartRecordTime( start ); resultMat3 = ang.ToMat3(); StopRecordTime( end ); GetBest( start, end, bestClocks ); } PrintClocks( " idAngles::ToMat3()", 1, bestClocks ); }
/* ============ hhDebrisSpawner::SpawnDebris ============ */ void hhDebrisSpawner::SpawnDebris() { const idKeyValue * kv = NULL; idEntity * debris; idDict args; idStr debrisEntity; idList<idStr> debrisEntities; int numDebris; // For entity sources idBounds sourceBounds; idVec3 sourceBoundCenter; idVec3 debrisOrigin; idBounds searchBounds; idVec3 debrisVelocity; bool fit; idBounds afBounds; //rww bool gotAFBounds = false; //rww idVec3 defOrigin = vec3_zero; idAngles defAngles = ang_zero; // Optimization: if player is far away, don't spawn the chunks if (!gameLocal.isMultiplayer) { float maxDistance = spawnArgs.GetFloat("max_debris_distance"); if (maxDistance > 0.0f) { float distSquared = (gameLocal.GetLocalPlayer()->GetOrigin() - origin).LengthSqr(); if (distSquared > maxDistance*maxDistance) { return; } } } args.SetInt( "nodrop", 1 ); args.SetVector( "origin", origin ); args.SetFloat( "duration", duration ); // Pass along variabes requested hhUtils::PassArgs( spawnArgs, args, "pass_" ); if (useAFBounds && sourceEntity && sourceEntity->IsType(idActor::Type)) { //rww - try for AF bounds idActor *actor = static_cast<idActor *>(sourceEntity); if (actor->IsActiveAF()) { //they are ragdolling, so we have a chance. idPhysics_AF *afPhys = actor->GetAFPhysics(); if (afPhys) { //got the af physics object, now loop through the bodies and collect an appropriate bounds. afBounds.Zero(); for (int bodyCount = 0; bodyCount < afPhys->GetNumBodies(); bodyCount++) { idAFBody *b = afPhys->GetBody(bodyCount); if (b) { idClipModel *bodyClip = b->GetClipModel(); if (bodyClip) { //now add the bounds of the clipModel into afBounds idBounds bodyBounds = bodyClip->GetBounds(); idVec3 point = (b->GetWorldOrigin()-origin); bodyBounds.AddPoint(point); afBounds.AddBounds(bodyBounds); gotAFBounds = true; } } } } } } // Find all Debris while ( GetNextDebrisData( debrisEntities, numDebris, kv, defOrigin, defAngles ) ) { int numEntities = debrisEntities.Num(); for ( int count = 0; count < numDebris; ++count ) { // Select a debris to use from the list debrisEntity = debrisEntities[ gameLocal.random.RandomInt( numEntities ) ]; // If we have a bounding box to fill, use that if ( fillBounds && ( sourceEntity || hasBounds ) ) { if (gotAFBounds) { //rww sourceBounds = afBounds; //gameRenderWorld->DebugBounds(colorGreen, afBounds, origin, 1000); } else if ( sourceEntity ) { sourceBounds = sourceEntity->GetPhysics()->GetBounds(); } else { sourceBounds = bounds; } fit = false; for ( int i = 0; i < 4; i++ ) { if ( i == 0 && defOrigin != vec3_zero ) { //first try bone origin without random offset debrisOrigin = defOrigin; } else { debrisOrigin = origin + hhUtils::RandomPointInBounds( sourceBounds ); } if ( !testBounds || hhUtils::EntityDefWillFit( debrisEntity, debrisOrigin, defAngles.ToMat3(), CONTENTS_SOLID, NULL ) ) { fit = true; break; // Found a spot for the gib } } if ( !fit ) { // Gib didn't fit after 4 attempts, so don't spawn the gib //common->Warning( "SpawnDebris: gib didn't fit when spawned (%s)\n", debrisEntity.c_str() ); defAngles = ang_zero; continue; } args.SetVector( "origin", debrisOrigin ); if ( sourceEntity ) { idMat3 sourceAxis = idAngles( 0, sourceEntity->GetAxis().ToAngles().yaw, 0 ).ToMat3(); args.SetMatrix( "rotation", defAngles.ToMat3() * sourceAxis ); } else { args.SetMatrix( "rotation", defAngles.ToMat3() ); } } if ( duration ) { args.SetFloat( "removeTime", duration + duration * gameLocal.random.CRandomFloat() ); } // Spawn the object debris = gameLocal.SpawnObject( debrisEntity, &args ); HH_ASSERT(debris != NULL); // JRM - Nick, I added this because of a crash I got. Hopefully this will catch it sooner // mdl: Added this check to make sure no AFs go through the debris spawner if ( debris->IsType( idAFEntity_Base::Type ) ) { gameLocal.Warning( "hhDebrisSpawner spawned an articulated entity: '%s'.", debrisEntity.c_str() ); } if ( nonSolid ) { idVec3 origin; if ( debris->GetFloorPos( 64.0f, origin ) ) { debris->SetOrigin( origin ); // Start on floor, since we're not going to be moving at all debris->RunPhysics(); // Make sure any associated effects get updated before we turn collision off } // Turn off collision debris->GetPhysics()->SetContents( 0 ); debris->GetPhysics()->SetClipMask( 0 ); debris->GetPhysics()->UnlinkClip(); debris->GetPhysics()->PutToRest(); } else { // Add in random velocity idVec3 randVel( gameLocal.random.RandomInt( power.x ) - power.x / 2, gameLocal.random.RandomInt( power.y ) - power.y / 2, gameLocal.random.RandomInt( power.z ) - power.z / 2 ); // Set linear velocity debrisVelocity.x = velocity.x * power.x * 0.25; debrisVelocity.y = velocity.y * power.y * 0.25; debrisVelocity.z = 0.0f; debris->GetPhysics()->SetLinearVelocity( debrisVelocity + randVel ); // Add random angular velocity idVec3 aVel; aVel.x = spawnArgs.GetFloat( "ang_vel", "90.0" ) * gameLocal.random.CRandomFloat(); aVel.y = spawnArgs.GetFloat( "ang_vel", "90.0" ) * gameLocal.random.CRandomFloat(); aVel.z = spawnArgs.GetFloat( "ang_vel", "90.0" ) * gameLocal.random.CRandomFloat(); if ( defAngles == ang_zero ) { debris->GetPhysics()->SetAxis( idVec3( 1, 0, 0 ).ToMat3() ); } debris->GetPhysics()->SetAngularVelocity( aVel ); } } defAngles = ang_zero; // Zero out the list debrisEntities.Clear(); } return; }
/* ===================== PutPrimitivesInAreas ===================== */ void PutPrimitivesInAreas( uEntity_t *e ) { uBrush_t *b; int i; side_t *side; primitive_t *prim; mapTri_t *tri; common->Printf( "----- PutPrimitivesInAreas -----\n"); // allocate space for surface chains for each area e->areas = (uArea_t *)Mem_Alloc( e->numAreas * sizeof( e->areas[0] ) ); memset( e->areas, 0, e->numAreas * sizeof( e->areas[0] ) ); // for each primitive, clip it to the non-solid leafs // and divide it into different areas for ( prim = e->primitives ; prim ; prim = prim->next ) { b = prim->brush; if ( !b ) { // add curve triangles for ( tri = prim->tris ; tri ; tri = tri->next ) { AddMapTriToAreas( tri, e ); } continue; } // clip in brush sides for ( i = 0 ; i < b->numsides ; i++ ) { side = &b->sides[i]; if ( !side->visibleHull ) { continue; } PutWindingIntoAreas_r( e, side->visibleHull, side, e->tree->headnode ); } } // optionally inline some of the func_static models if ( dmapGlobals.entityNum == 0 ) { bool inlineAll = dmapGlobals.uEntities[0].mapEntity->epairs.GetBool( "inlineAllStatics" ); for ( int eNum = 1 ; eNum < dmapGlobals.num_entities ; eNum++ ) { uEntity_t *entity = &dmapGlobals.uEntities[eNum]; const char *className = entity->mapEntity->epairs.GetString( "classname" ); if ( idStr::Icmp( className, "func_static" ) ) { continue; } if ( !entity->mapEntity->epairs.GetBool( "inline" ) && !inlineAll ) { continue; } const char *modelName = entity->mapEntity->epairs.GetString( "model" ); if ( !modelName ) { continue; } idRenderModel *model = renderModelManager->FindModel( modelName ); common->Printf( "inlining %s.\n", entity->mapEntity->epairs.GetString( "name" ) ); idMat3 axis; // get the rotation matrix in either full form, or single angle form if ( !entity->mapEntity->epairs.GetMatrix( "rotation", "1 0 0 0 1 0 0 0 1", axis ) ) { float angle = entity->mapEntity->epairs.GetFloat( "angle" ); if ( angle != 0.0f ) { axis = idAngles( 0.0f, angle, 0.0f ).ToMat3(); } else { axis.Identity(); } } idVec3 origin = entity->mapEntity->epairs.GetVector( "origin" ); for ( i = 0 ; i < model->NumSurfaces() ; i++ ) { const modelSurface_t *surface = model->Surface( i ); const srfTriangles_t *tri = surface->geometry; mapTri_t mapTri; memset( &mapTri, 0, sizeof( mapTri ) ); mapTri.material = surface->shader; // don't let discretes (autosprites, etc) merge together if ( mapTri.material->IsDiscrete() ) { mapTri.mergeGroup = (void *)surface; } for ( int j = 0 ; j < tri->numIndexes ; j += 3 ) { for ( int k = 0 ; k < 3 ; k++ ) { idVec3 v = tri->verts[tri->indexes[j+k]].xyz; mapTri.v[k].xyz = v * axis + origin; mapTri.v[k].normal = tri->verts[tri->indexes[j+k]].normal * axis; mapTri.v[k].st = tri->verts[tri->indexes[j+k]].st; } AddMapTriToAreas( &mapTri, e ); } } } } }
/* ============ idAASLocal::ShowWallEdges ============ */ void idAASLocal::ShowWallEdges( const idVec3 &origin, int mode, bool showNumbers ) const { const int MAX_WALL_EDGES = 1024; int edges[MAX_WALL_EDGES]; float textSize; idPlayer *player = gameLocal.GetLocalPlayer(); if ( player == NULL ) { return; } idMat3 viewAxis = player->GetViewAxis(); idVec3 viewOrigin = player->GetViewPos(); idMat3 playerAxis = idAngles( 0.0f, -player->GetViewAngles().yaw, 0.0f ).ToMat3(); if ( mode == 3 ) { textSize = 0.2f; } else { textSize = 0.1f; } float radius = file->GetSettings().obstaclePVSRadius; int areaNum = PointReachableAreaNum( origin, DefaultSearchBounds(), AAS_AREA_REACHABLE_WALK, TravelFlagInvalidForTeam() ); //int numEdges = GetWallEdges( areaNum, idBounds( origin ).Expand( radius ), TFL_WALK, 64.0f, edges, MAX_WALL_EDGES ); int numEdges = GetObstaclePVSWallEdges( areaNum, edges, MAX_WALL_EDGES ); // move the wall edges to the start of the list int numWallEdges = 0; for ( int i = 0; i < numEdges; i++ ) { if ( ( file->GetEdge( abs( edges[i] ) ).flags & AAS_EDGE_WALL ) != 0 ) { idSwap( edges[numWallEdges++], edges[i] ); } } for ( int i = 0; i < numEdges; i++ ) { idVec3 start, end; GetEdge( edges[i], start, end ); if ( mode == 2 ) { start.z = end.z = origin.z; } else if ( mode == 3 ) { ProjectTopDown( start, viewOrigin, viewAxis, playerAxis, radius * 2.0f ); ProjectTopDown( end, viewOrigin, viewAxis, playerAxis, radius * 2.0f ); } if ( ( file->GetEdge( abs( edges[i] ) ).flags & AAS_EDGE_WALL ) != 0 ) { gameRenderWorld->DebugLine( colorRed, start, end, 0 ); } else { gameRenderWorld->DebugLine( colorGreen, start, end, 0 ); } if ( showNumbers ) { gameRenderWorld->DrawText( va( "%d", edges[i] ), ( start + end ) * 0.5f, textSize, colorWhite, viewAxis, 1, 0 ); } } if ( mode == 3 ) { idVec3 box[7] = { origin, origin, origin, origin, origin, origin, origin }; box[0][0] += radius; box[0][1] += radius; box[1][0] += radius; box[1][1] -= radius; box[2][0] -= radius; box[2][1] -= radius; box[3][0] -= radius; box[3][1] += radius; box[4][1] += radius; box[5][0] += radius * 0.1f; box[5][1] += radius - radius * 0.1f; box[6][0] -= radius * 0.1f; box[6][1] += radius - radius * 0.1f; for ( int i = 0; i < 7; i++ ) { ProjectTopDown( box[i], viewOrigin, viewAxis, playerAxis, radius * 2.0f ); } for ( int i = 0; i < 4; i++ ) { gameRenderWorld->DebugLine( colorCyan, box[i], box[(i+1)&3], 0 ); } gameRenderWorld->DebugLine( colorCyan, box[4], box[5], 0 ); gameRenderWorld->DebugLine( colorCyan, box[4], box[6], 0 ); } }