Wednesday, June 10, 2009

Tutorial: How do i make my own weapon

Introduction to Weapons

This tutorial explains to you the structure of weapons on ROBLOX and why they work.
How Tools Work
Introduction

This section is a short description of how Tools work in the current version of Roblox. This may be handy to anyone who wants to write their own tools and doesn't care that any such tool may be short-lived due to the rapid development that is occurring in this area.
Client vs. Server

In a multi-player game, scripts can run in two places: on the client, or on the server. This is not a detail that can be ignored. Making a working tool requires orchestration of both client and server side scripts.
Where Scripts Run

There are now two kinds of scripts in Roblox: Scripts (the regular old kind) and LocalScripts.

- On the Server -

* Scripts run in the Workspace and in all Player Backpacks.
* LocalScripts don't run anywhere except in Backpacks.

- On the Client -

* Scripts run in HopperBins in the local player's Backpack (If I am playing, only the scripts in my backpack run on my machine, I don't run other scripts in other players' packs). We do this only to support legacy weapon scripts. This method of making weapons is deprecated and support may be withdrawn at any time. If you are making new weapons, do not use HopperBins. Regular Script objects don't run anywhere else on the client.

* LocalScripts run only in the local player's backpack and character model.

Solo Games

In any single player mode (solo visit or edit), the client and server are the same machine. As a rule of thumb, if your tool works in multi-player, it will work in solo mode. The converse is not always true.


Weapon Structure

The structure of a weapon looks something like this.

[Tool Name]
|-Sounds
|-Weapon Script
|-Projectile Script
|-Local Gui
|-Handle
| |-Mesh

Tool

The tool is the big thing at the top. It goes into people's backpacks and shows up in their screen. Tools have scripts, parts, and meshes that direct what the tool does. The only thing you really need to change in the tool is the name and the GripPos if you're trying to change how the player grips the weapon, or if your going to be fancy you can edit the weopon icon too using this part
Handle

The handle is the part that contains the mesh. Meshes can't be put into the game except under a part that defines its general shape (called the bounding box). The handle is the part that has a mesh in it that shows what the weapon looks like. Each weapon has its own mesh that it uses. Usually, if you want to make a new weapon, you should copy another existing weapon and change the script only so that you don't have to copy the mesh URLs and GripPos on the tool over. You can change the kind of mesh the mesh is by going under it's properties and changing the kind.
Weapon Script

The weapon script is usually called something related to the weapon name, such as "Server Launcher" for the Rocket Launcher and "Slingshot" for the slingshot. It dictates what the weapon does when its fired.
Projectile Script

The projectile script is attached to the projectile and handles what the projectile does when it flies out of the weapon. Usually it just handles what happens when it hits something.
Local Gui

The Local Gui is a LocalScript that deals with cursors on the client. It changes the cursor to a target when you switch to a weapon and adds the "reloading" text onto the cursor after firing. Usually there is nothing that needs to be changed in this script except for the reload time.
Sounds

You can't add sounds to your weapon, but you can take sounds from the other weapons.
How does the weapon work?

Here's a step by step process of what happens when you select and use the rocket launcher. The rocket launcher tree looks like this:

[LinkedRocketLauncher]
|-Explosion - Sound
|-Swoosh - Sound
|-RocketScript - Projectile Script
|-Server Launcher - Weapon Script
|-Local Gui
|-Handle
| |-Mesh

Client Script
Select the rocket from your weapons. Local Gui:

Tool.Equipped:connect(onEquippedLocal)

This adds a listener that changes the cursor to a target cursor. The listener waits for "Equipped" and then goes to the "onEquippedLocal" function.

mouse.Icon = "rbxasset://textures\\GunCursor.png"

The function changes the mouse icon.
Click on a target. Local Gui:

The onButton1Down function has a Debounce system that keeps it from repeatedly activating.

mouse.Icon = "rbxasset://textures\\GunWaitCursor.png"
wait(12)
mouse.Icon = "rbxasset://textures\\GunCursor.png"

Changes the cursor to "reloading," waits until the weapon is done reloading (12 seconds) and then changes the cursor back to the regular one.

Server Launcher:
The script at the top makes the rocket but it doesn't fire it yet.

script.Parent.Activated:connect(onActivated)

