Jump to content

Andreigl

VIP
  • Posts

    1958
  • Joined

  • Last visited

Posts posted by Andreigl

  1. 1 minute ago, Anette said:

    Acesta este motivul exact pentru care majoritatea ownerilor (nu neaparat de aici) aleg sa nu mai faca evenimente atat de des.

    Eu zic sa va multumiti ca macar omul a incercat sa ne ofere ceva, chiar daca nu este finalizat in totalitate. Sunt sigura ca Kelton va intelege si va muta data evenimentului intr-una accesibila pentru toti, ca sa nu stam 5 ore intr-o zi sa-l recuperam. Of, greu de inteles. Mie chiar imi place ideea evenimentului, chiar daca a trebuit sa dau 560 gold pentru un slot in garaj.

    frt, dc esti nervoasă

  2. @Vesca,

     

    dă edit la topic și într-un spoiler să pui toate funcțiile API-ului cerute (inclusiv asta de mai sus)

     

    Am nevoie de:

    1) ForAllPeds (direct din stActorPool)

    2) isActorDefined (a.k.a streamed) (dacă găseam asta, știam să fac și eu func. 1), dar era ineficientă așa :)))

    3) ActorCurrentCar sau playerCurrentCar (pHandle / playerID)

    4) ForAllVehicles (direct din stVehiclePool) 

     

    momentan doar atât :)) 

  3. Varianta 2, folosind tutorialul lui @Vesca (Click pentru a accesa tutorialul):

    main.h

    class Announcements {
    public:
    	static void __stdcall GiveLicense(std::string);
    	static void __stdcall At_Me(std::string);
    	static void __stdcall StartLesson(std::string);
    	static void __stdcall TestPassed(std::string);
    	static void __stdcall TestFailed(std::string);
    };
    
    std::unordered_map< std::string, std::pair<std::regex, std::string> >
    Syntaxes{
    	{ "GiveLicence", { std::regex("[0-999]+ [1-5]+"), "<Player ID> <Licence ID>" } },
    	{ "At_Me", { std::regex("[0-999]+ [1-5]+"), "<Player ID> <Licence ID>" } }
    };

     

    main.cpp

    void _stdcall Announcements::GiveLicense(std::string params)
    {
    	std::regex regex_syntax = Syntaxes["GiveLicence"].first;
    	if (std::regex_match(params, regex_syntax))
    	{
    		std::stringstream StringStream(params);
    		std::string Player_ID, Licence_ID;
    		StringStream >> Player_ID >> Licence_ID;
    		if (SF->getSAMP()->getPlayers()->IsPlayerDefined(std::stoi(Player_ID)))
    		{
    			if (std::stoi(Licence_ID) == 1)
    			{
    				std::string Format = "/givelicense " + Player_ID + " Flying";
    				char* Text = new char[Format.size() + 1];
    				strcpy_s(Text, Format.size() + 1, Format.c_str());
    				SF->getSAMP()->getPlayers()->pLocalPlayer->Say(Text);
    				free(Text);
    			}
    			if (std::stoi(Licence_ID) == 2)
    			{
    				std::string Format = "/givelicense " + Player_ID + " Sailing";
    				char* Text = new char[Format.size() + 1];
    				strcpy_s(Text, Format.size() + 1, Format.c_str());
    				SF->getSAMP()->getPlayers()->pLocalPlayer->Say(Text);
    				free(Text);
    			}
    			if (std::stoi(Licence_ID) == 3)
    			{
    				std::string Format = "/givelicense " + Player_ID + " Fishing";
    				char* Text = new char[Format.size() + 1];
    				strcpy_s(Text, Format.size() + 1, Format.c_str());
    				SF->getSAMP()->getPlayers()->pLocalPlayer->Say(Text);
    				free(Text);
    			}
    			if (std::stoi(Licence_ID) == 4)
    			{
    				std::string Format = "/givelicense " + Player_ID + " Weapon";
    				char* Text = new char[Format.size() + 1];
    				strcpy_s(Text, Format.size() + 1, Format.c_str());
    				SF->getSAMP()->getPlayers()->pLocalPlayer->Say(Text);
    				free(Text);
    			}
    			if (std::stoi(Licence_ID) == 5)
    			{
    				std::string Format = "/givelicense " + Player_ID + " Materials";
    				char* Text = new char[Format.size() + 1];
    				strcpy_s(Text, Format.size() + 1, Format.c_str());
    				SF->getSAMP()->getPlayers()->pLocalPlayer->Say(Text);
    				free(Text);
    			}
    		}
    		else
    		{
    			std::string Text = "{00d12d}[School Instructors]: {a1aba2}Player with ID " + Player_ID + " is not connected.";
    			SF->getSAMP()->getChat()->AddChatMessage(D3DCOLOR_XRGB(0, 0xFF, 0), Text.c_str());
    		}
    	}
    	else
    	{
    		std::string Text_Syntax = "{00d12d}[School Instructors]: {a1aba2}Syntax: " + Syntaxes["GiveLicence"].second;
    		SF->getSAMP()->getChat()->AddChatMessage(D3DCOLOR_XRGB(0, 0xFF, 0), Text_Syntax.c_str());
    	}
    }
  4. Dacă ai lucrat în cleo vreodată, atunci știi că poți afla parametrii în felul următor:

    SAMP.IsCommandTyped(0@)
    0AD4: 4@ = scan_string 0@ format "%s %d %s" 1@v 5@ 6@v

    și unde 4@ returnează numărul de parametrii (evident, în cazul nostru sunt 3, dar nu am pus-o ca și o condiție, deci nu-i obligatoriu să fie 3).

     

    În C++, pentru un mod SF, ce mi-a venit în cap, pentru a afla numărul de parametrii, putem verifica numărul de spații.

    De exemplu, se află un spațiu? Atunci avem 2 parametrii, nu se află nici un spațiu? Atunci avem unul singur.

     

    Funcția următoare ne dă numărul de parametrii:

    int params_count = 0;
    for (unsigned int contor = 0; contor < params.length(); contor++)
    	if (params[contor] == ' ')
    		params_count++;

     

    Cu funcția următoare putem verifica dacă jucătorul a trimis cel puțin un parametru:

    if (!params.empty())
    	std::cout << "Avem cel putin un parametru";
    else
    	std::cout << "Nu avem nici un parametru";

     

    Putem să verificăm dacă a trimis într-adevăr parametrii de care noi avem nevoie:

    if (!sscanf_s(params.c_str(), "%d %d", Player_ID, Licence_ID))
    {
    	SF->getSAMP()->getChat()->AddChatMessage(D3DCOLOR_XRGB(0, 0xFF, 0), "{00d12d}[School Instructors]: {a1aba2}Usage: /gl(givelicense) [Player ID] [License ID]");
    	SF->getSAMP()->getChat()->AddChatMessage(D3DCOLOR_XRGB(0, 0xFF, 0), "{00d12d}[School Instructors]: {a1aba2}ID Licenses: Flying (1), Sailing (2), Fishing (3), Weapon (4), Materials (5)");
    	return;
    }

     

    Un exemplu de utilizare (am început eu să traduc un mod CLEO în C++):

    void __stdcall Announcements::GiveLicense(std::string params)
    {
    	unsigned int params_count = 0;
    	for (unsigned int contor = 0; contor < params.length(); contor++)
    		if (params[contor] == ' ')
    			params_count++;
    
    	if (params.empty() || params_count == 0)
    	{
    		SF->getSAMP()->getChat()->AddChatMessage(D3DCOLOR_XRGB(0, 0xFF, 0), "{00d12d}[School Instructors]: {a1aba2}Usage: /gl(givelicense) [Player ID] [License ID]");
    		SF->getSAMP()->getChat()->AddChatMessage(D3DCOLOR_XRGB(0, 0xFF, 0), "{00d12d}[School Instructors]: {a1aba2}ID Licenses: Flying (1), Sailing (2), Fishing (3), Weapon (4), Materials (5)");
    		return;
    	}
    
    	int* Player_ID = new int;
    	int* Licence_ID = new int;
    	if (!sscanf_s(params.c_str(), "%d %d", Player_ID, Licence_ID))
    	{
    		SF->getSAMP()->getChat()->AddChatMessage(D3DCOLOR_XRGB(0, 0xFF, 0), "{00d12d}[School Instructors]: {a1aba2}Usage: /gl(givelicense) [Player ID] [License ID]");
    		SF->getSAMP()->getChat()->AddChatMessage(D3DCOLOR_XRGB(0, 0xFF, 0), "{00d12d}[School Instructors]: {a1aba2}ID Licenses: Flying (1), Sailing (2), Fishing (3), Weapon (4), Materials (5)");
    		free(Player_ID);
    		free(Licence_ID);
    		return;
    	}
    
    	if (SF->getSAMP()->getPlayers()->IsPlayerDefined(*Player_ID))
    	{
    		if (*Licence_ID >= 1 && *Licence_ID <= 5)
    		{
    			if (*Licence_ID == 1)
    			{
    				char* Event = new char[256];
    				snprintf(Event, 256, "/givelicense %d Flying", *Player_ID);
    				SF->getSAMP()->getPlayers()->pLocalPlayer->Say(Event);
    				free(Event);
    			}
    			if (*Licence_ID == 2)
    			{
    				char* Event = new char[256];
    				snprintf(Event, 256, "/givelicense %d Sailing", *Player_ID);
    				SF->getSAMP()->getPlayers()->pLocalPlayer->Say(Event);
    				free(Event);
    			}
    			if (*Licence_ID == 3)
    			{
    				char* Event = new char[256];
    				snprintf(Event, 256, "/givelicense %d Fishing", *Player_ID);
    				SF->getSAMP()->getPlayers()->pLocalPlayer->Say(Event);
    				free(Event);
    			}
    			if (*Licence_ID == 4)
    			{
    				char* Event = new char[256];
    				snprintf(Event, 256, "/givelicense %d Weapon", *Player_ID);
    				SF->getSAMP()->getPlayers()->pLocalPlayer->Say(Event);
    				free(Event);
    			}
    			if (*Licence_ID == 5)
    			{
    				char* Event = new char[256];
    				snprintf(Event, 256, "/givelicense %d Materials", *Player_ID);
    				SF->getSAMP()->getPlayers()->pLocalPlayer->Say(Event);
    				free(Event);
    			}
    		}
    		else
    		{
    			SF->getSAMP()->getChat()->AddChatMessage(D3DCOLOR_XRGB(0, 0xFF, 0), "{00d12d}[School Instructors]: {a1aba2}Wrong License ID.");
    			SF->getSAMP()->getChat()->AddChatMessage(D3DCOLOR_XRGB(0, 0xFF, 0), "{00d12d}[School Instructors]: {a1aba2}ID Licenses: Flying (1), Sailing (2), Fishing (3), Weapon (4), Materials (5)");
    		}
    	}
    	else
    	{
    		char Message[256];
    		_snprintf_s(Message, sizeof(Message), "{00d12d}[School Instructors]: {a1aba2}Player with ID %d is not connected.", *Player_ID);
    		SF->getSAMP()->getChat()->AddChatMessage(D3DCOLOR_XRGB(0, 0xFF, 0), Message);
    	}
    
    	free(Player_ID);
    	free(Licence_ID);
    }

     

    Singura problemă, care încă nu i-am dat de furcă, funcția say ne cere pointerul unui string, însă _snprintf_s nu poate implementa un pointer (noi ca să citim parametrii pe rând, folosim sscanf, iar aici trebuie să creem pointeri din nou). Eu am folosit în schimb snprintf, dar o să primim warning cum că funcția este unsecure. Bine înțeles, se poate dezactiva acest warning. Revin cu edit când o să găsesc o soluție.

  5. 4 hours ago, Madalin said:

    Dacă ne-ai spune şi cum decompilăm unul :D

    Nu ai cum, doar să vezi prin părți ce face programul cutare, dar sursa nu o poți recupera. 

    Asta se poate doar in C# :) 

     

    O altă variantă în loc de:

    std::string mesaj = "Salut, " + name + "!"; // <- creem mesajul de salut
    char* mesaj_char = new char[mesaj.size() + 1]; // <- il convertim la char
    strcpy(mesaj_char, mesaj.c_str());

     

    Ar mai fi:

    char* myChar = new char[256];
    snprintf(
        myChar, 256,
        "Jucatorul cu ID-ul %d are numele %s",
        Player_ID,
        SF->getSAMP()->getPlayers()->GetPlayerName(Player_ID)
    );

     

    P.S: Pentru cei care primesc eroare cum că nu se găsește Windows.h, trebuie să dați retarget la proiect.

    image.png.35d8aea7c00670f241489ff7b01a5523.png 

     

    și să-l upgradați la o versiune nouă (eu folosesc v142 2017).

  6. https://www.pbinfo.ro/solutii/user/neauzitul/problema/3272/sumdivogl

     

    Method 1 by @Vesca:

     

    #include <algorithm>
    #include <iostream>
    #include <string>
    
    int main()
    {
        int N; std::cin >> N;
        long long int sum = 0;
        int current_num;
    
        while (std::cin >> current_num) {
            std::string str_num = std::to_string(current_num);
            std::reverse(str_num.begin(), str_num.end());
            current_num = std::stoi(str_num);
    
            int div;
            for (div = 1; div * div < current_num; ++div) {
                sum += (div + current_num / div) * (current_num % div == 0);
            }
            sum += div * (div * div == current_num);
        }
    
        std::cout << sum << "\n";
    
        return 0;
    }

     

    Method 2:

    #include <iostream>
    
    int Oglindit(int Numar)
    {
        int Oglindit = 0;
        while (Numar)
        {
            Oglindit = Numar % 10 + Oglindit * 10;
            Numar /= 10;
        }
    
        return Oglindit;
    }
    
    long long int Divizori(int Numar)
    {
        long long int Suma = 0;
        for (int i = 1; i * i <= Numar; i++)
        {
            if (Numar % i == 0)
            {
                Suma += i;
    
                if (i * i < Numar)
                    Suma += Numar / i;
            }
        }
    
        return Suma;
    }
    
    int main()
    {
        int N, Numar;
        long long int Suma = 0;
        std::cin >> N;
    
        for (; N > 0; N--)
        {
            std::cin >> Numar;
            Suma += Divizori(Oglindit(Numar));
        }
    
        std::cout << Suma;
    }
  7. @TheTom

     

    CLEO te limitează până la 31 de variaible, ultimele 2 fiind timere (cresc cu 1 de fiecare dată când codul reia loop-ul principal).

    Deci ai 2 variante, ori înveți să folosești 

    0AB1: call_scm_func @GetSQR 1 10 $result

    ori folosești funcțiile de mai jos:

    :SET  
    0AC6: 3@ = get_label_pointer @MEMORY
    int 1@ *= 4  
    int 3@ += 1@
    0A8C: write_memory 3@ size 2@ value 0@ virtual_protect 0
    ret 0
    
    :GET
    0AC6: 3@ = get_label_pointer @MEMORY
    int 0@ *= 4
    int 3@ += 0@
    0A8D: 2@ = read_memory 3@ size 1@ virtual_protect 0
    ret 1 2@
    
    :Memory
    hex
    00 00 00 00 // variabila 1
    00 00 00 00 // variabila 2
    00 00 00 00 // variabila 3
    // ...
    00 00 00 00 // variabila n
    end

     

    Pentru a salva o variabilă se folosește funcția SET în felul următor:

    0AB1: @SET 3 passed_value 1@ var_number 2@ var_size 4

    unde 1@ reprezintă valoarea trimisă, iar 2@ numărul variabilei.

     

    Pentru a lua o variabilă salvată în Memory, se folosește funcția GET în felul următor:

    0AB1: @GET 2 var_number 1@ var_size 4 receiver 2@

    unde 1@ reprezintă numărul variabilei care vrem să-i aflăm valoarea, iar 2@ variabila unde valoarea variabilei 1@ o să fie stocată.

     

    Exemplu de script cu aceste funcții aveți mai jos:

    {$CLEO}
    
    repeat
        wait 0
    until 0AFA:
    
    goto @Main
    
    :SET  
    0AC6: 3@ = get_label_pointer @MEMORY
    int 1@ *= 4  
    int 3@ += 1@
    0A8C: write_memory 3@ size 2@ value 0@ virtual_protect 0
    ret 0
    
    :GET
    0AC6: 3@ = get_label_pointer @MEMORY
    int 0@ *= 4
    int 3@ += 0@
    0A8D: 2@ = read_memory 3@ size 1@ virtual_protect 0
    ret 1 2@
    
    :Memory
    hex
    00 00 00 00
    00 00 00 00
    00 00 00 00
    00 00 00 00
    00 00 00 00
    end
    
    :Main
    0C6A: 1@ = create_custom_thread_at_label @While_2
    
    while true
        wait 0
        
        if 33@ > 5000
        then 0AB1: @SET 3 passed_value 1 var_number 1 var_size 4 
        end
    end
    
    :While_2
    while true
        wait 0
        
        0AB1: @GET 2 var_number 1 var_size 4 receiver 0@
        if 0@ <> 0
        then chatmsg "Yes" -1
        end
    
    end

     

    Se observă că am trimis un parametru dintr-un thread într-un alt thread, ceea ce cu variabilele locale este imposibil.

  8. High Code:

    for 0@ = 0 to 999 step 1
        if SAMP.IsPlayerConnected(1@)
        then
    	// some code
        end
    end

    Low Code:

    0@ = 0 
    
    :Noname_7
    if 
       SAMP.IsPlayerConnected(1@)
    jf @Noname_23 
    
    :Noname_23
    0@ += 1 
      0@ > 999 
    jf @Noname_7 

     

    Pentru ce este de folos? Ei bine, voi știți, dar vă spun ce-mi trece prin cap acum:

    1. Crearea unui mod ce vinde / oferă arme / repair / refill tuturor jucătorilor de lângă tine
    2. Crearea unui mod ce dă find pe un jucător online (detective help job skill up sau ceva de genul)

     

    Pentru prima variantă, o să trebuiască să verificăm dacă jucătorul este în stream zone (luăm handle-ul), după verificăm distanța dintre cele 2 caractere (eu și el).

    Exemplu:

    for 0@ = 0 to 999 step 1
        if SAMP.IsPlayerConnected(0@)
        then
            1@ = SAMP.GetActorHandleByPlayerID(0@)
            if 056D:   actor 1@ defined
            then
                Actor.StorePos(1@, 2@, 3@, 4@)
                Actor.StorePos($PLAYER_ACTOR, 5@, 6@, 7@)
                050A: 8@ = distance_between_XYZ 2@ 3@ 4@ and_XYZ 5@ 6@ 7@
                if not 8@ >= 15.0 // feet
                then
                    // some code
                end
            end
        end
    end

     

     

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.