Skocz do zawartości

Witamy w Nieoficjalnym polskim support'cie AMX Mod X

Witamy w Nieoficjalnym polskim support'cie AMX Mod X, jak w większości społeczności internetowych musisz się zarejestrować aby móc odpowiadać lub zakładać nowe tematy, ale nie bój się to jest prosty proces w którym wymagamy minimalnych informacji.
  • Rozpoczynaj nowe tematy i odpowiedaj na inne
  • Zapisz się do tematów i for, aby otrzymywać automatyczne uaktualnienia
  • Dodawaj wydarzenia do kalendarza społecznościowego
  • Stwórz swój własny profil i zdobywaj nowych znajomych
  • Zdobywaj nowe doświadczenia

Dołączona grafika Dołączona grafika

Guest Message by DevFuse
 

Owner123 - zdjęcie

Owner123

Rejestracja: 12.10.2009
Aktualnie: Nieaktywny
Poza forum Ostatnio: 18.12.2011 18:32
*----

#266431 Ent i hitboxy

Napisane przez Owner123 w 04.07.2011 23:21

Jeśli chcesz aby twojego Enta można było "zabić" najlepiej użyć do tego Ham_TakeDamage i Ham_TraceAttack.
  • +
  • -
  • 1


#256145 Sprawdzanie czy gracz ma wybrane bronie w plecaku

Napisane przez Owner123 w 05.06.2011 12:19

if(sprawdz_bronie(id, (1 << CSW_USP) | (1 << CSW_DEAGLE)))
{
//ma usp lub deagla
}
else
{
//nie ma
}


stock bool:sprawdz_bronie(id, disallowed)
{
new weapons[32], num;
return (get_user_weapons(id, weapons, num) & disallowed)? true : false
}


Lekko przerobiony kod cypisa .. ;X
  • +
  • -
  • 1


#241254 Dublowanie się klas

Napisane przez Owner123 w 25.04.2011 07:26

Łatka będzie polegała na wprowadzeniu odpowiedniego zapytania MYSQL.
ALTER TABLE `TABELA_DIABLO` ADD PRIMARY KEY ( `TYP_ZAPISU` , `klasa` )
Zamiast TABELA_DIABLO wpisujecie nazwe swojej tabeli.
Zamiast TYP_ZAPISU dajecie rodzaj swojego zapisu. W przypadku zapisu na nick będzie to wyglądało następująco:
ALTER TABLE `dbmod_tablet` ADD PRIMARY KEY ( `nick` , `klasa` ) ;

Zapytanie nie zostanie wywołane jeśli ktoś posiada już zbugowany lvl. Nick osoby ktora ma zbugowany lvl zostanie wyświetlony w kodzie błedu, który może brzmieć mniej więcej tak:
Duplicate entry 'Ownelek.-1' for key 1
Na podstawie tego kodu błędu można odczytać że osoba o nicku Ownelek. ma zbugowaną klase 1 (czyli Maga).

Zapytanie wprowadzacie do PhpMyAdmina lub innych podobnych.
  • +
  • -
  • 8


#235249 Zmiana ilości pocisków w magazynku.

Napisane przez Owner123 w 10.04.2011 16:37

set_user_weapon_clip(id, newammo, weapon = 0)
{
new szWeapon[64], iWeapon = get_user_weapon(id);
if(!weapon)
{
if(!iWeapon)
return 0;

get_weaponname(get_user_weapon(id), szWeapon, 63);
}
else
{
if(!get_weaponname(weapon, szWeapon, 63))
return 0;
}

cs_set_weapon_ammo(find_ent_by_owner(-1, szWeapon, id), newammo);
return 1;
}

Wymagane cstrike + engine. Jeśli weapon = 0 to ammo bedzie zmieniane w obecnej broni, w przeciwnym wypadku bedzie zmienione w broni o podanym id.
  • +
  • -
  • 1


#208830 Task przysyłający dodatkowy index

Napisane przez Owner123 w 24.01.2011 02:03

new data[1]; data[0] = attacker

Jak sam napisales to musi byc tablica a nie zwykla zmienna.
  • +
  • -
  • 1


