bool CHalfLife2::GetMapDisplayName(const char *pMapName, char *pDisplayname, size_t nMapNameMax) { SMFindMapResult result = FindMap(pMapName, pDisplayname, nMapNameMax); if (result == SMFindMapResult::NotFound) { return false; } #if SOURCE_ENGINE == SE_CSGO // In CSGO, the path separator is used in workshop maps. char workshop[10]; ke::SafeSprintf(workshop, SM_ARRAYSIZE(workshop), "%s%c", "workshop", PLATFORM_SEP_CHAR); char *lastSlashPos; // In CSGO, workshop maps show up as workshop/123456789/mapname or workshop\123456789\mapname depending on OS if (strncmp(pDisplayname, workshop, 9) == 0 && (lastSlashPos = strrchr(pDisplayname, PLATFORM_SEP_CHAR)) != NULL) { ke::SafeStrcpy(pDisplayname, nMapNameMax, &lastSlashPos[1]); return true; } #elif SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_BMS char *ugcPos; // In TF2 and BMS, workshop maps show up as workshop/mapname.ugc123456789 regardless of OS if (strncmp(pDisplayname, "workshop/", 9) == 0 && (ugcPos = strstr(pDisplayname, ".ugc")) != NULL) { // Overwrite the . with a null and SafeStrcpy will handle the rest ugcPos[0] = '\0'; ke::SafeStrcpy(pDisplayname, nMapNameMax, &pDisplayname[9]); return true; } #endif return true; }
void SoundHooks::OnEmitSound2(IRecipientFilter &filter, int iEntIndex, int iChannel, const char *pSample, float flVolume, float flAttenuation, int iFlags, int iPitch, const Vector *pOrigin, const Vector *pDirection, CUtlVector<Vector> *pUtlVecOrigins, bool bUpdatePositions, float soundtime, int speakerentity) #endif { SoundHookIter iter; IPluginFunction *pFunc; cell_t res = static_cast<ResultType>(Pl_Continue); cell_t sndlevel = static_cast<cell_t>(ATTN_TO_SNDLVL(flAttenuation)); char buffer[PLATFORM_MAX_PATH]; strcpy(buffer, pSample); char soundEntry[PLATFORM_MAX_PATH] = ""; #if SOURCE_ENGINE >= SE_PORTAL2 Q_strncpy(soundEntry, pSoundEntry, sizeof(soundEntry)); #endif #if SOURCE_ENGINE < SE_PORTAL2 int nSeed = 0; #endif for (iter=m_NormalFuncs.begin(); iter!=m_NormalFuncs.end(); iter++) { int players[SM_MAXPLAYERS], size; size = _FillInPlayers(players, &filter); pFunc = (*iter); pFunc->PushArray(players, SM_ARRAYSIZE(players), SM_PARAM_COPYBACK); pFunc->PushCellByRef(&size); pFunc->PushStringEx(buffer, sizeof(buffer), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK); pFunc->PushCellByRef(&iEntIndex); pFunc->PushCellByRef(&iChannel); pFunc->PushFloatByRef(&flVolume); pFunc->PushCellByRef(&sndlevel); pFunc->PushCellByRef(&iPitch); pFunc->PushCellByRef(&iFlags); pFunc->PushStringEx(soundEntry, sizeof(soundEntry), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK); pFunc->PushCellByRef(&nSeed); g_InSoundHook = true; pFunc->Execute(&res); g_InSoundHook = false; switch (res) { case Pl_Handled: case Pl_Stop: { #if SOURCE_ENGINE >= SE_PORTAL2 RETURN_META_VALUE(MRES_SUPERCEDE, -1); #else RETURN_META(MRES_SUPERCEDE); #endif } case Pl_Changed: { /* Client validation */ for (int i = 0; i < size; i++) { int client = players[i]; IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client); if (!pPlayer) { pFunc->GetParentContext()->BlamePluginError(pFunc, "Client index %d is invalid", client); } else if (!pPlayer->IsInGame()) { pFunc->GetParentContext()->BlamePluginError(pFunc, "Client %d is not connected", client); } else { continue; } #if SOURCE_ENGINE >= SE_PORTAL2 RETURN_META_VALUE(MRES_IGNORED, -1 ); #else return; #endif } #if SOURCE_ENGINE >= SE_PORTAL2 if (strcmp(pSoundEntry, soundEntry) != 0 || strcmp(pSample, buffer) != 0) { if (strcmp(soundEntry, buffer) == 0) nSoundEntryHash = -1; else if (strcmp(soundEntry, "") != 0) nSoundEntryHash = GenerateSoundEntryHash(soundEntry); } #endif CellRecipientFilter crf; crf.Initialize(players, size); #if SOURCE_ENGINE >= SE_PORTAL2 RETURN_META_VALUE_NEWPARAMS( MRES_IGNORED, -1, static_cast<int (IEngineSound::*)(IRecipientFilter &, int, int, const char *, unsigned int, const char *, float, float, int, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>(&IEngineSound::EmitSound), (crf, iEntIndex, iChannel, soundEntry, nSoundEntryHash, buffer, flVolume, SNDLVL_TO_ATTN(static_cast<soundlevel_t>(sndlevel)), nSeed, iFlags, iPitch, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity) ); #elif SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_SDK2013 \ || SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_TF2 RETURN_META_NEWPARAMS( MRES_IGNORED, static_cast<void (IEngineSound::*)(IRecipientFilter &, int, int, const char *, float, float, int, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>(&IEngineSound::EmitSound), (crf, iEntIndex, iChannel, buffer, flVolume, SNDLVL_TO_ATTN(static_cast<soundlevel_t>(sndlevel)), iFlags, iPitch, iSpecialDSP, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity) ); #else RETURN_META_NEWPARAMS( MRES_IGNORED, static_cast<void (IEngineSound::*)(IRecipientFilter &, int, int, const char *, float, float, int, int, const Vector *, const Vector *, CUtlVector<Vector> *, bool, float, int)>(&IEngineSound::EmitSound), (crf, iEntIndex, iChannel, buffer, flVolume, SNDLVL_TO_ATTN(static_cast<soundlevel_t>(sndlevel)), iFlags, iPitch, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity) ); #endif } } } #if SOURCE_ENGINE >= SE_PORTAL2 RETURN_META_VALUE(MRES_IGNORED, -1 ); #endif }
SMFindMapResult CHalfLife2::FindMap(const char *pMapName, char *pFoundMap, size_t nMapNameMax) { ke::SafeStrcpy(pFoundMap, nMapNameMax, pMapName); #if SOURCE_ENGINE >= SE_LEFT4DEAD static char mapNameTmp[PLATFORM_MAX_PATH]; g_SourceMod.Format(mapNameTmp, sizeof(mapNameTmp), "maps%c%s.bsp", PLATFORM_SEP_CHAR, pMapName); if (filesystem->FileExists(mapNameTmp, "GAME")) { // If this is already an exact match, don't attempt to autocomplete it further (de_dust -> de_dust2). // ... but still check that map file is actually valid. // We check FileExists first to avoid console message about IsMapValid with invalid map. return engine->IsMapValid(pMapName) == 0 ? SMFindMapResult::NotFound : SMFindMapResult::Found; } static ConCommand *pHelperCmd = g_pCVar->FindCommand("changelevel"); // This shouldn't happen. if (!pHelperCmd || !pHelperCmd->CanAutoComplete()) { return engine->IsMapValid(pMapName) == 0 ? SMFindMapResult::NotFound : SMFindMapResult::Found; } static size_t helperCmdLen = strlen(pHelperCmd->GetName()); CUtlVector<CUtlString> results; pHelperCmd->AutoCompleteSuggest(pMapName, results); if (results.Count() == 0) return SMFindMapResult::NotFound; // Results come back as you'd see in autocomplete. (ie. "changelevel fullmapnamehere"), // so skip ahead to start of map path/name // Like the engine, we're only going to deal with the first match. bool bExactMatch = Q_strcmp(pMapName, &results[0][helperCmdLen + 1]) == 0; if (bExactMatch) { return SMFindMapResult::Found; } else { ke::SafeStrcpy(pFoundMap, nMapNameMax, &results[0][helperCmdLen + 1]); return SMFindMapResult::FuzzyMatch; } #elif SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_BMS static char szTemp[PLATFORM_MAX_PATH]; if (pFoundMap == NULL) { ke::SafeStrcpy(szTemp, SM_ARRAYSIZE(szTemp), pMapName); pFoundMap = szTemp; nMapNameMax = 0; } return static_cast<SMFindMapResult>(engine->FindMap(pFoundMap, static_cast<int>(nMapNameMax))); #elif SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_SDK2013 static IVEngineServer *engine21 = (IVEngineServer *)(g_SMAPI->GetEngineFactory()("VEngineServer021", nullptr)); return engine21->IsMapValid(pMapName) == 0 ? SMFindMapResult::NotFound : SMFindMapResult::Found; #else return engine->IsMapValid(pMapName) == 0 ? SMFindMapResult::NotFound : SMFindMapResult::Found; #endif }