static cell_t smn_PbSetVector2D(IPluginContext *pCtx, const cell_t *params) { GET_MSG_FROM_HANDLE_OR_ERR(); GET_FIELD_NAME_OR_ERR(); cell_t *vecParams; if ((err=pCtx->LocalToPhysAddr(params[3], &vecParams)) != SP_ERROR_NONE) { pCtx->ThrowNativeErrorEx(err, NULL); return 0; } Vector2D vec( sp_ctof(vecParams[0]), sp_ctof(vecParams[1])); int index = params[0] >= 4 ? params[4] : -1; if (index < 0) { if (!msg->SetVector2D(strField, vec)) { return pCtx->ThrowNativeError("Invalid field \"%s\" for message \"%s\"", strField, msg->GetProtobufMessage()->GetTypeName().c_str()); } } else { if (!msg->SetRepeatedVector2D(strField, index, vec)) { return pCtx->ThrowNativeError("Invalid field \"%s\"[%d] for message \"%s\"", strField, index, msg->GetProtobufMessage()->GetTypeName().c_str()); } } return 1; }
static cell_t smn_TEWriteVector(IPluginContext *pContext, const cell_t *params) { if (!g_TEManager.IsAvailable()) { return pContext->ThrowNativeError("TempEntity System unsupported or not available, file a bug report"); } if (!g_CurrentTE) { return pContext->ThrowNativeError("No TempEntity call is in progress"); } char *prop; pContext->LocalToString(params[1], &prop); cell_t *addr; pContext->LocalToPhysAddr(params[2], &addr); float vec[3] = {sp_ctof(addr[0]), sp_ctof(addr[1]), sp_ctof(addr[2])}; if (!g_CurrentTE->TE_SetEntDataVector(prop, vec)) { return pContext->ThrowNativeError("Temp entity property \"%s\" not found", prop); } return 1; }
static cell_t GetClientsInRange(IPluginContext *pContext, const cell_t *params) { cell_t *origin; pContext->LocalToPhysAddr(params[1], &origin); Vector vOrigin(sp_ctof(origin[0]), sp_ctof(origin[1]), sp_ctof(origin[2])); ClientRangeType rangeType = (ClientRangeType) params[2]; CBitVec<ABSOLUTE_PLAYER_LIMIT> players; engine->Message_DetermineMulticastRecipients(rangeType == ClientRangeType::Audibility, vOrigin, players); cell_t *outPlayers; pContext->LocalToPhysAddr(params[3], &outPlayers); int maxPlayers = params[4]; int curPlayers = 0; int index = players.FindNextSetBit(0); while (index > -1 && curPlayers < maxPlayers) { int entidx = index + 1; CPlayer *pPlayer = g_Players.GetPlayerByIndex(entidx); if (pPlayer && pPlayer->IsInGame()) { outPlayers[curPlayers++] = entidx; } index = players.FindNextSetBit(index + 1); } return curPlayers; }
static cell_t EmitAmbientSound(IPluginContext *pContext, const cell_t *params) { cell_t entity; Vector pos; char *name; float vol, delay; int pitch, flags, level; entity = SoundReferenceToIndex(params[3]); cell_t *addr; pContext->LocalToPhysAddr(params[2], &addr); pos.x = sp_ctof(addr[0]); pos.y = sp_ctof(addr[1]); pos.z = sp_ctof(addr[2]); pContext->LocalToString(params[1], &name); vol = sp_ctof(params[6]); level = params[4]; flags = params[5]; pitch = params[7]; delay = sp_ctof(params[8]); if (g_InSoundHook) { ENGINE_CALL(EmitAmbientSound)(entity, pos, name, vol, (soundlevel_t)level, flags, pitch, delay); } else { engine->EmitAmbientSound(entity, pos, name, vol, (soundlevel_t)level, flags, pitch, delay); } return 1; }
static cell_t FadeClientVolume(IPluginContext *pContext, const cell_t *params) { int client = params[1]; if (client < 1 || client > playerhelpers->GetMaxClients()) { return pContext->ThrowNativeError("Client index %d is not valid", client); } IGamePlayer *player = playerhelpers->GetGamePlayer(client); if (!player->IsInGame()) { return pContext->ThrowNativeError("Client index %d is not in game", client); } engine->FadeClientVolume( #if SOURCE_ENGINE == SE_DOTA player->GetIndex(), #else player->GetEdict(), #endif sp_ctof(params[2]), sp_ctof(params[3]), sp_ctof(params[4]), sp_ctof(params[5])); return 1; }
static cell_t sm_SetConVarBounds(IPluginContext *pContext, const cell_t *params) { Handle_t hndl = static_cast<Handle_t>(params[1]); HandleError err; ConVar *pConVar; if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar)) != HandleError_None) { return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err); } switch (params[2]) { case ConVarBound_Upper: pConVar->SetMax(params[3] ? true : false, sp_ctof(params[4])); break; case ConVarBound_Lower: pConVar->SetMin(params[3] ? true : false, sp_ctof(params[4])); break; default: return pContext->ThrowNativeError("Invalid ConVarBounds value %d"); } return 1; }
static cell_t sm_CreateConVar(IPluginContext *pContext, const cell_t *params) { char *name, *defaultVal, *helpText; pContext->LocalToString(params[1], &name); // While the engine seems to accept a blank convar name, it causes a crash upon server quit if (name == NULL || strcmp(name, "") == 0) { return pContext->ThrowNativeError("Convar with blank name is not permitted"); } pContext->LocalToString(params[2], &defaultVal); pContext->LocalToString(params[3], &helpText); bool hasMin = params[5] ? true : false; bool hasMax = params[7] ? true : false; float min = sp_ctof(params[6]); float max = sp_ctof(params[8]); Handle_t hndl = g_ConVarManager.CreateConVar(pContext, name, defaultVal, helpText, params[4], hasMin, min, hasMax, max); if (hndl == BAD_HANDLE) { return pContext->ThrowNativeError("Convar \"%s\" was not created. A console command with the same might already exist.", name); } return hndl; }
static cell_t smn_KvSetVector(IPluginContext *pCtx, const cell_t *params) { Handle_t hndl = static_cast<Handle_t>(params[1]); HandleError herr; HandleSecurity sec; KeyValueStack *pStk; sec.pOwner = NULL; sec.pIdentity = g_pCoreIdent; if ((herr=handlesys->ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk)) != HandleError_None) { return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr); } char *key; char buffer[64]; cell_t *vector; pCtx->LocalToStringNULL(params[2], &key); pCtx->LocalToPhysAddr(params[3], &vector); UTIL_Format(buffer, sizeof(buffer), "%f %f %f", sp_ctof(vector[0]), sp_ctof(vector[1]), sp_ctof(vector[2])); pStk->pCurRoot.front()->SetString(key, buffer); return 1; }
static cell_t sm_Pow(IPluginContext *pCtx, const cell_t *params) { float base = sp_ctof(params[1]); float exponent = sp_ctof(params[2]); return sp_ftoc(pow(base, exponent)); }
static cell_t smn_TRGetPointContents(IPluginContext *pContext, const cell_t *params) { cell_t *vec, *ent; IHandleEntity *hentity; Vector pos; int mask; pContext->LocalToPhysAddr(params[1], &vec); pContext->LocalToPhysAddr(params[2], &ent); pos.x = sp_ctof(vec[0]); pos.y = sp_ctof(vec[1]); pos.z = sp_ctof(vec[2]); if (*ent == -1) { mask = enginetrace->GetPointContents(pos); } else { #if SOURCE_ENGINE >= SE_LEFT4DEAD || SOURCE_ENGINE == SE_BMS mask = enginetrace->GetPointContents(pos, MASK_ALL, &hentity); #else mask = enginetrace->GetPointContents(pos, &hentity); #endif *ent = gamehelpers->EntityToBCompatRef(reinterpret_cast<CBaseEntity *>(hentity)); } return mask; }
static cell_t sm_ArcTangent2(IPluginContext *pCtx, const cell_t *params) { float val1 = sp_ctof(params[1]); float val2 = sp_ctof(params[2]); val1 = atan2(val1, val2); return sp_ftoc(val1); }
static cell_t GetRandomFloat(IPluginContext *pContext, const cell_t *params) { float fMin = sp_ctof(params[1]); float fMax = sp_ctof(params[2]); float fRandom = engrandom->RandomFloat(fMin, fMax); return sp_ftoc(fRandom); }
static cell_t smn_TRTraceRay(IPluginContext *pContext, const cell_t *params) { cell_t *startaddr, *endaddr; pContext->LocalToPhysAddr(params[1], &startaddr); pContext->LocalToPhysAddr(params[2], &endaddr); g_StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2])); switch (params[4]) { case RayType_EndPoint: { g_EndVec.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2])); break; } case RayType_Infinite: { g_DirAngles.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2])); AngleVectors(g_DirAngles, &g_EndVec); /* Make it unitary and get the ending point */ g_EndVec.NormalizeInPlace(); g_EndVec = g_StartVec + g_EndVec * MAX_TRACE_LENGTH; break; } } g_Ray.Init(g_StartVec, g_EndVec); enginetrace->TraceRay(g_Ray, params[3], &g_HitAllFilter, &g_Trace); g_Trace.UpdateEntRef(); return 1; }
void SoundHooks::OnEmitAmbientSound(CEntityIndex index, const Vector &pos, const char *samp, float vol, soundlevel_t soundlevel, int fFlags, int pitch, float delay) { int entindex = index.Get(); #else void SoundHooks::OnEmitAmbientSound(int entindex, const Vector &pos, const char *samp, float vol, soundlevel_t soundlevel, int fFlags, int pitch, float delay) { #endif SoundHookIter iter; IPluginFunction *pFunc; cell_t vec[3] = {sp_ftoc(pos.x), sp_ftoc(pos.y), sp_ftoc(pos.z)}; cell_t res = static_cast<ResultType>(Pl_Continue); char buffer[PLATFORM_MAX_PATH]; strcpy(buffer, samp); for (iter=m_AmbientFuncs.begin(); iter!=m_AmbientFuncs.end(); iter++) { pFunc = (*iter); pFunc->PushStringEx(buffer, sizeof(buffer), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK); pFunc->PushCellByRef(&entindex); pFunc->PushFloatByRef(&vol); pFunc->PushCellByRef(reinterpret_cast<cell_t *>(&soundlevel)); pFunc->PushCellByRef(&pitch); pFunc->PushArray(vec, 3, SM_PARAM_COPYBACK); pFunc->PushCellByRef(&fFlags); pFunc->PushFloatByRef(&delay); g_InSoundHook = true; pFunc->Execute(&res); g_InSoundHook = false; switch (res) { case Pl_Handled: case Pl_Stop: { RETURN_META(MRES_SUPERCEDE); } case Pl_Changed: { Vector vec2; vec2.x = sp_ctof(vec[0]); vec2.y = sp_ctof(vec[1]); vec2.z = sp_ctof(vec[2]); #if SOURCE_ENGINE == SE_DOTA RETURN_META_NEWPARAMS(MRES_IGNORED, &IVEngineServer::EmitAmbientSound, (CEntityIndex(entindex), vec2, buffer, vol, soundlevel, fFlags, pitch, delay)); #else RETURN_META_NEWPARAMS(MRES_IGNORED, &IVEngineServer::EmitAmbientSound, (entindex, vec2, buffer, vol, soundlevel, fFlags, pitch, delay)); #endif } } } }
static cell_t smn_TRPointOutsideWorld(IPluginContext *pContext, const cell_t *params) { cell_t *vec; Vector pos; pContext->LocalToPhysAddr(params[1], &vec); pos.x = sp_ctof(vec[0]); pos.y = sp_ctof(vec[1]); pos.z = sp_ctof(vec[2]); return enginetrace->PointOutsideWorld(pos); }
static cell_t sm_FloatCompare(IPluginContext *pCtx, const cell_t *params) { float val1 = sp_ctof(params[1]); float val2 = sp_ctof(params[2]); if (val1 > val2) { return 1; } else if (val1 < val2) { return -1; } return 0; }
static cell_t NormalizeVector(IPluginContext *pContext, const cell_t *params) { cell_t *addr; pContext->LocalToPhysAddr(params[1], &addr); Vector source(sp_ctof(addr[0]), sp_ctof(addr[1]), sp_ctof(addr[2])); float length = VectorNormalize(source); pContext->LocalToPhysAddr(params[2], &addr); SET_VECTOR(addr, source); return sp_ftoc(length); }
static cell_t GetVectorLength(IPluginContext *pContext, const cell_t *params) { cell_t *addr; pContext->LocalToPhysAddr(params[1], &addr); Vector source(sp_ctof(addr[0]), sp_ctof(addr[1]), sp_ctof(addr[2])); if (!params[2]) { return sp_ftoc(source.Length()); } else { return sp_ftoc(source.LengthSqr()); } }
static cell_t sm_FloatNot(IPluginContext *pCtx, const cell_t *params) { float val = sp_ctof(params[1]); if (ke::IsNaN(val)) return 1; return val ? 0 : 1; }
static cell_t smn_GetDistGainFromSoundLevel(IPluginContext *pContext, const cell_t *params) { int decibel = params[1]; float distance = sp_ctof(params[2]); return sp_ftoc(engsound->GetDistGainFromSoundLevel((soundlevel_t)decibel, distance)); }
static cell_t sm_RoundToNearest(IPluginContext *pCtx, const cell_t *params) { float val = sp_ctof(params[1]); val = (float)floor(val + 0.5f); return static_cast<int>(val); }
static cell_t sm_FloatFraction(IPluginContext *pCtx, const cell_t *params) { float val = sp_ctof(params[1]); val = val - floor(val); return sp_ftoc(val); }
static cell_t sm_RoundToCeil(IPluginContext *pCtx, const cell_t *params) { float val = sp_ctof(params[1]); val = ceil(val); return static_cast<int>(val); }
static cell_t sm_SetConVarFloat(IPluginContext *pContext, const cell_t *params) { Handle_t hndl = static_cast<Handle_t>(params[1]); HandleError err; ConVar *pConVar; if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar)) != HandleError_None) { return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err); } float value = sp_ctof(params[2]); pConVar->SetValue(value); #if SOURCE_ENGINE < SE_ORANGEBOX /* Should we replicate it? */ if (params[3] && IsFlagSet(pConVar, FCVAR_REPLICATED)) { ReplicateConVar(pConVar); } /* Should we notify clients? */ if (params[4] && IsFlagSet(pConVar, FCVAR_NOTIFY)) { NotifyConVar(pConVar); } #endif return 1; }
static cell_t sm_ArcCosine(IPluginContext *pCtx, const cell_t *params) { float val = sp_ctof(params[1]); val = acos(val); return sp_ftoc(val); }
static cell_t sm_ArcTangent(IPluginContext *pCtx, const cell_t *params) { float val = sp_ctof(params[1]); val = atan(val); return sp_ftoc(val); }
static cell_t sm_FloatRound(IPluginContext *pCtx, const cell_t *params) { float val = sp_ctof(params[1]); switch (params[2]) { case 1: { val = floor(val); break; } case 2: { val = ceil(val); break; } case 3: { if (val >= 0.0f) { val = floor(val); } else { val = ceil(val); } break; } default: { val = (float)floor(val + 0.5f); break; } } return static_cast<int>(val); }
static cell_t sm_FloatAbs(IPluginContext *pCtx, const cell_t *params) { float val = sp_ctof(params[1]); val = (val >= 0.0f) ? val : -val; return sp_ftoc(val); }
// native Float:L4D2_SetFloatWeaponAttribute(const String:weaponName[], L4D2IntWeaponAttribute:attr, Float:value); cell_t L4D2_SetFloatWeaponAttribute(IPluginContext *pContext, const cell_t *params) { if (g_pWeaponInfoDatabase == NULL) { return pContext->ThrowNativeError("WeaponInfoDatabase unavailable or unsupported. File a bug report."); } char * weapon = NULL; pContext->LocalToString(params[1], &weapon); int iIndex = g_pWeaponInfoDatabase->Find(weapon); if (!g_pWeaponInfoDatabase->IsValidIndex(iIndex)) { return pContext->ThrowNativeError("Invalid weapon name or weapon unavailable"); } CTerrorWeaponInfo *pInfo = g_pWeaponInfoDatabase->Element(iIndex); float * attr = FloatIdToAttr(pInfo, params[2]); if(attr == NULL) { return pContext->ThrowNativeError("Invalid attribute id"); } *attr=sp_ctof(params[3]); return 0; }
static cell_t smn_TRTraceRayFilter(IPluginContext *pContext, const cell_t *params) { cell_t *startaddr, *endaddr; IPluginFunction *pFunc; cell_t data; pFunc = pContext->GetFunctionById(params[5]); if (!pFunc) { return pContext->ThrowNativeError("Invalid function id (%X)", params[5]); } if (params[0] >= 6) { data = params[6]; } else { data = 0; } g_SMTraceFilter.SetFunctionPtr(pFunc, data); pContext->LocalToPhysAddr(params[1], &startaddr); pContext->LocalToPhysAddr(params[2], &endaddr); g_StartVec.Init(sp_ctof(startaddr[0]), sp_ctof(startaddr[1]), sp_ctof(startaddr[2])); switch (params[4]) { case RayType_EndPoint: { g_EndVec.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2])); break; } case RayType_Infinite: { g_DirAngles.Init(sp_ctof(endaddr[0]), sp_ctof(endaddr[1]), sp_ctof(endaddr[2])); AngleVectors(g_DirAngles, &g_EndVec); /* Make it unitary and get the ending point */ g_EndVec.NormalizeInPlace(); g_EndVec = g_StartVec + g_EndVec * MAX_TRACE_LENGTH; break; } } g_Ray.Init(g_StartVec, g_EndVec); enginetrace->TraceRay(g_Ray, params[3], &g_SMTraceFilter, &g_Trace); g_Trace.UpdateEntRef(); return 1; }