Raised This Month: $51 Target: $400
 12% 

Concept: Project base


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
Greyscale
SourceMod Plugin Approver
Join Date: Dec 2007
Location: strYoMommasHouse[you];
Old 01-29-2010 , 22:26   Concept: Project base
Reply With Quote #1

Firstly, keep in mind that this is designed for more complex, diverse plugins.

There's MetaMod:Source, which is a platform for plugins to use to interact with the source engine, and not conflict with each other.

Then there's SourceMod, which is another platform that lets us use a simplified version of C++ (SourcePawn) and also provides a server with some basic tools, like the admin system, translations, etc.

Well I'm currently developing a SM project base. Designing large plugins can become a hassle when code starts to get messy and overly-blended. By blended I mean one little bug in an insignificant feature breaks the entire plugin. Or when your searching through your player_spawn event callback for a single line of code, and it takes way longer than it should.

Well for any of you large plugin developers, I've come up with a solution to these problems. (And many, many other benefits/advantages) This "project base" I'm currently designing and developing will be almost like a template for your plugin.

It works like this:
  • Module Manager - modulemanager.inc
    Main component of the project base. This file is unconditionally required (the only one) to use the project base. Here is the API for registering and managing "modules." Modules in the context of this design are basically (ideally) independent include files that require 1 line of code to be added to the .sp file. That line will be located in OnPluginStart() and will look something like:
    Code:
    Module_OnPluginStart();
    After that's done, anything that the module will handle should be contained inside of its include file. Of course, calling OnPluginStart isn't enough to consider it a module, so in Module_OnPluginStart the module must register itself with the module manager. The first public API function in modulemanager.inc is

    Code:
    stock Module:ModuleMgr_Register(moduledata[ModuleData])
    The module will use this stock to register with the modulemanager and be included in a multitude of features that other components (discussed below) can access. I know that ideally we want each module to be independent, but that's not going to happen in most projects. So there is API that will allow you to communicate with other modules by reading its data, or just checking if it exists. Examples:

    Code:
    stock bool:ModuleMgr_IsModuleValid(Module:module)
    stock ModuleMgr_Disable(Module:module)
    stock ModuleMgr_Enable(Module:module)
    stock bool:ModuleMgr_IsDisabled(Module:module)
    Module:ModuleMgr_Find(ModuleData:data, any:value, Module:modules[] = {INVALID_MODULE}, &matched = 0)
    Module:ModuleMgr_FindByString(ModuleData:data, const String:value[], bool:casesensitive = false, Module:modules[] = {INVALID_MODULE}, &matched = 0)
    ModuleMgr_ReadAll(Module:module, moduledata[ModuleData])
    ModuleMgr_ReadCell(Module:module, ModuleData:data)
    ModuleMgr_ReadString(Module:module, ModuleData:data, String:output[], maxlen)
  • Event Manager - eventmanager.inc
    The Module Manager is the only required file for the whole project template. This components and all others below are optional and don't need to be compiled into the project at all. Although, the event manager is pretty vital to keep a clean, organized code space. With all these independent modules there needs to be a way for events to be forwarded to them, without manually forwarding each event by hand to each individual module. So what this does is provides an API for any module to use to forward any event (game event or custom ones too) to any function you define tell it to. All you need is the module's identifier value and the name of the function passed as a string to this component and the it'll do the rest. You can also disable or enable any event at any time. Here's a peek at the event manager API:

    Code:
    stock Function:EventMgr_RegisterEvent(Module:module, ProjectEvents:event, const String:functionname[])
    stock EventMgr_Disable(Module:module, ProjectEvents:event)
    stock EventMgr_Enable(Module:module, ProjectEvents:event)
    stock Function:EventMgr_SetEventForward(Module:module, ProjectEvents:event, const String:functionname[])
  • Translations Manager - translationsmanager.inc
    This API handles loading project translation files (and any additional ones specified by you) as well as translation files specifically for each module. This can be useful for modules you plan to port as separate plugins. Otherwise, may use the general project translations file for module translations. The API covers more than just loading files, it gives a very broad stock that will prefix plugin/module info on the text, print in chat center text console etc, or automatically grab the text from a translations phrase and print that. You can translate boolean values into translation phrases like "yes/no" "on/off" "enable/disable". API:

    Code:
    stock TransMgr_Register(Module:module)
    stock TransMgr_PrintText(client, MsgFormatting:msgformat, MsgTypes:msgtype, Module:module = INVALID_MODULE, bool:literal = false, any:...)
    stock TransMgr_PrintTextAll(bool:server, bool:admin, MsgFormatting:msgformat, MsgTypes:msgtype, Module:module = INVALID_MODULE, bool:literal = false, any:...)
    stock TransMgr_TranslateBoolToPhrase(target, bool:boolean, BoolPhrases:boolphrase, String:phrase[], maxlen, bool:lowercase = false)
    stock PhraseToBool:TransMgr_TranslatePhraseToBool(target, BoolPhrases:boolphrase, const String:phrase[])
  • Log Manager - logmanager.inc
    The log manager is a log system that the modules should use so the admin has control over who gets to print what. The admin can do this through 2 commands: project_log_whitelist_add and project_log_whitelist_remove. If the log whitelist is enabled, then only modules explicitly added the whitelist will be able to print logs. All base components will override this, as well as errors. The log manager lets you print logs with useful prefixed text, and if the log is fatal, it can automatically disable the module that printed the log, or even kill the whole plugin. API:

    Code:
    LogMgr_Print(Module:module, LogTypes:logtype, const String:description[], const String:text[], any:...)
  • Client Access - clientaccess.inc
    This component hasn't been started yet, but it'll basically provide a way to set and check admin flags required for access to each module. Not fully thought out or designed yet. Ideas welcome.

