FANDOM


Na początku zdefiniujmy czym jest broń palna, jak działa i jakie są jej rodzaje. Od razu mówię, że w tym tutorialu omówię tworzenie wyłącznie jednego typu - pistoletu.

Broń palna w świecie roblox to model składający się z: uchwytu, ciała i lufy.

Uchwyt(handle) to część każdej broni w ROBLOX. Będzie to po prostu blok za który nasza postać będzie chwyciła broń.

Ciało to cały model broni.

Lufa zaś jest podłużnym walcem, z którego wylatywały będą kule.

Działanie broni będzie niesamowicie proste; gdy gracz wciśnie LPM - wystrzelona zostanie kula w kierunku, w którym gracz celował. Co każdy strzał tracony zostaje jeden nabój z magazynku. Ilość naboi będą określały trzy zmienne - jedna będzie mówiła o całkowitym zapasie amunicji, druga o pojemności magazynku, a trzecia o ilości nabojów w tymże magazynku.

Wyróżniamy głównie 4 typy broni palnej:

Pistolety - mają słabą moc i duży rozrzut, każdy strzał wymaga oddzielnego wciśnięcia LPM;

Strzelby - to samo, co pistolety z tą różnicą, że ich moc jest większa, a rozrzut mniejszy;

Pistolety maszynowe - mają słabą moc i duży odrzut, ale wystrzały zachodzą nawet jeśli trzymany jest LPM;

Karabiny maszynowe - tak jak pm z tym, że ich moc jest większa, a odrzut mniejszy od pm.

W tym poradniku użyję pluginu Talon Hand Welding.

Model Edytuj

Jak wyżej wspomniałem, model będzie składał się z trzech części. Najpierw stwórzmy ciało. Zróbmy je w dużej skali. Ważne jest to, że musisz być w trybie Edit:
Bron1
Teraz zaznacz wszystkie klocki ciała i połącz je w unię(naciśnij na zaznaczonych obiektach PPM i wybierz Union), po czym skaluj unię do właściwych rozmiarów:
Bron2

Teraz tylko musisz odznaczyć(o ile są zaznaczone) parametry unii Anchored i CanCollide. Nazwij powstałą unię(ja nazwę ją Body)

W dokładnie taki sam sposób zrób "rączkę" i umieść ją tak, by była złączona z ciałem. Powstałą unię nazwij(TO WAŻNE) "Handle" i odznacz anchored i ZAZNACZ CanCollide:
Bron3
Teraz trzeba utworzyć trzecią część - lufę. Utwórz więc nowy klocek i dodaj do niego CylinderMesh. Umieśćmy lufę w broni, ustawmy CanCollide i Anchored na fałsz i nazwijmy lufę "Barrel":
Bron4

A teraz utwórz obiekt Tool i umieść w nim wszystkie trzy obiekty. Następnie zaznacz je(trzy obiekty) i za pomocą pluginu Talon Hand Welding wybierz z menu na górze Plugins>Handle Weld>Select some bricks with one named "Handle" and all the bricks will be welded to the Handle. A weld profile will be created and a script to re-weld the bricks for use in tools.

To pozwala na to, by klocki trzymały się spójnie i nie odpadały.

Ostatnie rzeczą którą teraz trzeba zrobić, jest ustawienie grip'u, czyli orientacji broni. Ustawić grip możesz za pomocą pól obiektu Tool. Ustawienia grip są trochę skomplikowane, więc ustaw go metodą prób i błędów w Solo Mode(a gdy już ustawisz broń, skopiuj ją i wklej w Edit Mode):
Bron5

U mnie wystarczyło zmienić GripForward na (-0.999, 0, 0.1).

Oprócz klocków w naszej broni będziemy potrzebowali też kilka wartości opisujących jej stan i cechy.

Stwórzmy dwie wartości typu int(obiekt IntValue) o nazwach "Ammo" i "StockAmmo" oraz dwie wartości typu number(obiekt NumberValue) o nazwach "Accuracy" i "Power"

Ammo to liczba pocisków w magazynku, StockAmmo to liczba pocisków w zapasie, Accuracy to celność, a Power to siła pocisku.

Skrypt Edytuj

