• Welcome to Vice City Multiplayer.
 
Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Topics - stormeus

#1
NOTE
This topic is locked to prevent people from ruining the succession of posts while the guide is being written. PM any errors or suggestions to stormeus.


The Absolute Beginner's
Guide to Pawn





Part I: Concepts              Part II: Control Structures             Part III: Arrays and Strings            Part IV: Basic Functions/Constructs           
#2
General Discussion / [Debate] Script Copyrighting
April 24, 2011, 06:24:24 AM
I think we should have a little debate over the copyrighting of scripts, mainly because I've been digging through a few old threads and I've seen instances of authors asking people to pull down scripts or flaming them because their scripts are similar or based off of one of theirs. I think this is a topic the community is somewhat divided on, so here goes nothing:

What's your stance on scripts and copyrights?

Personally, I think that unless someone releases a script under a license (which even then is a little harder to enforce), they cannot and should not have the right to tell someone else to take down their script just because it's based off of or looks like one of their scripts. My reason for this is that it blocks people from innovating scripts and improving them in ways the original author may not have thought of. Also, if someone wants to make a script with features similar to another server's, no one should flame the new script author just because they want to make their own interpretation of a popular server.

The development of scripts should be progressive, but authors should have some rights as well. That's why I release my scripts and programs (sometimes) under a Creative Commons license, so that people can alter my work as long as I get attribution and, sometimes, share alike and use the same license.

Note
Everyone is entitled to their own opinions. This thread is for a friendly debate about how (if) scripts should be copyrighted. We can agree to disagree, but please, do NOT flame other people because of what they believe.
#3
Script Showroom / [Beta] Multimode Server (MMS)
April 22, 2011, 11:57:25 AM
Table of Contents

Multimode Server (MMS)
So this is a little project I started a few days ago when I noticed that SA:MP servers have the ability to rotate between game modes, while VC:MP doesn't offer such a feature. Though I can't recode the VC:MP server itself, I've made a wrapper that lets you (almost) seamlessly rotate between multiple gamemodes on one server.

By having a separate process handle the actual rotation, editing the actual server configuration and spawning servers, it's now possible to have a mode rotation such as Bomb da Base, followed by Capture the Flag, in a similar way as GTA:IV's multiplayer. To make good use of it, you could string multiple gamemodes by using GameModeExit() while running the multimode server. Once the gamemode stops, so will the server. After it detects that the server's been shut down, it'll reload it with the next available gamemode.

If you want to shut down the multimode wrapper, go to the multimode console and press Ctrl + C. You can also use Ctrl + C on the server console to skip that gamemode.

Beta
MMS is currently in open beta. It should be stable enough for server enthusiasts to use. However, use on production servers is not endorsed by myself and will be done at the server owner's own risk.

Right now, MMS does not support Squirrel servers. Implementation for Squirrel will take time.


Installation
Unzip multi-svr(.exe) and multimode.cfg to your server's folder. That's all there is to it.

Configuration
Open multimode.cfg in Notepad (nano or vim on Linux) or any code editor. The config file works so that each line counts as a game mode. If you had two game modes: mode1 and mode2; your multimode.cfg file would look like this:


mode1
mode2


Download



Source Code


Mirrors always welcome!

Screenshots (Click for full size)



NOTE: "Mode1" was a typo across all the testing gamemodes. It's just to illustrate that the server is capable of rotating between multiple gamemodes.

Todo
Feature suggestions and bug reports can be made in this thread.


  • Implement support for Squirrel servers.
#4
ShowRoom (pawn) / Top Three Players (by K/D ratio)
April 18, 2011, 09:04:24 PM
This command (/c topoverall) was written for a help topic and is being moved to the Pawn showroom for anyone looking for it in the future. This command will get the three best players according to kill/death ratio.

Warning
As more people play on your server, this command will become more resource intensive.

Note
This command was made based off of a GUPS script. It likely will not work on a blank gamemode and the instructions might not be the same.

Screenshot



Include:

#include <dini>
#include <float>


Put this code in OnPlayerCommandText():