Example Module:
I'll post an example module soon.

Also, the whole project is designed in a way that should prevent you from needing to change anything in the base project files. So this way I can update the API without breaking your plugins. Here's the main include file that would be required for any base file. This should be the first included file in the .sp. Everything that the whole project will need access to is in here, as well as anything you will need to modify any of the components.

Code:
/*
 * ============================================================================
 *
 *  Project
 *
 *  File:          project.inc
 *  Type:          Base
 *  Description:   Contains defines, enums, etc available to anywhere in the project.
 *
 *  Copyright (C) 2009-2010  Greyscale
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * ============================================================================
 */

// ---------------
//     General
// ---------------

/**
 * The client index of the server.
 */
#define SERVER_INDEX 0


// --------------------------------
//        Module Reference
// --------------------------------
// Note: Treat this section like a stripper.  Look, don't touch.

/**
 * The amount of registered modules.
 * All integers less than this (and greater than or equal to zero) are valid module identifiers.
 */
#define MODULE_COUNT GetArraySize(ModuleMgr_GetList())

/**
 * Module identifier tag.
 */
enum Module
{
    INVALID_MODULE = -1     /** Used as an invalid module. */
}

/**
 * All the data modules need to register.
 */
enum ModuleData
{
    bool:ModuleData_Disabled = 0,       /** True if the module is disabled. */
    String:ModuleData_FullName[32],     /** Used for displaying modules. */
    String:ModuleData_ShortName[16],    /** Used for client interaction with modules. */
    String:ModuleData_Description[256], /** A description of the module */
    // gunna need more than this..
}

/**
 * The number of cells used to store all the data in enum ModuleData.
 */
#define MODULE_DATA_CELL_COUNT 1 + 32 + 16 + 256

/**
 * The longest string that can be stored in the module's data. (Cell size of ModuleData_FullName)
 */
#define MODULE_DATA_LONGEST_STRING 256

// --------------------------------
//     Event Forwarding Stuff
// --------------------------------
// Note: Since event HOOKING is done here, you can touch this one ;) (you can change/add/remove stuff here)
// Note: Ignore this section if eventmanager.inc won't be compiled into the plugin.
/**
 * This is a collection of ALL game and custom events.
 * Add any custom events here to the bottom of the list, and update define EVENT_DATA_CELL_COUNT. (below)
 * Also don't forget to add the display name of your event to g_ProjectEventDisplay. (below)
 */