Przejdźmy do najważniejszej części tutoriala - skryptu.

Utwórzmy obiekt LocalScript w obiekcie Tool. Obiekty LocalScript w odróżnieniu od obiektów typu Script pozwalają na uzyskanie dostępu do obiektów nie przetrzymywanych na serwerze, lub mających powiązanie z graczem. Dzięki temu uzyskamy dostęp do obiektu gracza.

Zacznijmy więc od inicjalizacji zmiennych na obiekty, które nam się w dalszej fazie przydadzą:

gun 
= script.Parent;
barrel 
= script.Parent:FindFirstChild("Barrel");
player 
= game.Players.LocalPlayer;--Dostep do gracza
accuracy 
= script.Parent:FindFirstChild("Accuracy");
power 
= script.Parent:FindFirstChild("Power");
ammo 
= script.Parent:FindFirstChild("Ammo");
stock 
= script.Parent:FindFirstChild("StockAmmo");
reloading 
= false--czy bron jest w tym momencie przeladowywana

A teraz napiszmy funkcję, która zostanie wywołana w razie przeładowania. Nazwijmy ją reload()

Na początku zmieńmy wartość reloadink na prawdę i wykonajmy funkcję czekającą(powiedzmy 2.5 sekundy):

function reload()
    reloading 
= true;
    wait(2.5);
end

Gdy magazynek będzie pełen, nie dojdzie do żadnej zmiany. W przeciwnym przypadku różnica między rozmiarem magazynku(w naszym przypadku 7), a ilością naboi zostanie dodana do magazynku i odjęta od zapasów, a w razie gdy liczba pocisków w zapasie będzie mniejsza od ww. różnicy, do magazynku zostanie dodana pozostała w zapasach liczba naboi. Może nie wygląda to do końca zrozumiale, ale mam nadzieję, że po dłuższym zapoznaniu się z przykładem wszystko zrozumiesz. Zapiszmy to dalej w funkcji reloading:

 --tu mozesz odtworzyc dzwiek przeladowanie(opcjonalne)
    if stock.Value >= 7 - ammo.Value then--jezeli w pociskow zapasie jest wiecej lub tyle samo ile brakuje do pelnego magazynka
        stock.Value 
= stock.Value - (7 - ammo.Value);--od zapasow odejmowana jest liczba potrzebnych do zapelnienia magazynku pociskow
        ammo.Value 
= 7;--magazynek jest uzupelniany do pelna
    else--jezeli liczba pociskow w zapasie nie wystarcza do calkowitego zapelnienia
        ammo.Value 
= stock.Value + ammo.Value;--dodana do magazynku zostaje reszta pociskow w zapasie
        stock.Value 
= 0;--oproznienie zapasow
    end

I na końcu poinformujmy skrypt, że przeładowywanie zostało zakończone:

reloading 
= false;

Ufff... to mogło być ciężkie do przełknięcia. Teraz jednak zajmiemy się funkcją, która zostanie wywołana, gdy gracz będzie chciał oddać strzał. Funkcję tę nazwę shoot(). Funkcja ta przyjmie argument cfhit, który pozwoli na określenie miejsca i rotacji naciśniecia LPM.

Oczywiście aby doszło do tego strzału, liczba pocisków w magazynku musi być większa od zera, a broń nie może być w tym samym momencie przeładowywana. Po oddaniu strzału od liczby pocisków w magazynku zostanie odjęte 1(chyba wiadomo czemu):

function shoot(cfhit)
    if not reloading and ammo.Value > 0 then--jezeli magazynek nie jest pusty, a bron nie jest przeladowywana,
        ammo.Value 
= ammo.Value - 1;
        
    end
end

Teraz zajmijmy się utworzeniem pocisku. Będzie to zwykły klocek z SpecialMesh pozwalającym na zmianę jego rozmiaru i kształtu na kulę:

