[GameMode] Collaborative RP - A SA-MP Community Production
#1

Hello everyone!

I recently realized how many people are looking for a nice, clean, basic roleplay gamemode that they can edit themselves and make personal instead of building one from the ground or using an already completed version. I came up with an idea; Why don't we all instead make this basic roleplay gamemode that people later can build onto and make their own?

The idea is that we - the community - all contribute to the script with ideas or our own scripts until it's ready! I've started building it and so far I've only completed the login and register system, together with some minor settings.

Remember: Dynamic, efficient and clean code is what we want!

Please post your own contributions (Ideas, thoughts, complaints, scripts even) in this thread and I'll combine it with the main script and put it here on the first post.

Script:
  • Current version: 0.1

  • Old versions:
    • None
Reply
#2

VERSION 0.1

Changes:
  • First version, everything
Notes:
  • Not compiled or tested.
Credits in this revision:
  • Lenny
    • Everything
pawn Код:
/*
    This is a base for a roleplay script using:
   
        * MySQL plugin
            By: G-sTyLeZzZ
            Link: https://sampforum.blast.hk/showthread.php?tid=56564
           
        * sscanf plugin
            By: ******
            Link: https://sampforum.blast.hk/showthread.php?tid=120356
           
        * foreach include
            By: ******
            Link: https://sampforum.blast.hk/showthread.php?tid=92679
           
        * zcmd include
            By: Zeex
            Link: https://sampforum.blast.hk/showthread.php?tid=91354
       
        * SHA512 plugin
            By: RyDeR`
            Link: https://sampforum.blast.hk/showthread.php?tid=188734
       
    Started by Lenny (lenny.carlson@hotmail.com) AKA Lenny the Cup @ forum.sa-mp.com
   
    This is a collaborative script, made by the SA-MP forum community of forum.sa-mp.com
   
    Features:
   
        * Dialog login system
   
*/


#include <a_samp>
#include <a_mysql>
#include <sscanf>
#include <foreach>
#include <zcmd>

//------------------------------------- Server configuration -------------------------------------
// DEFINITION                           VALUE                       COMMENT
#undef MAX_PLAYERS
#define MAX_PLAYERS                     10                          // The maximum amount of players on your server
#define DEBUG_MYSQL                     0                           // 1 = Use MySQL debugging
#define SHOW_MARKERS                    0                           // 0 = Off, 1 = Global, 2 = Streamed (Nearby) player markers on the map


#define MIN_PLAYER_PASSWORD             5
#define MAX_PLAYER_PASSWORD             15                          // The maximum string size for a players password

#define DEFAULT_SPAWN_X                 0.0
#define DEFAULT_SPAWN_Y                 0.0
#define DEFAULT_SPAWN_Z                 0.0
#define DEFAULT_SPAWN_ANGLE             0.0
#define DEFAULT_SPAWN_INTERIOR          0

//------------------------------------- Dialog IDs -------------------------------------
#define DIALOG_NOTHING                  1                           // An empty dialog ID, nothing happens when this is used
#define DIALOG_LOGIN                    2                           // Welcome, provide password
#define DIALOG_REGISTER                 3                           // Welcome, please register

//------------------------------------- MySQL Configuration -------------------------------------
#define SQL_HOST                        "localhost"
#define SQL_DB                          "database"
#define SQL_USER                        "user"
#define SQL_PASS                        "pass"

main() {}

//------------------------------------- Variables -------------------------------------
enum e_PlayerInfo
{
    pID,
    pName[MAX_PLAYER_NAME],
    bool: pLoggedIn,
    pCash,
    pAdmin,
    Float: pSpawn[4],                   // X, Y, Z, Angle
    pSpawnInt,
    pSkin
}
new PlayerInfo[MAX_PLAYERS][e_PlayerInfo];

//------------------------------------- Native Functions -------------------------------------
public OnGameModeInit()
{
    #if DEBUG_MYSQL == 1
        mysql_debug(1);
    #endif
    mysql_connect(SQL_HOST, SQL_USER,SQL_DB, SQL_PASS);
    ShowPlayerMarkers(SHOW_MARKERS);
}