enum ProjectEvents
{
    Event_RoundStart,
    Event_RoundFreezeEnd,
    Event_RoundEnd,
    Event_PlayerSpawn,
    Event_PlayerHurt,
    Event_PlayerDeath,
    Event_PlayerJump,
    Event_PlayerFire
}

/**
 * The number of cells used to store all the event enable data in enum ProjectEvents. (above)
 * To calculate this number, simply add up the number of items in enum ProjectEvents.
 * Keep this updated as ProjectEvents is modified. 
 */
#define EVENT_DATA_CELL_COUNT 8

/**
 * String array of display names for project events. (above)
 * Keep this updated as ProjectEvents is modified.
 */
new const String:g_ProjectEventDisplay[ProjectEvents][] = {
    "Round Start",
    "Round Freeze End",
    "Round End",
    "Player Spawn",
    "Player Hurt",
    "Player Death",
    "Player Jump",
    "Player Fire"
};

// ---------------
//    Editable
// ---------------

/**
 * If this is defined, then it should be in a mercurial repository.
 */
#define PROJECT_MERCURIAL
#define PROJECT_BRANCH "smprojectbase"  // Name of the Mercurial branch this is being developed in.

/**
 * @section Basic project information.  This will also be displayed in 'sm plugins *' commands.
 */
#define PROJECT_FULLNAME    "Project"   // Used when printing the plugin name anywhere.
#define PROJECT_SHORTNAME   "project"   // Used for filenames, etc.
#define PROJECT_AUTHOR      "Greyscale"
#define PROJECT_DESCRIPTION "A base for large plugins to load modules and use its API."
#define PROJECT_VERSION     "1.0.0"     // http://wiki.eclipse.org/Version_Numbering
#define PROJECT_URL ""
/**
 * @endsection
 */

/**
 * @section Additional information displayed in the version info.
 */
#define PROJECT_COPYRIGHT "Copyright (C) 2010  PROJECT_AUTHOR"
#define PROJECT_LICENSE "GNU GPL, Version 3"

/**
 * Your plugin's base command for module management.
 * This command will be very similar to the "sm" command except geared toward module management instead of plugin management.
 * Also handles printing plugin information like credits and version.
 * Comment out to remove command from the plugin.
 */
#define PROJECT_BASE_CMD PROJECT_SHORTNAME

/**
 * @section The formatting string for each option in enum MsgFormatting.
 * Note: These are only used if translationsmanager.inc is included.
 * Color chars vary from game to game. 
 */
#define TM_MSGFORMAT_PLUGIN_COLOR      "\x04[%s] \x01%s"          // 1st %s = Plugin name - 2nd %s = Text
#define TM_MSGFORMAT_PLUGIN_NOCOLOR    "[%s] %s"                  // 1st %s = Plugin name - 2nd %s = Text
#define TM_MSGFORMAT_MODULE_COLOR      "\x03[%s] \x01%s"          // 1st %s = Module name - 2nd %s = Text
#define TM_MSGFORMAT_MODULE_NOCOLOR    "[%s] %s"                  // 1st %s = Module name - 2nd %s = Text
#define TM_MSGFORMAT_BOTH_COLOR        "\x04[%s::\x03%s] \x01%s"  // 1st %s = Plugin name - 2nd %s = Module name - 3rd %s = Text
#define TM_MSGFORMAT_BOTH_NOCOLOR      "[%s::%s] %s"              // 1st %s = Plugin name - 2nd %s = Module name - 3rd %s = Text
/**
 * @endsection
 */

/**
 * The formatting string for all logs.
 * Note: This is only used if logmanager.inc is included.
 */
#define LM_FORMAT "[%s] [%s] %s"    // 1st %s = Module name - 2nd %s = Short description - 3rd = Log text

/**
 * Load any extra translation files here.
 *  
 * Automatically loaded translations files for the project are:
 * translations/<projectshortname>/<projectshortname>.phrases.txt
 * translations/<projectshortname>/projectbase.phrases.txt
 *  
 * Translation files for modules should be loaded via TransMgr_Register.
 * Note: This is only used if translationsmanager.inc is included.
 */
