Raised This Month: $18 Target: $400
 4% 

Accessing entity information in MetaMod:Source


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
ManuHeel
New Member
Join Date: May 2024
Location: France
Old 05-27-2024 , 16:07   Accessing entity information in MetaMod:Source
Reply With Quote #1

Hi!

MetaMod:Source beginner here, with just a little bit of experience coding in C++ and coding within the Source engine.

I'm currently porting code I made for a Source engine modification, where I was overriding the client.dll and server.dll, to a Metamod:Source plugin as I'd like my addons to be more portable and compatible with different mods overriding these DLLs.

I managed to compile everything from the samples, adapt them into my plugins, code some stuff, link external DLLs and libs, all right, however I'm stuck at interacting with entities (CBaseEntity and such) and edicts (edict_t). I'm used to be in the engine and having access to CBase, CBaseEntity, and most importantly the global gEntList variable which is quite useful, but it seems I cannot do it the same way with a plugin.

I had code like this snippet right there to find NPCs in the map and do something with it (only read data though) :


CBaseEntity *pNPC = nullptr;
while ((pNPC = gEntList.FindEntityByClassname(pNPC, "npc_*")) != nullptr) {
auto *pAI = dynamic_cast<CAI_BaseNPC *>(pNPC);
if (pAI) {
int relationToPlayer = pAI->IRelationType(pPlayer); // I already had a pointer to my player
// something something
}
}