This causes "onActivated" to run when the script.Parent, or the Rocket Launcher, is run. onActivated uses Debounce as well.

local targetPos = humanoid.TargetPoint
fire(targetPos)

This gets what the target is and then calls the fire function that will actually shoot the rocket. I won't go into what the fire function actually does, but the key things are:

local missile = Rocket:clone()
missile.RocketScript.Disabled = false
missile.Parent = game.Workspace

This makes a new missile from the Rocket at the top, activates its script (the projectile script) and puts it into the game.
Rocket flies out and makes a whooshing noise. RocketScript:

swoosh:play()

This will play the sound that the rocket makes.

fly()

This causes the rocket to keep flying forward without falling due to gravity.
RocketScript:

Rocket hits target, explodes, and blows up a person.


connection = shaft.Touched:connect(blow)

This causes the rocket to blow up when it touches something by calling the blow function.

explosion = Instance.new("Explosion")
explosion.Position = shaft.Position
explosion.Parent = game.Workspace

This makes the explosion.
How do I make my own weapons?

Weapons are available in most Roblox maps. They can be either copied, or created. The easiest way to make weapons is to modify a previously made BrickBattle weapon. This tutorial will explain how to create your very own weapons.
Scripting
Creating a Projectile

When the weapon is selected, the HopperBin object activates the "Selected" event. To check when the weapon is selected (change cursor, etc.), use this code: script.Parent.Selected:connect(Function)

When the mouse is clicked, the mouse activates the "Button1Down" event.To check for clicks, use this code: mouse.Button1Down:connect(Function)

While some weapons are propelled in the direction of the mouse, such as the Superball, others are created at the mouse, walls, for example, or are sent to the point clicked on, such as Rocket. The position clicked on is a CFrame, accessed by mouse.Hit
Damage

To do damage, the weapon must decrease the "Health","armor" variable of any Humanoid or Monsteroid objects it touches/attacks; It can also create an explosion.

If the weapon does damage, then the human needs to be "skill" so kills can be recorded. To do this, two functions are available. They are tagHumanoid and unTagHumandoid


function tagHumanoid(humanoid)
-- todo: make tag expire
local tag = script.Parent:findFirstChild("creator") -- Where "creator" is an [[RBX.lua.ObjectValue|ObjectValue]] placed in the script's parent. Its value is set to "game.Players.LocalPlayer" by the script that makes it.
if tag ~= nil then
local new_tag = tag:clone()
new_tag.Parent = humanoid=monsteroid
end
end

Before un-tagging the humanoid, the game must be given a chance to record the kill. To do this, a wait of two seconds is reasonable.


function untagHumanoid(humanoid)
if humanoid ~= nil then
local tag = humanoid:findFirst("creator")
if tag ~= nil then
tag.Parent = nil
end
end
end

WeldScript

Weapons can also have more than one piece on them. You have to write a script to keep the pieces together. Here are the instructions for making a weld script for weapons with more than one piece.

local w1 = Instance.new("Weld")

w1.Parent = script.Parent.Handle
w1.Part0 = w1.Parent
w1.Part1 = script.Parent.Handle2
w1.C1 = CFrame.new(X, Y, Z)

But in some cases you may want to have your brick at a certain angle. To do this you must input on the last line.

w1.C1 = CFrame.fromEulerAnglesXYZ(X, Y, Z) * CFrame.new(X, Y, Z)

And after that you must put w2, w3, w4, w5, etc. You must also put Handle and Handle2, Handle3, etc.
Style
Weapon Icons
An example of an icon.
An example of an icon.

Weapons can be given icons. These are shown in the weapon selection bar. If no icon is selected, the name of the HopperBin object is displayed.
Cursors

Weapons often have a specific type of cursor. The cursor is an important stylistic choice. The creator of a weapon can choose a cursor to finish to style of the weapon. To change the cursor, the creator must change the mouse.Icon property. mouse.Icon = "Texture Path"

The list of official cursor texture paths:

* The arrow: Ready: rbxasset://textures\\ArrowCursor.png Reloading wait: rbxasset://textures\\ArrowFarCursor.png
* The target recticle: Ready: rbxasset://textures\\GunCursor.png Reloading wait: rbxasset://textures\\GunWaitCursor.png