stock TransMgr_LoadExtraTranslations()
{
    // Standard phrases provided by SM.
    LoadTranslations("common.phrases");
}
So please provide any ideas, requests, thoughts you have about this idea. I don't care if you hate the idea, I will be using this for myself regardless. It's being designed to handle the largest, most complex (as far as I know) SM plugin. So if it can handle that, it should be able to handle just about anything.


If you have any requests add them here
http://code.google.com/p/smprojectba...&ts=1264821076
__________________

Last edited by Greyscale; 01-29-2010 at 22:38.
Greyscale is offline
rhelgeby
Veteran Member
Join Date: Oct 2008
Location: 0x4E6F72776179
Old 01-30-2010 , 12:55   Re: Concept: Project base
Reply With Quote #2

Greyscale had this idea because of our big and complex Zombie:Reloaded plugin. We're gonna update ZR to this project base some time.

I don't know how well this will work on small plugins, but a template like this will save developing time, at least on bigger plugins.
__________________
Richard Helgeby

Zombie:Reloaded | PawnUnit | Object Library
(Please don't send private messages for support, they will be ignored. Use the forum.)
rhelgeby is offline
Send a message via MSN to rhelgeby
exvel
SourceMod Donor
Join Date: Jun 2006
Location: Russia
Old 01-30-2010 , 15:31   Re: Concept: Project base
Reply With Quote #3

Looks cool and complicated.
__________________
For admins: My plugins

For developers: Colors library
exvel is offline
Send a message via ICQ to exvel
Greyscale
SourceMod Plugin Approver
Join Date: Dec 2007
Location: strYoMommasHouse[you];
Old 01-30-2010 , 15:33   Re: Concept: Project base
Reply With Quote #4

Quote:
Originally Posted by exvel View Post
Looks cool and complicated.
The cool thing about its complexity is you can take out whatever parts of it you don't need, making it less complex
__________________
Greyscale is offline
Greyscale
SourceMod Plugin Approver
Join Date: Dec 2007
Location: strYoMommasHouse[you];
Old 02-11-2010 , 01:42   Re: Concept: Project base
Reply With Quote #5

Code:
/*
 * ============================================================================
 *
 *  Red Rover
 *
 *  File:          gamedata.inc
 *  Type:          Module
 *  Description:   Handles virtual offsets and signatures.
 *
 *  Copyright (C) 2009-2010  Greyscale
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * ============================================================================
 */

/**
 * General module defines.
 */
#define GAMEDATA_FILE "plugin.redrover"

/**
 * This module's identifier.
 */
//new Module:g_moduleGameData;

/**
 * Gamedata handles.
 */
new Handle:g_hGameConfig;
new Handle:g_hTerminateRound;

/**
 * Register this module.
 */
GameData_Register()
{
    // Define all the module's data as layed out by enum ModuleData in project.inc.
    new moduledata[ModuleData];
    
    moduledata[ModuleData_Disabled] = false;
    moduledata[ModuleData_Hidden] = true;
    strcopy(moduledata[ModuleData_FullName], CM_DATA_FULLNAME, "GameData");
    strcopy(moduledata[ModuleData_ShortName], CM_DATA_SHORTNAME, "gamedata");
    strcopy(moduledata[ModuleData_Description], CM_DATA_DESCRIPTION, "Handles virtual offsets and signatures.");
    
    // Send this array of data to the module manager.
    /*g_moduleGameData = */
    ModuleMgr_Register(moduledata);
    
    // Register all the events needed for this module.
    //EventMgr_RegisterEvent(g_moduleModule, Event_OnAllPluginsLoaded,      "_OnAllPluginsLoaded");
    //EventMgr_RegisterEvent(g_moduleModule, Event_OnPluginEnd,             "_OnPluginEnd");
    //EventMgr_RegisterEvent(g_moduleModule, Event_OnMapStart,              "_OnMapStart");
    //EventMgr_RegisterEvent(g_moduleModule, Event_OnMapEnd,                "_OnMapEnd");
    //EventMgr_RegisterEvent(g_moduleModule, Event_OnAutoConfigsBuffered,   "_OnAutoConfigsBuffered");
    //EventMgr_RegisterEvent(g_moduleModule, Event_OnConfigsExecuted,       "_OnConfigsExecuted");
    //EventMgr_RegisterEvent(g_moduleModule, Event_OnClientPutInServer,     "_OnClientPutInServer");
    //EventMgr_RegisterEvent(g_moduleModule, Event_OnClientDisconnect,      "_OnClientDisconnect");
    //EventMgr_RegisterEvent(g_moduleModule, Event_RoundStart,              "_RoundStart");
    //EventMgr_RegisterEvent(g_moduleModule, Event_RoundFreezeEnd,          "_RoundFreezeEnd");
    //EventMgr_RegisterEvent(g_moduleModule, Event_RoundEnd,                "_RoundEnd");
    //EventMgr_RegisterEvent(g_moduleModule, Event_PlayerTeam,              "_PlayerTeam");
    //EventMgr_RegisterEvent(g_moduleModule, Event_PlayerSpawn,             "_PlayerSpawn");
    //EventMgr_RegisterEvent(g_moduleModule, Event_PlayerHurt,              "_PlayerHurt");
    //EventMgr_RegisterEvent(g_moduleModule, Event_PlayerDeath,             "_PlayerDeath");
    //EventMgr_RegisterEvent(g_moduleModule, Event_PlayerJump,              "_PlayerJump");
    //EventMgr_RegisterEvent(g_moduleModule, Event_WeaponFire,              "_WeaponFire");
}

/**
 * Plugin is loading.
 */
GameData_OnPluginStart()
{
    // Register the module.
    GameData_Register();
    
    // Load game config file.
    g_hGameConfig = LoadGameConfigFile(GAMEDATA_FILE);
    
    // If gamedata file can't be loaded, then stop the plugin.
    if (g_hGameConfig == INVALID_HANDLE)
    {
        SetFailState("Can't load game config file (%s) from the \"gamedata\" directory.", GAMEDATA_FILE);
    }
    
    // Prep the SDKCall for "TerminateRound."
    StartPrepSDKCall(SDKCall_GameRules);
    PrepSDKCall_SetFromConf(g_hGameConfig, SDKConf_Signature, "TerminateRound");
    PrepSDKCall_AddParameter(SDKType_Float, SDKPass_Plain);
    PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain);
    g_hTerminateRound = EndPrepSDKCall();
    
    // If offset "TerminateRound" can't be found, then stop the plugin.
    if(g_hTerminateRound == INVALID_HANDLE)
    {
        SetFailState("Signature \"CGameRules::TerminateRound\" was not found.");
    }
}