#202096 Jak zrobic blyskawice na graczu by zabierala zycie

Napisane przez Owner123 w 01.01.2011 20:10

Lekko przerobilem kod podany przez Knopersa :)

Tutaj kolejny cel jest znajdywany na podstawie pierwszego celu.

Mógłbym to nieco ulepszyc, aby znajdowalo wiele celow ale lenistwo bierze gore xD

Edit.
Dobra jednak sie przelamalem i napisalem kawalek kodu.
Nietestowany, mam nadzieje ze dziala :D

Załączone pliki


  • +
  • -
  • 2


#201801 Jak rozłożyć tabele by nie wyskakiwał błąd..

Napisane przez Owner123 w 31.12.2010 17:10

formatex(str_query,511, "INSERT INTO fbh_xp (xp, lvl, sptk, pgraw, pspeed, pfuria, \
pczar, pnc, fbhy, gz, lpm, s_prz, lpmt_os, s_lvl, s_graw, s_speed, lpmtos, os_scout, os_scout_s)\
VALUES ('%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d');",\
PlayerName, PlayerXP[id], PlayerLevel[id], SkillPoints[id], PtkGraw[id], PtkSpeed[id], PtkFuria[id], PtkFizyk[id], PtkCzar[id], PtkNc[id],\
marzenia[id], gratz[id], lpm[id], sprawdz_przejsca[id], lpmt_os[id], sprawdz_level[id], sprawdz_graw[id], sprawdz_speed[id], lpmtOS[id],\
os_scout[id], os_scout_s[id]);


Takie coś już przełknie :)
  • +
  • -
  • 1


#191656 Niepotrzebne wpisy w msql

Napisane przez Owner123 w 26.11.2010 12:10

Takie zapytanie powinno pomóc:
SELECT `klasa` FROM %s WHERE `nick/sid/ip` = '%s' AND `klasa` = '%i';

Później w handle od SQL_ThreadQuery wykonujesz SQL_NumResults > 0 (jesli true, ma klase etc. jesli false mozesz spokojnie tworzyc)
  • +
  • -
  • 1


#180657 GunXP Mysql

Napisane przez Owner123 w 16.10.2010 17:51

Zamień client_connect na client_authorized. Zdecydowanie bezpieczniej + to co kolega wyżej podał.
  • +
  • -
  • 1


#179391 +10 hp za każde zabicie

Napisane przez Owner123 w 12.10.2010 19:00

        if(klasa_gracza[attacker] == TWOJA_KLASA)
{ new zdrowie = get_user_health(attacker)
set_user_health(attacker,zdrowie +10)
maksymalne_zdrowie_gracza[attacker] += 10
}


Edit. Chociaż nie, to nie zadziała :F w8, zaraz wkleje nowe ...
Pod:
new maksymalne_zdrowie_gracza[33]

Dodaj:
new dodatkowe_zdrowie_gracza[33]


Zamiast tego kodu wyzej daj to:
        if(klasa_gracza[attacker] == TWOJA_KLASA)
{ new zdrowie = get_user_health(attacker)
set_user_health(attacker,zdrowie +10)
dodatkowe_zdrowie_gracza[attacker] += 10
}


W Odrodzenie(id) zamiast:
maksymalne_zdrowie_gracza[id] = zdrowie_klasy[klasa_gracza[id]]+zdrowie_gracza[id]*2;

Daj to:
maksymalne_zdrowie_gracza[id] = zdrowie_klasy[klasa_gracza[id]]+zdrowie_gracza[id]*2+dodatkowe_zdrowie_gracza[id];


I wsio ...
  • +
  • -
  • 1


#175812 Jak dać kilka granatów?

Napisane przez Owner123 w 30.09.2010 21:55

give_item(id, "weapon_hegrenade");
cs_set_user_bpammo(id, CSW_HEGRENADE, 4);

"4", możesz zastąpić inną liczbą, zależy ile chcesz mieć granatów.
  • +
  • -
  • 1


#174438 XVary - Co to jest ?

Napisane przez Owner123 w 26.09.2010 11:11

