SA-MP Forums Archive
[Tutorial] Advanced Capturable Zone Scripting [Easy,Very Fast,Efficient,Variable Time TO Capture For DONOR , More STOCKS ,Foreach] - Printable Version

+- SA-MP Forums Archive (https://sampforum.blast.hk)
+-- Forum: SA-MP Scripting and Plugins (https://sampforum.blast.hk/forumdisplay.php?fid=8)
+--- Forum: Scripting Help (https://sampforum.blast.hk/forumdisplay.php?fid=12)
+---- Forum: Tutorials (https://sampforum.blast.hk/forumdisplay.php?fid=70)
+---- Thread: [Tutorial] Advanced Capturable Zone Scripting [Easy,Very Fast,Efficient,Variable Time TO Capture For DONOR , More STOCKS ,Foreach] (/showthread.php?tid=477350)



Advanced Capturable Zone Scripting [Easy,Very Fast,Efficient,Variable Time TO Capture For DONOR , More STOCKS ,Foreach] - kN1GhT - 23.11.2013

Advanced Capturable Zone Scripting [Easy,Very Fast,Efficient,Variable Time TO Capture For DONOR , More STOCKS ,Foreach]


Hello SAMP

In The Following Tutorial I Would Be Trying To Teach You How To Create Capture Zones

This Tutorial would be helpfull For TDM GM's



Some FAQ's


So Whats New and Unique About Your Tutorial.?
Well This Tutorial Would Allow You To Create Capture Zones Which Have Different Time For Capturing For Different Players According to The Privledges Available to Them(The Donations They MAKE)
Also This Kind OF Capturable Zones Are Faster , Logical and Easy To Make.
With the use of Foreach i would also unish the team who has Failed to save the Capture Zone from being Captured and rewarding the team who did it. :P


Why Do I See That You Keep Stocking All The Stuff.R U Retarded?
You Would See That I Stock Most Of The Things Like SetGangZoneColor ...This May Seem Useless To You If You Are Just Making Only 1 Capture Zone . But It IS Really Efficient For More Zones.

Why Shall You USe This Method?
You Can Use The Logic to Create More Capture Zones With Less Than 10 Extra Lines!!.


How DaHell Did U Add Public CallBacks On Your Own?
The Only CallBack i Made For This is
Код:
forward GangCount(playerid, checkpointid, zonename);
public GangCount(playerid, checkpointid, zonename)
This Would Be Called When A Player IS Checked Of The
Код:
public OnPlayerEnterDynamicCP
CallBack.



Ok Lets Start
You Would Need The foreach Include and the streamer Include & Plugin

First You Would Need To Call the the includes That You Are Using

Код:
#include <a_samp>
#include <foreach>
#include <streamer>
Now Write Down The Following Color Defines
These Would Be The Colours We Are Going To Use In The Script
Код:
#define LIGHTBLUE 			                 0x33CCFFFF
#define RED 				 0xFF0000FF
#define WHITE 			                0xFFFFFFFF
#define LIGHTGREEN 			0x33FF33FF
#define WHITE_ZONE_COLOR		0xFFFFFF77
#define GREEN_ZONE_COLOR 		0x15FF0077
#define GREY 				    0xAFAFAFFF
The Time Needed To Capture a Certain Zone For Different Players Depending on the privledges They Have
Код:
#define NoDonorRankHolder 	25 //for Regular Players
#define Donor1CaptureTime 	20 // For Gold VIP(dRank 3)
#define Donor2CaptureTime 	15 //For Silver VIP(dRank 2)
#define Donor3CaptureTime 	10 //For Bronze VIP(dRank 1)
Lets Define The Teams Available

Код:
#define T_1			    100
#define T_2 			    101
And Some More DEclarations
Код:
new OnDuty[MAX_PLAYERS];//To BE USed When an admin goes On Duty...
new PlayerCount[MAX_PLAYERS];
new PlayerCountTimer[MAX_PLAYERS];
new gTeam[MAX_PLAYERS]; //I Recomemd You To Set This During OnPlayerRequestClass
Lets Declare the Properties of the Zones

Код:
new AZone;
new AArea;
new ACP;
new AColor;
Now Lets Declare Some Enums About The Zone And Some About The Players
Код:
//Enums
enum CaptureInfo
{
	gAttacked = 0,
	gOwner = 0,
}

new CaptureZoneInfo[][CaptureInfo];

enum PlayerData
{
	pCaptureZone,
	drank
}
new PlayerInfo[MAX_PLAYERS][PlayerData];
We Now Move On To The CallBack public OnGameModeInit() which is called when The Script is Completed and loaded
We Now Set The Properties of the Zones We Have Declared Above



Код:
{
                 AZone = GangZoneCreate(-366, 1512, -270, 1578);
	AArea = CreateDynamicRectangle(-366, 1512, -270, 1578, -1, -1, -1);
	ACP = CreateDynamicCP(-308.9923,1537.8146,75.5625, 3.0, -1, -1, -1, 100.0);
	AColor = GREY;
	return 1;
}


We Need To Make the Zone Visible to Players
So We USe public OnPlayerConnect CallBack For IT



Код:
{

    GangZoneShowForPlayer(playerid, AZone, AColor);
	return 1;
	
}
Now Lets Keep OurSelf Updated And Stock The Information About The Player , The Color of the Zone , and many Other Things


Код:
stock PlayerArea(playerid)
{
	new pZone;
    if(IsPlayerInDynamicArea(playerid, AArea))
	{
 		GangZoneFlashForAll(AZone, PlayerGangColor(playerid));
 		pZone = AZone;
	}
	
return pZone;
}
Код:
//Which Team Color to FLASH? This Stock Helps
stock PlayerGangColor(playerid)
{
	new str;
	if	   (gTeam[playerid] == T_1) str =(WHITE_ZONE_COLOR);
    else if(gTeam[playerid] == T_2) str =(GREEN_ZONE_COLOR);
	return str;
}
Код:
//Lets Stock The Names OF The ZONE
stock ZoneName(checkpointid)
{

	new str[32];
	if  (checkpointid == ACP) str = ("A Trial Zone");
	return str;
}
Код:
//The Color To BE Set
stock SetZoneColor(zonename, playerid)
{
	if(zonename == AZone)
	{
	    AColor = PlayerGangColor(playerid);
	}
}

Now We Are Ready To Start The Real Scripting Work


Now We use A CallBack which would be called when the player enters the checkpoint using The Streamer Plugin
Код:
forward OnPlayerEnterDynamicCP(playerid, checkpointid);
public OnPlayerEnterDynamicCP(playerid, checkpointid)
Inside This We Do The Following


We Check For Conditions
Remember This is Under the condition if(checkpointid == ACP)


Wether The Player is in a vehicle

Wether The Player Is ON Admin Duty(To BE SET )


if None of the conditions are satisfied We Begin Our Code


Checks IF The Player Is a Donor and Correspondingly Sets The TIME For Capture

Notifying TO The Whole Server That The Zone is Being Taken Over and Prepares The Counting OF Seconds to Capture
Here PlayerCountTime Is Another CallBack Which Would Be Called From This.


So Together This Would Look Like

Код:
forward OnPlayerEnterDynamicCP(playerid, checkpointid);
public OnPlayerEnterDynamicCP(playerid, checkpointid)
if(checkpointid == ACP)
{


        //Messages InCase The Player Is Not Allowed To Capture
	    new string[128], pZone;
		[COLOR="rgb(46, 139, 87)"]//If The ZONE is Already Getting Captured[/COLOR]
	    if(CaptureZoneInfo[checkpointid][gAttacked] == 1)
	         return SendClientMessage(playerid, RED, "The zone is being captured!");
	   //If The Zone Has Been Already Captured By That Team
	    if(CaptureZoneInfo[checkpointid][gOwner] == gTeam[playerid])
             return SendClientMessage(playerid, LIGHTBLUE, "Your team owns this zone.");
	  [COLOR="rgb(46, 139, 87)"] //Wether The Player is in a vehicle[/COLOR]
	    if(IsPlayerInAnyVehicle(playerid))
		     return SendClientMessage(playerid, RED, "You cant capture while in a vehicle!");
	  [COLOR="rgb(46, 139, 87)"] //Wether The Player Is ON Duty(To BE SET)[/COLOR]
	    if(OnDuty[playerid] == 1)
		     return SendClientMessage(playerid, RED, "You cant capture when on duty!");

	    CaptureZoneInfo[checkpointid][gAttacked] = 1;

	    pZone = PlayerArea(playerid);
	    PlayerInfo[playerid][pCaptureZone] = 1;



	  [COLOR="rgb(46, 139, 87)"] //Checks IF The Player Is a Donor and Correspondingly Sets The TIME For Capture[/COLOR]
	   
	    if(PlayerInfo[playerid][drank] == 1)
	    
	    {
	        PlayerCount[playerid] = Donor1CaptureTime;
		}
		
		else if(PlayerInfo[playerid][drank] == 2)
		{
		    PlayerCount[playerid] = Donor2CaptureTime;
		}
		else if(PlayerInfo[playerid][drank] == 3)
		{
  			PlayerCount[playerid] = Donor3CaptureTime;
		}
		else
		{
			PlayerCount[playerid] = NoDonorRankHolder;
		}


		[COLOR="rgb(46, 139, 87)"]//Notifying TO The Whole Server That The Zone is Being Taken Over and Prepares The Counting OF [/COLOR]Seconds to Capture
		PlayerCountTimer[playerid] = SetTimerEx("GangCount", 1000, true, "iii", playerid,  checkpointid, pZone);
		format(string, sizeof(string), "[ZONE] %s is being taken over!", ZoneName(checkpointid));
		SendClientMessageToAll(LIGHTGREEN, string);
		
	}
	return 1;
}


pff That was Some Real Work
But WE Still need to Count The Seconds

So Lets Start
WE DECLARE our CallBack

Now Lets Start Work

WE Count the Time And Display it to the Player as a GameText

We Are using the PlayerCount From The Previous CallBack

Now Once The Player Has Finished the Ammount of time required to Capture The PlayerCount Becomes 0


we use it to Stop Flashing the GangZone and other things

Now We Tell Everyone that the zone is captued and reward the player who captured the zone

punishment to for the Team Who Failed to save its Capture Zone From Being Captured and reward for the team which captured it

Last Thing here

Kill The Timer and Update the owner of the GangZone


Done And The Whole Callback Would look Like

Код:
forward GangCount(playerid, checkpointid, zonename);
public GangCount(playerid, checkpointid, zonename)
{
	new time[16];
	PlayerCount[playerid] --;
	format(time, sizeof(time), "~g~%i..", PlayerCount[playerid]);
	GameTextForPlayer(playerid, time, 1100, 3);

	if(PlayerCount[playerid] == 0)
	{
        CaptureZoneInfo[checkpointid][gAttacked] = 0;
        GangZoneStopFlashForAll(zonename);
    	GangZoneShowForAll(zonename, PlayerGangColor(playerid));
    	SetZoneColor(zonename, playerid);
    	
			//rewards
			new string[128], Float:armour;
	    format(string, sizeof(string), "You get {FFFF00}+3 score, +20 armor and $2500{FFFFFF} for capturing zone {15FF00}%s!", ZoneName(checkpointid));
		SendClientMessage(playerid, WHITE, string);
		 //Cant Give More Than 99 Armour Hence Check IT
		GetPlayerArmour(playerid, armour);
		if(armour+20.0 > 99) SetPlayerArmour(playerid, 99);
		else SetPlayerArmour(playerid, armour+20.0);
		
		GivePlayerMoney(playerid, 5000);
		SetPlayerScore(playerid, GetPlayerScore(playerid)+3);

		PlayerInfo[playerid][pCaptureZone] = 0;

		foreach(Player, i)
		{
		    if(CaptureZoneInfo[checkpointid][gOwner] == gTeam[i])
		    {
    			format(string, sizeof(string), "Your team has lost the zone {FF0000}%s{FFFFFF}, you lose {FF0000}-1{FFFFFF} score!", ZoneName(checkpointid));
    			SetPlayerScore(i, GetPlayerScore(i)-1);
      			SendClientMessage(i, WHITE, string);
			}
			else if(gTeam[i] == gTeam[playerid])
			{
			    if(i != playerid)
			    {
			        format(string, sizeof(string), "Your team has captured the zone {15FF00}%s{FFFFFF}, you get {15FF00}+1{FFFFFF} score!", ZoneName(checkpointid));
			        SetPlayerScore(i, GetPlayerScore(i)+1);
			        SendClientMessage(i, WHITE, string);
				}
			}
		}

  		KillTimer(PlayerCountTimer[playerid]);
		CaptureZoneInfo[checkpointid][gOwner] = gTeam[playerid];
	}
	return 1;
}
Now We Deal When The Player Leaves The Zone]


Using Simple Logic
When A Player Enters and leaves a zone already owned By His TEAM WE Do Nothing

Now IF This is not the case
WE Would Kill The Timer adn send message that the person has failed to capture the zone

The Call BAck Would Look Like This When Done

Код:
forward OnPlayerLeaveDynamicCP(playerid, checkpointid);
public OnPlayerLeaveDynamicCP(playerid, checkpointid)
{
	if(PlayerInfo[playerid][pCaptureZone] == 1)
	{
 		if(CaptureZoneInfo[checkpointid][gOwner] == gTeam[playerid])
		   return 0;

		new pZone;
  		CaptureZoneInfo[checkpointid][gAttacked] = 0;
		pZone = PlayerArea(playerid);
  		GangZoneStopFlashForAll(pZone);

		SendClientMessage(playerid, RED, "You stopped capturing the zone!");
		KillTimer(PlayerCountTimer[playerid]);
		PlayerInfo[playerid][pCaptureZone] = 0;
	}
	return 1;
}
What NExt ..we need to stop the Timer And Stop the zone from being captured if a player disconnects or Dies In The Process

WE DO THE Following

Код:
public OnPlayerDeath(playerid, killerid, reason)
{
    {
        SendClientMessageToAll(playerid, RED, "[Zone] was Not Captured Since The Played Died While Capturing It!");
        KillTimer(PlayerCountTimer[playerid]);
		PlayerInfo[playerid][pCaptureZone] = 0;
	}
	return 1;
}


public OnPlayerDisconnect(playerid, reason)
{
       {
        SendClientMessageToAll(playerid, RED, "[Zone] Was Not Captured Since The Player Left The Server");
        KillTimer(PlayerCountTimer[playerid]);
		PlayerInfo[playerid][pCaptureZone] = 0;
        }
        
  	return 1;
}


Questions And Answers

Q:I want to do more than One Zone.How do i do it?
A:This is Simple Just Follow the 7 Steps

Given with Example

1-u need to declare the properties of the Zones(read above) ,
2-Define them in the callback OnGamemodeInit ,
3-Set The Colour of the Gangzone OnPlayerConnect(as done for mine)

4-Add to The Stock PlayerArea(playerid)
Eg:
Код:
stock PlayerArea(playerid)
{
	new pZone;
    if(IsPlayerInDynamicArea(playerid, AArea))
	{
 		GangZoneFlashForAll(AZone, PlayerGangColor(playerid));
 		pZone = AZone;
	}
if(IsPlayerInDynamicArea(playerid, AnotherCaptureArea))
	{
 		GangZoneFlashForAll(AnotherCaptureZone, PlayerGangColor(playerid));
 		pZone = AnotherCaptureZone;
	}
	
return pZone;
}
5- Add to stock ZoneName
EG:
Код:
stock ZoneName(checkpointid)
{

	new str[32];
	if  (checkpointid == ACP) str = ("A Trial Zone");
                 if  (checkpointid == AnotherCaptureCP) str = ("second Trial Zone");
	return str;
}
6-Stock SetZoneColor
Eg:
Код:
stock SetZoneColor(zonename, playerid)
{
	if(zonename == AZone)
	{
	    AColor = PlayerGangColor(playerid);
	}
                  if(zonename == AnotherCaptureZone)
	{
	    AnotherCaptureColor = PlayerGangColor(playerid);
	}
}
7-Edit The PublicOnPlayerEnterDynamicCP and add a or condition
eg:
Код:
public OnPlayerEnterDynamicCP(playerid, checkpointid)
{

if(checkpointid == ACP || checkpointid == AnotherCaptureCP )
And DONE



Q:I Have More Than One Team in my script . How do i Do it Now?

Aefine a Colour

AND

Just Edit The stock PlayerGangColor(playerid)

eg :
Код:
stock PlayerGangColor(playerid)
{
	new str;
	if	   (gTeam[playerid] == T_1) str =(WHITE_ZONE_COLOR);
                 else if(gTeam[playerid] == T_2) str =(GREEN_ZONE_COLOR);
                 else if(gTeam[playerid] == T_3) str =(Orange_ZONE_COLOR);
	return str;
}
Credits

Incognto [for streamer]
The Maker OF Foreach Include
SA-MP Team



Thank You.
Hope I HElped



Re: Advanced Capturable Zone Scripting [Easy,Very Fast,Efficient,Variable Time TO Capture For DONOR , More STOCKS ,Forea - _Mohit_ - 24.11.2013

Very nice Tutorial.Makes it easy for scripters to add Capture zones.Good Job +rep


Re: Advanced Capturable Zone Scripting [Easy,Very Fast,Efficient,Variable Time TO Capture For DONOR , More STOCKS ,Forea - JimmyCh - 24.11.2013

Well, I didn't read it all, just saw it at small..
The OnPlayerDeath you didn't even check if player is capturing to make it stop the capture and send the message, that means it will send that message everytime someone dies, same for the OnPlayerDisconnect.

The donator rank and admin rank of yours show that this was taken from a gamemode, and not created..
I'd suggest editing it before putting it as a tutorial.

For the rest, not bad.



{{
PS: SendClientMessageToAll(playerid, etc... ) is wrong.
It's SendClientMessageToAll(COLOR, MESSAGE) and not SendClientMessageToAll(playerid, COLOR, MESSAGE).. }}


Too busy to find more mistakes.


Re: Advanced Capturable Zone Scripting [Easy,Very Fast,Efficient,Variable Time TO Capture For DONOR , More STOCKS ,Forea - kN1GhT - 24.11.2013

Quote:
Originally Posted by JimmyCh
Посмотреть сообщение
Well, I didn't read it all, just saw it at small..
The OnPlayerDeath you didn't even check if player is capturing to make it stop the capture and send the message, that means it will send that message everytime someone dies, same for the OnPlayerDisconnect.

The donator rank and admin rank of yours show that this was taken from a gamemode, and not created..
I'd suggest editing it before putting it as a tutorial.

For the rest, not bad.



{{
PS: SendClientMessageToAll(playerid, etc... ) is wrong.
It's SendClientMessageToAll(COLOR, MESSAGE) and not SendClientMessageToAll(playerid, COLOR, MESSAGE).. }}


Too busy to find more mistakes.

If you read my tutorial (the FAQ) you would know that why i have done it for Drank.....its beczuse there were no previous tutorials showing how to make capture zones which have different time to capture ...

And no....i created it and didnt take it from a GM....

IDK where did u read that SendClientMessageToAll with playerid....t would just be a typo



PS- Please read the whole tutorial...u dont need to check if the person is capturing or not OnPlayerDisconnect...u just kill the timer.....as even ghough he isnt capturing that time....killing the timer wouldnt hurt (its better and efficient this way)


Re: Advanced Capturable Zone Scripting [Easy,Very Fast,Efficient,Variable Time TO Capture For DONOR , More STOCKS ,Forea - Raza2013 - 25.11.2013

Nice


Re: Advanced Capturable Zone Scripting [Easy,Very Fast,Efficient,Variable Time TO Capture For DONOR , More STOCKS ,Forea - RajatPawar - 25.11.2013

You have a major error in there:
pawn Код:
enum CaptureInfo
{
    gAttacked = 0,
    gOwner = 0,
}
I am sure you wanted to set the variables to 0.

Read in this (https://sampforum.blast.hk/showthread.php?tid=318307) topic that setting to constants in enums sets their POSITION and not their value. Hence gOwner and gAttacked would be BOTH at the position 0 which is not good.

Example - try running this code here. (http://slice-vps.nl:7070/)
pawn Код:
#include <a_samp>

enum r_EXAMPLE
{
    my_position_is_5 = 5,
    my_position_is_10 = 10
}
new rEnum[ 1 ][ r_EXAMPLE ];

main()
{
    printf(" %i, %d ", rEnum[ 0 ][ my_position_is_5 ], rEnum[ 0 ][my_position_is_10] );
}
It returns "0, 0" and not "5, 10".


Re: Advanced Capturable Zone Scripting [Easy,Very Fast,Efficient,Variable Time TO Capture For DONOR , More STOCKS ,Forea - kN1GhT - 25.11.2013

Quote:
Originally Posted by Rajat_Pawar
Посмотреть сообщение
You have a major error in there:
pawn Код:
enum CaptureInfo
{
    gAttacked = 0,
    gOwner = 0,
}
I am sure you wanted to set the variables to 0.

Read in this (https://sampforum.blast.hk/showthread.php?tid=318307) topic that setting to constants in enums sets their POSITION and not their value. Hence gOwner and gAttacked would be BOTH at the position 0 which is not good.

Example - try running this code here. (http://slice-vps.nl:7070/)
pawn Код:
#include <a_samp>

enum r_EXAMPLE
{
    my_position_is_5 = 5,
    my_position_is_10 = 10
}
new rEnum[ 1 ][ r_EXAMPLE ];

main()
{
    printf(" %i, %d ", rEnum[ 0 ][ my_position_is_5 ], rEnum[ 0 ][my_position_is_10] );
}
It returns "0, 0" and not "5, 10".
Ok understood

But let me ask u something
Would this really affect the efficiency of the code by a very large scale?


Re: Advanced Capturable Zone Scripting [Easy,Very Fast,Efficient,Variable Time TO Capture For DONOR , More STOCKS ,Forea - RajatPawar - 25.11.2013

It's not about efficient or better code. Your enum is flawed. It would keep over-writing! I am not giving you an option for better code, it's a fix for the code! Make sure you fix it! Keep coding


Re: Advanced Capturable Zone Scripting [Easy,Very Fast,Efficient,Variable Time TO Capture For DONOR , More STOCKS ,Forea - JimmyCh - 25.11.2013

pawn Код:
public OnPlayerDeath(playerid, killerid, reason)
{
    {
        SendClientMessageToAll(playerid, RED, "[Zone] was Not Captured Since The Played Died While Capturing It!");
        KillTimer(PlayerCountTimer[playerid]);
        PlayerInfo[playerid][pCaptureZone] = 0;
    }
    return 1;
}


public OnPlayerDisconnect(playerid, reason)
{
       {
        SendClientMessageToAll(playerid, RED, "[Zone] Was Not Captured Since The Player Left The Server");
        KillTimer(PlayerCountTimer[playerid]);
        PlayerInfo[playerid][pCaptureZone] = 0;
        }
       
    return 1;
}
This is where you put playerid in SendClientMessageToAll.

Actually, there are many tutorials on how to make capture zones, mine is one of them here.


Anyway it's not bad, I already told you.


Re: Advanced Capturable Zone Scripting [Easy,Very Fast,Efficient,Variable Time TO Capture For DONOR , More STOCKS ,Forea - kN1GhT - 26.11.2013

Quote:
Originally Posted by ******
Посмотреть сообщение
Could I suggest adding in clearly delineated sections? I use large coloured text to separate them but you are free to use whatever method you like. As it is, this is tricky to follow as everything just runs on.

And Stop Capitalising Every Word, It Is Very Hard To Read.
K ..doing it


Re: Advanced Capturable Zone Scripting [Easy,Very Fast,Efficient,Variable Time TO Capture For DONOR , More STOCKS ,Forea - xF4Life - 28.11.2013

nice.


Re: Advanced Capturable Zone Scripting [Easy,Very Fast,Efficient,Variable Time TO Capture For DONOR , More STOCKS ,Forea - TahaAsif12 - 28.11.2013

Good TUT


Re: Advanced Capturable Zone Scripting [Easy,Very Fast,Efficient,Variable Time TO Capture For DONOR , More STOCKS ,Forea - kN1GhT - 29.11.2013

Quote:
Originally Posted by TahaAsif12
Посмотреть сообщение
Good TUT
Thanks

@XF thanks man


Re: Advanced Capturable Zone Scripting [Easy,Very Fast,Efficient,Variable Time TO Capture For DONOR , More STOCKS ,Forea - HydraHumza - 13.03.2015

Really Nice!!