/**
 * All round end reasons.
 * Used an enum instead of defines so the include order doesn't matter.
 */
enum RoundEndReasons
{
    ROUNDEND_TARGET_BOMBED = 1,             /** Target Successfully Bombed! */
    ROUNDEND_VIP_ESCAPED = 2,               /** The VIP has escaped! */
    ROUNDEND_VIP_ASSASSINATED = 3,          /** VIP has been assassinated! */
    ROUNDEND_TERRORISTS_ESCAPED = 4,        /** The terrorists have escaped! */
    ROUNDEND_CTS_PREVENTESCAPE = 5,         /** The CT's have prevented most of the terrorists from escaping! */
    ROUNDEND_ESC_TS_NEUTRALIZED = 6,        /** Escaping terrorists have all been neutralized! */
    ROUNDEND_BOMB_DEFUSED = 7,              /** The bomb has been defused! */
    ROUNDEND_CTS_WIN = 8,                   /** Counter-Terrorists Win! */
    ROUNDEND_TERRORISTS_WIN = 9,            /** Terrorists Win! */
    ROUNDEND_ROUND_DRAW = 10,               /** Round Draw! */
    ROUNDEND_ALL_HOSTAGES_RESCUED = 11,     /** All Hostages have been rescued! */
    ROUNDEND_TARGET_SAVED = 12,             /** Target has been saved! */
    ROUNDEND_HOSTAGES_NOT_RESCUED = 13,     /** Hostages have not been rescued! */
    ROUNDEND_TERRORISTS_NOT_ESCAPED = 14,   /** Terrorists have not escaped! */
    ROUNDEND_VIP_NOT_ESCAPED = 15,          /** VIP has not escaped! */
    ROUNDEND_GAME_COMMENCING = 16           /** Game Commencing! */
}