local bullet 
= Instance.new("Part", game.Workspace);--tworzymy pocisk
local bulletShape 
= Instance.new("SpecialMesh", bullet);--i ksztalt pocisku
bullet.BrickColor 
= BrickColor.new("Really black");--nadajemy mu kolor
bullet.FormFactor 
= Enum.FormFactor.Custom;--i zmienamy budowe tak, bo mozna go bylo maksymalnie zmniejszyc
bullet.Size 
= Vector3.new(0.2, 0.2, 0.2);--i zmniejszamy go
bullet.Material 
= Enum.Material.Metal;--nadajemy mu metalowy material
bulletShape.MeshType 
= Enum.MeshType.Sphere;--ksztalt kuli
bulletShape.Scale 
= Vector3.new(0.7, 0.7, 0.7);--i jeszcze raz go zmniejszamy

Po tym zajmijmy się jedną z najważniejszych rzeczy - pędem pocisku. Umieśćmy pocisk w koordynatach lufy.

bullet.Position 
= barrel.Position;
bullet.CFrame 
= CFrame.new(bullet.CFrame.p, cfhit.p);

W drugiej linijce powyższego kodu znajduje się konstruktor CFrame, który działa tak, że na podstawie dwóch pozycji tworzy CFrame wraz z kątem między tymi dwoma pozycjami. Pocisk zostaje obrócony w stronę miejsca, gdzie dotyka kursor myszy.

Zanim przejdziemy bezpośrednio do siły, zajmijmy się rozrzutem, czyli losowością kierunku wystrzelonych pocisków. Utwórzymy trzy losowe zmienne zmiennoprzecinkowe wahające się między liczbą określającą celność i jej przeciwnością:

local dispX 
= math.random(-accuracy.Value, accuracy.Value);
local dispY 
= math.random(-accuracy.Value, accuracy.Value);
local dispZ 
= math.random(-accuracy.Value, accuracy.Value);

Będą one odpowiadały za rozrzut względem danej osi.

Teraz przejdźmy do samej siły. Na samym początku musimy ją utworzyć i "wrzucić" do naszego pocisku:

local force 
= Instance.new("BodyForce", bullet);

Po tym określmy kierunek tej siły. Jest on wyrażony w postaci Vector3, który można mnożyć przez zwykłe, jednowymiarowe wartości "skalując" go. Naszym kierunkiem siły będzie kierunkiem w który kula się "patrzy". Vector ten pomnożymy przez jakiś literał liczbowy(u mnie 20) i przez siłę broni:

force.force 
= bullet.CFrame.lookVector 
* 20 
* power.Value;

Następnie zmodyfikujmy wektor siły w taki sposób, by dodać do niego wartości rozrzutu:

force.force 
= Vector3.new(force.force.x + dispX, force.force.y + dispY, force.force.z + dispZ);

Teraz nasz pocisk może lecieć, ale póki co nie wyrządzi nikomu najmniejszej krzywdy.

Utwórzmy więc zdarzenie, które sprawdzi, czy kula dotknęła jakiegoś kolcka. Zdarzenie to powinieneś znać z poradnika dotyczącego tworzenia drzwi dla VIP'ów :

bullet.Touched:connect(function(brick)
            
end)

Na początku sprawdźmy, czy klocek jest postacią. W takim wypadku jego rodzic zawiera obiekt Humanoid:

local human 
= brick.Parent:FindFirstChild("Humanoid");
if human ~= nil then
                    
end

Teraz w zależności od miejsca trafienia odejmujemy odpowiednią ilość HP pomnożoną przez siłę broni. Miejsce trafienia to jest zawarte w nazwie trafionego klocka. Oto przykład:

if brick.Name 
== "Torso" then
    human.Health 
= human.Health - 35 
* power.Value;
elseif brick.Name 
== "Head" then
    human.Health 
= human.Health - 60 
* power.Value;
elseif brick.Name 
== "Left Arm" or brick.Name 
== "Right Arm" then
    human.Health 
= human.Health - 20 
* power.Value;
elseif brick.Name 
== "Left Leg" or brick.Name 
== "Right Leg" then
    human.Health 
= human.Health - 10 
* power.Value;
end


Teraz wystarczy wywołać napisane funkcje dla odpowiednich zdarzeń:

Sprawdźmy najpierw, czy postać nosi naszą splówę poprzez event Equipped: Event ten zwraca obiekt myszy:

gun.Equipped:connect(function(mouse)
    
end)

Następnie nasz skrypt powinien sprawdzić, czy gracz wcisnął klawisz, a następnie sprawdzić, czy ten klawisz to r. Jeżeli tak, to wykonana zostanie funkcja reload():

