Jump to content
  • 0

pomoc Object ID problém


Meric

Dotaz

Ahojte, po dlouhé době jsem se dostal k pawnu a narazil jsem na problém, který jsem řešil asi 3 hodiny a furt nemůžu přijít na to, kde je chyba. Příkaz funguje jak má, ale jen u objektu s pořadovým ID 0. Tudíž když vytvořím druhou pásku, tak nejde ani upravit, ani smazat. Už mi došly nápady, poradíte mi, prosím? :-)

Spoiler

CMD:cross(playerid, params[])
{
	new typ[100];
	if(Player[playerid][Faction] == fPD || Player[playerid][Faction] == fSD)
	if(sscanf(params, "s", typ)) return SCM(playerid, -1, "SYNTAXE: /cross [POLOZIT, SEBRAT, UPRAVIT]");

	if(!strcmp("polozit", typ, false))
	{
		new Float:x, Float:y, Float:z, Float:a;
		GetPlayerPos(playerid, x, y, z);
		GetPlayerFacingAngle(playerid, a);
     	CreatePaska(x, y, z, a);
	    return 1;
	}
	if(!strcmp("upravit", typ, false))
	{
	    for(new i = 0; i < MAX_PASKA; i++)
	    {
     		if(IsPlayerInRangeOfPoint(playerid, 2.0, Paska[i][paX], Paska[i][paY], Paska[i][paZ]))
     		{
     		    EditDynamicObject(i, Paska[i][pObject]);
     		    LastPaskaEdit[playerid] = i;
     		    PaskaEdit[playerid] = true;
     		    return 1;
     		}
     	}
     	return ErrorBox(playerid, "Nejsi dostatecne blizko.");
    }
	if(!strcmp("sebrat", typ, false))
	{
        DeleteClosestPaska(playerid);
		return 1;
	}
	return 1;
}

// Stocky

stock CreatePaska(Float:x,Float:y,Float:z,Float:a)
{
	new temp[128];
	for(new i = 0; i < sizeof(Paska); i++)
  	{
  	    format(temp, sizeof(temp), PASPATH, i);
		if(!fexist(temp))
  		{
    		new Float:px, Float:py, Float:pz;
      		GetPlayerPos(i, px, py, pz);
        	GetXYInFrontOfPlayer(i, px, py, 1.5);

			new INI:File = INI_Open(temp);
			INI_WriteFloat(File, "X", px);
			Paska[i][paX] = px;
			INI_WriteFloat(File, "Y", py);
			Paska[i][paY] = py;
			INI_WriteFloat(File, "Z", pz - 0.1);
			Paska[i][paZ] = pz - 0.1;
			INI_WriteFloat(File, "RotX", 0.0);
			Paska[i][paRX] = 0.0;
			INI_WriteFloat(File, "RotY", 0.0);
			Paska[i][paRY] = 0.0;
			INI_WriteFloat(File, "RotZ", 0.0);
			Paska[i][paRZ] = 0.0;
			INI_Close(File);

        	Paska[i][pObject] = CreateDynamicObject(19834, x, y, z, 0, 0, a);
  			return 1;
		}
  	}
  	return 0;
}


stock DeleteClosestPaska(playerid)
{
    for(new i = 0; i < MAX_PASKA; i++)
  	{
  	    new temp[128];
		format(temp, sizeof(temp), PASPATH, i);
		if(fexist(temp))
		{
  	    	if(IsPlayerInRangeOfPoint(playerid, 2.0, Paska[i][paX], Paska[i][paY], Paska[i][paZ]))
        	{
				fremove(temp);
				Paska[i][paX]=0.0;
	   			Paska[i][paY]=0.0;
	      		Paska[i][paZ]=0.0;
	      		Paska[i][paRX]=0.0;
	        	Paska[i][paRY]=0.0;
	         	Paska[i][paRZ]=0.0;
	          	DestroyDynamicObject(Paska[i][pObject]);
	          	SCMEx(playerid, INFOCOLOR, "> Smazal jsi pásku ID: %d.", i);
	           	return 1;
	        }
		}
  	}
    return ErrorBox(playerid, "Nejsi dostatecne blizko.");
}