Making Multi Handles
Building

First, make your weapon. Make it however you want it to look like after you have made it. Make sure that the part that you'll hold is named "Handle", and everything else a different name other than Handle. You can add a SpecialMesh to it as well, to make it look better. What type of mesh you use doesn't matter. Later on, you'll need to fine-tune the weapon. When you just start out, the weapon may look very strange.
Basic Script

The script consists of mainly the Weld Script which some how got into Free Models, and an onEquipped function. A Weld is the thing that keeps your tool together. (The parts don't necessarily need to be touching each other in order to be welded.)

This is your basic Weld.


local w1 = Instance.new("Weld")
w1.Parent = script.Parent.Handle -- The main Handle.
w1.Part0 = w1.Parent
w1.Part1 = script.Parent.PARTNAME -- Change this to your second part's name.
w1.C1 = CFrame.fromEulerAnglesXYZ(0, 0, 0) * CFrame.new(0, 0, 0)

You can add more welds to it, too. Just make sure you change the name of the Local Weld first. (Instead of w1, change it to w2 or so on.)

For a second weld, do this:

local w1 = Instance.new("Weld")
w1.Parent = script.Parent.Handle -- This is the original Handle.
w1.Part0 = w1.Parent
w1.Part1 = script.Parent.PARTNAME1 -- Change PARTNAME to your second part's name.
w1.C1 = CFrame.fromEulerAnglesXYZ(0, 0, 0) * CFrame.new(0, 0, 0)

local w2 = Instance.new("Weld")
w2.Parent = script.Parent.Handle
w2.Part0 = w1.Parent
w2.Part1 = script.Parent.PARTNAME2 -- Change to the third part's name.
w2.C1 = CFrame.fromEulerAnglesXYZ(0, 0, 0) * CFrame.new(0, 0, 0)

And so on. Just change PARTNAME to your second tool part's name.
Editing the script

Here's where the time and work actually have to be put in. You'll need to fine-tune the angles. Maybe even down to the decimals.

You will need to change the X,Y,Z axis' to change how the tool looks. If you need help finding out which one moves which one, use Anaminus' Rotate Tool. Just press the corresponding key to move the axis. Click a brick to apply it.

The basic script above makes the weapon have multiple parts, but it won't work. It needs to know when to apply it. So, add:

function onEquipped()
end
script.Parent.Equipped:connect(onEquipped)

So now our script looks like this.

function onEquipped()
local w1 = Instance.new("Weld")
w1.Parent = script.Parent.Handle -- This is the original Handle.
w1.Part0 = w1.Parent
w1.Part1 = script.Parent.PARTNAME -- Change PARTNAME to your second part's name.
w1.C1 = CFrame.fromEulerAnglesXYZ(0, 0, 0) * CFrame.new(0, 0, 0)

local w2 = Instance.new("Weld")
w2.Parent = script.Parent.Handle
w2.Part0 = w1.Parent
w2.Part1 = script.Parent.PARTNAME -- Change to the third part's name.
w2.C1 = CFrame.fromEulerAnglesXYZ(0, 0, 0) * CFrame.new(0, 0, 0)
end
script.Parent.Equipped:connect(onEquipped)

In order to drop it and allow it to stay together, add:


function onUneqipped()
end
script.Parent.Unequipped:connect(onUnequipped)

Line in. Now it makes it droppable. Put the weld script between it so it makes the weld(s) again AFTER it gets dropped.

So now the script looks like this:

function Weldnow()
local w1 = Instance.new("Weld")
w1.Parent = script.Parent.Handle -- This is the original Handle.
w1.Part0 = w1.Parent
w1.Part1 = script.Parent.PARTNAME -- Change PARTNAME to your second part's name.
w1.C1 = CFrame.fromEulerAnglesXYZ(0, 0, 0) * CFrame.new(0, 0, 0)

local w2 = Instance.new("Weld")
w2.Parent = script.Parent.Handle
w2.Part0 = w1.Parent
w2.Part1 = script.Parent.PARTNAME -- Change this to the third part's name.
w2.C1 = CFrame.fromEulerAnglesXYZ(0, 0, 0) * CFrame.new(0, 0, 0)
end
script.Parent.Equipped:connect(Weldnow)
script.Parent.Unequipped:connect(Weldnow)

Change the script to make the tool look like what you imagined it. What can get frustrating is the fact that the X,Y,Z factors can go into the negatives, giving you even more variables! If you do everything correctly, your weapon will look very nice.
Diagram

Here's a diagram of what your basic sword tool should look like.

[-]Tool
...Handle
...Part
...Part
...Weld Script
...SwordScript
...LocalGUI

Here's what your basic gun should look like.

[-]Tool
...Handle
...Part
...Part
...Weld Script
...GunScript
...ProjectileScript
...LocalGUI


Remember to make new welds for each and every part! If not, your tool will not work.
See Also

HopperBins

Radians
How do I make weapon buttons?
Inserting the Script

1. Open your place with Roblox Studio, select My Roblox, and select Edit.
2. Select Insert in the game window, and click any brick of your choice. A brick will appear in your map. (This brick will be your new weapon giver brick.)
3. Select that brick.
4. Select Insert in the toolbar near the top of the screen.
5. Select Object.
6. Select Script from the window that pops up.
7. Press OK.
8. The new script should now have appeared in the Explorer on the right underneath your weapon giver brick. Double-click the script, and a new window should open with nothing but

print ("Hello World!")

Paste the script which is at the bottom of this article there.

9. All you have to do now is change "WeaponNameHere" at the middle line of the script to the name of your weapon. Remember, you must keep it in quotes, and spelling counts! If you have not already placed your weapon in Lighting, continue reading to find out how; if you have already done that, then you're done!
Putting a Weapon Into Lighting

In order for this button to function properly, the weapon you want to give to players must be in the game's Lighting Directory.


1. Find a weapon that you want to be given to players. These can be found by selecting the Insert button from the game window, and then either going to Tools, or going to Free Models/My Models and searching for one. Once you find the weapon you want, click it, and when asked if you want to put it in the Starterpack, select Yes (don't worry, it won't be staying there).


2. Once your weapon is in the Starterpack, or if it's in the Workspace, find it in the Explorer tab on the right. From there, hold-click and drag the weapon to the Lighting Directory, which is also in the Explorer tab (represented by the lightbulb).


3. If you have already placed the script below into a brick, then you're done! Your button should be ready to hand out weapons!
The Script

function onTouched(part)
p = game.Players:playerFromCharacter(part.Parent)
if p == nil then return end
gun = game.Lighting.WEAPONNAMEHERE:clone() --Change WEAPONNAMEHERE to the name of the weapon
if p.Backpack:findFirstChild(gun.Name) ~= nil then return end
gun.Parent = p.Backpack
end

script.Parent.Touched:connect(onTouched)


An example of what the changed line would look like for, e.g., a rocket launcher would be:

gun = game.Lighting.LinkedRocketLauncher:clone()

Troubleshooting

The name of the weapon might not be spelled correctly in the script.
The weapon might not be in the Lighting directory.
How to edit a weapon mesh
What you'll need

A weapon with a SpecialMesh object in it (often named "Mesh").
Making it bigger or smaller and also wider

1. To begin, let's get a sword out: (Insert... Tools... Sword).

2. When asked, drop the sword into the 3d view by selecting "No". You will Edit the sword first, then you can move the sword into the StarterPack later.

2. Next, we go to the Explorer then into Workspace, find the sword, go into it, into the Handle object, then to its Mesh object.

3. You have to make it the size you want it to be by editing its scale. You can either click the + to open up the X, Y, Z or put the numbers between the commas after "Scale".

Here's a chart of what each axis is.

X = Horizontal, or left and right. Y = Vertical, or up and down. Z = Depth, or diagonal.
Changing the color

Changing the color is actualy quite simple.

1. Look under the weapon's handle, then its mesh.

2. Look into the "Properties" section, and look for the mesh's TextureID.

3. Select the TextureID, and delete it.

4. Change the HANDLE's brick color, or transparency, or even reflectance. This changes the entire weapon's color.

Now you have a weapon with a more exciting color other than the original color(s).

You can also change the vertex color of the mesh and that way keep the texture but have a different color. Keep in mind that the first number means blue, second means green and third means red. Having all of them the same will mean that you are having the basic colors.