Jump to content
  • 0

pomoc SAMP - Problém s více typů PickUp


MichaelMik9

Dotaz

Ahoj mám dost velký problém s vytvořením více druhů pickupů a to tak, že chci vytvořit pickup pro hidden package a další pro opravu vozidel/vyléčení hráče.

Kód mám vytvořen takto:

public OnPlayerPickUpPickup(playerid, pickupid)
{
	if(pickupid == Package[PICKUP])
	{
	    new money = RandomInt(500, 1000);
	    new message[128];

		if(Vip[playerid][VIP_ACTIVE] == true)
		{
		    new moneyVip = money*2;
		    format(message, sizeof(message), "{0EB3F1}[PACKAGE]{46FF33}[VIP] {ffffff}Získal jsi za balíček 2x tolik peněz! {46FF33}%i $", moneyVip);
		    if(User[playerid][COUNT_TELEPORT] == 0)
		    {
		        Reward(playerid, money, 2, 2);
		    }
		    else
		    {
		    	Reward(playerid, money, 0, 0);
		    	SendClientMessage(playerid, COLOR_LIGHTRED, "Za misi nezískáš žádné Rank body, protože jsi se teleportoval!");
		    }
		}
		else
		{
		    format(message, sizeof(message), "{0EB3F1}[PACKAGE] {ffffff}Získal jsi za balíček {46FF33}%i $", money);
		    if(User[playerid][COUNT_TELEPORT] == 0)
		    {
				Reward(playerid, money, 0, 0);
				User[playerid][MONEY] = User[playerid][MONEY]+money;
		    }
		    else
		    {
		    	Reward(playerid, money, 1, 1);
		    	User[playerid][MONEY] = User[playerid][MONEY]+money;
		    	SendClientMessage(playerid, COLOR_LIGHTRED, "Za misi nezískáš žádné Rank body, protože jsi se teleportoval!");
		    }
		}

		SendClientMessage(playerid, -1, message);
		new messageToAll[256];
		format(messageToAll, sizeof(messageToAll), "{0EB3F1}[PACKAGE] {ffffff}Hráč {2C97CA}%s {ffffff}našel skrytý balíček!", User[playerid][NAME]);
		SendClientMessageToAll(-1, messageToAll);

		new logText[400];
		format(logText, sizeof(logText), "[*#0EB3F1*][PACKAGE][*/Color] Hrac [*#0EB3F1*]%s[*/Color] nasel skryty balicek!", User[playerid][NAME]);
		new log[328];
		new date = GetTime();

		format(log, sizeof(log), "INSERT INTO `samp_online_log`(`Date`, `Text`) VALUES ('%i', '%s')", date, logText);
		mysql_query(Database, log);

		GameTextForPlayer(playerid, "Balicek nalezen!", 3000, 1);
        PlayerPlaySound(playerid, 1150, 0.0, 0.0, 0.0);
		DestroyPickup(Package[PICKUP]);
		for(new i = 0; i <= 100; i++)
	    {
	        RemovePlayerMapIcon(i, 1);
	    }
	    Game[HIDDEN_PACKAGE_ACTIVE] = false;
	    User[playerid][COUNT_TELEPORT] = 0;
	    Package[PICKUP] = 0;
	    GangZoneDestroy(Package[ZONE]);

	    new randomMinutes = RandomInt(5,40);
		new timeForPackage = 1000*60*randomMinutes;
   		Game[PACKAGE_TIMER] = SetTimer("generateHiddenPackage", timeForPackage, 1);
	}
	else
	{
		for(new repick = 0; repick < Game[REPAIR_COUNT]; repick++)
		{
			if(pickupid == RepairPickup[repick][PICKUP_ID])
			{
				if(IsPlayerInAnyVehicle(playerid))
				{
					new vehId = GetPlayerVehicleID(playerid);
					RepairVehicle(vehId);
					SendClientMessage(playerid, COLOR_LIGHTRED, "Vozidlo opraveno!");
				}
				else
				{
					SetPlayerHealth(playerid, 100);
					SendClientMessage(playerid, COLOR_LIGHTRED, "Zdraví doplněno!");
				}
			}
		}
	}
	return 1;
}

První zapsaný typ pickupu (Package[PICKUP]) funguje bez problémů. Problém nastává v momentě, kdy chci vzít ten druhý typ pickupu pro vyléčení - hráče nevyléčí ale "sebere skrytý balíček" - místo toho aby hráč sebral druhý typ, tak se zpracuje ten první.

Může prosím někdo poradit jak to odlišit? 

 Děkuji za případnou pomoc :) 

Link to comment
Share on other sites

8 odpovědí na tuto otázku

Recommended Posts

  • 0

Zdravím,