public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
    Dialog_Welcome(playerid, dialogid, response, listitem, inputtext);
}

public OnPlayerConnect(playerid)
{
    GreetPlayer();
}

//------------------------------------- Other Functions -------------------------------------
// Dialog_Welcome
// By: Lenny
// Date: 11/11 2010
stock Dialog_Welcome(playerid, dialogid, response, listitem, inputtext[])
{
    switch(dialogid)
    {
        case DIALOG_LOGIN:
        {
            if(!response)
                KickPlayer(playerid, "Cancelled login.");
            if(isnull(inputtext))
                return ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_INPUT, "Welcome back!", "Please provide your password.\n\nError: No password provided. Please try again.", "Submit", "Cancel");
            new
                String[128];   
            SHA512(inputtext, String, 128);
            if(strcmp(String, GetPVarString(playerid, "Password"), false, 128)) // Wrong password!
            {
                SetPVarInt(playerid, "WrongLoginTries", GetPVarInt(playerid, "WrongLoginTries")+1);
                if(GetPVarInt(playerid, "WrongLoginTries") == 3)
                    KickPlayer(playerid, "Too many login tries.");
                format(String, 128, "Please provide your password.\n\nError: Invalid password.\n\nWrong tries: %d/3", GetPVarInt(playerid, "WrongLoginTries"));
                return ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_INPUT, "Welcome back!", String, "Submit", "Cancel");
            }
            LoadPlayerStats(playerid);
            SpawnPlayer(playerid);
            return 1;
        }
        case DIALOG_REGISTER:
        {
            if(!response)
                KickPlayer(playerid, "Cancelled register.");
            if(isnull(inputtext))
                return ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_INPUT, "Welcome!", "To play on this server, you need to register with a password.\n\n Please provide your password of choice below.\n\nError: No password provided. Please try again.", "Submit", "Cancel");
            if(strlen(inputtext) < MIN_PLAYER_PASSWORD || strlen(inputtext) > MAX_PLAYER_PASSWORD)
                return ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_INPUT, "Welcome!", "To play on this server, you need to register with a password.\n\n Please provide your password of choice below.\n\nError: Password is too long or too short. Please try again.", "Submit", "Cancel");
            RegisterPlayer(playerid, inputtext);
            LoadPlayerStats(playerid);
            SpawnPlayer(playerid);
            return 1;
        }
    }
}