// Show the best players overall
else if(strcmp(cmd, "topoverall", true) == 0)
{
// Declare some variables that we'll need
new topUser1[2][128],
topUser2[2][128],
topUser3[2][128],
userFile[64],
Float:deaths,
Float:kills,
Float:ratio,
sRatio[10],
nick[128],
i,
j;

// Set the default ratios for our top users
topUser1[1] = "0.00";
topUser2[1] = "0.00";
topUser3[1] = "0.00";

// Get the total number of known users.
j = dini_Int("/AllUsers.ini", "Index");

// Iterate through all known users
for(i = 1; i < j + 1; i++)
{
// Get this person's nickname.
nick = dini_Get("/AllUsers.ini", IntToStr(i));

// Find this user's file.
format
(
// String formatting
userFile,
sizeof(userFile),
"/Users/%s.ini",

// Variables, respectively
nick
);

// Get their kills and deaths.
kills  = dini_Int(userFile, "Kills");
deaths = dini_Int(userFile, "Deaths");

// Now find their K/D ratio.
ratio = floatdiv(kills, deaths);

// Is this ratio better than the current first-place holder's?
if(ratio > floatstr(topUser1[1]))
{
// Is there a person in first place?
if(floatstr(topUser1[1]) > 0)
{
// Is there a person in second place?
if(floatstr(topUser2[1]) > 0)
{
// Move the previous second place winner to third place
topUser3 = topUser2;

// Move the previous first place winner to second place
topUser2 = topUser1;
}
// Nope
else
{
// Move the previous first place winner to second place
topUser2 = topUser1;
}
}

// Set them as first-place.
topUser1[0] = nick;

// Convert their ratio to a string
format
(
// String formatting
sRatio,
sizeof(sRatio),
"%f",

// Variables, respectively
ratio
);

// Set their ratio as the ratio string
topUser1[1] = sRatio;

// Done here.
continue;
}
// No, but is it better than second-place?
else if(ratio > floatstr(topUser2[1]))
{
// Is there a person in second place?
if(floatstr(topUser2[1]) > 0)
{
// Move the previous second place winner to third place
topUser3 = topUser2;
}

// Set them as second-place.
topUser2[0] = nick;

// Convert their ratio to a string
format
(
// String formatting
sRatio,
sizeof(sRatio),
"%f",

// Variables, respectively
ratio
);

// Set their ratio as the ratio string
topUser2[1] = sRatio;

// Done here.
continue;
}
// No, but is it better than third-place?
else if(ratio > floatstr(topUser3[1]))
{
// Yes. Set them as third-place.
topUser3[0] = nick;

// Convert their ratio to a string
format
(
// String formatting
sRatio,
sizeof(sRatio),
"%f",

// Variables, respectively
ratio
);

// Set their ratio as the ratio string
topUser3[1] = sRatio;

// Done here.
continue;
}
// They did not rank in the Top 3.
else
{
continue;
}
}

// Start posting the top three
SendClientMessageToAll(COLOR_YELLOW, "** Top Three Players **");

// Format a message string for first place.
format
(
// String formatting
szMsg,
sizeof(szMsg),
"1. %s - %.2f",

// Variables, respectively
topUser1[0],
floatstr(topUser1[1])
);

// Send to everyone
SendClientMessageToAll(COLOR_YELLOW, szMsg);

// Format a message for second place.
format
(
// String formatting
szMsg,
sizeof(szMsg),
"2. %s - %.2f",

// Variables, respectively
topUser2[0],
floatstr(topUser2[1])
);

// Send to everyone
SendClientMessageToAll(COLOR_YELLOW, szMsg);

// Format a message for third place.
format
(
// String formatting
szMsg,
sizeof(szMsg),
"3. %s - %.2f",

// Variables, respectively
topUser3[0],
floatstr(topUser3[1])
);

// Send to everyone
SendClientMessageToAll(COLOR_YELLOW, szMsg);

// Done.
return 1;
}


Put this code in OnGameModeInit():

// Create the all users INI if it does not exist
if(!dini_Exists("/AllUsers.ini"))
{
    // Create it with an index of 0 for no users
    dini_Create("/AllUsers.ini");
    dini_IntSet("/AllUsers.ini", "Index", 0);
}


Put this code in OnPlayerConnect() under if(dini_Exists(file)):

// Add them to the All Users INI if they aren't in it
new j = dini_Int("/AllUsers.ini", "Index"),
i,
found = 0,
result[128];

// Iterate through all users
for(i = 1; i < j + 1; i++)
{
// Get this user's nick.
result = dini_Get("/AllUsers.ini", IntToStr(i));

// This is them.
if(strcmp(result, gPlayers[playerid], true) == 0)
{
// Found them!
found = 1;

// Stop
break;
}
}

// They're not there.
if(found == 0)
{
// Increment the index.
j++;

// Add them to the index.
dini_Set("/AllUsers.ini", IntToStr(j), gPlayers[playerid]);

// Reset the index to variable "j"
dini_IntSet("/AllUsers.ini", "Index", j);
}
#5
ShowRoom (pawn) / phPSA (rev1)
April 17, 2011, 08:14:34 AM
phPSA is a project I started due to the inactivity of PSA (the Pawn Supporting Application) and its incompatibility with Linux servers. For guaranteed cross-compatibility and to let you guys look at the source easily, phPSA is written in PHP. Since this is a new project, a few bugs are expected here and there and it may not be as efficient as you'd like it to be, so please, post constructive feedback.

PHP Pawn Supporting Application
phPSA is an external application, extending Pawn's functionality. It communicates with Pawn through text files, allowing PSA to perform a variety of actions normally unavaliable in Pawn. You can think of PSA as a plugin, only external.