Dzisiejszy tutorial będzie poświęcony rzadko spotykanym - XVarom !

Co to jest?
Jest to specjalny rodzaj zmiennej, która może być obsługiwana z poziomu innego pluginu przy użyciu odpowienich natyw.
Te natywy to:
/* Sprawdza czy XVar o podanej nazwie istnieje. */
native xvar_exists( const name[] );

/* Zwraca unikalne ID XVara. Jeśli nie istnieje zwraca -1. */
native get_xvar_id( const name[] );

/* Zwraca liczbę naturalna XVara. Id to wartość zwrócona przez get_xvar_id(). */
native get_xvar_num( id );

/* Zwraca liczbę rzeczywistą XVara. Id to wartość zwrócona przez get_xvar_id(). */
native Float:get_xvar_float( id );

/* Ustawia wartosc dla XVara. Id to wartość zwrócona przez get_xvar_id(). */
native set_xvar_num( id, value = 0 );

/* Ustawia liczbę rzeczywistą dla XVara. Id to wartość zwrócona przez get_xvar_id(). */
native set_xvar_float( id, Float:value = 0.0 );

Do tworzenia XVara służy słowo public.
Wygląda to mniej więcej tak:
public XvarExample;
public Float:XvarExampleFloat;
public bool:XvarExampleBool;

XVary mogą być tylko globalne, w przypadku próby użycia XVara jako zmienną lokalną, kompilator zasygnalizuję błąd.

Jak z tego korzystać ?
Najprostsze użycie XVarów wygląda tak:
#1
#include <amxmodx>

public XvarExample; /* Tworzymy xvary różnego typu */
public Float:XvarExampleFloat; /* Tutaj mamy Floata */
public bool:XvarExampleBool; /* A tutaj Boola */

public plugin_init()
{
register_plugin("XVar Tutorial", "1.0.0", "Owner dla AMXX.PL")
XvarExample = 100;
XvarExampleBool = true;
XvarExampleFloat = 1337.666;
}

#2
#include <amxmodx>

new g_pXvarPointers[3];
new bool:g_bXvarValue;
new Float:g_fXvarValue;
new g_iXvarValue;

public plugin_init()
{
register_plugin("XVar Tutorial", "1.0.0", "Owner dla AMXX.PL")
if(xvar_exists("XvarExample"))
g_pXvarPointers[0] = get_xvar_id("XvarExample");
if(xvar_exists("XvarExampleBool"))
g_pXvarPointers[1] = get_xvar_id("XvarExampleBool");
if(xvar_exists("XvarExampleFloat"))
g_pXvarPointers[2] = get_xvar_id("XvarExampleFloat");

g_iXvarValue = get_xvar_num(g_pXvarPointers[0]);
g_bXvarValue = bool:get_xvar_num(g_pXvarPointers[1]);
g_fXvarValue = get_xvar_float(g_pXvarPointers[2]);

}


Zaś ustawianie wartości wygląda następująco:
// ustawia wartośc dla liczby całkowitej
set_xvar_num( g_pXvarPointers[0], 10 );

// ustawia wartość dla zmiennej logicznej
set_xvar_num( g_pXvarPointers[1], false );

// ustawia wartość dla liczby rzeczywistej
set_xvar_float( g_pXvarPointers[2], 19.6 );


Podwojenia
Podwojenia są to 2 Xvary o takiej samej nazwie. Gdy chcemy z poziomu innego pluginu ustawić wartość dla niego, wartość Xvara zostanie zmieniona w tym pluginie, który jest wyżej w plugins.ini, poniżej przykład:
// To jest #1 plugin w plugins.ini

#include <amxmodx>

public bool:ShowRoundMessage;

public plugin_init()
{
register_plugin("New Round Displayer", "1.0.0", "Owner dla AMXX.PL");
register_event("HLTV", "NewRound", "a", "1=0", "2=0");
}

public NewRound()
{
if(ShowRoundMessage)
client_print(0, print_center, "Round Started");
}

// To jest #2 plugin w plugins.ini

#include <amxmodx>

