static void CLH2_RelinkEntities() { h2entity_t* ent; int i, j; float frac, f, d; vec3_t delta; //float bobjrotate; vec3_t oldorg; int c; c = 0; // determine partial update time frac = CLQH_LerpPoint(); // // interpolate player info // for ( i = 0; i < 3; i++ ) { cl.qh_velocity[ i ] = cl.qh_mvelocity[ 1 ][ i ] + frac * ( cl.qh_mvelocity[ 0 ][ i ] - cl.qh_mvelocity[ 1 ][ i ] ); } if ( clc.demoplaying && !h2intro_playing ) { // interpolate the angles for ( j = 0; j < 3; j++ ) { d = cl.qh_mviewangles[ 0 ][ j ] - cl.qh_mviewangles[ 1 ][ j ]; if ( d > 180 ) { d -= 360; } else if ( d < -180 ) { d += 360; } cl.viewangles[ j ] = cl.qh_mviewangles[ 1 ][ j ] + frac * d; } } // start on the entity after the world for ( i = 1,ent = h2cl_entities + 1; i < cl.qh_num_entities; i++,ent++ ) { if ( !ent->state.modelindex ) { // empty slot continue; } // if the object wasn't included in the last packet, remove it if ( ent->msgtime != cl.qh_mtime[ 0 ] && !( clh2_baselines[ i ].flags & BE_ON ) ) { ent->state.modelindex = 0; continue; } VectorCopy( ent->state.origin, oldorg ); if ( ent->msgtime != cl.qh_mtime[ 0 ] ) { // the entity was not updated in the last message // so move to the final spot VectorCopy( ent->msg_origins[ 0 ], ent->state.origin ); VectorCopy( ent->msg_angles[ 0 ], ent->state.angles ); } else { // if the delta is large, assume a teleport and don't lerp f = frac; for ( j = 0; j < 3; j++ ) { delta[ j ] = ent->msg_origins[ 0 ][ j ] - ent->msg_origins[ 1 ][ j ]; if ( delta[ j ] > 100 || delta[ j ] < -100 ) { f = 1; // assume a teleportation, not a motion } } // interpolate the origin and angles for ( j = 0; j < 3; j++ ) { ent->state.origin[ j ] = ent->msg_origins[ 1 ][ j ] + f * delta[ j ]; d = ent->msg_angles[ 0 ][ j ] - ent->msg_angles[ 1 ][ j ]; if ( d > 180 ) { d -= 360; } else if ( d < -180 ) { d += 360; } ent->state.angles[ j ] = ent->msg_angles[ 1 ][ j ] + f * d; } } c++; if ( ent->state.effects & H2EF_DARKFIELD ) { CLH2_DarkFieldParticles( ent->state.origin ); } if ( ent->state.effects & H2EF_MUZZLEFLASH ) { CLH2_MuzzleFlashLight( i, ent->state.origin, ent->state.angles, true ); } if ( ent->state.effects & H2EF_BRIGHTLIGHT ) { CLH2_BrightLight( i, ent->state.origin ); } if ( ent->state.effects & H2EF_DIMLIGHT ) { CLH2_DimLight( i, ent->state.origin ); } if ( ent->state.effects & H2EF_DARKLIGHT ) { CLH2_DarkLight( i, ent->state.origin ); } if ( ent->state.effects & H2EF_LIGHT ) { CLH2_Light( i, ent->state.origin ); } int ModelFlags = R_ModelFlags( cl.model_draw[ ent->state.modelindex ] ); if ( ModelFlags & H2MDLEF_GIB ) { CLH2_TrailParticles( oldorg, ent->state.origin, rt_blood ); } else if ( ModelFlags & H2MDLEF_ZOMGIB ) { CLH2_TrailParticles( oldorg, ent->state.origin, rt_slight_blood ); } else if ( ModelFlags & H2MDLEF_BLOODSHOT ) { CLH2_TrailParticles( oldorg, ent->state.origin, rt_bloodshot ); } else if ( ModelFlags & H2MDLEF_TRACER ) { CLH2_TrailParticles( oldorg, ent->state.origin, rt_tracer ); } else if ( ModelFlags & H2MDLEF_TRACER2 ) { CLH2_TrailParticles( oldorg, ent->state.origin, rt_tracer2 ); } else if ( ModelFlags & H2MDLEF_ROCKET ) { CLH2_TrailParticles( oldorg, ent->state.origin, rt_rocket_trail ); } else if ( ModelFlags & H2MDLEF_FIREBALL ) { CLH2_TrailParticles( oldorg, ent->state.origin, rt_fireball ); CLH2_FireBallLight( i, ent->state.origin ); } else if ( ModelFlags & H2MDLEF_ACIDBALL ) { CLH2_TrailParticles( oldorg, ent->state.origin, rt_acidball ); CLH2_FireBallLight( i, ent->state.origin ); } else if ( ModelFlags & H2MDLEF_ICE ) { CLH2_TrailParticles( oldorg, ent->state.origin, rt_ice ); } else if ( ModelFlags & H2MDLEF_SPIT ) { CLH2_TrailParticles( oldorg, ent->state.origin, rt_spit ); CLH2_SpitLight( i, ent->state.origin ); } else if ( ModelFlags & H2MDLEF_SPELL ) { CLH2_TrailParticles( oldorg, ent->state.origin, rt_spell ); } else if ( ModelFlags & H2MDLEF_GRENADE ) { CLH2_TrailParticles( oldorg, ent->state.origin, rt_smoke ); } else if ( ModelFlags & H2MDLEF_TRACER3 ) { CLH2_TrailParticles( oldorg, ent->state.origin, rt_voor_trail ); } else if ( ModelFlags & H2MDLEF_VORP_MISSILE ) { CLH2_TrailParticles( oldorg, ent->state.origin, rt_vorpal ); } else if ( ModelFlags & H2MDLEF_SET_STAFF ) { CLH2_TrailParticles( oldorg, ent->state.origin,rt_setstaff ); } else if ( ModelFlags & H2MDLEF_MAGICMISSILE ) { if ( ( rand() & 3 ) < 1 ) { CLH2_TrailParticles( oldorg, ent->state.origin, rt_magicmissile ); } } else if ( ModelFlags & H2MDLEF_BONESHARD ) { CLH2_TrailParticles( oldorg, ent->state.origin, rt_boneshard ); } else if ( ModelFlags & H2MDLEF_SCARAB ) { CLH2_TrailParticles( oldorg, ent->state.origin, rt_scarab ); } if ( ent->state.effects & H2EF_NODRAW ) { continue; } refEntity_t rent; Com_Memset( &rent, 0, sizeof ( rent ) ); rent.reType = RT_MODEL; VectorCopy( ent->state.origin, rent.origin ); rent.hModel = cl.model_draw[ ent->state.modelindex ]; rent.frame = ent->state.frame; rent.syncBase = ent->syncbase; rent.skinNum = ent->state.skinnum; CLH2_SetRefEntAxis( &rent, ent->state.angles, oldvec3_origin, ent->state.scale, ent->state.abslight, ent->state.drawflags ); CLH2_HandleCustomSkin( &rent ); if ( i <= cl.qh_maxclients ) { CLH2_SetPlayerColours( &rent, i - 1 ); } if ( i == cl.viewentity && !chase_active->value ) { rent.renderfx |= RF_THIRD_PERSON; } R_AddRefEntityToScene( &rent ); CLH2_AddColourShadeRefEnt( &rent, ent->state.colormap, ent->state.drawflags ); } }
static void CLHW_LinkPacketEntities() { hwpacket_entities_t* pack = &cl.hw_frames[ clc.netchan.incomingSequence & UPDATE_MASK_HW ].packet_entities; hwpacket_entities_t* PrevPack = &cl.hw_frames[ ( clc.netchan.incomingSequence - 1 ) & UPDATE_MASK_HW ].packet_entities; float f = 0; // FIXME: no interpolation right now for ( int pnum = 0; pnum < pack->num_entities; pnum++ ) { h2entity_state_t* s1 = &pack->entities[ pnum ]; h2entity_state_t* s2 = s1; // FIXME: no interpolation right now // if set to invisible, skip if ( !s1->modelindex ) { continue; } // create a new entity refEntity_t ent; Com_Memset( &ent, 0, sizeof ( ent ) ); ent.reType = RT_MODEL; qhandle_t model = cl.model_draw[ s1->modelindex ]; ent.hModel = model; // set skin ent.skinNum = s1->skinnum; // set frame ent.frame = s1->frame; int drawflags = s1->drawflags; vec3_t angles; for ( int i = 0; i < 3; i++ ) { float a1 = s1->angles[ i ]; float a2 = s2->angles[ i ]; if ( a1 - a2 > 180 ) { a1 -= 360; } if ( a1 - a2 < -180 ) { a1 += 360; } angles[ i ] = a2 + f * ( a1 - a2 ); } // calculate origin for ( int i = 0; i < 3; i++ ) { ent.origin[ i ] = s2->origin[ i ] + f * ( s1->origin[ i ] - s2->origin[ i ] ); } // scan the old entity display list for a matching vec3_t old_origin; int i; for ( i = 0; i < PrevPack->num_entities; i++ ) { if ( PrevPack->entities[ i ].number == s1->number ) { VectorCopy( PrevPack->entities[ i ].origin, old_origin ); break; } } if ( i == PrevPack->num_entities ) { CLH2_SetRefEntAxis( &ent, angles, oldvec3_origin, s1->scale, s1->abslight, drawflags ); R_AddRefEntityToScene( &ent ); CLH2_AddColourShadeRefEnt( &ent, s1->colormap, drawflags ); continue; // not in last message } for ( i = 0; i < 3; i++ ) //if ( abs(old_origin[i] - ent->origin[i]) > 128) if ( abs( old_origin[ i ] - ent.origin[ i ] ) > 512 ) { // this is an issue for laggy situations... // no trail if too far VectorCopy( ent.origin, old_origin ); break; } // some of the effects need to know how far the thing has moved... if ( clhw_siege ) { if ( ( int )s1->effects & H2EF_NODRAW ) { ent.skinNum = 101; //ice, but in siege will be invis skin for dwarf to see drawflags |= H2DRF_TRANSLUCENT; s1->effects &= ~H2EF_NODRAW; } } vec3_t angleAdd; HandleEffects( s1->effects, s1->number, &ent, angles, angleAdd ); CLH2_SetRefEntAxis( &ent, angles, angleAdd, s1->scale, s1->abslight, drawflags ); R_AddRefEntityToScene( &ent ); CLH2_AddColourShadeRefEnt( &ent, s1->colormap, drawflags ); // add automatic particle trails int ModelFlags = R_ModelFlags( ent.hModel ); if ( !ModelFlags ) { continue; } // Model Flags if ( ModelFlags & H2MDLEF_GIB ) { CLH2_TrailParticles( old_origin, ent.origin, rt_blood ); } else if ( ModelFlags & H2MDLEF_ZOMGIB ) { CLH2_TrailParticles( old_origin, ent.origin, rt_slight_blood ); } else if ( ModelFlags & H2MDLEF_TRACER ) { CLH2_TrailParticles( old_origin, ent.origin, rt_tracer ); } else if ( ModelFlags & H2MDLEF_TRACER2 ) { CLH2_TrailParticles( old_origin, ent.origin, rt_tracer2 ); } else if ( ModelFlags & H2MDLEF_ROCKET ) { CLH2_TrailParticles( old_origin, ent.origin, rt_rocket_trail ); } else if ( ModelFlags & H2MDLEF_FIREBALL ) { CLH2_TrailParticles( old_origin, ent.origin, rt_fireball ); CLH2_FireBallLight( i, ent.origin ); } else if ( ModelFlags & H2MDLEF_ICE ) { CLH2_TrailParticles( old_origin, ent.origin, rt_ice ); } else if ( ModelFlags & H2MDLEF_SPIT ) { CLH2_TrailParticles( old_origin, ent.origin, rt_spit ); CLH2_SpitLight( i, ent.origin ); } else if ( ModelFlags & H2MDLEF_SPELL ) { CLH2_TrailParticles( old_origin, ent.origin, rt_spell ); } else if ( ModelFlags & H2MDLEF_GRENADE ) { CLH2_TrailParticles( old_origin, ent.origin, rt_grensmoke ); } else if ( ModelFlags & H2MDLEF_TRACER3 ) { CLH2_TrailParticles( old_origin, ent.origin, rt_voor_trail ); } else if ( ModelFlags & H2MDLEF_VORP_MISSILE ) { CLH2_TrailParticles( old_origin, ent.origin, rt_vorpal ); } else if ( ModelFlags & H2MDLEF_SET_STAFF ) { CLH2_TrailParticles( old_origin, ent.origin,rt_setstaff ); } else if ( ModelFlags & H2MDLEF_MAGICMISSILE ) { if ( ( rand() & 3 ) < 1 ) { CLH2_TrailParticles( old_origin, ent.origin, rt_magicmissile ); } } else if ( ModelFlags & H2MDLEF_BONESHARD ) { CLH2_TrailParticles( old_origin, ent.origin, rt_boneshard ); } else if ( ModelFlags & H2MDLEF_SCARAB ) { CLH2_TrailParticles( old_origin, ent.origin, rt_scarab ); } else if ( ModelFlags & H2MDLEF_ACIDBALL ) { CLH2_TrailParticles( old_origin, ent.origin, rt_acidball ); } else if ( ModelFlags & H2MDLEF_BLOODSHOT ) { CLH2_TrailParticles( old_origin, ent.origin, rt_bloodshot ); } } }
void CLH2_SetRefEntAxis( refEntity_t* entity, vec3_t entityAngles, vec3_t angleAdd, int scale, int absoluteLight, int drawFlags ) { if ( drawFlags & H2DRF_TRANSLUCENT ) { entity->renderfx |= RF_TRANSLUCENT; entity->shaderRGBA[ 3 ] = 100; } vec3_t angles; if ( R_IsMeshModel( entity->hModel ) ) { if ( R_ModelFlags( entity->hModel ) & H2MDLEF_FACE_VIEW ) { // yaw and pitch must be 0 so that renderer can safely multply matrices. angles[ PITCH ] = 0; angles[ YAW ] = 0; angles[ ROLL ] = entityAngles[ ROLL ]; AnglesToAxis( angles, entity->axis ); } else { if ( R_ModelFlags( entity->hModel ) & H2MDLEF_ROTATE ) { angles[ YAW ] = AngleMod( ( entity->origin[ 0 ] + entity->origin[ 1 ] ) * 0.8 + ( 108 * cl.serverTime * 0.001 ) ); } else { angles[ YAW ] = entityAngles[ YAW ]; } angles[ ROLL ] = entityAngles[ ROLL ]; // stupid quake bug angles[ PITCH ] = -entityAngles[ PITCH ]; if ( angleAdd[ 0 ] || angleAdd[ 1 ] || angleAdd[ 2 ] ) { float BaseAxis[ 3 ][ 3 ]; AnglesToAxis( angles, BaseAxis ); // For clientside rotation stuff float AddAxis[ 3 ][ 3 ]; AnglesToAxis( angleAdd, AddAxis ); MatrixMultiply( AddAxis, BaseAxis, entity->axis ); } else { AnglesToAxis( angles, entity->axis ); } } if ( ( R_ModelFlags( entity->hModel ) & H2MDLEF_ROTATE ) || ( scale != 0 && scale != 100 ) ) { entity->renderfx |= RF_LIGHTING_ORIGIN; VectorCopy( entity->origin, entity->lightingOrigin ); } if ( R_ModelFlags( entity->hModel ) & H2MDLEF_ROTATE ) { // Floating motion float delta = sin( entity->origin[ 0 ] + entity->origin[ 1 ] + ( cl.serverTime * 0.001 * 3 ) ) * 5.5; VectorMA( entity->origin, delta, entity->axis[ 2 ], entity->origin ); absoluteLight = 60 + 34 + sin( entity->origin[ 0 ] + entity->origin[ 1 ] + ( cl.serverTime * 0.001 * 3.8 ) ) * 34; drawFlags |= H2MLS_ABSLIGHT; } if ( scale != 0 && scale != 100 ) { float entScale = ( float )scale / 100.0; float esx; float esy; float esz; switch ( drawFlags & H2SCALE_TYPE_MASKIN ) { case H2SCALE_TYPE_UNIFORM: esx = entScale; esy = entScale; esz = entScale; break; case H2SCALE_TYPE_XYONLY: esx = entScale; esy = entScale; esz = 1; break; case H2SCALE_TYPE_ZONLY: esx = 1; esy = 1; esz = entScale; break; } float etz; switch ( drawFlags & H2SCALE_ORIGIN_MASKIN ) { case H2SCALE_ORIGIN_CENTER: etz = 0.5; break; case H2SCALE_ORIGIN_BOTTOM: etz = 0; break; case H2SCALE_ORIGIN_TOP: etz = 1.0; break; } vec3_t Out; R_CalculateModelScaleOffset( entity->hModel, esx, esy, esz, etz, Out ); VectorMA( entity->origin, Out[ 0 ], entity->axis[ 0 ], entity->origin ); VectorMA( entity->origin, Out[ 1 ], entity->axis[ 1 ], entity->origin ); VectorMA( entity->origin, Out[ 2 ], entity->axis[ 2 ], entity->origin ); VectorScale( entity->axis[ 0 ], esx, entity->axis[ 0 ] ); VectorScale( entity->axis[ 1 ], esy, entity->axis[ 1 ] ); VectorScale( entity->axis[ 2 ], esz, entity->axis[ 2 ] ); entity->nonNormalizedAxes = true; } } else { angles[ YAW ] = entityAngles[ YAW ]; angles[ ROLL ] = entityAngles[ ROLL ]; angles[ PITCH ] = entityAngles[ PITCH ]; AnglesToAxis( angles, entity->axis ); } int mls = drawFlags & H2MLS_MASKIN; if ( mls == H2MLS_ABSLIGHT ) { entity->renderfx |= RF_ABSOLUTE_LIGHT; entity->absoluteLight = absoluteLight / 128.0; } else if ( mls != H2MLS_NONE ) { // Use a model light style (25-30) entity->renderfx |= RF_ABSOLUTE_LIGHT; entity->absoluteLight = cl_lightstyle[ 24 + mls ].value[ 0 ] / 2; } }
void NQD_LinkEntities (void) { entity_t ent; centity_t *cent; entity_state_t *state; float f; struct model_s *model; int modelflags; vec3_t cur_origin; vec3_t old_origin; float autorotate; int i; int num; f = NQD_LerpPoint (); NQD_LerpPlayerinfo (f); autorotate = anglemod (100*cl.time); memset (&ent, 0, sizeof(ent)); for (num = 1; num < nq_num_entities; num++) { cent = &cl_entities[num]; state = ¢->current; if (cent->lastframe != cl_entframecount) continue; // not present in this frame MSG_UnpackOrigin (state->s_origin, cur_origin); if (state->effects & EF_BRIGHTFIELD) CL_EntityParticles (cur_origin); // spawn light flashes, even ones coming from invisible objects if (state->effects & EF_MUZZLEFLASH) { vec3_t angles, forward; cdlight_t *dl; dl = CL_AllocDlight (-num); MSG_UnpackAngles (state->s_angles, angles); AngleVectors (angles, forward, NULL, NULL); VectorMA (cur_origin, 18, forward, dl->origin); dl->origin[2] += 16; dl->radius = 200 + (rand()&31); dl->minlight = 32; dl->die = cl.time + 0.1; dl->type = lt_muzzleflash; } if (state->effects & EF_BRIGHTLIGHT) { if (state->modelindex != cl_playerindex || r_powerupglow.value) { vec3_t tmp; VectorCopy (cur_origin, tmp); tmp[2] += 16; V_AddDlight (state->number, tmp, 400 + (rand()&31), 0, lt_default); } } if (state->effects & EF_DIMLIGHT) if (state->modelindex != cl_playerindex || r_powerupglow.value) V_AddDlight (state->number, cur_origin, 200 + (rand()&31), 0, lt_default); // if set to invisible, skip if (!state->modelindex) continue; cent->current = *state; ent.model = model = cl.model_precache[state->modelindex]; if (!model) Host_Error ("CL_LinkPacketEntities: bad modelindex"); if (cl_r2g.value && cl_grenadeindex != -1) if (state->modelindex == cl_rocketindex) ent.model = cl.model_precache[cl_grenadeindex]; modelflags = R_ModelFlags (model); // rotate binary objects locally if (modelflags & MF_ROTATE) { ent.angles[0] = 0; ent.angles[1] = autorotate; ent.angles[2] = 0; } else { vec3_t old, cur; MSG_UnpackAngles (cent->current.s_angles, old); MSG_UnpackAngles (cent->previous.s_angles, cur); LerpAngles (old, cur, f, ent.angles); } if (num == nq_viewentity) { extern float nq_speed; float f; nq_speed = 0; for (i = 0; i < 3; i++) { f = (cent->current.s_origin[i] - cent->previous.s_origin[i]) * 0.125; nq_speed += f * f; } if (nq_speed) nq_speed = sqrt(nq_speed); nq_speed /= nq_mtime[0] - nq_mtime[1]; } // calculate origin for (i = 0; i < 3; i++) { if (abs(cent->current.s_origin[i] - cent->previous.s_origin[i]) > 128 * 8) { // teleport or something, don't lerp VectorCopy (cur_origin, ent.origin); if (num == nq_viewentity) nq_player_teleported = true; break; } ent.origin[i] = cent->previous.s_origin[i] * 0.125 + f * (cur_origin[i] - cent->previous.s_origin[i] * 0.125); } if (num == nq_viewentity) { VectorCopy (ent.origin, cent->trail_origin); // FIXME? continue; // player entity } if (cl_deadbodyfilter.value && state->modelindex == cl_playerindex && ( (i=state->frame)==49 || i==60 || i==69 || i==84 || i==93 || i==102) ) continue; if (cl_gibfilter.value && cl.modelinfos[state->modelindex] == mi_gib) continue; // set colormap if (state->colormap && state->colormap <= MAX_CLIENTS && state->modelindex == cl_playerindex ) ent.colormap = state->colormap; else ent.colormap = 0; // set skin ent.skinnum = state->skinnum; // set frame ent.frame = state->frame; // add automatic particle trails if ((modelflags & ~MF_ROTATE)) { if (false /*cl_entframecount == 1 || cent->lastframe != cl_entframecount-1*/) { // not in last message VectorCopy (ent.origin, old_origin); } else { VectorCopy (cent->trail_origin, old_origin); for (i=0 ; i<3 ; i++) if ( abs(old_origin[i] - ent.origin[i]) > 128) { // no trail if too far VectorCopy (ent.origin, old_origin); break; } } if (modelflags & MF_ROCKET) { if (r_rockettrail.value) { if (r_rockettrail.value == 2) CL_GrenadeTrail (old_origin, ent.origin, cent->trail_origin); else CL_RocketTrail (old_origin, ent.origin, cent->trail_origin); } else VectorCopy (ent.origin, cent->trail_origin); if (r_rocketlight.value) CL_NewDlight (state->number, ent.origin, 200, 0.1, lt_rocket); } else if (modelflags & MF_GRENADE && r_grenadetrail.value) CL_GrenadeTrail (old_origin, ent.origin, cent->trail_origin); else if (modelflags & MF_GIB) CL_BloodTrail (old_origin, ent.origin, cent->trail_origin); else if (modelflags & MF_ZOMGIB) CL_SlightBloodTrail (old_origin, ent.origin, cent->trail_origin); else if (modelflags & MF_TRACER) CL_TracerTrail (old_origin, ent.origin, cent->trail_origin, 52); else if (modelflags & MF_TRACER2) CL_TracerTrail (old_origin, ent.origin, cent->trail_origin, 230); else if (modelflags & MF_TRACER3) CL_VoorTrail (old_origin, ent.origin, cent->trail_origin); } cent->lastframe = cl_entframecount; V_AddEntity (&ent); } if (nq_viewentity == 0) Host_Error ("viewentity == 0"); VectorCopy (cl_entities[nq_viewentity].trail_origin, cl.simorg); }