mouse.KeyDown:connect(function(key)
    if key 
== "r" then
        reload();
    end
end)

Sprawdźmy jeszcze, czy gracz wcisnął LPM. Jeżeli tak, to wykonana zostanie funkcja shoot(), do której argumentu "wsadzimy" parametr Hit obiektu myszy, czyli CFrame mówiący o pozycji myszy na obszarze 3D:

mouse.Button1Down:connect(function()
    shoot(mouse.Hit);
end)

Cały skryptEdytuj

gun

= script.Parent;

barrel

= script.Parent:FindFirstChild("Barrel");

player

= game.Players.LocalPlayer;--Dostep do gracza

accuracy

= script.Parent:FindFirstChild("Accuracy");

power

= script.Parent:FindFirstChild("Power");

ammo

= script.Parent:FindFirstChild("Ammo");

stock

= script.Parent:FindFirstChild("StockAmmo");

reloading

= false--czy bron jest w tym momencie przeladowywana

function reload()

reloading

if stock.Value >= 7 - ammo.Value then--jezeli w pociskow zapasie jest wiecej lub tyle samo ile brakuje do pelnego magazynka

stock.Value

= stock.Value - (7 - ammo.Value);--od zapasow odejmowana jest liczba potrzebnych do zapelnienia magazynku pociskow

ammo.Value

= 7;--magazynek jest uzupelniany do pelna

else--jezeli liczba pociskow w zapasie nie wystarcza do calkowitego zapelnienia

ammo.Value

= stock.Value + ammo.Value;--dodana do magazynku zostaje reszta pociskow w zapasie

stock.Value

= 0;--oproznienie zapasow

reloading

= false;

end

= true;

wait(2.5);

end

function shoot(cfhit)

if not reloading and ammo.Value > 0 then--jezeli magazynek nie jest pusty, a bron nie jest przeladowywana,

ammo.Value

= ammo.Value - 1;

local bullet

= Instance.new("Part", game.Workspace);--tworzymy pocisk

local bulletShape

= Instance.new("SpecialMesh", bullet);--i ksztalt pocisku

bullet.BrickColor

= BrickColor.new("Really black");--nadajemy mu kolor

bullet.FormFactor

= Enum.FormFactor.Custom;--i zmienamy budowe tak, bo mozna go bylo maksymalnie zmniejszyc

bullet.Size

= Vector3.new(0.2, 0.2, 0.2);--i zmniejszamy go

bullet.Material

= Enum.Material.Metal;--nadajemy mu metalowy material

bulletShape.MeshType

= Enum.MeshType.Sphere;--ksztalt kuli

bulletShape.Scale

= Vector3.new(0.7, 0.7, 0.7);--i jeszcze raz go zmniejszamy

bullet.Position

= barrel.Position;

bullet.CFrame

= CFrame.new(bullet.CFrame.p, cfhit.p);

local dispX

= math.random(-accuracy.Value, accuracy.Value);

local dispY

= math.random(-accuracy.Value, accuracy.Value);

local dispZ

= math.random(-accuracy.Value, accuracy.Value);

local force

= Instance.new("BodyForce", bullet);

force.force

= bullet.CFrame.lookVector

* 20

* power.Value;

force.force

= Vector3.new(force.force.x + dispX, force.force.y + dispY, force.force.z + dispZ);

bullet.Touched:connect(function(brick)

end)

if brick.Name

== "Torso" then

human.Health

= human.Health - 35

* power.Value;

elseif brick.Name

== "Head" then

human.Health

= human.Health - 60

* power.Value;

elseif brick.Name

== "Left Arm" or brick.Name

== "Right Arm" then

human.Health

= human.Health - 20

* power.Value;

elseif brick.Name

== "Left Leg" or brick.Name

== "Right Leg" then

human.Health

= human.Health - 10

* power.Value;

end

gun.Equipped:connect(function(mouse)

end)

mouse.KeyDown:connect(function(key)

if key

== "r" then

reload();

end

end)

mouse.Button1Down:connect(function()

shoot(mouse.Hit);

end)


end

end

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.

Więcej z Fandomu

Losowa wiki