// KickPlayer
// By: Lenny
// Date: 11/11 2010
// Usage: KickPlayer(1, 2, 3, 4, 5);
// 1 = Integer - ID of the player to kick
// 2 = String - Reason for the kick
// 3 = Integer - ID of the kicking player, INVALID_PLAYER_ID if nobody (Default)
// 4 = Bool - Silent or broadcast to everyone, true (Default) or false
// 5 = Bool - Log the kick, true or false (Default)
stock KickPlayer(playerid, const reason[], kicker = INVALID_PLAYER_ID, bool: silent = true, bool: log = false)
{
    new
        String[168],
        KickerName[MAX_PLAYER_NAME];
    if(kicker == INVALID_PLAYER_ID)
    {
        format(KickerName, MAX_PLAYER_NAME, "SYSTEM");
    else
    {
        format(String, 168, "You kicked %s, reason: %s", PlayerInfo[playerid][pName], reason);
        SendClientMessage(kicker, COLOR_CONFIRM, String);
        format(KickerName, MAX_PLAYER_NAME, PlayerInfo[kicker][pName]);
    }
    format(String, 168, "You were kicked by %s, reason: %s", KickerName, reason);
    SendClientMessage(playerid, COLOR_WARNING, String);
    Kick(playerid);
    if(silent == false)
    {
        format(String, 168, "%s kicked %s, reason: %s", KickerName, PlayerInfo[playerid][pName], reason);
        SendClientMessageToAll(COLOR_WARNING, String);
    }
    return 1;
}

// BanPlayer
// By: Lenny
// Date: 11/11 2010
// Usage: BanPlayer(1, 2, 3, 4, 5);
// 1 = Integer - ID of the player to ban
// 2 = String - Reason for the ban
// 3 = Integer - ID of the banning player, INVALID_PLAYER_ID if nobody (Default)
// 4 = Bool - Silent or broadcast to everyone, true (Default) or false
// 5 = Bool - Log the ban, true or false (Default)
stock BanPlayer(playerid, const reason[], banner = INVALID_PLAYER_ID, bool: silent = true, bool: log = false)
{
    new
        String[168],
        BannerName[MAX_PLAYER_NAME];
    if(banner == INVALID_PLAYER_ID)
    {
        format(BannerName, MAX_PLAYER_NAME, "SYSTEM");
    else
    {
        format(String, 168, "You kicked %s, reason: %s", PlayerInfo[playerid][pName], reason);
        SendClientMessage(banner, COLOR_CONFIRM, String);
        format(BannerName, MAX_PLAYER_NAME, PlayerInfo[banner][pName]);
    }
    format(String, 168, "You were kicked by %s, reason: %s", BannerName, reason);
    SendClientMessage(playerid, COLOR_WARNING, String);
    BanEx(playerid, reason);
    if(silent == false)
    {
        format(String, 168, "%s kicked %s, reason: %s", BannerName, PlayerInfo[playerid][pName], reason);
        SendClientMessageToAll(COLOR_WARNING, String);
    }
    return 1;
}

// GreetPlayer
// By: Lenny
// Date: 11/11 2010
stock GreetPlayer(playerid)
{
    GetPlayerName(playerid, PlayerInfo[playerid][pName], MAX_PLAYER_NAME);
    new
        Query[128];
    format(Query, 75, "SELECT `password` FROM `players` WHERE `name` = '%s'", PlayerInfo[playerid][pName]);
    mysql_query(Query);
    mysql_store_result();
    if(mysql_num_rows())
    {
        mysql_fetch_field_row(Query, "password");
        SetPVarString(playerid, "Password", Query);
        ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_INPUT, "Welcome back!", "Please provide your password.", "Submit", "Cancel");
    }
    else
    {
        ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_INPUT, "Welcome!", "To play on this server, you need to register with a password.\n\n Please provide your password of choice below.", "Submit", "Cancel");
    }
    mysql_free_result();
}

// LoadPlayerStats
// By: Lenny
// Date: 11/11 2010
stock LoadPlayerStats(playerid)
{
    new
        Query[210]];
    format(Query, 210, "SELECT `id`,`cash`,`admin`,`spawnx`,`spawny`,`spawnz`,`spawna`,`spawnint`,`skin` FROM `players` WHERE `name` = %s", GetPlayerName(playerid));
    mysql_query(Query);
    mysql_store_result();
    mysql_fetch_row_format(Query, " ")
    if(!mysql_num_rows())
    {
        mysql_free_result();
        return 0;
    }
    PlayerInfo[playerid][pID] = mysql_fetch_int();
    PlayerInfo[playerid][pCash] = mysql_fetch_int();
    PlayerInfo[playerid][pAdmin] = mysql_fetch_int();
    PlayerInfo[playerid][pSpawn][0] = mysql_fetch_float();
    PlayerInfo[playerid][pSpawn][1] = mysql_fetch_float();
    PlayerInfo[playerid][pSpawn][2] = mysql_fetch_float();
    PlayerInfo[playerid][pSpawn][3] = mysql_fetch_float();
    PlayerInfo[playerid][pSpawnInt] = mysql_fetch_int();
    PlayerInfo[playerid][pSkin] = mysql_fetch_int();
    mysql_free_result();
    SetSpawnInfo(playerid, 0, skin, PlayerInfo[playerid][pSpawn][0], PlayerInfo[playerid][pSpawn][1], PlayerInfo[playerid][pSpawn][2], PlayerInfo[playerid][pSpawn][3], 0, 0, 0, 0, 0, 0)
    return 1;
}