/**
 * Terminates the round.
 * 
 * @param delay     The time between ending the round, and the new round beginning.
 * @param reason    The reason for the round ending.  See enum RoundEndReasons.
 */
stock GameData_TerminateRound(Float:delay, RoundEndReasons:reason)
{
    SDKCall(g_hTerminateRound, delay, _:reason);
}

/**
 * Takes a winning team index and returns its corresponding round end reason.
 * Ex: Takes index '2' and returns the Terrorists_Win round end reason.
 * 
 * @param teamindex     The team index that won the round.
 * 
 * @return              The round end reason.  ROUNDEND_GAME_COMMENCING if invalid teamindex.
 */
stock RoundEndReasons:Util_TeamToReason(teamindex)
{
    if (teamindex == CS_TEAM_T)
        return ROUNDEND_TERRORISTS_WIN;
    
    else if (teamindex == CS_TEAM_CT)
        return ROUNDEND_CTS_WIN;
    
    return ROUNDEND_GAME_COMMENCING;
}

Here's an example of a module that can easily be ported between plugins using the project base.

This module can be developed as a separate entity and then the file can be copied into a project base and easily be compiled into the plugin. This specific module requires nothing but the modulemanager.inc (and of course project.inc which is just a plethora of defines)

I hope once it's out of development others can find use in this for their projects. I plan on making several more useful modules like this that can be used in any variety of plugins.

For example:
Usermessage module: Just a library of usermsgs wrapped in functions with defined parameters.
No objectives module: Creates a cvar (the prefix of the cvar will even change automatically between different projects) that strips all objectives from the map.


Also, as it stands now, this will be the module template.

Code:
/*
 * ============================================================================
 *
 *  <Project Name>
 *
 *  File:          .inc
 *  Type:          Module
 *  Description:   
 *
 *  Copyright (C) 2009-2010  <Author>
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * ============================================================================
 */

/**
 * Template instructions:
 * 
 * All module-specific text has been replaced with text enclosed in <>
 * This is to make preparing this file to become the module you need easier.
 * Simply search-and-replace (usually CTRL+H) each of the tags below and replace it with the module specifics.
 * 
 * Tags:
 * <Project Name>       The name of the project.  (PROJECT_FULLNAME)
 * <Author>             The author(s) of the project.  (PROJECT_AUTHOR)
 * <FuncPrefix>         The prefix of your module's functions.  Usually the module's full name with no whitespaces.
 * <ModuleVarName>      Usually the same as <FuncPrefix>.  Names the global variable that stores this module's identifier.
 */

/**
 * This module's identifier.
 */
new Module:g_module<ModuleVarName>;

/**
 * Register this module.
 */