dej sem prosím ještě kód, kde pickupy vytváříš. Proč ukládáš vůbec pickupid do pole, když máš pouze jeden? Rozhodně zde nedoporučuji používat ELSE, už jen díky tomu že hodnotu v Package[PICKUP] nuluješ, což ti může způsobovat právě toto chování (například pickup pro vyléčení bude mít právě id 0, ty jdeš sebrat pickup s penězi, který má id 1, sebereš jej a proměnnou pickupu s penězi nastavíš na 0, pak jdeš sebrat ten pro vyléčení, nojo, jenže proměnná, už je vynulovaná, tudíž pickupid s id 0 zachytí první blok a do else se to už nedostane). Když už, tak nenastavovat nulu, ale nějakou zápornou hodnotu, které createPickup nevrací. Nějak se ztrácím v těch tvých proměnných, určitě by bylo lepší ty proměnné pro pickupy nějak sjednotit. ;) 

Např.:

enum pickups{ //vytvoříš enum, kde si pojmenuješ pickupy podle funkce, enum pak použíješ pro tvorbu pole
 	MONEY,
	HEALTH
};

new PICKUP[pickups]; //vytvoříš pole pro pickupy o velikosti enumu (2)

//a pak už jen vytváříš pickup
PICKUP[MONEY] = createPickup(...);
PICKUP[HEALTH] = createPickup(...);

//a v OnPlayerPickUpPickup()
if(pickupid == PICKUP[MONEY])
{ ... }
else if(pickupid == PICKUP[HEALTH])
{ ... }

//a pro stronování proměnných rozhodně nepoužívej nulu (může ji mít totiž nějaký jiný pickup), ale záporné hodnoty

 

A ještě jestli můžu doporučit, nepoužívej v cyklu pro odstranění ikony hráčům pevně danou hodnotu - 100, ale nějakou konstantu, kterou můžeš kdykoliv změnit (obecně využívej proměnných a konstant v cyklech, nejen zde). A ještě lépe můžeš použít funkci GetPlayerPoolSize(), která ti vrátí největší id připojeného hráče. ;) 

Edited by The hidden face
  • Líbí se mi to! (+1) 1
Link to comment
Share on other sites

  • 0

Ahoj,

Druhý typ pickupů je vytvořen přes cykl .. tzn, že jinak nevím jak bych je měl vytvořit .. chci udělat po celém světě ozdravné pickupy .. plus další, které se generují po jednom a tím jso ty skryté balíčky :)

addPickups()
{
	//repair pickups
	mysql_query(Database, "SELECT * FROM `samp_repair_pickup`");
	new countRepairs;
	cache_get_row_count(countRepairs);
	Game[REPAIR_COUNT] = countRepairs;

	for(new rp = 0; rp < countRepairs; rp++)
	{
		new Float:posx, Float:posy, Float:posz;
		cache_get_value_name_float(rp, "PosX", posx);
		cache_get_value_name_float(rp, "PosY", posy);
		cache_get_value_name_float(rp, "PosZ", posz);

		RepairPickup[rp][PICKUP_ID] = CreatePickup(1240, 1, posx, posy, posz, -1);

		for(new idx = 0; idx < MAX_PLAYERS; idx++)
		{
			SetPlayerMapIcon(idx, rp, posx, posy, posz, 27, -1, MAPICON_LOCAL);
		}
	}

	printf("Loaded %i Repair Pickups from Database", countRepairs);
}

a vygenerování balíčku:

public generateHiddenPackage(playerid)
{
	//if no package mission active
	if(Game[HIDDEN_PACKAGE_ACTIVE] == false && Game[ONLINE_PLAYERS]!=0)
	{
	    User[playerid][COUNT_TELEPORT] = 0;
	    //get position - random
	    new selectPackages[65];
	    format(selectPackages, sizeof(selectPackages), "SELECT * FROM `samp_hidden_packages`");
	    mysql_query(Database, selectPackages);

	    new maxPack;
	    cache_get_row_count(maxPack);

	    new randomPack = RandomInt(1, maxPack);//get random pack

	    new selectPack[128];
	    format(selectPack, sizeof(selectPack), "SELECT * FROM `samp_hidden_packages` WHERE id='%i' LIMIT 1", randomPack);
	    mysql_query(Database, selectPack);


	    //Get Position from db
		new Float:x, Float:y, Float:z;
		cache_get_value_name_float(0, "PosX", x);
	    cache_get_value_name_float(0, "PosY", y);
	    cache_get_value_name_float(0, "PosZ", z);

	    Package[PICKUP] = CreatePickup(1279, 800, x, y, z, -1);

	    new Float:minx = x-RandomInt(80,180);
	    new Float:miny = y-RandomInt(80,180);
	    new Float:maxx = x+RandomInt(80,180);
	    new Float:maxy = y+RandomInt(80,180);

	    Package[ZONE] = GangZoneCreate(Float:minx, Float:miny, Float:maxx, Float:maxy);
	    GangZoneShowForAll(Package[ZONE], COLOR_YELLOW);


		Game[HIDDEN_PACKAGE_ACTIVE] = true;

		new messageToAll[125];
		format(messageToAll, sizeof(messageToAll), "{0EB3F1}[PACKAGE] {ffffff}Nový {CFC21F}balíček {ffffff}připraven k vyzvednutí! (Ĺ˝luté pole na mapě)");
		SendClientMessageToAll(-1, messageToAll);

		printf("[PACKAGE] New hidden package was shown in San Andreas!");

		//mesage for online log
 		new logText[200];
		format(logText, sizeof(logText), "[*#0EB3F1*][PACKAGE][*/Color] Na serveru se nachazi [*#0EB3F1*]skryty balicek[*/Color]!");
		samp_log(logText);

	}

	if(Game[HIDDEN_PACKAGE_ACTIVE] == true && Game[ONLINE_PLAYERS] == 0)
	{
	    DestroyPickup(Package[PICKUP]);
	    for(new i = 0; i <= 100; i++)
	    {
			RemovePlayerMapIcon(i, 1);
		}
	    Game[HIDDEN_PACKAGE_ACTIVE] = false;
	    Package[PICKUP] = 0;
	}
}

 