// RegisterPlayer
// By: Lenny
// Date: 11/11 2010
stock RegisterPlayer(playerid, password[])
{
    new
        EncryptedPass[168],
        String[400];
    SHA512(password, EncryptedPass, 400);
    format(String, x, "INSERT INTO `players` (`name`,`password`,`spawnx`,`spawny`,`spawnz`,`spawna`,`spawnint`,`spawnskin`,`admin`,`cash`) VALUES ('%s','%s','%f','%f','%f','%f','%d','%d','0','0')", PlayerInfo[playerid][pName], EncryptedPass, DEFAULT_SPAWN_X, DEFAULT_SPAWN_Y, DEFAULT_SPAWN_Z, DEFAULT_SPAWN_ANGLE, DEFAULT_SPAWN_INTERIOR);
    mysql_query(String);
    if(!mysql_affected_rows())
        return 0;
    return 1;
}
Reply
#3

hi, i have some very cool suggestions that i hope you make it...

my suggestions is that you put some GANGHOUSES with gang system, bank system, house system, some deathmatches, some stunts, businesses, payday, rank system too...

Ganghouses/gang system: when we create a gang we can buy a gang house and recruit people and the recruited ones have to rent the gang house and he will spawn there.. or if we dont like to be in a gang we could buy a house and spawn there too..

Bank system: you know what i mean ( deposit, withdraw, that kind of stuff...)

House System: already talked about that in "Ganghouses/gang system" paragraph...

Deathmatches: some deathmatches so can people can go up in their rank and to fight with other gangs and so..

Stunts: you could put some stunts in the airport or so... so people can hang out...

business: people can buy some business and win money when other players enter the biz, and can buy guns and fill the health/armour...

Payday: in a hour people can win some money...

Rank/stats System: a rank system would be great...

so man if you could put those suggestions... this can be the greatest gamemode evermade its kinda like public enemy with improvements... so said that i hope, but really hope you can put this things in this gamemode, please.

hope i got good news from you soon... please make this ideas

thx alot

Ruben.
Reply
#4

To be honest a lot of your ideas aren't applicable to a universal script, so I can't put them in this script because it would ruin the purpose.
Quote:
Originally Posted by Ruben_pt
Посмотреть сообщение
Bank system: you know what i mean ( deposit, withdraw, that kind of stuff...)
This is the only thing out of your suggestions that would be appropriate, so thank you for that!

And thank you for taking your time to say what you think!
Reply
#5

oh

that's sad... only one suggestion accepted
well.. its fine.. hope you put me on special thanks for my suggestion, atleast
thx anyway dude. hope you finish your gamemode soon and with success bye and thx
Reply
#6

I haven't taken a look at the majority of the code, though I've already picked up on some issues in your code.

1) Why are you creating defines for things you can define yourself, fair enough if the item was relatively important and needed to be used more than once (talking about the show markers define, that's easy to configure yourself).

2) Why are you creating excessive functions for features that are only used once?

3) Why are you using PVars? PVars are convenient, but the lookup speed is slower than it is for normal variables. Seeing as krisk was the first one to find that out (well, according to the speed test/tutorial Carlton posted) I'm surprised you didn't know that, unless you have other reasoning behind using PVars.

4) You've inadvertently violated forum rule: "Don't post huge scripts. Use http://pawn.pastebin.com/ instead." Why don't you store the script (and plugins) in an SVN repository? I assume that would not only be more convenient for those who decide to use this script, it would probably also be convenient for developing on.

5) I'm a bit confused as to why this code compiles, seeing as (be it a minor mistake):
Quote:

stock LoadPlayerStats(playerid)
{
new
Query[210]];
//...
}

Other than that, the concept of a collaborative script sounds nice. Good luck pulling it off.
Reply
#7

Thanks for your feedback Calgon, let me answer your questions

Quote:
Originally Posted by Calgon
Посмотреть сообщение
1) Why are you creating defines for things you can define yourself, fair enough if the item was relatively important and needed to be used more than once (talking about the show markers define, that's easy to configure yourself).
It's to allow a user with basic to no scripting knowledge to adjust the script according to their preferences.

Quote:
Originally Posted by Calgon
Посмотреть сообщение
2) Why are you creating excessive functions for features that are only used once?
The script is just a base and I'm confident the functions I've created so far will be used in other parts of the script than where they are right now. As for the dialog function, it's to give a proper overview of the script. I don't like scripts that have everything packed into one function, it gets incredibly messy.

