[Tutorial] How to Mini-Game / Event 101
#1

Basic concept of a mini-game/event
There are many ways to do this and it can vary from one person to another but here is how i'd do
a mini-game/event


First: What is a mini-game/event?
Basically a process a player goes through as a side event on the server like Deathmatching/TeamDeathMatch/Race/Derby..etc.
=======
What comes first in your mind when you first hear MiniGame?
Yes command, the command to enter that minigame.
PHP Code:
public OnPlayerCommandText(playeridcmdtext[])
{
    if (
strcmp("/dmevent"cmdtexttrue10) == 0)
    {
        if(
GetPlayerState(playerid) == PLAYER_STATE_ONFOOT)//Related to event
        
{
            if(
dmstarted) return SendClientMessage(playerid, -1,"DM IS ALREADY IN PROCESS");//if its already in progress
            
if(GetPlayerWantedLevel(playerid) >=1) return SendClientMessage(playerid,-1,"You can't join events if you're wanted!");//(Optioinal)
            
if(!IsPlayerInRangeOfPoint(playeridEventRangeX,Y,Z)) return SendClientMessage(playerid,-1,"You need to be in the event range.");//(Optional)
            
if(GetPlayerMoney(playerid) < EventCash) return SendClientMessage(playerid,-1,"You don't have enough cash (EventCash$)");//Price Optional
            
if(pleasewait)  return SendClientMessage(playerid,-1,"You need to wait at least 2 seconds between each player entering!");// Precaution
               
if(playernumberdm ==MAX_EVENT_PLAYERS) return SendClientMessage(playerid,-1,"You can't join dm its full!");//Max players in depending on the positions you put.
               
if(playernumberdm ==0)//setting the starter timer only once
            
{
                 
SetTimerEx("DelayDmEvent"Delay_Timefalse"d"playerid);//Delay timer to give players a chance to join.
                
SendClientMessageToAll(-1,"DEATH MATCHING EVENT(DM) IS STARTING IN 50 SECONDS!");//Notify players.
                
}
            
playerstimerdm[playerid] = SetTimerEx("DmCheck"1000true"i"playerid);//in event check explained in its function
            
TogglePlayerControllable(playerid,0), ResetPlayerWeapons(playerid); //Optional related to the event
            
indm[playerid] = truepleasewait true//a check that we'll need one for indm to see if a player is in the DM event and the other is to keep 2 players from entering at the same second.
            
SetTimer("removepleasewait"2000false), playernumberdm++;//increasing the player's count and removing the wait check.
            
SetPlayerVirtualWorld(playerid,DmWorld);//Related to Event
            
GivePlayerWeapon(playerid27,500), GivePlayerWeapon(playerid31,500), GivePlayerWeapon(playerid28,500);//Related To event
            
GivePlayerWeapon(playerid34,500), GivePlayerWeapon(playerid24,500), GivePlayerWeapon(playerid8,500);//Related To event
            
SetPlayerHealth(playerid,100), SetPlayerArmour(playerid,100);//Related To event
            
PlayerPos(playerid), GivePlayerMoney(playerid, -2500);//Related To event
            
}
        else
        {
            
SendClientMessage(playerid,-1,"YOU NEED TO BE ON FOOT TO ENTER THE DM EVENT");//Related To event
            
}
        return 
1;
        }
    return 
0;

I've used variables with realistic names to make it more clear about what does what and so on read it carefully, I made comments on every line to what it does.
PlayerPos is the position each player enters inside to make sure players don't collapse with each other here is how it should look like each x , y and Z for each player must be different positions inside the minigame.

PHP Code:
forward PlayerPos(playerid);
public 
PlayerPos(playerid)
{
    switch(
playernumberdm)//Setting player's position depending on the count number this is better than rand cuz rand might return one pos 2 times = players stuck.
    
{
    case 
1:
    {
        
SetPlayerPos(playeridx,y,z);
        }
    case 
2:
    {
        
SetPlayerPos(playerid,x,y,z);
        }
    case 
3:
    {
        
SetPlayerPos(playeridx,y,z);
        }
    case 
4:
    {
        
SetPlayerPos(playeridx,y,z);
        }
    case 
5:
    {
        
SetPlayerPos(playerid,x,y,z);
        }
    case 
6:
    {
        
SetPlayerPos(playeridx,y,z);
        }
    }
    return 
1;

Using switch cases since its faster increase the positions depending on how many players you want inside.
========
Second thing to be set are the timers we put on that command, why do we delay? to give players a chance to enter, why set a on-going timer? to keep getting the player's state inside the game to know if he's dead/alive...etc so first start with the delayed function:
PHP Code:
forward DelayDmEvent(playerid);
public 
DelayDmEvent(playerid)//after Delay_Time had passed
{
    if(
playernumberdm <=1)//if there's only one player or less inside end it and kill all variables that were set.
    
{
        
SendClientMessage(playerid,-1,"DM HAS ENDED DUE TO NOT ENOUGH PLAYERS ENTERING");//notify
        
TogglePlayerControllable(playerid,1);//unfreeze the player
        
GivePlayerMoney(playerid,EventCash);//give him back his cash
        
dmstarted =false;//cancel the dm started variable
        
pfrozen[playerid] =false;//cancel the freezing variable
        
playernumberdm =0;//reset the number of players to be ready for next event
        
indm[playerid] =false;//not in  the dm event anymore
        
KillTimer(playerstimerdm[playerid]);//kill the constant timer we set.
        
SetPlayerVirtualWorld(playerid,0);//set back to the original virtual world.
        
SetPlayerPos(playeridX,Y,Z);//send the player back outside the event to where he entered from.
        
}
    else
//if there is more than 1 player start it.
    
{
        
SendClientMessageToAll(-1,"DM HAS STARTED!");//notify
        
dmstarted true;//it started
        
TogglePlayerControllable(playerid,1);//unfreeze the player.
        
}
    return 
1;

So this is the timer that was called for the first player entering, regarding the players that enter after this is where the constant timer we set does.
======
The timer that was set:
PHP Code:
forward DmCheck(playerid,vehicleid);
public 
DmCheck(playerid,vehicleid)//The event checker to see who won this is set for each player entering separately.
{
    new 
names[26],strings[126];
    if(
dmstarted && !pfrozen[playerid])//unfreezing the player after the event starts.
    
{
        
pfrozen[playerid] =true;//to avoid unfreeze spam.
        
TogglePlayerControllable(playerid,1);
        }
    if(
playernumberdm==&& dmstarted)//if there's only one player in there (the player with this timer) and it has started then announce the winner and end it.
    
{//then kill all variables that were set.
        
GetPlayerName(playerid,names,sizeof(names));
        
format(strings,sizeof(strings),".:%s HAS WON THE DM AND EARNED 5000$!:.",names);
        
SendClientMessageToAll(-1,strings);
        
TogglePlayerControllable(playerid,1), ResetPlayerWeapons(playerid), SetPlayerWantedLevel(playerid,0);
        
pfrozen[playerid] =falseindm[playerid] =falsedmstarted false;
        
GivePlayerMoney(playeridEventCash*2);
        
SetPlayerVirtualWorld(playerid,0), SetPlayerPos(playerid,X,Y,Z);
        
KillTimer(playerstimerdm[playerid]), playernumberdm =0;
        }
    return 
1;

Each and every variable was explained and their names indicate what they do, Read carefully if there's any line you don't understand comment below and i'll gladly explain it both here and to you in the comments.
======
So this is how it is basically done, BUT there are 2 more things to be done,
what if a player dies in the event?? what if a player disconnects in an event?

PHP Code:
public OnPlayerDisconnect(playerid,reason)// if a player disconnects in the event.
{
    if(
indm[playerid])//if he's in the event kill his variables and decrease the allocated number of players inside.
    
{
        
indm[playerid] =falsepfrozen[playerid] =false;
        
SetPlayerWantedLevel(playerid,0), ResetPlayerWeapons(playerid);
        
playernumberdm--, KillTimer(playerstimerdm[playerid]);
        }
    return 
1;

Didn't have to do much here as the constant set timer or the delayed timer will do the rest.
PHP Code:
public OnPlayerDeath(playerid,killerid,reason)//If a player dies in the event
{
    if(
indm[playerid] && !dmstarted && playernumberdm ==1)//If he's in the event and it hasn't started and there's only one player in there (him) then end the event.
    
{
        
SendClientMessage(playerid,-1,"DM HAS ENDED DUE TO NO PLAYERS ENTERING");
        
TogglePlayerControllable(playerid,1), ResetPlayerWeapons(playerid);
        
pfrozen[playerid] =falsedmstarted =falseindm[playerid] =false;
        
GivePlayerMoney(playerid,2500), playernumberdm =0;
        
KillTimer(playerstimerdm[playerid]), SetPlayerVirtualWorld(playerid,0);
        }
    else if(
indm[playerid])//if he's just in the event and someone killed him or he just died.
    
{
        
playernumberdm--;//decrease the allocated number of players in the event and kill his variables.
        
indm[playerid] =falsepfrozen[playerid] =false;
        
ResetPlayerWeapons(playerid), SetPlayerVirtualWorld(playerid,0);
        
SetPlayerWantedLevel(playerid,0), KillTimer(playerstimerdm[playerid]);
        }
    return 
1;

======
That's about it, i'm going to post a pastebin link so that you can paste the full code and read it in your pawno if it'll be easier on you, this is basically the concept used in making most events or mini-games if you may call them, the idea is to set the right things and reset them at the right time I've had many problems at first because i forgot to set variables when a player dies/disconnects.. etc but reading this will make you understand what's needed to be done.
Pastebin: Link with a total of 160 lines, it will compile but that doesn't mean it will magically work you have to add your own values for positions and so on.
Here is the sum up of variables and defines used to make this compile for test purposes:
PHP Code:
#define FILTERSCRIT
#include <a_samp>
new bool:dmstarted,bool:pfrozen[MAX_PLAYERS],bool:pleasewait,bool:indm[MAX_PLAYERS];//Event variables Indicated By Names
new playernumberdm,playerstimerdm[MAX_PLAYERS];//Event Variables Indicated by names
new Float:X,Float:Y,Float:Z;//Event Entering Place
new Float:x,Float:y,Float:z;//Event Place Inside for each player (make sure each is different.)
#define EventCash 2500 // The cash fee to enter.
#define DmWorld 6487 // The virtual world to separate the players from other players not playing the event.
#define EventRange 5.0 // the range where the player enters from
#define MAX_EVENT_PLAYERS 6 //the max amount of players in the event depends on the position cases at PlayerPos
#define Delay_Time 50*1000 // 50 seconds to give players a chance to join 
ALSO forgot to mention the part that removes the enter of a player to let another one in, you have to declare the function of removepleasewait like so:
PHP Code:
forward removepleasewait();
public 
removepleasewait() return pleasewait false
====
If you already got your way of making a mini game then there's no need for this, if you see me missing something or could've done something better comment and i'll gladly update.
Hope this helped you. Good luck.
EDIT: this is optional but recommended you should prevent players from pausing and for that i advise emmet's include for samp's callbacks Here by using OnPlayerPause and do if indm[playerid]==1 return Kick(playerid);
Reply
#2

As your first tutorial. I think you did a good job. I liked the way you named the variables. I also liked how you provided the complete code in pastebin for newbies to poke around with. However, I think you need to have a little more explanation about how stuff worked. And I'm not sure if SA-MP forums messed it up but identation isn't the best. Also uh, I think use ZCMD.

3/5
Reply
#3

Quote:
Originally Posted by Ritzy
View Post
As your first tutorial. I think you did a good job. I liked the way you named the variables. I also liked how you provided the complete code in pastebin for newbies to poke around with. However, I think you need to have a little more explanation about how stuff worked. And I'm not sure if SA-MP forums messed it up but identation isn't the best. Also uh, I think use ZCMD.

3/5
mate the code has a full proper indentation copy paste it in your pawno you'll see, samp forums always messes up indentation but once u paste it in pawno its fixed, i've already added useless variables to compile it and i got 0 warnings & 0 errors, i also used onplayercommandtext to show a basic format to avoid confusing players who don't use zcmd the purpose of this was to educate people about the basic concept of a minigame.
Thanks for everyone's support.
Reply
#4

Nice tutorial but PHP tags do not support BBcode

PHP Code:
[B]PlayerPos(playerid)[/B], GivePlayerMoney(playerid, -2500);//Related To event 
Reply
#5

Quote:
Originally Posted by rfr
View Post
Nice tutorial but PHP tags do not support BBcode

PHP Code:
[B]PlayerPos(playerid)[/B], GivePlayerMoney(playerid, -2500);//Related To event 
Ouch... lmao the more you know, fixed, thanks for that.
Reply
#6

Helpful.
Reply
#7

Quote:
Originally Posted by MarkNelson
View Post
Helpful.
Thanks i edited the final part of removing pleasewait variable.
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)