Link to comment
Share on other sites

  • 0

Nebude lepší nápad uložiť si pre každý pickup, či ide o skrytý balíček, o pickup na opravu auta, (prípadne o nejaký iný typ), alebo to nie je žiaden z týchto prípadov?

Tých 16 kB ( ak správne počítam 4096 * 4 B ) pamäte nikoho nezabije a ak potom budeš mať viac pickupov rovnakého typu, budeš môcť v konštantnom čase zistiť, aký typ pickupu si zobral.
Momentálne musíš napríklad na zistenie, či si zobral repair pickup, prechádzať celé pole s repair pickupmi.

Myslím to nejak takto (kód som neskúšal, nezaručujem funkčnosť, chcem iba ukázať myšlienku):

Spoiler

enum E_PICKUP_TYPE 
{
    PICKUP_TYPE_UNDEFINED,
    PICKUP_TYPE_PACKAGE,
    PICKUP_TYPE_REPAIR
}

new E_PICKUP_TYPE:gPickupType[MAX_PICKUPS] = {PICKUP_TYPE_UNDEFINED};

public OnPlayerPickUpPickup(playerid, pickupid)
{
    if (gPickupType[pickupid] == PICKUP_TYPE_PACKAGE)
    {
        // Hráč našiel skrytý balíček
        return 1;
    }
    
    if (gPickupType[pickupid] == PICKUP_TYPE_REPAIR)
    {
        // Hráč našiel pickup na opravu vozidla
        return 1;
    }

    return 1;
}

// Túto funkciu budeš používať vždy namiesto CreatePickup, má 1 nepovinný parameter navyše, v ktorom môžeš uviesť, o aký typ pickupu ide
// Namiesto 
// RepairPickup[rp][PICKUP_ID] = CreatePickup(1240, 1, posx, posy, posz, -1); 
// teda môžeš napísať: 
// CreatePickupEx(1240, 1, posx, posy, posz, -1, PICKUP_TYPE_REPAIR);
stock CreatePickupEx(model, type, Float:X, Float:Y, Float:Z, virtualworld, E_PICKUP_TYPE:pickupType=PICKUP_TYPE_UNDEFINED)
{
    new pickup = CreatePickup(model, type, Float:X, Float:Y, Float:Z, virtualworld);
    gPickupType[pickup] = pickupType;
}

// Túto funkciu budeš používať vždy namiesto DestroyPickup na vynulovanie informácie o type pickupu
// Keďže sa táto informácia resetuje pri vytvorení nového pickupu, niekto by mohol argumentovať, že táto funkcia nie je potrebná
// Problém je ale u pickupov vytvorených cez iné scripty, ktoré nepoužívajú tvoju CreatePickupEx, ale klasicky CreatePickup
stock DestroyPickupEx(pickup)
{
    DestroyPickup(pickup);
    gPickupType[pickup] = PICKUP_TYPE_UNDEFINED;
}

 

A ešte lepší nápad by bol asi využiť Streamer plugin, jeho CreateDynamicPickup, Streamer_SetArrayData a Streamer_GetArrayData.

Ako na to sa môžeš dočítať napríklad tu.

Edited by DuFF
Link to comment
Share on other sites

  • 0

Tak jsem to tedy zkusil a ten pickup se mi už vůbec nevygeneruje  .. 