<FuncPrefix>_Register()
{
    // Define all the module's data as layed out by enum ModuleData in project.inc.
    new moduledata[ModuleData];
    
    moduledata[ModuleData_Disabled] = ;
    moduledata[ModuleData_Hidden] = ;
    strcopy(moduledata[ModuleData_FullName], CM_DATA_FULLNAME, "");
    strcopy(moduledata[ModuleData_ShortName], CM_DATA_SHORTNAME, "");
    strcopy(moduledata[ModuleData_Description], CM_DATA_DESCRIPTION, "");
    
    // Send this array of data to the module manager.
    g_module<ModuleVarName> = ModuleMgr_Register(moduledata);
    
    // Register all the events needed for this module.
    //EventMgr_RegisterEvent(g_module<ModuleVarName>, Event_OnAllPluginsLoaded,      "<FuncPrefix>_OnAllPluginsLoaded");
    //EventMgr_RegisterEvent(g_module<ModuleVarName>, Event_OnPluginEnd,             "<FuncPrefix>_OnPluginEnd");
    //EventMgr_RegisterEvent(g_module<ModuleVarName>, Event_OnMapStart,              "<FuncPrefix>_OnMapStart");
    //EventMgr_RegisterEvent(g_module<ModuleVarName>, Event_OnMapEnd,                "<FuncPrefix>_OnMapEnd");
    //EventMgr_RegisterEvent(g_module<ModuleVarName>, Event_OnAutoConfigsBuffered,   "<FuncPrefix>_OnAutoConfigsBuffered");
    //EventMgr_RegisterEvent(g_module<ModuleVarName>, Event_OnConfigsExecuted,       "<FuncPrefix>_OnConfigsExecuted");
    //EventMgr_RegisterEvent(g_module<ModuleVarName>, Event_OnClientPutInServer,     "<FuncPrefix>_OnClientPutInServer");
    //EventMgr_RegisterEvent(g_module<ModuleVarName>, Event_OnClientDisconnect,      "<FuncPrefix>_OnClientDisconnect");
    //EventMgr_RegisterEvent(g_module<ModuleVarName>, Event_RoundStart,              "<FuncPrefix>_RoundStart");
    //EventMgr_RegisterEvent(g_module<ModuleVarName>, Event_RoundFreezeEnd,          "<FuncPrefix>_RoundFreezeEnd");
    //EventMgr_RegisterEvent(g_module<ModuleVarName>, Event_RoundEnd,                "<FuncPrefix>_RoundEnd");
    //EventMgr_RegisterEvent(g_module<ModuleVarName>, Event_PlayerTeam,              "<FuncPrefix>_PlayerTeam");
    //EventMgr_RegisterEvent(g_module<ModuleVarName>, Event_PlayerSpawn,             "<FuncPrefix>_PlayerSpawn");
    //EventMgr_RegisterEvent(g_module<ModuleVarName>, Event_PlayerHurt,              "<FuncPrefix>_PlayerHurt");
    //EventMgr_RegisterEvent(g_module<ModuleVarName>, Event_PlayerDeath,             "<FuncPrefix>_PlayerDeath");
    //EventMgr_RegisterEvent(g_module<ModuleVarName>, Event_PlayerJump,              "<FuncPrefix>_PlayerJump");
    //EventMgr_RegisterEvent(g_module<ModuleVarName>, Event_WeaponFire,              "<FuncPrefix>_WeaponFire");
    
    // Register config file(s) that this module will use.
    // ConfigMgr_Register(g_module<ModuleVarName>, "<FuncPrefix>_OnConfigReload", "configs/<projectshortname>/<config>.txt");
}

/**
 * Plugin is loading.
 */
<FuncPrefix>_OnPluginStart()
{
    // Register the module.
    <FuncPrefix>_Register();
}

/**
 * All plugins have loaded.
 */
public <FuncPrefix>_OnAllPluginsLoaded()
{
}

/**
 * Plugin is ending.
 */
public <FuncPrefix>_OnPluginEnd()
{
}

/**
 * The map has started.
 */
public <FuncPrefix>_OnMapStart()
{
}

/**
 * The map has ended.
 */
public <FuncPrefix>_OnMapEnd()
{
}

/**
 * This is called before OnConfigsExecuted but any time after OnMapStart.
 * Per-map settings should be set here. 
 */
public <FuncPrefix>_OnAutoConfigsBuffered()
{
}

/**
 * All convars are set, cvar-dependent code should use this.
 */
public <FuncPrefix>_OnConfigsExecuted()
{
}

/**
 * Called when a registered config file (by this module) is manually.
 */
public <FuncPrefix>_OnConfigReload(configindex)
{
}

/**
 * Client has joined the server.
 * 
 * @param client    The client index.
 */
public <FuncPrefix>_OnClientPutInServer(client)
{
}

/**
 * Client is disconnecting from the server.
 * 
 * @param client    The client index.
 */
public <FuncPrefix>_OnClientDisconnect(client)
{
}

/**
 * Round has started.
 */
public <FuncPrefix>_RoundStart()
{
}

/**
 * Pre-round has freezetime has finished.
 */
public <FuncPrefix>_RoundFreezeEnd()
{
}

/**
 * Round has ended.
 */
public <FuncPrefix>_RoundEnd()
{
}