This code is probably written like shit but it worked, I had access to cbase.h so with baseentity.h, so with gEntList and the base classes like CBaseEntity, but now in Metamod I don't.
I tried including the cbase.h header, of course, but I can't find a way to link it, and I'm almost certain that's not the way plugins work, they probably don't know what the hell is happening in the engine and maybe I'm not at all permitted to include cbase.h.
I get this kind of linker error which is expected, even if I link every public/*.lib file in the sdk's source :
error LNK2019: unresolved external symbol "public: class CBaseEntity * __thiscall CGlobalEntityList::FindEntityByClassname(clas s CBaseEntity *,char const *)" (?FindEntityByClassname@CGlobalEntityList@@QA EPAVCBaseEntity@@PAV2@PBD@Z) referenced in function [...]

How can I then find data about what entities are currently in the game? How can I access this data, and use the methods of basic classes like CBaseEntity? Can I even known which entities are in the game with like gEntList?

Navigating through the Source engine's doc, I found info on those edict_t objects, which I found in some plugins' methods' signature (so I guess Metamod deals with them), I can get some info from them (like the player's position with pEdict->GetCollideable()->GetCollisionOrigin()) but I can't get more info from it. The doc says I can do think kind of stuff to get an entity from my edict, but it does not work, and I can't compile with CBaseEntity stuff in any case:
pEdit->GetUnknown()->GetBaseEntity()

ex:

void MyPlugin::Hook_ClientPutInServer(edict_t *pEntity, char const *playername) {
Vector position = pEdict->GetCollideable()->GetCollisionOrigin(); // this works
float health = pEdit->GetUnknown()->GetBaseEntity()->GetHealth(); // this returns me 0.0f in any case, and I can't debug from GetBaseEntity() as I get this result in the immediate window : Function IServerUnknown::GetBaseEntity has no address, possibly due to compiler optimizations.
}

Am I missing something? Is there any explicit doc about how to handle CBaseEntity and/or edicts and their data with Metamod:Source?

Thanks a lot.
Manu.
ManuHeel is offline
asherkin
SourceMod Developer
Join Date: Aug 2009
Location: OnGameFrame()
Old 06-02-2024 , 18:55   Re: Accessing entity information in MetaMod:Source
Reply With Quote #2

Depending on the game you're dealing with, you can probably use the IServerTools Valve interface to help with this.
__________________
asherkin is offline
ManuHeel
New Member
Join Date: May 2024
Location: France
Old 06-03-2024 , 01:13   Re: Accessing entity information in MetaMod:Source
Reply With Quote #3

Hi asherkin, thanks for you help.

I'm modding HL2/HL2 Update through the hl2sdk-sdk2013 engine version.

Thank you for the insight! I'll take a look into the IServerTools interface to see if I can hook it up to one of my classes and find some more info, but it looks promising.

If you have resources or code snippet about implementing the IServerTools interface, I'm up for it.
Quickly searching on Google, I found this kind of similar approach here (https://www.codereversing.com/archives/512). This is Aimbot-related but that's not my goal, I'm not even searching for coding a multiplayer plugin, however it could help me implementing the interface.
ManuHeel is offline
asherkin
SourceMod Developer
Join Date: Aug 2009
Location: OnGameFrame()
Old 06-03-2024 , 04:53   Re: Accessing entity information in MetaMod:Source
Reply With Quote #4

The stub_mm/sample_mm plugins both have examples of getting IServerGameDLL from the serverFactory - it’s exactly the same but with IServerTools as the type and VSERVERTOOLS_INTERFACE_VERSION as the name.

The problem with reading health is probably the mod’s class layout is different from the SDK and GetHealth isn’t where the header says it should be. Reverse engineering the entire SDK per-game is silly work, so it’s generally just got the core engine stuff and plugins like SM abstract things like virtual function offsets to configuration. Try instead reading the m_iHealth property with https://wiki.alliedmods.net/Entity_Properties (your game might have a different name, check it against a property dump from SM).
__________________
asherkin is offline
ManuHeel
New Member
Join Date: May 2024
Location: France
Old 06-06-2024 , 01:55   Re: Accessing entity information in MetaMod:Source
Reply With Quote #5

Hi asherkin,

I've explored IServerTools and it looks promising. In parralel I've also read the "Entity Properties" wiki page and tried the Datamap Properties example, which was almost the same as my need for health, except I swapped the "set" usecase to a "get" usecase.

Still, I'm stuck in the same "headers and compiling" issues.
I've added this include in my file :
#include "itoolentity.h"
...which grants me access to the IServerTools interface, but this header only defines a forward declaration to CBaseEntity, so I cannot access anything related to it.

Compiling with the added snippet from the "Entity Properties" wiki page gives me this error, as I don't have a Class declaration of CBaseEntity:

1>------ Build started: Project: my_plugin, Configuration: Debug - Orange Box Valve Win32 ------
1> my_watcher.cpp
1>c:\users\manuel\code\source_mods\metamod-source\projects\my_plugin\my_watcher.cpp(51): error C2027: use of undefined type 'CBaseEntity'
1> c:\users\manuel\code\source_mods\hl2sdk-sdk2013\public\gametrace.h(22) : see declaration of 'CBaseEntity'
1>c:\users\manuel\code\source_mods\metamod-source-my\projects\my_plugin\my_watcher.cpp(51): error C2227: left of '->GetDataDescMap' must point to class/struct/union/generic type
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========


I tried including "baseentity.h" and it load up a shitload of missing references (see below),pretty much the same with "baseentity_shared.h", and even worse if I try, naively, to include "cbase.h", I always end up stuck with missing classes like "CNetworkHandle" or such.
I think I'm missing a piece of information on how to get access to class methods of the CBaseEntity class...
Sorry if this is a noob C++ question, I'm still learning.
Do you have any tips?


The shitload of missing references:
1>------ Build started: Project: my_plugin, Configuration: Debug - Orange Box Valve Win32 ------
1> my_watcher.cpp
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\entitylist.h(74): error C2504: 'CBaseEntityList' : base class undefined
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\entitylist.h(179): error C3861: 'LookupEntity': identifier not found
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\entitylist.h(18: error C3861: 'LookupEntity': identifier not found
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\entitylist.h(197): error C3861: 'LookupEntity': identifier not found
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\entitylist.h(206): error C3861: 'LookupEntity': identifier not found
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\entitylist.h(256): error C2146: syntax error : missing ';' before identifier 'hEnt'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\entitylist.h(256): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\entityoutput.h(67): error C2061: syntax error : identifier 'ISave'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\entityoutput.h(6: error C2061: syntax error : identifier 'IRestore'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\entityoutput.h(82): error C2079: 'CBaseEntityOutput::m_Value' uses undefined class 'variant_t'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\entityoutput.h(74): error C2228: left of '.FieldType' must have class/struct/union
1> type is 'int'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\entityoutput.h(136): error C2228: left of '.SetVector3D' must have class/struct/union
1> type is 'int'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\entityoutput.h(141): error C2228: left of '.SetVector3D' must have class/struct/union
1> type is 'int'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\entityoutput.h(142): error C2664: 'void CBaseEntityOutput::FireOutput(variant_t,CBase Entity *,CBaseEntity *,float)' : cannot convert argument 1 from 'int' to 'variant_t'
1> Source or target has incomplete type
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\entityoutput.h(147): error C2228: left of '.Vector3D' must have class/struct/union
1> type is 'int'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\entityoutput.h(15: error C2228: left of '.SetPositionVector3D' must have class/struct/union
1> type is 'int'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\entityoutput.h(163): error C2228: left of '.SetPositionVector3D' must have class/struct/union
1> type is 'int'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\entityoutput.h(164): error C2664: 'void CBaseEntityOutput::FireOutput(variant_t,CBase Entity *,CBaseEntity *,float)' : cannot convert argument 1 from 'int' to 'variant_t'
1> Source or target has incomplete type
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\entityoutput.h(169): error C2228: left of '.Vector3D' must have class/struct/union
1> type is 'int'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\entityoutput.h(190): error C2065: 'EHANDLE' : undeclared identifier
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\entityoutput.h(190): error C2923: 'CEntityOutputTemplate' : 'EHANDLE' is not a valid template type argument for parameter 'Type'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\shared\collisionproperty.h(61): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\shared\collisionproperty.h(61): warning C4183: 'DECLARE_PREDICTABLE': missing return type; assumed to be a member function returning 'int'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\shared\collisionproperty.h(28: error C2065: 'DT_CollisionProperty' : undeclared identifier
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\shared\collisionproperty.h(28: error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\servernetworkproperty.h(7 2): error C2061: syntax error : identifier 'EHANDLE'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\servernetworkproperty.h(1 21): error C2146: syntax error : missing ';' before identifier 'm_hParent'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\servernetworkproperty.h(1 21): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\servernetworkproperty.h(1 70): error C2065: 'EHANDLE' : undeclared identifier
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\servernetworkproperty.h(1 70): error C2146: syntax error : missing ')' before identifier 'hParent'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\servernetworkproperty.h(1 70): error C2761: 'void CServerNetworkProperty::SetNetworkParent(void )' : member function redeclaration not allowed
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\servernetworkproperty.h(1 70): error C2059: syntax error : ')'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\servernetworkproperty.h(1 71): error C2143: syntax error : missing ';' before '{'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\servernetworkproperty.h(1 71): error C2447: '{' : missing function header (old-style formal list?)
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\servernetworkproperty.h(2 22): error C3861: 'ENTINDEX': identifier not found
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(39): error C2143: syntax error : missing ';' before '<'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(39): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(210): error C2079: 'inputdata_t::value' uses undefined class 'variant_t'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(377): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(377): warning C4183: 'DECLARE_PREDICTABLE': missing return type; assumed to be a member function returning 'int'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(821): error C2065: 'CPredictableId' : undeclared identifier
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(821): error C2923: 'CNetworkVarBase' : 'CPredictableId' is not a valid template type argument for parameter 'Type'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1020): error C2061: syntax error : identifier 'touchlink_t'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1022): error C2143: syntax error : missing ';' before '*'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1022): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1022): warning C4183: 'AddEntityToGroundList': missing return type; assumed to be a member function returning 'int'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1026): error C2061: syntax error : identifier 'groundlink_t'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1156): error C2146: syntax error : missing ';' before identifier 'm_hDamageFilter'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1156): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1505): error C2143: syntax error : missing ';' before '*'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1505): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1505): warning C4183: 'PhysicsMarkEntityAsTouched': missing return type; assumed to be a member function returning 'int'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1609): error C2146: syntax error : missing ';' before identifier 'm_pParent'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1609): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1617): error C2061: syntax error : identifier 'm_hMoveParent'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1617): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1617): warning C4183: 'CNetworkHandle': missing return type; assumed to be a member function returning 'int'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1619): error C2146: syntax error : missing ';' before identifier 'm_hMoveChild'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1619): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1621): error C2146: syntax error : missing ';' before identifier 'm_hMovePeer'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1621): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1627): error C2061: syntax error : identifier 'm_hOwnerEntity'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1627): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1627): error C2535: 'int CBaseEntity::CNetworkHandle(CBaseEntity)' : member function already defined or declared
1> c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1617) : see declaration of 'CBaseEntity::CNetworkHandle'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1627): warning C4183: 'CNetworkHandle': missing return type; assumed to be a member function returning 'int'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(162: error C2061: syntax error : identifier 'm_hEffectEntity'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(162: error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(162: error C2535: 'int CBaseEntity::CNetworkHandle(CBaseEntity)' : member function already defined or declared
1> c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1617) : see declaration of 'CBaseEntity::CNetworkHandle'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(162: warning C4183: 'CNetworkHandle': missing return type; assumed to be a member function returning 'int'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1647): error C2061: syntax error : identifier 'm_hGroundEntity'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1647): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1647): warning C4183: 'CNetworkHandleInternal': missing return type; assumed to be a member function returning 'int'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(166: error C2146: syntax error : missing ';' before identifier 'm_pBlocker'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(166: error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1729): error C2059: syntax error : '<'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1729): error C2238: unexpected token(s) preceding ';'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1901): error C2065: 'm_hMoveParent' : undeclared identifier
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1901): error C2228: left of '.Get' must have class/struct/union
1> type is 'unknown-type'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1906): error C2065: 'm_hMoveChild' : undeclared identifier
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1906): error C2228: left of '.Get' must have class/struct/union
1> type is 'unknown-type'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1911): error C2065: 'm_hMovePeer' : undeclared identifier
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1911): error C2228: left of '.Get' must have class/struct/union
1> type is 'unknown-type'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1917): error C2065: 'm_pParent' : undeclared identifier
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(1917): error C2228: left of '.Get' must have class/struct/union
1> type is 'unknown-type'
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(2290): error C3861: 'INDEXENT': identifier not found
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(2297): error C3861: 'INDEXENT': identifier not found
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(2642): error C2065: 'FCAP_ACROSS_TRANSITION' : undeclared identifier
1>c:\users\manuel\code\source_mods\hl2sdk-sdk2013\game\server\baseentity.h(2654): error C2065: 'FCAP_ACROSS_TRANSITION' : undeclared identifier
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
ManuHeel is offline
ManuHeel
New Member
Join Date: May 2024
Location: France
Old 06-27-2024 , 16:03   Re: Accessing entity information in MetaMod:Source
Reply With Quote #6

Hi,
Back to the forum after a pause, just for information I transitioned into using the Discord to ask my questions there (great Discord server!).

TL;DR: I've updated my MetaMod plugin into a SourceMod extension and started using SourceMod for everything that's related to entity datamaps and such, as SourceMod already did this heavy lifting for me.

Thank you for the help though, much appreciated. See you in the Discord maybe!
ManuHeel is offline
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 13:40.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode