int CPlayer::GetLifeState() { if (lifestate_offset == -1) { if (!g_pGameConf->GetOffset("m_lifeState", &lifestate_offset)) { lifestate_offset = -2; } } if (lifestate_offset < 0) { IPlayerInfo *info = GetPlayerInfo(); if (info == NULL) { return PLAYER_LIFE_UNKNOWN; } return info->IsDead() ? PLAYER_LIFE_DEAD : PLAYER_LIFE_ALIVE; } if (m_pEdict == NULL) { return PLAYER_LIFE_UNKNOWN; } CBaseEntity *pEntity; IServerUnknown *pUnknown = m_pEdict->GetUnknown(); if (pUnknown == NULL || (pEntity = pUnknown->GetBaseEntity()) == NULL) { return PLAYER_LIFE_UNKNOWN; } if (*((uint8_t *)pEntity + lifestate_offset) == LIFE_ALIVE) { return PLAYER_LIFE_ALIVE; } else { return PLAYER_LIFE_DEAD; } }
//--------------------------------------------------------------------------------- // Purpose: called once per server frame, do recurring work here (like checking for timeouts) //--------------------------------------------------------------------------------- void WebSpecPlugin::GameFrame( bool simulating ) { if (gpGlobals->curtime - g_lastUpdateTime > WEBSPEC_UPDATE_RATE_IN_SECONDS && ws_spectators.Count() > 0) { char *buffer = (char *)malloc(MAX_BUFFER_SIZE); Vector playerOrigin; QAngle playerAngles; float playerUberCharge; int userid, health, playerClass; IPlayerInfo *playerInfo; CBaseEntity *playerEntity; int bufferLength; bufferLength = sprintf(buffer, "O"); for (int i = 1; i < gpGlobals->maxClients; i++) { playerInfo = playerInfoManager->GetPlayerInfo(engine->PEntityOfEntIndex(i)); if (playerInfo == NULL || !playerInfo->IsConnected() || playerInfo->IsDead()) continue; if (strlen(buffer) > 1) snprintf(buffer, MAX_BUFFER_SIZE, "%s|", buffer); userid = playerInfo->GetUserID(); health = playerInfo->GetHealth(); playerOrigin = playerInfo->GetAbsOrigin(); playerEntity = serverGameEnts->EdictToBaseEntity(engine->PEntityOfEntIndex(i)); playerClass = *MakePtr(int*, playerEntity, WSOffsets::pCTFPlayer__m_iClass); playerAngles = CBaseEntity_EyeAngles(playerEntity); if (playerClass == TFClass_Medic) { CBaseCombatCharacter *playerCombatCharacter = CBaseEntity_MyCombatCharacterPointer(playerEntity); CBaseCombatWeapon *slot1Weapon = CBaseCombatCharacter_Weapon_GetSlot(playerCombatCharacter, 1); playerUberCharge = *MakePtr(float*, slot1Weapon, WSOffsets::pCWeaponMedigun__m_flChargeLevel); } else {
//================================================================================= // Callback for the 'webspec' protocol // Manages spectator connections & sending Initial messages to new spectators //================================================================================= int webspec_callback(struct libwebsocket_context *ctx, struct libwebsocket *wsi, enum libwebsocket_callback_reasons reason, void *user, void *in, size_t len) { switch (reason) { case LWS_CALLBACK_ESTABLISHED: { Msg("[WS] New connection\n"); // New connection ws_spectators.AddToTail(wsi); // Send basic game info to let client set up // MapName, Server name (may remove), current team names char *buffer = (char*)malloc(MAX_BUFFER_SIZE); char *mapName = (char*) STRING(gpGlobals->mapname); ConVarRef hostNameCVar = ConVarRef("hostname"); string_t hostname; if (hostNameCVar.IsValid()) hostname = MAKE_STRING(hostNameCVar.GetString()); else hostname = MAKE_STRING("WebSpec Demo Server"); //Can't imagine when hostname would be invalid, but this is Source int length = snprintf(buffer, MAX_BUFFER_SIZE, "%c%s:%s:%s:%s", WSPacket_Init, mapName, STRING(hostname), STRING(ws_teamName[1]), STRING(ws_teamName[0])); SendPacketToOne(buffer, length, wsi); free(buffer); //Send connected players IPlayerInfo *playerInfo; for (int i=1; i<=gpGlobals->maxClients; i++) { playerInfo = playerInfoManager->GetPlayerInfo(engine->PEntityOfEntIndex(i)); if (playerInfo != NULL && playerInfo->IsConnected()) { buffer = (char *)malloc(MAX_BUFFER_SIZE); int userid = playerInfo->GetUserID(); int teamid = playerInfo->GetTeamIndex(); int health = playerInfo->GetHealth(); int maxHealth = playerInfo->GetMaxHealth(); bool alive = !playerInfo->IsDead(); string_t playerName = MAKE_STRING(playerInfo->GetName()); //Pointer magic to get TF2 class CBaseEntity *playerEntity = serverGameEnts->EdictToBaseEntity(engine->PEntityOfEntIndex(i)); int playerClass = *MakePtr(int*, playerEntity, WSOffsets::pCTFPlayer__m_iClass); float uberCharge = 0.0f; if (playerClass == TFClass_Medic) { //Way more pointer magic to get ubercharge from medigun CBaseCombatCharacter *playerCombatCharacter = CBaseEntity_MyCombatCharacterPointer(playerEntity); CBaseCombatWeapon *slot1Weapon = CBaseCombatCharacter_Weapon_GetSlot(playerCombatCharacter, 1); uberCharge = *MakePtr(float*, slot1Weapon, WSOffsets::pCWeaponMedigun__m_flChargeLevel); } int length = snprintf(buffer, MAX_BUFFER_SIZE, "%c%d:%d:%d:%d:%d:%d:0:%d:%s", 'C', userid, teamid, playerClass, health, maxHealth, alive, Round(uberCharge*100.0f), STRING(playerName)); SendPacketToOne(buffer, length, wsi); free(buffer); } } break; }