pred@2224: /** pred@2224: * vim: set ts=4 : pred@2224: * ============================================================================= pred@2224: * SourceMod Sample Extension pred@2224: * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. pred@2224: * ============================================================================= pred@2224: * pred@2224: * This program is free software; you can redistribute it and/or modify it under pred@2224: * the terms of the GNU General Public License, version 3.0, as published by the pred@2224: * Free Software Foundation. pred@2224: * pred@2224: * This program is distributed in the hope that it will be useful, but WITHOUT pred@2224: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS pred@2224: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more pred@2224: * details. pred@2224: * pred@2224: * You should have received a copy of the GNU General Public License along with pred@2224: * this program. If not, see . pred@2224: * pred@2224: * As a special exception, AlliedModders LLC gives you permission to link the pred@2224: * code of this program (as well as its derivative works) to "Half-Life 2," the pred@2224: * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software pred@2224: * by the Valve Corporation. You must obey the GNU General Public License in pred@2224: * all respects for all other code used. Additionally, AlliedModders LLC grants pred@2224: * this exception to all derivative works. AlliedModders LLC defines further pred@2224: * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), pred@2224: * or . pred@2224: * pred@2224: * Version: $Id$ pred@2224: */ pred@2224: pred@2224: #include "extension.h" pred@2224: #include "utldict.h" pred@2224: pred@2224: class FileWeaponInfo_t; pred@2224: typedef unsigned short WEAPON_FILE_INFO_HANDLE; pred@2224: pred@2224: inline edict_t *GetEdict(cell_t num) pred@2224: { pred@2224: edict_t *pEdict = engine->PEntityOfEntIndex(num); pred@2224: if (!pEdict || pEdict->IsFree()) pred@2224: { pred@2224: return NULL; pred@2224: } pred@2224: pred@2224: return pEdict; pred@2224: } pred@2224: pred@2224: inline edict_t *GetEntity(cell_t num, CBaseEntity **pData) pred@2224: { pred@2224: edict_t *pEdict = engine->PEntityOfEntIndex(num); pred@2224: if (!pEdict || pEdict->IsFree()) pred@2224: { pred@2224: return NULL; pred@2224: } pred@2224: pred@2224: IServerUnknown *pUnk; pred@2224: if ((pUnk=pEdict->GetUnknown()) == NULL) pred@2224: { pred@2224: return NULL; pred@2224: } pred@2224: *pData = pUnk->GetBaseEntity(); pred@2224: return pEdict; pred@2224: } pred@2224: pred@2224: int CheckBaseHandle(CBaseHandle &hndl) pred@2224: { pred@2224: if (!hndl.IsValid()) pred@2224: { pred@2224: return -1; pred@2224: } pred@2224: pred@2224: int index = hndl.GetEntryIndex(); pred@2224: pred@2224: edict_t *pStoredEdict; pred@2224: CBaseEntity *pStoredEntity; pred@2224: pred@2224: pStoredEdict = GetEntity(index, &pStoredEntity); pred@2224: pred@2224: if (pStoredEdict == NULL || pStoredEntity == NULL) pred@2224: { pred@2224: return -1; pred@2224: } pred@2224: pred@2224: IServerEntity *pSE = pStoredEdict->GetIServerEntity(); pred@2224: pred@2224: if (pSE == NULL) pred@2224: { pred@2224: return -1; pred@2224: } pred@2224: pred@2224: if (pSE->GetRefEHandle() != hndl) pred@2224: { pred@2224: return -1; pred@2224: } pred@2224: pred@2224: return index; pred@2224: } pred@2224: pred@2224: //native GetStructInt(Handle:struct, const String:member[]); pred@2224: static cell_t GetStructInt(IPluginContext *pContext, const cell_t *params) pred@2224: { pred@2224: Handle_t hndl = static_cast(params[1]); pred@2224: HandleError err; pred@2224: HandleSecurity sec; pred@2224: pred@2224: sec.pOwner = NULL; pred@2224: sec.pIdentity = myself->GetIdentity(); pred@2224: pred@2224: StructHandle *pHandle; pred@2224: if ((err = g_pHandleSys->ReadHandle(hndl, g_StructHandle, &sec, (void **)&pHandle)) pred@2224: != HandleError_None) pred@2224: { pred@2224: return pContext->ThrowNativeError("Invalid struct handle %x (error %d)", hndl, err); pred@2224: } pred@2224: pred@2224: char *member; pred@2224: pContext->LocalToString(params[2], &member); pred@2224: pred@2224: int value; pred@2224: pred@2224: if (!pHandle->GetInt(member, &value)) pred@2224: { pred@2224: return pContext->ThrowNativeError("Invalid member, or incorrect data type"); pred@2224: } pred@2224: pred@2224: return value; pred@2224: } pred@2224: pred@2224: //native SetStructInt(Handle:struct, const String:member[], value); pred@2224: static cell_t SetStructInt(IPluginContext *pContext, const cell_t *params) pred@2224: { pred@2224: Handle_t hndl = static_cast(params[1]); pred@2224: HandleError err; pred@2224: HandleSecurity sec; pred@2224: pred@2224: sec.pOwner = NULL; pred@2224: sec.pIdentity = myself->GetIdentity(); pred@2224: pred@2224: StructHandle *pHandle; pred@2224: if ((err = handlesys->ReadHandle(hndl, g_StructHandle, &sec, (void **)&pHandle)) pred@2224: != HandleError_None) pred@2224: { pred@2224: return pContext->ThrowNativeError("Invalid struct handle %x (error %d)", hndl, err); pred@2224: } pred@2224: pred@2224: char *member; pred@2224: pContext->LocalToString(params[2], &member); pred@2224: pred@2224: if (!pHandle->SetInt(member, params[3])) pred@2224: { pred@2224: return pContext->ThrowNativeError("Invalid member, or incorrect data type"); pred@2224: } pred@2224: pred@2224: return 1; pred@2224: } pred@2224: pred@2224: //native GetStructFloat(Handle:struct, const String:member[], &Float:value); pred@2224: static cell_t GetStructFloat(IPluginContext *pContext, const cell_t *params) pred@2224: { pred@2224: Handle_t hndl = static_cast(params[1]); pred@2224: HandleError err; pred@2224: HandleSecurity sec; pred@2224: pred@2224: sec.pOwner = NULL; pred@2224: sec.pIdentity = myself->GetIdentity(); pred@2224: pred@2224: StructHandle *pHandle; pred@2224: if ((err = g_pHandleSys->ReadHandle(hndl, g_StructHandle, &sec, (void **)&pHandle)) pred@2224: != HandleError_None) pred@2224: { pred@2224: return pContext->ThrowNativeError("Invalid struct handle %x (error %d)", hndl, err); pred@2224: } pred@2224: pred@2224: char *member; pred@2224: pContext->LocalToString(params[2], &member); pred@2224: pred@2224: float value; pred@2224: pred@2224: if (!pHandle->GetFloat(member, &value)) pred@2224: { pred@2224: return pContext->ThrowNativeError("Invalid member, or incorrect data type"); pred@2224: } pred@2224: pred@2224: return sp_ftoc(value); pred@2224: } pred@2224: pred@2224: //native SetStructFloat(Handle:struct, const String:member[], Float:value); pred@2224: static cell_t SetStructFloat(IPluginContext *pContext, const cell_t *params) pred@2224: { pred@2224: Handle_t hndl = static_cast(params[1]); pred@2224: HandleError err; pred@2224: HandleSecurity sec; pred@2224: pred@2224: sec.pOwner = NULL; pred@2224: sec.pIdentity = myself->GetIdentity(); pred@2224: pred@2224: StructHandle *pHandle; pred@2224: if ((err = g_pHandleSys->ReadHandle(hndl, g_StructHandle, &sec, (void **)&pHandle)) pred@2224: != HandleError_None) pred@2224: { pred@2224: return pContext->ThrowNativeError("Invalid struct handle %x (error %d)", hndl, err); pred@2224: } pred@2224: pred@2224: char *member; pred@2224: pContext->LocalToString(params[2], &member); pred@2224: pred@2224: if (!pHandle->SetFloat(member, sp_ctof(params[3]))) pred@2224: { pred@2224: return pContext->ThrowNativeError("Invalid member, or incorrect data type"); pred@2224: } pred@2224: pred@2224: return 1; pred@2224: } pred@2224: pred@2224: //native GetStructVector(Handle:struct, const String:member[], Float:vec[3]); pred@2224: static cell_t GetStructVector(IPluginContext *pContext, const cell_t *params) pred@2224: { pred@2224: Handle_t hndl = static_cast(params[1]); pred@2224: HandleError err; pred@2224: HandleSecurity sec; pred@2224: pred@2224: sec.pOwner = NULL; pred@2224: sec.pIdentity = myself->GetIdentity(); pred@2224: pred@2224: StructHandle *pHandle; pred@2224: if ((err = g_pHandleSys->ReadHandle(hndl, g_StructHandle, &sec, (void **)&pHandle)) pred@2224: != HandleError_None) pred@2224: { pred@2224: return pContext->ThrowNativeError("Invalid struct handle %x (error %d)", hndl, err); pred@2224: } pred@2224: pred@2224: char *member; pred@2224: pContext->LocalToString(params[2], &member); pred@2224: pred@2224: cell_t *addr; pred@2224: pContext->LocalToPhysAddr(params[3], &addr); pred@2224: pred@2224: Vector value; pred@2224: pred@2224: if (!pHandle->GetVector(member, &value)) pred@2224: { pred@2224: return pContext->ThrowNativeError("Invalid member, or incorrect data type"); pred@2224: } pred@2224: pred@2224: addr[0] = sp_ftoc(value.x); pred@2224: addr[1] = sp_ftoc(value.y); pred@2224: addr[2] = sp_ftoc(value.z); pred@2224: pred@2224: return 1; pred@2224: } pred@2224: pred@2224: //native SetStructVector(Handle:struct, const String:member[], Float:vec[3]); pred@2224: static cell_t SetStructVector(IPluginContext *pContext, const cell_t *params) pred@2224: { pred@2224: Handle_t hndl = static_cast(params[1]); pred@2224: HandleError err; pred@2224: HandleSecurity sec; pred@2224: pred@2224: sec.pOwner = NULL; pred@2224: sec.pIdentity = myself->GetIdentity(); pred@2224: pred@2224: StructHandle *pHandle; pred@2224: if ((err = g_pHandleSys->ReadHandle(hndl, g_StructHandle, &sec, (void **)&pHandle)) pred@2224: != HandleError_None) pred@2224: { pred@2224: return pContext->ThrowNativeError("Invalid struct handle %x (error %d)", hndl, err); pred@2224: } pred@2224: pred@2224: char *member; pred@2224: pContext->LocalToString(params[2], &member); pred@2224: pred@2224: Vector value; pred@2224: pred@2224: cell_t *addr; pred@2224: pContext->LocalToPhysAddr(params[3], &addr); pred@2224: pred@2224: value.x = sp_ctof(addr[0]); pred@2224: value.y = sp_ctof(addr[1]); pred@2224: value.z = sp_ctof(addr[2]); pred@2224: pred@2224: if (!pHandle->SetVector(member, value)) pred@2224: { pred@2224: return pContext->ThrowNativeError("Invalid member, or incorrect data type"); pred@2224: } pred@2224: pred@2224: return 1; pred@2224: } pred@2224: pred@2224: //native GetStructString(Handle:struct, const String:member[], String:value[], maxlen); pred@2224: static cell_t GetStructString(IPluginContext *pContext, const cell_t *params) pred@2224: { pred@2224: Handle_t hndl = static_cast(params[1]); pred@2224: HandleError err; pred@2224: HandleSecurity sec; pred@2224: pred@2224: sec.pOwner = NULL; pred@2224: sec.pIdentity = myself->GetIdentity(); pred@2224: pred@2224: StructHandle *pHandle; pred@2224: if ((err = g_pHandleSys->ReadHandle(hndl, g_StructHandle, &sec, (void **)&pHandle)) pred@2224: != HandleError_None) pred@2224: { pred@2224: return pContext->ThrowNativeError("Invalid struct handle %x (error %d)", hndl, err); pred@2224: } pred@2224: pred@2224: char *member; pred@2224: pContext->LocalToString(params[2], &member); pred@2224: pred@2224: char *string; pred@2224: if (!pHandle->GetString(member, &string)) pred@2224: { pred@2224: return pContext->ThrowNativeError("Invalid member, or incorrect data type"); pred@2224: } pred@2224: pred@2224: pContext->StringToLocal(params[3], params[4], string); pred@2224: pred@2224: return 1; pred@2224: } pred@2224: pred@2224: //native SetStructString(Handle:struct, const String:member[], String:value[]); pred@2224: static cell_t SetStructString(IPluginContext *pContext, const cell_t *params) pred@2224: { pred@2224: Handle_t hndl = static_cast(params[1]); pred@2224: HandleError err; pred@2224: HandleSecurity sec; pred@2224: pred@2224: sec.pOwner = NULL; pred@2224: sec.pIdentity = myself->GetIdentity(); pred@2224: pred@2224: StructHandle *pHandle; pred@2224: if ((err = g_pHandleSys->ReadHandle(hndl, g_StructHandle, &sec, (void **)&pHandle)) pred@2224: != HandleError_None) pred@2224: { pred@2224: return pContext->ThrowNativeError("Invalid struct handle %x (error %d)", hndl, err); pred@2224: } pred@2224: pred@2224: char *member; pred@2224: pContext->LocalToString(params[2], &member); pred@2224: pred@2224: char *string; pred@2224: pContext->LocalToString(params[3], &string); pred@2224: pred@2224: if (!pHandle->SetString(member, string)) pred@2224: { pred@2224: return pContext->ThrowNativeError("Invalid member, or incorrect data type"); pred@2224: } pred@2224: pred@2224: return 1; pred@2224: } pred@2224: pred@2224: //native GetStructEnt(Handle:struct, const String:member[], &ent); pred@2224: static cell_t GetStructEnt(IPluginContext *pContext, const cell_t *params) pred@2224: { pred@2224: Handle_t hndl = static_cast(params[1]); pred@2224: HandleError err; pred@2224: HandleSecurity sec; pred@2224: pred@2224: sec.pOwner = NULL; pred@2224: sec.pIdentity = myself->GetIdentity(); pred@2224: pred@2224: StructHandle *pHandle; pred@2224: if ((err = g_pHandleSys->ReadHandle(hndl, g_StructHandle, &sec, (void **)&pHandle)) pred@2224: != HandleError_None) pred@2224: { pred@2224: return pContext->ThrowNativeError("Invalid struct handle %x (error %d)", hndl, err); pred@2224: } pred@2224: pred@2224: char *member; pred@2224: pContext->LocalToString(params[2], &member); pred@2224: pred@2224: CBaseHandle *value; pred@2224: if (!pHandle->GetEHandle(member, &value)) pred@2224: { pred@2224: return pContext->ThrowNativeError("Invalid member, or incorrect data type"); pred@2224: } pred@2224: pred@2224: return CheckBaseHandle(*value); pred@2224: } pred@2224: pred@2224: //native SetStructEnt(Handle:struct, const String:member[], ent); pred@2224: static cell_t SetStructEnt(IPluginContext *pContext, const cell_t *params) pred@2224: { pred@2224: Handle_t hndl = static_cast(params[1]); pred@2224: HandleError err; pred@2224: HandleSecurity sec; pred@2224: pred@2224: sec.pOwner = NULL; pred@2224: sec.pIdentity = myself->GetIdentity(); pred@2224: pred@2224: StructHandle *pHandle; pred@2224: if ((err = g_pHandleSys->ReadHandle(hndl, g_StructHandle, &sec, (void **)&pHandle)) pred@2224: != HandleError_None) pred@2224: { pred@2224: return pContext->ThrowNativeError("Invalid struct handle %x (error %d)", hndl, err); pred@2224: } pred@2224: pred@2224: char *member; pred@2224: pContext->LocalToString(params[2], &member); pred@2224: pred@2224: CBaseHandle *value; pred@2224: if (!pHandle->GetEHandle(member, &value)) pred@2224: { pred@2224: return pContext->ThrowNativeError("Invalid member, or incorrect data type"); pred@2224: } pred@2224: pred@2224: edict_t *pEdict = GetEdict(params[3]); pred@2224: pred@2224: if (pEdict == NULL) pred@2224: { pred@2224: return pContext->ThrowNativeError("Invalid entity %i", params[3]); pred@2224: } pred@2224: pred@2224: IServerEntity *pEntOther = pEdict->GetIServerEntity(); pred@2224: value->Set(pEntOther); pred@2224: pred@2224: if (!pHandle->SetEHandle(member, value)) pred@2224: { pred@2224: return pContext->ThrowNativeError("Invalid member, or incorrect data type"); pred@2224: } pred@2224: pred@2224: return 1; pred@2224: } pred@2224: pred@2224: static cell_t GetWeaponStruct(IPluginContext *pContext, const cell_t *params) pred@2224: { pred@2224: char *weapon; pred@2224: pContext->LocalToString(params[1], &weapon); pred@2224: pred@2224: void **func; pred@2224: pred@2224: #if defined WIN32 pred@2224: void *addr = NULL; pred@2224: func = &addr; pred@2224: #else pred@2224: WEAPON_FILE_INFO_HANDLE (*LookupWeaponInfoSlot)(const char *) = NULL; pred@2224: func = (void **)&LookupWeaponInfoSlot; pred@2224: #endif pred@2224: pred@2224: FileWeaponInfo_t *(*GetFileWeaponInfoFromHandle)( WEAPON_FILE_INFO_HANDLE handle ) = NULL; pred@2224: pred@2224: if (!conf->GetMemSig("LookupWeaponInfoSlot", func) || *func == NULL) pred@2224: { pred@2224: return pContext->ThrowNativeError("Failed to locate signature LookupWeaponInfoSlot"); pred@2224: } pred@2224: pred@2224: if (!conf->GetMemSig("GetFileWeaponInfoFromHandle", (void **)&GetFileWeaponInfoFromHandle) || GetFileWeaponInfoFromHandle == NULL) pred@2224: { pred@2224: return pContext->ThrowNativeError("Failed to locate signature GetFileWeaponInfoFromHandle"); pred@2224: } pred@2224: pred@2224: #if defined WIN32 pred@2224: int offset; pred@2224: pred@2224: if (!conf->GetOffset("m_WeaponInfoDatabase", &offset)) pred@2224: { pred@2224: return pContext->ThrowNativeError("Failed to locate offset m_WeaponInfoDatabase"); pred@2224: } pred@2224: pred@2224: addr = (unsigned char *)addr + offset; pred@2224: pred@2224: CUtlDict< FileWeaponInfo_t*, unsigned short > *m_WeaponInfoDatabase = *(CUtlDict< FileWeaponInfo_t*, unsigned short > **)addr; pred@2224: pred@2224: WEAPON_FILE_INFO_HANDLE handle = m_WeaponInfoDatabase->Find(weapon); pred@2224: pred@2224: if (handle == -1 || handle == m_WeaponInfoDatabase->InvalidIndex()) pred@2224: { pred@2224: return pContext->ThrowNativeError("Could not find weapon %s", weapon); pred@2224: } pred@2224: #else pred@2224: WEAPON_FILE_INFO_HANDLE handle = LookupWeaponInfoSlot(weapon); pred@2224: #endif pred@2224: FileWeaponInfo_t *info = GetFileWeaponInfoFromHandle(handle); pred@2224: pred@2224: //g_pSM->LogMessage(myself, "%i %i %x", handle, GetInvalidWeaponInfoHandle(), info); pred@2224: pred@2224: if (!info) pred@2224: { pred@2224: return pContext->ThrowNativeError("Weapon does not exist!"); pred@2224: } pred@2224: pred@2224: /* Offsets! */ pred@2224: /* pred@2224: g_pSM->LogMessage(myself, "Offsets for FileWeaponInfo_t"); pred@2224: g_pSM->LogMessage(myself, "bParsed: %i", (unsigned char *)&(info->bParsedScript) - (unsigned char *)info); pred@2224: g_pSM->LogMessage(myself, "bLoadedHudElements: %i", (unsigned char *)&(info->bLoadedHudElements) - (unsigned char *)info); pred@2224: g_pSM->LogMessage(myself, "szClassName: %i", (unsigned char *)&(info->szClassName) - (unsigned char *)info); pred@2224: g_pSM->LogMessage(myself, "szPrintName: %i", (unsigned char *)&(info->szPrintName) - (unsigned char *)info); pred@2224: g_pSM->LogMessage(myself, "szViewModel: %i", (unsigned char *)&(info->szViewModel) - (unsigned char *)info); pred@2224: g_pSM->LogMessage(myself, "szWorldModel: %i", (unsigned char *)&(info->szWorldModel) - (unsigned char *)info); pred@2224: g_pSM->LogMessage(myself, "szAnimationPrefix: %i", (unsigned char *)&(info->szAnimationPrefix) - (unsigned char *)info); pred@2224: g_pSM->LogMessage(myself, "iSlot: %i", (unsigned char *)&(info->iSlot) - (unsigned char *)info); pred@2224: g_pSM->LogMessage(myself, "iPosition: %i", (unsigned char *)&(info->iPosition) - (unsigned char *)info); pred@2224: g_pSM->LogMessage(myself, "iMaxClip1: %i", (unsigned char *)&(info->iMaxClip1) - (unsigned char *)info); pred@2224: g_pSM->LogMessage(myself, "iMaxClip2: %i", (unsigned char *)&(info->iMaxClip2) - (unsigned char *)info); pred@2224: g_pSM->LogMessage(myself, "iDefaultClip1: %i", (unsigned char *)&(info->iDefaultClip1) - (unsigned char *)info); pred@2224: g_pSM->LogMessage(myself, "iDefaultClip2: %i", (unsigned char *)&(info->iDefaultClip2) - (unsigned char *)info); pred@2224: g_pSM->LogMessage(myself, "iWeight: %i", (unsigned char *)&(info->iWeight) - (unsigned char *)info); pred@2224: g_pSM->LogMessage(myself, "iRumbleEffect: %i", (unsigned char *)&(info->iRumbleEffect) - (unsigned char *)info); pred@2224: g_pSM->LogMessage(myself, "bAutoSwitchTo: %i", (unsigned char *)&(info->bAutoSwitchTo) - (unsigned char *)info); pred@2224: g_pSM->LogMessage(myself, "bAutoSwitchFrom: %i", (unsigned char *)&(info->bAutoSwitchFrom) - (unsigned char *)info); pred@2224: g_pSM->LogMessage(myself, "iFlags: %i", (unsigned char *)&(info->iFlags) - (unsigned char *)info); pred@2224: g_pSM->LogMessage(myself, "szAmmo1: %i", (unsigned char *)&(info->szAmmo1) - (unsigned char *)info); pred@2224: g_pSM->LogMessage(myself, "szAmmo2: %i", (unsigned char *)&(info->szAmmo2) - (unsigned char *)info); pred@2224: g_pSM->LogMessage(myself, "aShootSounds: %i", (unsigned char *)&(info->aShootSounds) - (unsigned char *)info); pred@2224: g_pSM->LogMessage(myself, "iAmmoType: %i", (unsigned char *)&(info->iAmmoType) - (unsigned char *)info); pred@2224: g_pSM->LogMessage(myself, "iAmmo2Type: %i", (unsigned char *)&(info->iAmmo2Type) - (unsigned char *)info); pred@2224: g_pSM->LogMessage(myself, "m_bMeleeWeapon: %i", (unsigned char *)&(info->m_bMeleeWeapon) - (unsigned char *)info); pred@2224: g_pSM->LogMessage(myself, "m_bBuiltRightHanded: %i", (unsigned char *)&(info->m_bBuiltRightHanded) - (unsigned char *)info); pred@2224: g_pSM->LogMessage(myself, "m_bAllowFlipping: %i", (unsigned char *)&(info->m_bAllowFlipping) - (unsigned char *)info); pred@2224: */ pred@2224: return g_StructManager.CreateStructHandle("FileWeaponInfo_t", info); pred@2224: }; pred@2224: pred@2224: const sp_nativeinfo_t MyNatives[] = pred@2224: { pred@2224: {"GetStructInt", GetStructInt}, pred@2224: {"SetStructInt", SetStructInt}, pred@2224: {"GetStructFloat", GetStructFloat}, pred@2224: {"SetStructFloat", SetStructFloat}, pred@2224: {"GetStructVector", GetStructVector}, pred@2224: {"SetStructVector", SetStructVector}, pred@2224: {"GetStructString", GetStructString}, pred@2224: {"SetStructString", SetStructString}, pred@2224: {"GetStructEnt", GetStructEnt}, pred@2224: {"SetStructEnt", SetStructEnt}, pred@2224: {"GetWeaponStruct", GetWeaponStruct}, pred@2224: {NULL, NULL}, pred@2224: };