dal jsem tedy do funkce generateHiddenPackage(){... CreatePickupEx(1279, 15, x, y, z, -1, PICKUP_TYPE_PACKAGE); ...} a pro jistotu jsem na ten pickup dal ještě Ikonu abych věděl přesnou pozici .. a když tam dojdu tak pickup tam není.  a to STOCK u té funkce znamená co? :) 

(CreatePickupEx jsem si poupravil, že jsem vyměnil parametry - world jsem dal jako poslední)

 

Edited by MichaelMik9
Link to comment
Share on other sites

  • 0
před 4 hodinami, MichaelMik9 said:

když tam dojdu tak pickup tam není

Práve som testoval tento kód a po zadaní príkazu /createpickup sa pickup vedľa mňa vytvoril. Keď som sa naň postavil, zobrazila sa mi tiež hláška „Skrytý balíček“.

Spoiler

#include <a_samp>

enum E_PICKUP_TYPE
{
    PICKUP_TYPE_UNDEFINED,
    PICKUP_TYPE_PACKAGE,
    PICKUP_TYPE_REPAIR
}

new E_PICKUP_TYPE:gPickupType[MAX_PICKUPS] = {PICKUP_TYPE_UNDEFINED};

public OnPlayerPickUpPickup(playerid, pickupid)
{
    if (gPickupType[pickupid] == PICKUP_TYPE_PACKAGE)
    {
        // Hráč našiel skrytý balíček
        SendClientMessage(playerid, -1, "Skrytý balíček");
        return 1;
    }

    if (gPickupType[pickupid] == PICKUP_TYPE_REPAIR)
    {
        // Hráč našiel pickup na opravu vozidla
        SendClientMessage(playerid, -1, "Oprava vozidla");
        return 1;
    }

    return 1;
}

stock CreatePickupEx(model, type, Float:X, Float:Y, Float:Z, virtualworld, E_PICKUP_TYPE:pickupType=PICKUP_TYPE_UNDEFINED)
{
    new pickup = CreatePickup(model, type, Float:X, Float:Y, Float:Z, virtualworld);
    gPickupType[pickup] = pickupType;
}

stock DestroyPickupEx(pickup)
{
    DestroyPickup(pickup);
    gPickupType[pickup] = PICKUP_TYPE_UNDEFINED;
}

#include <zcmd>
CMD:createpickup(playerid, params[])
{
    new Float:x, Float:y, Float:z;
    GetPlayerPos(playerid, x, y, z);
    CreatePickupEx(1279, 1, x + 2.0, y + 2.0, z, -1, PICKUP_TYPE_PACKAGE);
    return 1;
}

 

 
před 4 hodinami, MichaelMik9 said:

CreatePickupEx jsem si poupravil, že jsem vyměnil parametry - world jsem dal jako poslední

Toto bude pravdepodobne dôvod, prečo sa ti pickup nezobrazil.
Parameter pickupType som dal účelovo ako posledný, aby mohol byť nepovinný (defaultne PICKUP_TYPE_UNDEFINED).
Ak vymeníš poradie parametrov v definícii funkcie, musíš vymeniť aj poradie argumentov vo volaní funkcie.

Predpokladám, že upravená definícia funkcie u teba vyzerá nasledovne:
stock CreatePickupEx(model, type, Float:X, Float:Y, Float:Z, E_PICKUP_TYPE:pickupType, virtualworld)

V tomto prípade chceš funkciu volať nasledovne:

CreatePickupEx(1279, 15, x, y, z, PICKUP_TYPE_PACKAGE, -1);

Navrhujem ti vyskúšať najskôr neupravenú verziu funkcie a do úprav sa púšťať až keď ti bude neupravená verzia fungovať.

před 4 hodinami, MichaelMik9 said:

a to STOCK u té funkce znamená co?

Modifikátor „stock“ pri funkcii znamená, že funkcia bude do výsledného .amx súboru zahrnutá iba vtedy, ak sa niekde v kóde používa. Ak ju nikde nepoužiješ, kompilátor ju bude ignorovať a na rozdiel od klasickej funkcie (bez modifikátoru) nedostaneš varovanie, že funkcia nie je nikde použitá. Využíva sa to napríklad v includoch (väčšinou nepotrebuješ použiť všetky funkcie, ktoré include obsahuje). Viac o funkciách a modifikátore stock sa môžeš dočítať napríklad tu.

Edited by DuFF
Link to comment
Share on other sites

  • 0

Ahojte, tak mám problém vyřešený a moc všem děkuji za pomoc

pro každou funkci jsem nepoužil CreatePickupEx ale typ jsem vytvořil samostatně např.:

addpickupsrepair()

{

...

       new pickup = CreatePickup(1240, 14, posx, posy, posz, -1);
        gPickupType[pickup] = PICKUP_TYPE_REPAIR;

}

..což pak v onplayerenterpickup funguje (když jsem smazal pak returny)

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...