/* ================= UpdateClientData Data sent to current client only engine sets cd to 0 before calling. ================= */ void UpdateClientData ( const struct edict_s *ent, int sendweapons, struct clientdata_s *cd ) { cd->flags = ent->v.flags; cd->health = ent->v.health; cd->viewmodel = MODEL_INDEX( STRING( ent->v.viewmodel ) ); cd->waterlevel = ent->v.waterlevel; cd->watertype = ent->v.watertype; cd->weapons = ent->v.weapons; // Vectors cd->origin = ent->v.origin; cd->velocity = ent->v.velocity; cd->view_ofs = ent->v.view_ofs; cd->punchangle = ent->v.punchangle; cd->bInDuck = ent->v.bInDuck; cd->flTimeStepSound = ent->v.flTimeStepSound; cd->flDuckTime = ent->v.flDuckTime; cd->flSwimTime = ent->v.flSwimTime; cd->waterjumptime = ent->v.teleport_time; strcpy( cd->physinfo, ENGINE_GETPHYSINFO( ent ) ); cd->maxspeed = ent->v.maxspeed; cd->fov = ent->v.fov; cd->weaponanim = ent->v.weaponanim; cd->pushmsec = ent->v.pushmsec; // Spectator cd->iuser1 = ent->v.iuser1; cd->iuser2 = ent->v.iuser2; if ( sendweapons ) { entvars_t *pev = (entvars_t *)&ent->v; CBasePlayer *pl = ( CBasePlayer *) CBasePlayer::Instance( pev ); if ( pl ) { cd->m_flNextAttack = pl->m_flNextAttack; if ( pl->m_pActiveItem ) { CBasePlayerWeapon *gun; gun = (CBasePlayerWeapon *)pl->m_pActiveItem->GetWeaponPtr(); if ( gun && gun->UseDecrement() ) { ItemInfo II; memset( &II, 0, sizeof( II ) ); gun->GetItemInfo( &II ); cd->m_iId = II.iId; } } } } }
void StartFrame() { edict_t* ent = NULL; while( !FNullEnt( ent = FIND_ENTITY_BY_STRING( ent, "classname", "player" ) ) ) { if( esfmodels[ENTINDEX(ent)-1].bSet ) { ent->v.modelindex = MODEL_INDEX( esfmodels[ENTINDEX(ent)-1].szModel ); ent->v.model = MAKE_STRING( esfmodels[ENTINDEX(ent)-1].szModel ); } } RETURN_META( MRES_HANDLED ); }
/* AddToFullPack Return 1 if the entity state has been filled in for the ent and the entity will be propagated to the client, 0 otherwise state is the server maintained copy of the state info that is transmitted to the client a MOD could alter values copied into state to send the "host" a different look for a particular entity update, etc. e and ent are the entity that is being added to the update, if 1 is returned host is the player's edict of the player whom we are sending the update to player is 1 if the ent/e is a player and 0 otherwise pSet is either the PAS or PVS that we previous set up. We can use it to ask the engine to filter the entity against the PAS or PVS. we could also use the pas/ pvs that we set in SetupVisibility, if we wanted to. Caching the value is valid in that case, but still only for the current frame */ int AddToFullPack( struct entity_state_s *state, int e, edict_t *ent, edict_t *host, int hostflags, int player, unsigned char *pSet ) { int i; // don't send if flagged for NODRAW and it's not the host getting the message if ( ( ent->v.effects == EF_NODRAW ) && ( ent != host ) ) return 0; // Ignore ents without valid / visible models if ( !ent->v.modelindex || !STRING( ent->v.model ) ) return 0; // Don't send spectators to other players if ( ( ent->v.flags & FL_SPECTATOR ) && ( ent != host ) ) { return 0; } // Ignore if not the host and not touching a PVS/PAS leaf // If pSet is NULL, then the test will always succeed and the entity will be added to the update if ( ent != host ) { if ( !ENGINE_CHECK_VISIBILITY( (const struct edict_s *)ent, pSet ) ) { // env_sky is visible always if( !FClassnameIs( ent, "env_sky" )) { return 0; } } } // Don't send entity to local client if the client says it's predicting the entity itself. if ( ent->v.flags & FL_SKIPLOCALHOST ) { if ( hostflags & 4 ) return 0; // it's a portal pass if ( ( hostflags & 1 ) && ( ent->v.owner == host ) ) return 0; } if ( host->v.groupinfo ) { UTIL_SetGroupTrace( host->v.groupinfo, GROUP_OP_AND ); // Should always be set, of course if ( ent->v.groupinfo ) { if ( g_groupop == GROUP_OP_AND ) { if ( !(ent->v.groupinfo & host->v.groupinfo ) ) return 0; } else if ( g_groupop == GROUP_OP_NAND ) { if ( ent->v.groupinfo & host->v.groupinfo ) return 0; } } UTIL_UnsetGroupTrace(); } memset( state, 0, sizeof( *state ) ); // Assign index so we can track this entity from frame to frame and // delta from it. state->number = e; state->entityType = ENTITY_NORMAL; // Flag custom entities. if ( ent->v.flags & FL_CUSTOMENTITY ) { state->entityType = ENTITY_BEAM; } // // Copy state data // // Round animtime to nearest millisecond state->animtime = (int)(1000.0 * ent->v.animtime ) / 1000.0; memcpy( state->origin, ent->v.origin, 3 * sizeof( float ) ); memcpy( state->angles, ent->v.angles, 3 * sizeof( float ) ); memcpy( state->mins, ent->v.mins, 3 * sizeof( float ) ); memcpy( state->maxs, ent->v.maxs, 3 * sizeof( float ) ); memcpy( state->startpos, ent->v.startpos, 3 * sizeof( float ) ); memcpy( state->endpos, ent->v.endpos, 3 * sizeof( float ) ); memcpy( state->velocity, ent->v.velocity, 3 * sizeof( float ) ); state->impacttime = ent->v.impacttime; state->starttime = ent->v.starttime; state->modelindex = ent->v.modelindex; state->frame = ent->v.frame; state->skin = ent->v.skin; state->effects = ent->v.effects; // This non-player entity is being moved by the game .dll and not the physics simulation system // make sure that we interpolate it's position on the client if it moves if ( !player && ent->v.animtime && ent->v.velocity[ 0 ] == 0 && ent->v.velocity[ 1 ] == 0 && ent->v.velocity[ 2 ] == 0 ) { state->eflags |= EFLAG_SLERP; } state->scale = ent->v.scale; state->solid = ent->v.solid; state->colormap = ent->v.colormap; state->movetype = ent->v.movetype; state->sequence = ent->v.sequence; state->framerate = ent->v.framerate; state->body = ent->v.body; for (i = 0; i < 4; i++) { state->controller[i] = ent->v.controller[i]; } for (i = 0; i < 2; i++) { state->blending[i] = ent->v.blending[i]; } state->rendermode = ent->v.rendermode; state->renderamt = ent->v.renderamt; state->renderfx = ent->v.renderfx; state->rendercolor.r = ent->v.rendercolor.x; state->rendercolor.g = ent->v.rendercolor.y; state->rendercolor.b = ent->v.rendercolor.z; state->aiment = 0; if ( ent->v.aiment ) { state->aiment = ENTINDEX( ent->v.aiment ); } state->owner = 0; if ( ent->v.owner ) { int owner = ENTINDEX( ent->v.owner ); // Only care if owned by a player if ( owner >= 1 && owner <= gpGlobals->maxClients ) { state->owner = owner; } } state->onground = 0; if ( ent->v.groundentity ) { state->onground = ENTINDEX( ent->v.groundentity ); } // HACK: Somewhat... // Class is overridden for non-players to signify a breakable glass object ( sort of a class? ) if ( !player ) { state->playerclass = ent->v.playerclass; } // Special stuff for players only if ( player ) { memcpy( state->basevelocity, ent->v.basevelocity, 3 * sizeof( float ) ); state->weaponmodel = MODEL_INDEX( STRING( ent->v.weaponmodel ) ); state->gaitsequence = ent->v.gaitsequence; state->spectator = ent->v.flags & FL_SPECTATOR; state->friction = ent->v.friction; state->gravity = ent->v.gravity; // state->team = ent->v.team; // state->usehull = ( ent->v.flags & FL_DUCKING ) ? 1 : 0; state->health = ent->v.health; } return 1; }
/* ================= UpdateClientData Data sent to current client only engine sets cd to 0 before calling. ================= */ void UpdateClientData ( const struct edict_s *ent, int sendweapons, struct clientdata_s *cd ) { cd->flags = ent->v.flags; cd->health = ent->v.health; cd->viewmodel = MODEL_INDEX( STRING( ent->v.viewmodel ) ); cd->waterlevel = ent->v.waterlevel; cd->watertype = ent->v.watertype; cd->weapons = ent->v.weapons; // Vectors cd->origin = ent->v.origin; cd->velocity = ent->v.velocity; cd->view_ofs = ent->v.view_ofs; cd->punchangle = ent->v.punchangle; cd->bInDuck = ent->v.bInDuck; cd->flTimeStepSound = ent->v.flTimeStepSound; cd->flDuckTime = ent->v.flDuckTime; cd->flSwimTime = ent->v.flSwimTime; cd->waterjumptime = ent->v.teleport_time; strcpy( cd->physinfo, ENGINE_GETPHYSINFO( ent ) ); cd->maxspeed = ent->v.maxspeed; cd->fov = ent->v.fov; cd->weaponanim = ent->v.weaponanim; cd->pushmsec = ent->v.pushmsec; #if defined( CLIENT_WEAPONS ) if ( sendweapons ) { entvars_t *pev = (entvars_t *)&ent->v; CBasePlayer *pl = ( CBasePlayer *) CBasePlayer::Instance( pev ); if ( pl ) { cd->m_flNextAttack = pl->m_flNextAttack; cd->fuser2 = pl->m_flNextAmmoBurn; cd->fuser3 = pl->m_flAmmoStartCharge; cd->vuser1.x = pl->ammo_9mm; cd->vuser1.y = pl->ammo_357; cd->vuser1.z = pl->ammo_argrens; cd->ammo_nails = pl->ammo_bolts; cd->ammo_shells = pl->ammo_buckshot; cd->ammo_rockets = pl->ammo_rockets; cd->ammo_cells = pl->ammo_uranium; cd->vuser2.x = pl->ammo_hornets; if ( pl->m_pActiveItem ) { CBasePlayerWeapon *gun; gun = (CBasePlayerWeapon *)pl->m_pActiveItem->GetWeaponPtr(); if ( gun && gun->UseDecrement() ) { ItemInfo II; memset( &II, 0, sizeof( II ) ); gun->GetItemInfo( &II ); cd->m_iId = II.iId; cd->vuser3.z = gun->m_iSecondaryAmmoType; cd->vuser4.x = gun->m_iPrimaryAmmoType; cd->vuser4.y = pl->m_rgAmmo[gun->m_iPrimaryAmmoType]; cd->vuser4.z = pl->m_rgAmmo[gun->m_iSecondaryAmmoType]; if ( pl->m_pActiveItem->m_iId == WEAPON_RPG ) { cd->vuser2.y = ( ( CRpg * )pl->m_pActiveItem)->m_fSpotActive; cd->vuser2.z = ( ( CRpg * )pl->m_pActiveItem)->m_cActiveRockets; } } } } } #endif }