/**
 * Client has joined a team.
 * 
 * @param client        The client index.
 * @param team          The client's new team.
 * @param oldteam       The team the client is switching from.
 * @param disconnect    True if the client is disconnecting, false if switching to a team.
 */
public <FuncPrefix>_PlayerTeam(client, team, oldteam, bool:disconnect)
{
}

/**
 * Client has spawned.
 * 
 * @param client    The client index.
 * 
 */
public <FuncPrefix>_PlayerSpawn(client)
{
}

/**
 * Client has been damaged.
 * 
 * @param victim        The index of the hurt client.
 * @param attacker      The index of the attacking client.
 * @param health        How much health the client has after the damage.
 * @param armor         How much armor the client has after the damage.
 * @param weapon        The weapon classname used to hurt the victim. (No weapon_ prefix)
 * @param dmg_health    The amount of health the victim lost.
 * @param dmg_armor     The amount of armor the victim lost.
 * @param hitgroup      The hitgroup index of the victim that was damaged.
 */
public <FuncPrefix>_PlayerHurt(victim, attacker, health, armor, const String:weapon[], dmg_health, dmg_armor, hitgroup)
{
}

/**
 * Client has been killed.
 * 
 * @param victim    The index of the killed client.
 * @param attacker  The killer of the victim.
 * @param weapon    The weapon classname used to kill the victim. (No weapon_ prefix)
 * @param headshot  True if the death was by headshot, false if not.
 */
public <FuncPrefix>_PlayerDeath(victim, attacker, const String:weapon[], bool:headshot)
{
}

/**
 * Client has jumped.
 * 
 * @param client        The client index.
 */
public <FuncPrefix>_PlayerJump(client)
{
}

/**
 * Client has fired a weapon.
 * 
 * @param client        The client index.
 * @param weapon        The weapon classname fired. (No weapon_ prefix)
 */
public <FuncPrefix>_WeaponFire(client, const String:weapon[])
{
}
__________________

Last edited by Greyscale; 02-11-2010 at 01:46.
Greyscale is offline
Greyscale
SourceMod Plugin Approver
Join Date: Dec 2007
Location: strYoMommasHouse[you];
Old 02-12-2010 , 22:28   Re: Concept: Project base
Reply With Quote #6

First plugin to use this project base idea:

http://forums.alliedmods.net/showthread.php?t=118624
__________________
Greyscale is offline
arsirc
Veteran Member
Join Date: Dec 2007
Location: Carinthia,Austria,Earth
Old 03-23-2010 , 05:18   Re: Concept: Project base
Reply With Quote #7

i will give it a try ...
arsirc is offline
Greyscale
SourceMod Plugin Approver
Join Date: Dec 2007
Location: strYoMommasHouse[you];
Old 03-23-2010 , 13:56   Re: Concept: Project base
Reply With Quote #8

http://code.google.com/p/smprojectbase/source/browse/

That's a link to the source you'll need to start your project in. It might be a bit tough for you because there is no user manual yet. If you're good at reading code you should be able to figure it out.

Keep in mind that you shouldn't have to edit anything in the base/ folder. Plugin-specifics are set in project.inc.

An exception to the "dont edit the base/ files" is that you need to fix 2 include paths to match the directory structure of your project.

For example
#include "project/base/hgversion"

Most people contain the source in a folder named after the plugin, so you'll have to change "project" to the folder name you use.
__________________
Greyscale is offline
arsirc
Veteran Member
Join Date: Dec 2007
Location: Carinthia,Austria,Earth
Old 03-25-2010 , 06:01   Re: Concept: Project base
Reply With Quote #9

what is the best way to keep the base uptodate?
arsirc is offline
rhelgeby
Veteran Member
Join Date: Oct 2008
Location: 0x4E6F72776179
Old 03-25-2010 , 13:25   Re: Concept: Project base
Reply With Quote #10

You should only need to update files in the base folder.
__________________
Richard Helgeby

Zombie:Reloaded | PawnUnit | Object Library
(Please don't send private messages for support, they will be ignored. Use the forum.)
rhelgeby is offline
Send a message via MSN to rhelgeby
Reply



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 02:15.


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