public bool:ShowRoundMessage;

public plugin_init()
{
register_plugin("New Round Displayer", "1.0.0", "Owner dla AMXX.PL");
register_event("HLTV", "NewRound", "a", "1=0", "2=0");
}

public NewRound()
{
if(ShowRoundMessage)
client_print(0, print_center, "Round Started");
}

Zgadza się, te 2 pluginy są identyczne. Aby pokazać jak działa podwojenie potrzebny jest #3 plugin, który zmieni wartość naszego XVara:
#include <amxmodx>

new g_pXvar;

public plugin_init()
{
register_plugin("New Round Displayer Enabler", "1.0.0", "Owner dla AMXX.PL");
if((g_pXvar = get_xvar_id("ShowRoundMessage")) != -1)
set_xvar_num(g_pXvar, true);
}


Po rozpoczęciu rundy, pokaże się tylko jeden komunikat - co za tym idzie, wartość została zmieniona tylko dla pluginu #1.

Na zakończenie
To chyba wszystko jeśli chodzi o Xvary. W razie niejasności pisać a postaram się jak najszybciej to poprawić.
  • +
  • -
  • 4


#174001 Wyrzucanie określonej broni.

Napisane przez Owner123 w 25.09.2010 08:46

engclient_cmd(id, "drop", "weapon_ak47");

  • +
  • -
  • 2


#173684 [Photoshop] Zanikanie - wyjątkowy gradient i warstwy? :P

Napisane przez Owner123 w 23.09.2010 20:53

Bierzesz Zaznaczenie ustawiasz Feather na 20 zaznaczasz dany obszar i usuwasz. I masz ładny efekt takiego właśnie przejścia. Nie mam pod ręką PS'a więc nie jestem w stanie ci tego lepiej wytłumaczyć. Jak gdzieś tam znajdziesz opcje Select>Inverse to jej użyj jak zaznaczysz dany obszar(jak chcesz zostawić środek a nie boki :P)
  • +
  • -
  • 1


#173556 [Orpheu] Podstawowe zagadnienia.

Napisane przez Owner123 w 23.09.2010 15:28

W tym o to tutorialu postaram się przybliżyć potęgę oraz pomóc zrozumieć nieco ten moduł.

Orpheu, jest to moduł autorstwa joaquimandrade. Jest możliwy do pobrania stąd: Module: Orpheu2.3a - AlliedModders

No to lecimy !
Pierwsza rzecz, jaka jest potrzebna, to dekompilator Windowsowy/Linuxowy. Osobiście posiadam IDA Pro Advanced + Hex Rays Decompiler.
Wszystkie poniższe operacje będę przeprowadzał właśnie na tym programie.