// Související část z plně funkčního OnPlayerEditDynamicObject

		.....
		if(PaskaEdit[playerid] == true)
		{
			format(temp, sizeof(temp), PASPATH, LastPaskaEdit[playerid]);
			new INI:File = INI_Open(temp);
			INI_WriteFloat(File, "X", x);
            Paska[LastPaskaEdit[playerid]][paX]= x;
            INI_WriteFloat(File, "Y", y);
            Paska[LastPaskaEdit[playerid]][paY]= y;
            INI_WriteFloat(File, "Z", z);
            Paska[LastPaskaEdit[playerid]][paZ]= z;
            INI_WriteFloat(File, "RotX", rx);
            Paska[LastPaskaEdit[playerid]][paRX]= rx;
            INI_WriteFloat(File, "RotY", ry);
            Paska[LastPaskaEdit[playerid]][paRX]= ry;
            INI_WriteFloat(File, "RotZ", rz);
            Paska[LastPaskaEdit[playerid]][paRX]= rz;

            InfoBox(playerid, "Paska ulozena");
            PaskaEdit[playerid] = false;
		}
		if(.....)

 

 

Link to comment
Share on other sites

6 odpovědí na tuto otázku

Recommended Posts

  • 0

A to není jediný problém... stock CreatePaska funguje na stejném principu, jak ten případ zmíněný výše. Místo playerid využíváš proměnné pro cyklus.. :/ Takže tyhle funkce:

GetPlayerPos(i, px, py, pz);
GetXYInFrontOfPlayer(i, px, py, 1.5);

Ti opravdu nemohou pracovat korektně. To za prvé..

 

Za druhé. Proč je vytváření pásky v cyklu? Neznám pravý smysl tvého kódu, ale takhle vytvoříš na jednom místě sizeof(paska) pásek. Což je další věc co nechápu... V DeleteClosestPaska využíváš konstanty MAX_PASKA a tady ZJIŠŤUJEŠ VELIKOST PROMĚNNÉ, NIKOLIV JEJÍ HODNOTU. Teoreticky je díky chybě ve tvém kódu nevytvoříš na jednom místě, ale tam kde se zrovna pohybuje hráč s id, které zrovna procházíš. Pro pochopení: zavoláš příkaz, za předpokladu, že jsi id 0 se první páska vytvoří opravdu u tebe, v dalším cyklu ovšem zjišťuješ pozice úplně jiného hráče (id 1) a u něho se vytvoří další páska, a takhle dál a dál...

Takže rozhodně smaž cyklus ve vytváření pásky, protože předpokládám, že chceš na jednom místě vytvořit pouze jednu pásku. Nezapomeň do tvého stocku přidat parametr playerid a využít ho.

 