Quote:
Originally Posted by Calgon
Посмотреть сообщение
3) Why are you using PVars? PVars are convenient, but the lookup speed is slower than it is for normal variables. Seeing as krisk was the first one to find that out (well, according to the speed test/tutorial Carlton posted) I'm surprised you didn't know that, unless you have other reasoning behind using PVars.
PVars are convenient when dealing with variables that will only be used once per player or generally seldom. Using up 500 bytes for something that's only checked once per OnPlayerConnect is pretty stupid in my opinion, and in this case I'm weighing memory over CPU performance. You won't see a lot of PVars in the "finished" version though.

Quote:
Originally Posted by Calgon
Посмотреть сообщение
4) You've inadvertently violated forum rule: "Don't post huge scripts. Use http://pawn.pastebin.com/ instead." Why don't you store the script (and plugins) in an SVN repository? I assume that would not only be more convenient for those who decide to use this script, it would probably also be convenient for developing on.
You're right, sorry. I can't really say it's huge yet though it's good you've given me the heads-up, and an SVN repository sounds like a great idea indeed!

Quote:
Originally Posted by Calgon
Посмотреть сообщение
5) I'm a bit confused as to why this code compiles, seeing as (be it a minor mistake):
If you look in the notes for the release you'll see that I haven't made sure it compiles or runs, it's just something I created in an hour or so.

Quote:
Originally Posted by Calgon
Посмотреть сообщение
Other than that, the concept of a collaborative script sounds nice. Good luck pulling it off.
Thank you!
Reply
#8

Looks Good. I look forward to having free time and maybe script something for it
Reply
#9

This idea seems pretty good but when you truly think about it, it's going to end up as a failure. This is like giving everyone an image on the internet and telling them to write there names on it - some people won't write their names, some will right others' names, and some will write useless stuff.
Reply
#10

Quote:
Originally Posted by Jacob_Venturas
Посмотреть сообщение
This idea seems pretty good but when you truly think about it, it's going to end up as a failure. This is like giving everyone an image on the internet and telling them to write there names on it - some people won't write their names, some will right others' names, and some will write useless stuff.
That makes no sense.

OFC there will be people who steal credits, as we have seen that in full GM releases anyways.
Reply
#11

Quote:
Originally Posted by Hal
Посмотреть сообщение
That makes no sense.

OFC there will be people who steal credits, as we have seen that in full GM releases anyways.
So you're saying everyone who fully releases a GM steals their published stuff from other people? That's a shame. BTW my post did make sense. I would like you to experiment that.
Reply
#12

Quote:
Originally Posted by Jacob_Venturas
Посмотреть сообщение
So you're saying everyone who fully releases a GM steals their published stuff from other people? That's a shame. BTW my post did make sense. I would like you to experiment that.
First What is there to experiment that your post made no sense.

Second, i said that "there will be people" which means not all, BUT SOME who steal credits.
And "steal credits, as we have seen that in full GM releases anyways." Means that the community has seen its fair share of GMs (ex. Re-releasing Raven' RP) that have been released and the credits are stolen.

Fuck, i though someone with brains can understand that.
Reply
#13

Nice idea, but I don't get it:
pawn Код:
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
    Dialog_Welcome(playerid, dialogid, response, listitem, inputtext);
}
Reply
#14

Quote:
Originally Posted by Hal
Посмотреть сообщение
First What is there to experiment that your post made no sense.

Second, i said that "there will be people" which means not all, BUT SOME who steal credits.
And "steal credits, as we have seen that in full GM releases anyways." Means that the community has seen its fair share of GMs (ex. Re-releasing Raven' RP) that have been released and the credits are stolen.

Fuck, i though someone with brains can understand that.
Yes, it does make mistake. Someone "with brains" can understand that. As for your cute exclamation, good job, "brains", for elaborating the obvious.
Reply
#15

It's open source, not possible to "steal" anything. Anything used in this script can be taken from it.
Reply
#16

1. Use threaded queries.
2. Use MySQL's SHA2 not separate plugin.
3. Learn what GetPVarString is and what it does.
4. Learn about efficient usage of MySQL (why do you compare password with pawn?).
Reply
#17

Hm...can't wait till i get some freetime and i could add my ideas and stuff into this. Awesome
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)