Currently phPSA only supports SQL data storage. IRC echo support will be implemented at a later time.

Download
The current phPSA version is Revision 1. You can download it using any of the following links:

The archive includes:




readme.htmHelp and tutorial file
phpsa.phpphPSA script. This is an executable AND the source code.
phpsa.cfgphPSA Configuration

Installation

  • Put the appropriate functions in your script. These functions are written below.
    Quote






    new gColumns[24][128]...Variables used for reading rows from SELECT queries.
    PSAtimer()PSA timer function. Processes activity between phPSA and your gamemode.
    SetTimer("PSAtimer", 200, 1)Activates the phPSA timer function every 200ms repeatedly.
    PerformSQLquery(str[])Performs a regular SQL query.
    OnQueryResult(qid[], str[], index)Called whenever any query is done. Returns the number of rows affected OR 1 on a SELECT query.
    If the query is a SELECT query, the column names are stored in gColumns and the values in gValues.
  • Put phpsa.php and phpsa.cfg in your server's root dir (where vcmp-svr is).
  • Edit phpsa.cfg with your MySQL settings
  • Launch phpsa.php using the PHP runtime.

phPSA REQUIRES PHP to work.

Ubuntu/Debian users can use this command to install PHP:
sudo apt-get install php5

Function Code

PerformSQLquery(str[])
{
// Open a file pointer to SQL input
new File: filex;
filex = fopen("sql_input.psa");

// Perform the query
fwrite(filex, str);

// Close the buffer
fclose(filex);

// Return
return 1;
}

new gColumns[32][24][128],
gValues[32][24][128],
allColumns[24][256],
allValues[2][128];

OnQueryResult(str[], index)
{
// Try to parse it
// If there's an = sign, it's a DINI
if(strfind(str, "=") > 0)
{
   // Declare some variables
   new i, j;
   
   // Find the prefix
   new prefix[4];
format(prefix, sizeof(prefix), "%d=", index);
   
   // Get rid of the "index=" prefix
   strdel(str, 0, strlen(prefix));

// Split according to each column in a row
split(str, allColumns, ',');
   
   // Now read all columns
   for(i = 0; i < 24; i++)
   {
       // Not empty, keep going
       if(strlen(allColumns[i]))
       {
       // Now split the string according to equal signs
       split(allColumns[i], allValues, '=');
       
       // And read all the values
        for(j = 0; j < sizeof(allValues); j++)
       {
           // The column name has to be set
           gColumns[index - 1][i] = allValues[j];
           
            // Increment j again. We only read every two values.
           j++;
           
           // The column value has to be set
           gValues[index - 1][i]  = allValues[j];
       }
       }
// It's empty. There can't possibly be more.
else
{
   // Format a message string
   new szMsg[256];
   format(szMsg, sizeof(szMsg), "Column %s == %s", gColumns[0][0], gValues[0][0]);
   
   // Output the first row's value for the first column
   // Uncomment this if you ever want to debug it
   SendClientMessageToAll(COLOR_YELLOW, szMsg);

   // Break the for loop.
   break;
}
   }
   
   // We're done. Everything went better than expected.
   return 1;
}
// Number of rows affected
else
{
   // Return the number of affected rows as an integer
   return strval(str);
}
}

public PSAtimer() // PSA timer for reading things.
{
// Declare some variables
new cont[2048], str[256], File: filex, index;

// Check if we have SQL output
if(fexist("sql_output.psa"))
{
// Open a pointer to the SQL output
filex = fopen("sql_output.psa");

// The index is 1.
index = 1;

// Read the output
while(fread(filex,cont,sizeof(cont)))
{
   if(strlen(cont))
   {
// Keep reading until we hit the end of the file
while(strfind(cont,"\n")>0)
{
strmid(str,cont,0,strfind(cont,"\n"));
strdel(cont,0,strfind(cont,"\n"));
}

// Call the "OnQueryResult" event
OnQueryResult(str,index);

// Increment the index
index++;
}
}

// Close the pointer
fclose(filex);

// Delete the files for a fresh start next time
fremove("sql_input.psa");
fremove("sql_output.psa");
}
}
stock split(const strsrc[], strdest[][], delimiter)
{
new k, li;
new aNum;
new len;
while(k <= strlen(strsrc))
{
if(strsrc[k] == delimiter || k == strlen(strsrc))
{
len = strmid(strdest[aNum], strsrc, li, k, 128);
strdest[aNum][len] = 0;
li = k+1;
aNum++;
}
k++;
}
return 1;
}


To-Do

  • Implement IRC functions.
  • Convert to SQLite? (Discuss in thread)

Feedback
Suggestions, questions, and bug reports should be posted in this thread.

Version History
Revision 1

  • PSA rewritten in PHP for cross-compatibility
  • Pawn functions written for easy SELECT querying