Od czego zacząć?
Pierwszą operacje, jaką przeprowadzimy będzie dekompilacji biblioteki. Mamy 2 rodzaje bibliotek:
- engine - silnik gry (nie mylić z biblioteką HL!). Jest to podstawa każdego modu. Nazwa pliku: swds.dll(Windows)/hlds_engine*(Linux).
- mod - silnik moda np. Counter-Strike, Half-Life, Team Fortress etc. Nazwa pliku:(dla Cs'a) mp.dll(Windows)/cs_i386.so(Linux). Oba te pliki znajdują się w cstrike/dlls.

Po otwarciu IDA ukaże się takie o to okienko:
Dołączona grafika
Wybieramy "New".
Dołączona grafika
I tutaj mamy wybór. Możemy dekompilować biblioteke Windowsową albo Linuxową. Wybieramy Linuxową, dlaczego ? Ponieważ zdekompilowana biblioteka Windowsa jest nieczytelna :>
Dołączona grafika
Klikamy to co zaznaczyłem na screenie wyżej i szukamy odpowiedniej biblioteki.

Dołączona grafika

Aby otworzyć odpowiednią zakładkę, klikamy w Views>Open Subviews>Names.
Jak zapewne niektórzy zauważyli, są tu podane funkcje występujące w danej bibliotece.

Dobra mamy podstawę. Jak mam napisać z tego plugin !?
Aby móc korzystać z tych funkcji, potrzebna jest tzw. sygnatura.

Są 2 rodzaje sygnatur:
- do zwykłych funkcji, znacznie trudniej zrobić do nich sygaturę
- do funkcji wirtualnych, o wiele łatwiejsze do wykonania

Zwykłe funkcje
Każda funkcja posiada swój własny offset w bibliotece. W systemie Linux ten offset bardzo łatwo znaleść - jest to jego nazwa. W systemie Windows sprawa nie wygląda już tak pięknie i łatwo. Tutaj aby znaleść odpowiedni offset, trzeba mieć przedewszystkim cierpliwość.
No dobra, mamy funkcję InstallGameRules, o to jej 'pseudocode' z biblioteki Linuxowej:
int __cdecl InstallGameRules()
{
  int result; // eax@2
  int v1; // eax@2
  int v2; // eax@3

  (*(void (__cdecl **)(_DWORD))&g_engfuncs[156])("exec game.cfg\n");
  (*(void (**)(void))&g_engfuncs[160])();
  if ( *(float *)(gpGlobals + 20) == 0.0 )
  {
    v2 = __builtin_new(0x2C4u);
    result = __18CHalfLifeMultiplay(v2);
  }
  else
  {
    v1 = __builtin_new(0x2D8u);
    result = __17CHalfLifeTraining(v1);
  }
  return result;
}

Tutaj bardzo łatwo można zobaczyć szczególną cechę tej funkcji, string'a exec game.cfg\n. Skoro chcemy znaleść jej offset w Windowsie, dekompilujemy binarkę Windowsa i szukamy tego stringa w kodzie. Powinnyśmy znaleść coś w tym stylu:
//----- (10088530) --------------------------------------------------------
int __cdecl sub_10088530()
{
  long double v0; // fst7@1
  int v1; // eax@2
  int v3; // eax@4

  dword_101623DC("exec game.cfg\n");
  dword_101623E0();
  v0 = *(float *)(LODWORD(dword_101625B8) + 20);
  if ( v0 == 0.0 )
  {
    v1 = (int)operator new(0x2E8u);
    if ( v1 )
      return sub_100C5EF0(v1, v0);
  }
  else
  {
    v3 = (int)operator new(0x2D0u);
    if ( v3 )
      return sub_10093D80(v3, v0);
  }
  return 0;
}
Jak zapewne widać, oba kody różnią się od siebie. Naszym offsetem w Windowsie jest sub_10088530. Ponieważ jest wartość wyrażona w systemie szesnastwkowym, prawidłowy zapis wygląda w ten sposób: 0x88530.
Teraz możemy już napisać naszą sygnaturę, dla tej funkcji będzie ona wyglądać następująco:
{
    "name" : "InstallGameRules",
    "library" : "mod",
    "return" : 
    {
        "type" : "CHalfLifeMultiplay *",
	"info" : "Ten parametr jest opcjonalny. Jeśli chcemy przechwycić returna tej funkcji, to musimy uwzględnić tą zakladke u siebie"
    },
    "identifiers":
    [
        {
            "os" : "windows",
            "mod" : "cstrike",
            "value" : 0x88530
        },
	{
            "os" : "linux",
            "mod" : "cstrike",
            "value" : "InstallGameRules"
	}
    ]
}

Sygnaturę wrzucamy do configs/orpheu/functions.
W przypadku gdy funkcja należy do jakiejś klasy tworzymy dodatkowo folder z nazwą danej klasy. Np. dla funkcji CBaseEntity::Spawn ścieżka będzie następująca: configs/orpheu/functions/CBaseEntity.

Przykładowy kod z wykorzystaniem tej funkcji:
#include <amxmodx>
#include <orpheu>
#include <orpheu_stocks>

new g_pGameRules

public plugin_precache()
{
OrpheuRegisterHook(OrpheuGetFunction("InstallGameRules"),"OnInstallGameRules",OrpheuHookPost) // pobieramy uchwyt i rejestrujemy hooka
}
public OnInstallGameRules()
{
g_pGameRules = OrpheuGetReturn() // pobieramy wartość która jest zwracana przez daną funkcję
}


Funkcje wirtualne
Dla tych, którzy nie wiedzą co to są funckje wirtualne - krótkie wyjaśnienie.
Jak zapewne widzicie mamy klase CBaseEntity oraz CAWP. Jak zapewne wiadomo, każda broń jest bytem, ale nie każdy byt jest bronią. Klasa CAWP jest klasą pochodną od klasy CBaseEntity. Ponieważ klasa CBaseEntity posiada funkcje Spawn(id), klasa CAWP również posiada funkcję Spawn(id). I tutaj jest istota działania funkcji wirtualnych. Wystarczy że zrobimy sygnaturę dla CBaseEntity::Spawn i możemy przechwytywać tą funkcję niemal że dla każdego bytu !
Teraz możesz jeszcze nie rozumieć zabardzo tego, jednakże spójrz na ten przykład: chce przechwycić Spawn dla AWP. więc przy użyciu sygnatury dla CBaseEntity::Spawn jest to możliwe. Wystarczy skonkretyzować dla jakiego obiektu ma ta funkcja zostać przechwycona. W naszym przypadku dla CAWP.

Dobra, zajmijmy się tworzeniem sygnatur.
Otwieramy IDA, wybieramy bibliotekę Linuxa i szukamy.
Funkcje wirtualne są zawarte w <nazwa_klasy>::'vtbl'.
Np. CBaseEntity::'vtbl'.
W IDA wygląda to następująco:
Dołączona grafika
Dołączona grafika
Zapewne niektórzy się domyślają, jest to spis funkcji wirtualnych w danej klasie. Tutaj zamiast offsetów mamy id. ID Spawn w Windowsie wynosi 0, a w Linuxie 2. (zawsze +2)
Jeśli chcemy poznać id danej funkcji możemy liczyć, bądź zajrzeć do pliku addons/amxmodx/cofigs/hamdata.ini. W tym pliku mamy dokładnie podane id wszystkich (prawie) funkcji wirtualnych do wszystkich modów opartych na silniku HL. Zarówno na Linuxie jak i Windowsie.

Tutaj sygnatura za mocno się nie zmienia. Jedyna różnica jest taka, że zamiast "indentifiers" mamy "indexes".
Sygnatura funkcji wirtualnej Spawn będzie wyglądać następująco:
{
    "name" : "Spawn",
    "class" : "CBaseEntity",
    "library" : "mod",
    "indexes":
    [
        {
            "os" : "windows",
            "mod" : "cstrike",
            "value" : 0
        },
	{
            "os" : "linux",
            "mod" : "cstrike",
            "value" : 2
	}
    ]
}

Sygnaturę wrzucamy do folderu virtualFunctions zamiast do folderu functions. Reszta jest tak samo.

Kod będzie również wyglądać inaczej. zamiast użycia funkcji OrpheuGetFunction, używamy funkcji OrpheuGetFunctionFromClass. Dlaczego ? Jak już wcześniej powiedziałem, musimy "powiedzieć" kompilatorowi dla jakiej klasy ta funkcja ma zostać wykonana.
#include <amxmodx>
#include <orpheu>
new OrpheuFunction:g_pSpawn;

public plugin_init()
{
register_plugin("Orpheu Tutorial", "1.0.0", "Owner dla AMXX.PL");
g_pSpawn = OrpheuGetFunctionFromClass("weapon_awp", "Spawn", "CBaseEntity"); // pobieramy uchwyt dla funkcji CBaseEntity::Spawn
OrpheuRegisterHook(g_pSpawn, "on_AwpSpawn"); // rejetrujemy hooka
}

public OrpheuHookReturn:on_AwpSpawn(ent)
return OrpheuSupercede; // blokujemy respawn broni


No cóż, to chyba wszystko jeśli chodzi o podstawy. W przyszłości postaram się napisać coś więcej o Orpheu np. zmiana stringów, bądź edycja wybranych bajtów w biblioteki.
Zapraszam do komentowania oraz krytykowania. Każdy post mile widziany ;)
  • +
  • -
  • 12