A jak zprovoznit, aby jsi zjistil volné ID pro pásku? Stačí ti k tomu globální proměnná, kam budeš ukládat aktuální ID pásek - při vytváření pásky ID použiješ a následně ho navýšíš. Ovšem díky tomu, že pásky můžeš i odstranit, by ti vznikaly prázdná místa... Tam by bylo řešení též jednoduché, stačilo by si vytvořit pole a tam ukládat ID, která jsou opět volná. V praxi se to ovšem moc nedělá a vždy se používá nové ID, vracet se ke starému je risk a akorát si zakládáš na zmatky. :( 

Proto si myslím, že by bylo nejlepší řešení vytvořit si tu globální proměnnou pro ID a dále pro počet vytvořených pásek. Kdy ID by samozřejmě uchovávalo další volné ID pro pásku a počet pásek aktuální počet vytvořených pásek, takže při vytváření by jsi proměnnou navýšil a při mazání snížil. Pak by jsi jen při volání příkazu kontroloval, zda hráči nepoložili více pásek než jsi chtěl (určitě to budeš limitovat - přeci na serveru nechceš mít přepáskováno.. :d  ) 

 

Link to comment
Share on other sites

  • 1

Pri id 0 ti to funguje preto, lebo i je nula, a id objectu tiež nula, ale ak je i 1, editovanie dá hráčovi s ID 1, Objectu ID 1.. Predpokladam že niesi nováčik :d Ale 3 hodiny a nevšimnúť si toto ?? Ja som to našiel po 10 minútach :d Dávaš editovanie hráčovi i, objectu i :d

EditDynamicObject(i, Paska[i][pObject]);
	

 

Zmeň to i na playerid.

Edited by EvoLve.
Link to comment
Share on other sites

  • 0

//Edit:

Tak je to koukám všechno úplně jinak... Ty ve stokcu CreatePaska vyžaduješ parametry, které vůbec nepoužíváš? Proč? Nejdřív vše zjištíš v bloku pro položit, tam zavoláš stock a ve stocku je zjišťuješ znovu? A ke všemu špatně - jak píši výše? Nejpřehlednější by pro tebe bylo chtít jen parametr playerid, a pozice si zjistit až v tom stocku. Stejně tak i to editování.. Proč ten kód vypadá, jak když ho psali minimálně 2 lidi? Vždyť máš pokaždé jinou strukturu :/  Kdyby jsi dodržel tu strukturu psaní kódu, jak máš u DeletePaska, koukni se jak by tvůj příkaz byl o dost přehlednější...

CMD:cross(playerid, params[])
{
	new typ[100];
	if(Player[playerid][Faction] == fPD || Player[playerid][Faction] == fSD)
	if(sscanf(params, "s", typ)) return SCM(playerid, -1, "SYNTAXE: /cross [POLOZIT, SEBRAT, UPRAVIT]");

	if(!strcmp("polozit", typ, false)){
    	CreatePaska(playerid);
	}
	else if(!strcmp("upravit", typ, false)){
		EditPaska(playerid);
	}
	else if(!strcmp("sebrat", typ, false))
	{
		DeleteClosestPaska(playerid);
	}
	return 1;
}

Link to comment
Share on other sites

  • 0

Jo, to je protože jsem ten kód celý upravoval na jiný systém a trochu to chtěl zrenovovat, abych na to nemusel mít dva různý příkazy a k tomu jsem přidal i možnost úpravy. Abych se přiznal, nejsem sice úplně začátečník, ale nejsem ani úplně pokročilý. Původně jak jste mě opravili u toho EditDynamicObject "i" na "playerid", tak tam jsem měl právě to playerid původně a taky to nefachalo, takže tohle byl spíš hokus pokus. Dost jsem už pozapomínal po době, co jsem s pawnem nedělal. Ale už je to vyřešené a děkuji vám za pomoc. Už jsem nezaznamenal chybu. Pošlu sem ještě kód, abych ukázal řešení. 

 

Spoiler

CMD:cross(playerid, params[])
{
    new typ[100];
    if(Player[playerid][Faction] == fPD || Player[playerid][Faction] == fSD)
    {
        if(Player[playerid][fDuty] == true)
        {
            if(!sscanf(params, "s[100]", typ))
            {
                if(strcmp(typ, "polozit", true) == 0)
                {
                    CreatePaska(playerid);
                    return 1;
                }
                else if(strcmp(typ, "upravit", true) == 0)
                {
                    new i = GetClosestPaska(playerid);
                    if(IsPlayerInRangeOfPoint(playerid, 20.0, Paska[i][paX], Paska[i][paY], Paska[i][paZ]))
                    {
                        EditDynamicObject(playerid, Paska[i][pObject]);
                        LastPaskaEdit[playerid] = i;
                        PaskaEdit[playerid] = true;
                        return 1;
                    }
                    else return ErrorBox(playerid, "Nejsi pobliz zadne pasky.");
                }
                else if(strcmp(typ, "sebrat", true) == 0)
                {
                    DeleteClosestPaska(playerid);
                    return 1;
                }
            } else return SCM(playerid, -1, "SYNTAXE: /cross [POLOZIT, SEBRAT, UPRAVIT]");
        } else return ErrorBox(playerid, "Nejsi ve sluzbe.");
    } else ErrorBox(playerid, "Tento prikaz nemuzes pouzivat.");
    return 1;
}

stock CreatePaska(playerid)
{
    new temp[128];
    for(new i = 0; i < sizeof(Paska); i++)
    {
        format(temp, sizeof(temp), PASPATH, i);
        if(!fexist(temp))
        {
            new Float:px, Float:py, Float:pz, Float:pa;
            GetPlayerPos(playerid, px, py, pz);
            GetPlayerFacingAngle(playerid, pa);
            GetXYInFrontOfPlayer(playerid, px, py, 1.5);

            new INI:File = INI_Open(temp);
            INI_WriteFloat(File, "X", px);
            Paska[i][paX] = px;
            INI_WriteFloat(File, "Y", py);
            Paska[i][paY] = py;
            INI_WriteFloat(File, "Z", pz - 0.1);
            Paska[i][paZ] = pz - 0.1;
            INI_WriteFloat(File, "RotX", 0.0);
            Paska[i][paRX] = 0.0;
            INI_WriteFloat(File, "RotY", 0.0);
            Paska[i][paRY] = 0.0;
            INI_WriteFloat(File, "RotZ", pa);
            Paska[i][paRZ] = pa;
            INI_Close(File);

            Paska[i][pObject] = CreateDynamicObject(19834, px, py, pz, 0, 0, pa);
            return 1;
        }
    }
    return 0;
}


stock GetClosestPaska(playerid)
{
        new
                retElement = -1,
                Float:distance = 9999.0
        ;
        new temp[128];
        for(new i = 0; i < MAX_PASKA; i++)
        {
            format(temp, 128, PASPATH, i);
            if(fexist(temp))
            {
                if(IsValidDynamicObject(Paska[i][pObject]))
                {
                    new Float:odist = GetPlayerDistanceFromPoint(playerid, Paska[i][paX], Paska[i][paY], Paska[i][paZ]);
                    if (retElement == -1)
                    {
                        retElement = i;
                        distance = odist;
                    }
                    else if (odist < distance)
                    {
                        retElement = i;
                        distance = odist;
                    }
                }
            }
        }
        return retElement;
}

stock DeleteClosestPaska(playerid)
{
    for(new i = 0; i < MAX_PASKA; i++)
  	{
  	    new temp[128];
		format(temp, sizeof(temp), PASPATH, i);
		if(fexist(temp))
		{
  	    	if(IsPlayerInRangeOfPoint(playerid, 2.0, Paska[i][paX], Paska[i][paY], Paska[i][paZ]))
        	{
				fremove(temp);
				Paska[i][paX]=0.0;
	   			Paska[i][paY]=0.0;
	      		Paska[i][paZ]=0.0;
	      		Paska[i][paRX]=0.0;
	        	Paska[i][paRY]=0.0;
	         	Paska[i][paRZ]=0.0;
	          	DestroyDynamicObject(Paska[i][pObject]);
	          	SCMEx(playerid, INFOCOLOR, "> Smazal jsi pásku ID: %d.", i);
	           	return 1;
	        }
		}
  	}
    return ErrorBox(playerid, "Nejsi dostatecne blizko.");
}

 

 

Link to comment
Share on other sites

  • 0

A co pořád ten cyklus v CreatePaska? Neříkej, že ti to pracuje korektně.. :/ Když jsi ještě jednou přečteš, co jsem ti psal, tak zjištíš, že ne.. Vždyť na jednom místě nevytváříš jednu pásku, ale hned několik... A když už by jsi to chtěl, tak použij tvojí konstantu MAX_PASKA a ne velikost proměnné paska.. 

Link to comment
Share on other sites

  • 0

Pff, tak já nevím. Testoval jsem to a pásku to vytvoří v místě, kde má, pak se to upravuje. Samozřejmě jeden člověk může vytvořit i více pásek, ale na místě to vytvoří jen jednu pásku s daným ID. S tou se pak pracuje a kdykoliv se může smazat. Když se to testovalo na serveru, nikdo žádnou chybu ani nehlásil, naopak si s tím policajti docela hojně hráli. :-D Každopádně to duplicitní zjišťování pozic jsem vymazal, a zkusím jak to bude fungovat bez toho cyklu tedy. Jinak jak jsi mi ukázal ten příklad zjednodušeného příkazu:

 

EditDynamicObject(playerid, Paska[i][pObject]);
LastPaskaEdit[playerid] = i;
PaskaEdit[playerid] = true;

Tam být musí, protože pracuji s publicem OnPlayerEditDynamicObject, jsem si tak všiml, že jsi to v příkladu neuvedl a napsal jsi tam EditPaska(playerid); jsem pak byl trochu zmaten z toho, kde jsi to vzal. :d 

Edited by Meric
Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
×
×
  • Create New...