Professional Documents
Culture Documents
Introduction
vbGOREmania is based on vbGORE, a powerful, open source, and free online RPG engine. With this
engine you can create an impressive 2D MMORPG (Massively Multiplayer Online Role-Playing
Game)! It is simply a collection of add-ons, tweaks, upgrades, and more made by me (GOREmania)
and others of the vbGORE community. vbGORE is not my creation, and this is not the official
vbGORE website nor is it a replacement. This Guide is a compilation of the vbGORE wiki and
vbGOREmania features.
Help Topics
Map Editor
This is the main window for the map editor. One of the most important things to point out is the tool
icon bar, shown below:
Display Buttons
The following buttons can turn on or off certain layers and objects to be displayed.
Hide/Show Weather
File Buttons
Optimize: Cleans up the map to speed it up and reduce size
Search Bar
The Search Bar is found on the bottom of the map editor screen. The search bar cannot be moved or
altered. It is used to help you search for a tile you need:
Grh Index
- This will search through all the tiles in the grh index to find one with a number that matches
your search.
File Number
- This will search through the file numbers to find the tile that you are looking for.
Description
- This will give you a description of what you are searching for.
If you do a search for 49 and select Grh Index, then click search, something like this will display:
It is texture 9, but if you click on the 4th one over, you can see the grh number is 49.
By clicking the view sheet button located on the bottom of the map editor screen and to the right of the
search bar will bring up the following screen:
Start Number
This number represents the number of the tile you wish to start with from the list of tiles, this will
be very helpful if you have thousands of tiles. For example, if you would like to start with tile
number 673, you can type that into the start number line, and the list of tiles will be from 673 to
all the tiles after that.
Preview Size
Setting the width/height allows you to define how wide/tall you want to have the tile preview
drawn. This is useful so that you can tell which of your tiles are 32x32 and which are
bigger(whole trees and things).
Show Options
These check boxes allow you to pick and choose which tiles you would like to look at among the
large list of tiles. If you check only outside objects and click save changes it will show you just
the tiles used for outside. You can also use the start number to narrow the tiles down a bit more
too. If you were to put the start number at 673, and click the outside object box only, it will show
tiles for the outside starting from tile number 673.
By clicking the “Select From PNG” button located on the bottom of the map editor screen and to the
right of the search bar will bring up the following screen:
Set Tiles
The 'Set tiles' button is the sixth button from the left
Click this to bring up the Set Tiles window, as shown below:
2 – Hide/Show Layers
Number 2 is pointing to checkboxes beneath the Layer Section. When a checkbox is checked,
the associated layer will be rendered (shown) on the map editor, else it is hidden. This is useful if
you want to see something that is hidden by the layer above.
5 - Light Values
This is set up to where you can change the light for each of the corners. Number 5 points to the
four values to change. Be warned though, if the light check box is not checked your tile will be
drawn without the custom light value. These values are ARGB (Alpha Red Green Blue) values.
Alpha is the transparency of the light, where 255 is opaque and 0 is invisible. To get this value,
either click the ARGB <-> Long Tool button on the bottom of the map editor, or use the
ToolColorCon program that comes with vbGORE.
6 - Shadows
Number 6 is the check box for shadows and a value you need to set(Probably done this way so
you do not need to replace the tile if you want to just turn off the shadow). Set the value to 1 to
set the shadow and 0 to allow you to take it off.
It is also good to note that when you are setting Grhs on a map, the tile your mouse hovers over will be
highlighted. This will help you know what you are actually selecting.
Blocked Tiles
This window is simple in that you use it to set whether the tile is blocked for moving/ranged attacks or
not.
Checking the "Set walk" Checkbox allows you to make tiles blocked or not. Choose the direction or
directions that you wish the player to not be able to move(center check box for all directions) and then
start clicking where you want blocked.
Checking the "Set Attack" Checkbox allows you to make tiles block attacks or not. Once checked, a
new "No Attack" checkbox appears on the bottom right of the window. Checking this makes which tile
you click block attacks.
You may use movement/attack block set both at once.
Also, you may check the “Reflective” checkbox to make the selected tile reflective. When the player
stands on such a tile, their reflection appears just below them.
Map Floods
This button is used to flood the map with certain things. It combos with the first button and others to
allow you to flood a single layer or more using whatever tile/light/etc. settings you choose.
Map
If you choose a grh and click map, it will flood the entire map with the grh.
Screen
If you choose a Grh and click screen, it will flood just the area where your screen was.
When you click one of these options it will bring up a box that asks you if you are sure that you want to
flood the map. It will show you what options you have selected. These options are set from the other
windows. Note that this uses the same actions as the normal tile set, which means the other windows
must be opened to be used.
Tile Information
The next button is the tile info button. Clicking this button will bring up the following window:
This window shows info on tiles. Right click a tile to see the information displayed here. Easy changes
can by typed into the fields if desired. Currently, the only way to set mailbox/sign flags is through this
window - just enter a 1 into the mailbox/sign field to place the mailbox/sign, and a 0 to remove it. For
convenience, the button next to Signs will open a window with a list of all signs and their descriptions.
For example:
This next button is the exits button. Clicking this button will bring up the following window:
This button allows you to setup an exit by using the following fields:
Map
This is the number of the map that the exit leads to. It can be either the same map, or another one.
X/Y
This is the coordinate of where the exit leads to.
NPC Window
Next button is the NPCs button . Clicking this button will bring up the following window:
This shows all npc's you have for your game. Just choose either to place/erase from the tiles(s) you
later select.
NOTE
It is good to note now that you should uncheck or close the “Set Tile” window when setting NPCs, and
vice versa, so that you are not both setting tiles and NPCs.
Next is the Particles button, Clicking this button will bring up the following window:
Gfx
Is the texture used for the particle. In the \Grh\ folder, the files with the prefix p stand for a
particle texture. For example, 10 will use p10.png, the skulls, and p3 will use p3.png, the ankh.
X and Y
Are the absolute pixel positions of the effect. The values defined in here are the amount of pixels
away from the top-left corner of the map. You can see this value when moving your cursor over
the screen in the map editor.
Particles
States how many particles are used. The amount you want to use depends greatly on the particle
effect - how dense you want it, what kind of graphic it is using, how large of an area it covers,
etc. Try to keep the number under 1000, though, or you may notice a bit of hit to performance.
Dir
Or Direction, is an optional parameter. Some effects use a Direction value to state which way
they are animating, such as the fire. Whether this is used or not depends completely on how the
effect is written. It is easiest to see if this is used by a certain effect by if it is used in the
Effect_Begin sub in the Effects module. The value is always saved, but not always used.
Sound Effects
Next is the Sound Effects button, Clicking this button will bring up the following window:
Each sound effect is setup with a number. Just type it in and click the tile you want it to be on.
Map Information
Next is the Map Info button. Clicking this button will bring up the following window:
Is Property
This is used for player housing/property. It just means that the player can buy this map as a
property. You have to have at least one NPC on this map with the Servant AI if you set the map as a
Property. More info will be provided later for how to setup player housing.
Walkthrough Players/NPCs
These options let players and NPCs walk through each other. It is good to have this option
selected on maps where there may be a lot of people. Though, making it so players can't pass through
each other or through NPCs is good if you want to make escape from battle hard!
Particle Editor
This editor will let you create awesome new particle effects for your game. This aspect of the game
design can be a challenge, but this editor helps make it easier. First thing to note are the Inputs:
First off add a new constant for your Effect at the top of Particles.bas. Example:
Public Const EffectNum_Wormhole As Byte = 24
Then go to Effect_UpdateAll and add the required code that will update your effect's animation:
If Effect(LoopC).EffectNum = EffectNum_Waterfall Then Effect_Waterfall_Update LoopC
Then in frmMain.frm, you need to add your effect to the combobox so you can modify it with the
editor:
Case 17
DispEffect = Effect_Spawn_Begin(EffectNum_Wormhole, ResetX, ResetY, cmbGfx.ListIndex + 1,
Val(txtParticles.Text), Val(TxtSize.Text), Val(txtTime.Text), Val(txtRed.Text), Val(txtGreen.Text), Val(txtBlue.Text),
Val(txtAlpha.Text))
House Editor
The housing editor is used set up maps as property (Player Houses). To set up a new property, click
new. Enter the map number, property value, and warp (x,y) coordinate for where the player enters
when using house teleport. When done, press “Save,” and move on to Step 2.
When you want to remove a property, select it from the list on the left and press Delete, then move on
to Step 2.
To Edit an existing property, select it from the list and change the appropriate values and press Save.
Take note of what Step 2 says. After you set up a map as a property via this editor, you have to use the
map editor and proceed to the Map Info window and select the “Property” Checkbox. You also have to
have an NPC with the Servant AI on this map.
Servants
servants allow a player to put up items for sale and to set a Premium (5-15%) on items they sell. For
example, an item with a value of 100 sold at a premium of 5% will sell for 105 (100 + (100 * 0.5)).
It is through the servant that players can buy/sell the property. When a player sells a property, they get
back 75% of its value. When someone buys from the store, the owner gets the money added to their
bank! Players can also talk to the servant to Rest at the map (as you would at an Inn), and restore hp
and mp.
Due to how the store script works, the Store Menu will not open unless there's an item in there. And
Job Editor
There are three types of job skills: Blacksmith, Alchemy, and Crafting. Job skills are used to make
items. Blacksmiths can make weapons, armor, shields, etc. Crafting is used to make bows, furniture,
etc. Alchemy is used to make potions. All the jobs have the following common properties:
Name: The name of the item to be made.
Level: The level of the appropriate skill required to make the item.
XP: The amount of experience to be gained from making the item.
Index: The slot in the job menu the item is. (Shown Below)
Page: The page of the menu the item is located on. Each menu has three pages.
Crafting
Note: One page two and page three, the index continues as shown above, starting the next number
from where the count left off.
Blacksmith (Items)
Item: The item to be made
Metal: The material (Metal bar) to be used to make the item
Amount: The amount of metal to be used to make the item
Alchemy Potions
Potion: The item to be made
Herb: The material (herb) to be used to make the item
Amount: The amount of herbs to be used to make the item
Craft Items
Product: The item to be made
Material: The material (herb) to be used to make the item
Amount: The amount of herbs to be used to make the item
When you are done inputing the details for your new item, hit the appropriate Create button. Step by
step instructions will then appear with details on how to add the new item to the job menu and into the
game.
This editor serves to help you add, edit, and delete NPCs in an easy to follow layout, rather than having
to edit the Database. All existing NPCs are shown in the list on the left. Click on an NPC to edit it.
ID: The id of the NPC. It must be unique. In the editor, this field is only visible while editing an
existing NPC
Name: The name of your NPC.
Description: This is the NPC's description. It is shown in your ingame chatbox when you right click on
the NPC.
AI: This decides what your NPC does. To add your own type of AI or see the available ones you need
to open GameServer.vbp in vbGORE folder and find
Public Sub NPC_AI(ByVal NPCIndex As Integer)
located in the NPCS module. The number you put in the database will correspond to the Case found in
that method.
Job: This only matters if the AI is set to 10, which refers to a Job NPC such as an Anvil, Furnace, etc.
1. Job Menu
2. Anvil
3. Alchemy Table
4. Craft Table
Quest: The ID of the quest that the NPC gives, 0 = No quest. Quests can be found in the Database
under Quest Table. This editor conveniently displays the list of existing quests.
Hair: What hair ID the NPC will have. This can be found in
vbGORE folder >> Data >> Hair.dat
Head: What head ID the NPC will have. This can be found in
vbGORE folder >> Data >> Head.dat
Nody: What body ID the NPC will have. This can be found in
vbGORE folder >> Data >> Body.dat
Weapon: What weapon ID the NPC will have. This can be found in
vbGORE folder >> Data >> Weapon.dat
Wings: What wing ID the NPC will have. This can be found in
vbGORE folder >> Data >> Wing.dat
Shop: This decides whether the NPC is a shop or not. Leaving it empty means its not a shop. The
format is as followed
ITEMID PRICE
Example
1 500
Example
5 10 98
Furniture Basics:
The way it works is that the user clicks on the furniture in their inventory. That item is removed from
their inventory and a new NPC (specified by the NPC_Spawn field of the object) is added to the map
representing the furniture. When the user clicks on the furniture NPC, the NPC is removed and the item
(specified in the Drop field) is added to the user's inventory.
Furniture NPCs sprites are stored in the Hair.dat file. Everything is labeled so you know. Basically
when a furniture NPC is spawned on the map, it is just the Hair item (no body or head). This was done
this way to save creating extra *.dat files and fields in the database.
Job NPCs
Job NPCs sprites (i.e. Anvils) are stored in the Hair.dat file. Everything is labeled so you know.
Basically when a furniture NPC is spawned on the map, it is just the Hair item. This was done this way
to save creating extra dat files and fields in the database.
Jobs are activated by clicking on the job NPC instance (i.e. furnace, anvil, craft table, or alchemy
table).
One the left-hand side of the editor, you will see a list of all NPC chats in the file you are editing. To
change which language file you are editing, select the appropriate language from the “Language”
combobox at the top of the editor. Also at the top of the editor are three other comboboxes:
Condition: This defines when the chat will take place. One of each condition may be used for each
line. If you do not define a condition for each line, the last used condition for the current chat ID is
used. If you do not define a condition at all, no conditions will be required.
• !CLEAR - Clears all the conditions. You MUST use this if you want to get rid of previous
conditions!
• !SAY x - The chat will only be said if the user types a message that contains the text X. X can
be broken into multiple statements separated by commas. Underscores must be made where
spaces are required!
◦ IE: !SAY test,_test_,_test,test_
◦ Enter [EMPTY] for text to say nothing but still use the delay (mainly used for the
RANDOM).
• !LEVELLESSTHAN x - The user's level must be <= X.
• !LEVELMORETHAN x - The user's level must be >= X.
These three comboboxes are simply there to help you remember and insert commands faster, and the
Chat Library on the left is only to help you locate Chat Ids faster. Selecting an option from these
comboboxes and then clicking the “+” button next to them will insert the selected option, i.e. !CLEAR,
to where the cursor is in the chat file. This editor will not write your NPC messages for you. You still
need to be familiar how to format your commands and messages. See below for more information.
Commands:
• BEGINFILE - States that from this marker and on, there is actually going to be data. Keep your
header text, and only your header text above this.
• [x] - Holds the chat ID to be used, where "x" is the ID.
• !x - Holds the conditions required for the chat to start.
• FORMAT x - Holds the chat type, where "x" is the format.
• STYLE x - Forces all the following lines of chat to use the defined chat style, "x".
• SAY x y - Says a message with the text "y" then waits x milliseconds after saying that text.
• Also know that you can add line breaks to SAY and ASK lines with /r
Examples:
[1]
FORMAT RANDOM
STYLE BOX
SAY 5000 This is a chat test! I appear in the box only!
STYLE BOTH
SAY 5000 This is a chat test! I appear in the box and bubble!
[2]
FORMAT LINEAR
STYLE BUBBLE
!HPLESSTHAN 50
SAY 5000 This message will only appear when your HP is less than 50%!
SAY 5000 And so will this one!
!HPMORETHAN 50
SAY 5000 HP <= 50 and HP >= 50 is applied, so this will only appear is HP is exactly 50%!
!CLEAR
SAY 5000 This will appear no matter what!
SAY 5000 So does this!
SAY 5000 Conditions carry on linearly - so until a !CLEAR is reached, or a new index is acquired, the
conditions stay!
[5]
FORMAT LINEAR
STYLE BUBBLE
SAY 5000 You can put the any index anywhere you want! Though it is best to put them in order, or else
SAY 5000 you can easily loose track of some indexes! It is best to NEVER skip an index, or else you
[3]
FORMAT LINEAR
STYLE BOTH
!LEVELLESSTHAN 5
!HPLESSTHAN 50
!DONTKNOWSKILL 1
!LEVELMORETHAN 5
!HPMORETHAN 50
!KNOWSKILL 3
SAY 5000 You can apply as many conditions as you wish! Though make sure you use !CLEAR when
you want to remove some!
[4]
FORMAT LINEAR
STYLE BOTH
SAY 5000 This appears no matter what, even though theres no conditions! !CLEAR is automatically
called when a new index (the [4]) is gathered!
Object/Item Editor
Items are handled in vbGORE server-side on the database. It is then up to the server to send data to the
client on items. This, though, just covers how to actually add items, which is a very easy process. You
can either edit existing items, add new items, or delete existing items. The Object Editor makes
adding items a breeze!
On the left hand side of the editor is a list of all items in the database. You can select from this list to
edit/delete an item, or you can create a new item by clicking on “New.”
NPC Spawn: Index of NPC to spawn. Used for Furniture objects. When furniture is used (placed on
board), the item is removed from inventory and an NPC is created on the board.
Body: What body ID to change the body to if the item is used. The body ID can be found at
vbGORE folder >> Data >> Body.dat
Weapon: What weapon ID to show if the item is used. The weapon ID can be found at
vbGORE folder >> Data >> Weapon.dat
Hair: What hair ID to show on the character if the item is used. The hair ID can be found at
vbGORE folder >> Data >> Hair.dat
Head: What head ID to show on the character if the item is used. The head ID can be found at
vbGORE folder >> Data >> Head.dat
Wings: What wings ID to show on the character if the item is used. The wings ID can be found at
vbGORE folder >> Data >> Wings.dat
Mount: What mount ID to show on the character if item is used. The mount ID can be found at
vbGORE folder >> Data >> Mount.dat
Elemental Bonuses: The amount of the element bonus (Air, Earth, Fire Water) object gives when
equipped
Replenish Hp: How much HP the character will replenish when the item is used.
Replenish Mp: How much MP the character will replenish when the item is used.
Replenish Sp: How much SP the character will replenish when the item is used.
Replenish Hp Percent: How many % of HP the character will replenish when the item is used.
Replenish Mp Percent: How many % of MP the character will replenish when the item is used.
Replenish Sp Percent: How many % of SP the character will replenish when the item is used.
Stats: How much of the stat (strength, HP, SP, Speed, Agility, etc) the object gives when equipped
Requirements: How much of the stat (Combat Level, Strength, Agility, and Magic) is required for the
use of the item.
Furniture Basics:
The way it works is that the user clicks on the furniture in their inventory. That item is removed from
their inventory and a new NPC (specified by the NPC_Spawn field of the object) is added to the map
representing the furniture. When the user clicks on the furniture NPC, the NPC is removed and the item
(specified in the drop field) is added to the user's inventory. When placing furniture down in the house,
the furniture will face the same direction as the player.
Player Housing Furniture Items spawn Furniture NPCs and vice versa. The Item added to a player's
inventory when picking up furniture is indicated in the NPC's drop field in the database. NPCs
spawned when users click on Furniture Items in their inventory is stored in the NPC_Spawn field of the
object table in the database.
Items and Furniture NPCs sprites are stored in the Hair.dat file. Everything is labeled so you know.
Basically when a furniture NPC is spawned on the map, it is just the Hair item. This was done this way
to save creating extra dat files and fields in the database.
The Quest Editor is used to help you quickly add/edit/delete quests. On the left side of the editor is a
list of all quests. You can select one to edit or delete. You may add a new quest by clicking the “New”
button.
Id: The unique id of the Quest - you can only have 1 of each ID.
Name: The quest name.
Redo-able: Whether the player can do the quest more than once
Start Text: This is what the NPC who starts the quest says when you right click him.
Accept Text: This is what the NPC who gives the quest says after you accept it.
Quest Incomplete: This is what the NPC who gives the quest says when you talk to it while not having
finished the quest yet.
Finish Text: What the NPC who gives the quest says when you return with the quest finished.
Quest Description: The description of the quest. It appears on the client quest screen.
Requirements to Accept
Required Level: The level your character has to be to be able to accept the quest.
Required Object: The object your character must have to be able to accept the quest.
Required object Amount: The amout of required objects your player must have to accept the quest.
Prerequisite: The quest your player must have already finished to accept this quest.
Requirements To Finish
Required Object: The object the player must have when finishing the quest.
Required Object Amount: The amount of required objects the player must have to complete the quest.
Kill NPC: What NPC must be killed to finish the quest.
Kill NPC Amount: The amount of required NPCs must be killed the finish the quest.
Note: The other textboxes will be enabled/disabled depending on which effect you are using. For
example, if you are creating a teleport skill, Body Index will be disabled since that has no relevance.
When you are done setting up your new skill, push “Generate” to have the skill code generated for you!
Tips
Transformations:
Animals/Creatures that are a single paperdoll layer are stored in the body.dat file. Transformations into
such creatures results in only displaying the players body which represents this creature. You can
specify which stats are affected from this transformation. Everything from Elemental bonus to stat
modifications are applied! This can be used by NPCs and PCs
Summoning NPC:
Only player characters can perform summoning. Enter into the Summon NPC field the NPC Index of
the NPC you wish to have summoned.
Teleport:
Only player characters can teleport. Enter the map, x, and y coordinates and the Teleport Effect
(particles) you wish to display. The Teleport effect is a numeric value which corresponds to the particle
effect you wish to use. You can see which numbers refer to what effect in
Client.TCP.Data_Server_Teleport. You can also add more effects in this section of code.
Adjust Stats
You can have your new skill affect just the stats, and thus create bonuses, curses, etc that impact your
target. This can be used by NPCs and PCs.
The Spell Icon is the icon you would like to have displayed above the caster's head. You can manually
type in your custom icon or select from existing icons in the list. An example value is
Hard-Coding Skills
The most important part of the spell code is the spell code itself. These are all held in the server's Skills
module. Most of the default vbGORE spells offer support for casting from PC->NPC, NPC->NPC, and
PC->PC. Also, constants are added to the top to easily define certain values. These are not required, but
it is recommended for ease-of-use. Its all about personal style, though.
Checking Conditions:
The first part of the skill sub is checking for valid conditions. This depends on if the caster or target is a
NPC or PC. Casting between two PCs will have the most checks.
Start with making sure the user is even in the state to cast the spell or be casted on, such as if they are
online (or the NPC is alive). For example, from PC->PC:
If UserList(CasterIndex).flags.UserLogged = 0 Then Exit Sub
If UserList(TargetIndex).flags.UserLogged = 0 Then Exit Sub
If UserList(CasterIndex).Counters.SpellExhaustion > 0 Then Exit Sub
The next step is to make sure the user who is casting the skill knows it. If it is a NPC, it is often safe to
assume that if the routine is being called, they are supposed to be casting it, so checks on NPC for this
is not required:
'Check if the caster knows the skill
If UserList(CasterIndex).KnownSkills(SkID.Bless) = 0 Then
Data_Send ToIndex, CasterIndex, cMessage(37).Data
Exit Sub
End If
After this, make sure the caster (NPC or PC) has enough mana, stamina or health to use the skill if any
is needed. For example:
'Check for enough mana to cast
If UserList(CasterIndex).Stats.BaseStat(SID.MinMAN) <
Int(UserList(CasterIndex).Stats.ModStat(SID.Mag) * Bless_Cost) Then
Data_Send ToIndex, CasterIndex, cMessage(38).Data
Exit Sub
End If
For users, it is often important to, just in case, put in a distance check before the skill is used if it is
target-based:
'Check for a valid target distance
If Server_CheckTargetedDistance(CasterIndex) = 0 Then Exit Sub
For ailments or buff spells, like a Curse or Blessing, you will often want to make sure that the user
doesn't already have the skill applied on them with a stronger power. The reason for this is you don't
want someone to be able to have a weaker buff casted on them by their enemy to cancel theirs out. A
good idea is to allow the skill to be casted on them either way if the one casted on them is about to run
out - this will allow users to avoid that "unbuffed time" between when the old buff runs out, and the
new one is casted. The below example doesn't do this, though:
'Cast on the target
If UserList(TargetIndex).Counters.BlessCounter > 0 Then
If UserList(TargetIndex).Skills.Bless >
UserList(CasterIndex).Stats.ModStat(SID.Mag) Then
Next is to deal with the icons displayed above the caster and target, if any. The most common on is the
spell exhaustion (time that must be waited between casting skills). The below is an example that will
display the bless icon:
'Display the bless icon (only if it isn't already displayed)
If UserList(TargetIndex).Skills.Bless = 0 Then
ConBuf.PreAllocate 4
ConBuf.Put_Byte DataCode.Server_IconBlessed
ConBuf.Put_Byte 1
ConBuf.Put_Integer UserList(TargetIndex).Char.CharIndex
Data_Send ToMap, CasterIndex, ConBuf.Get_Buffer,
UserList(CasterIndex).Pos.Map, PP_StatusIcons
End If
And spell exhaustion (icon plus adding the spell exhaustion time):
'Add the spell exhaustion and display it
UserList(CasterIndex).Counters.SpellExhaustion = timeGetTime Bless_Exhaust
ConBuf.PreAllocate 4
ConBuf.Put_Byte DataCode.Server_IconSpellExhaustion
ConBuf.Put_Byte 1
ConBuf.Put_Integer UserList(CasterIndex).Char.CharIndex
Data_Send ToMap, CasterIndex, ConBuf.Get_Buffer, UserList(CasterIndex).Pos.Map,
PP_StatusIcons
Keep in mind that times are calculated as CurrentTime Length (in milliseconds), not just length. This
helps reduce CPU load for timer-based calculations, along with much more accuracy.
Theres a few more display tasks left. The below is an example of how to tell the caster and target that
bless was casted:
'Send the message to the caster
If TargetIndex <> CasterIndex Then
End If
Now, for the display effects. This has to be handled more on the client which we will get to later. If you
want to display a spell effect, you will have to pass the skill ID, then specific parameters for that skill
ID. Often, this is just the character index of the target and caster:
'Display the effect
ConBuf.PreAllocate 6
ConBuf.Put_Byte DataCode.User_CastSkill
ConBuf.Put_Byte SkID.Bless
ConBuf.Put_Integer UserList(CasterIndex).Char.CharIndex
ConBuf.Put_Integer UserList(TargetIndex).Char.CharIndex
Data_Send ToMap, CasterIndex, ConBuf.Get_Buffer, UserList(CasterIndex).Pos.Map,
PP_DisplaySpell
Finally, the very last thing is the sound. The sound requires just sending the sound number (such as 6
for 6.wav) along with the tile position:
'Play sound effect
ConBuf.PreAllocate 4
ConBuf.Put_Byte DataCode.Server_PlaySound3D
ConBuf.Put_Byte Bless_Sfx
ConBuf.Put_Byte UserList(CasterIndex).Pos.X
ConBuf.Put_Byte UserList(CasterIndex).Pos.Y
Data_Send ToPCArea, CasterIndex, ConBuf.Get_Buffer, , PP_Sound
Anywhere in the SkillID UDT, add the name of your skill, such as:
MySkill As Byte
Make sure you update the NumSkills constant with the number of skills you have. In most cases, this
will be the same number as there are variables in the SkillID UDT.
Public Const NumSkills As Byte = 9 'Change to highest skill ID
And adding in the next free number for your skill, such as:
.MySkill = 9
SkillID To …
While the server only needs to know the SkillID number and what skill subs it relates to, the client
needs to be able to convert the skill ID into the skill name and grh to display the skill information on
the client. These subs are Engine_SkillIDtoGRHID and Engine_SkillIDtoSkillName. The usage for
them are very self explanatory, you just have to enter the Grh number and skill name.
You will see a lot of skill counters in here already. As stated before, the value stored in this counter is
not how long the skill lasts, but at what time the skill will run out, which is found by timeGetTime
Length, and is represented in milliseconds. Keep all counters as a Long.
Next, for adding the information of the skill to the user, search for:
Type Skills
This holds the power of the skill. How you use and calculate this value is up to you. Some skills, like
Iron Skill, is just either on or off, while the others are held by value, where a higher value = higher
power.
Next, you want to make sure you are checking to see if the counter runs out. Plenty of examples of this
can be found if you look for the code:
'*** Update the counters ***
The basic concept of this is if the spell ran out, set the skill value to 0 (turn off the ailment), turn off the
icon and update their mod stats.
The final step is to make use of the ailment. This is done in User_UpdateModStats. For example:
'Protection
If UserList(UserIndex).Skills.Protect > 0 Then
Log "User_UpdateModStats: Updating effects of skill/spell Protection",
Color Selector
This is a useful tool that you most likely will be using when you want to figure out the ARGB color of
something.
For example, if you want your menus to appear translucent, you could input
• Alpha: 100
• Red: 255
• Green: 255
• Blue: 255
Alpha, Red, Green, and Blue range from 0 (none) to 255 (fullest). Changing these values for Red,
Green, and Blue to different combinations will yield different colors. For example. 255 for Red and
Green and 0 for Blue will create Yellow. Changing the value of Alpha will make something more
transparent.
File Processor
Open ToolFileProcessor.exe. In this tutorial I will use RC4 Algorithim so select the Algorithim RC4,
put the key and the altered extension. The Unaltered Extension and Sub-Folder will be the default
("PNG" and "Grh\").
Replace this:
'Get the path
FilePath = GrhPath & TextureNum & ".png"
To this:
'Get the path
TempFile = GrhPath & TextureNum & ".enc" '<<<<PUT THE ALTERED EXTENSION
FilePath = GrhPath & TextureNum & ".png"
Example Image:
End If
For i = 1 To UBound(ParticleTexture())
TempPart = GrhPath & "p" & i & ".enc"
FilePart = GrhPath & "p" & i & ".png"
End Sub
Log Remover
ToolLogRemover.exe
A tool that removes the current log files of the game. It is good to occasionally clean up the logs when
they get too big.
Grh Categorizer
ToolGrhCategorizer.exe
This tool allows to sort all your GRH's graphics into different categorises for easier use in the
EditorMap.
Turns your Grh1.raw files into Grh.dat files, and calculates the values for your Grh.ini file. Every time
you add or make changes to a Grh, you must run this tool to have it show up in the game.
Before you do anything, you have to open a texture (*.png) file! Click the “...” button do do this. Once
you open a texture file, the widthe, height, and other information for it will be displayed under “Texture
Information”
This tool has a built in feature to display a grid. You can set the width and height, total rows and
columns, and the starting coordinate for this grid. The grid is simply used to create a series of “Grid-
Created Grhs” in the bottom left corner of the editor. This is a shortcut way of creating Grhs. Should
you use this method, just click the “Append” button at the top right corner of the editor to add all the
“Grid-Created Grhs.” If there is a Grh in the list you don't want, you can select it and push the Delete
key to remove it. If you make adjustments to the grid (such as width, start coordinate, etc), push
Refresh to update the grid and “Grid-Created Grhs.”
Adding Grh
Click “Add GRH” button on the far left of the editor to add a new Grh.
Grh: The Grh number for your new Grh. Use the ToolFreeNumber.exe for help finding next free
number (Or click Next Free Grh).
File: This is the texture file number, inserted automatically for you based on the currently open *.png
Width/Height: The dimensions of your Grh
X,Y: The coordinate of your Grh in the texture file.
Category: You can optionally input the category number for your Grh. If unsure, you can later do this
with the ToolGrhCategorizer.exe
On the far left side, under Existing Grhs, select a Grh from the list. When you do, the Grh will be
highlighted with a yellow border in the displayed texture. For Example:
Next, click the “Edit GRH” button to edit (Or Remove to delete). In the form that opens, the following
fields will be automatically filled in with the properties of the selected Grh.
Grh: The Grh number for your Grh.
File: This is the texture file
Width/Height: The dimensions of your Grh
X,Y: The coordinate of your Grh in the texture file.
Category: The category for you texture, used for easier finding of your Grh in the map editor. If
unsure, you can later do this with the ToolGrhCategorizer.exe
Change the values to your liking, and then click save. If you are removing the Grh, click the Remove
button instead. Note, If the Grh being edited is animated, the form in the following section would
actually show.
Click on the “Add Animated” to add a Grh that is animated. In the form that opens, the following
fields will show:
File: The texture file (inserted for you based on the open texture file)
Grh: The number for the new Grh
Frames: The frames in your animated Grh
• <Frames( >1)>: The total frames in your animation (must be greater than 1)
• -#-#-#-#...: The list of Grhs for each frame of the animation. For example, if you had 3 frames
in your animation, you would put something like this: 245-246-247
• <Speed>: The frame rate for the animation. The higher, the faster.
Example:
2-365-388-8-(128)
There's one button not mentioned yet, and that is “Open GrhRaw.txt” which will open the GrhRaw.txt
file so you can manually edit the grh list file directly, rather than through this editor. That is something
you should only do if you know what you are doing.
IMPORTANT!
Don't forget, run the ToolGrhDatMaker.exe after you add/edit/remove Grhs!
Control Panel
This tool is provided for mere convenience. From this tool you can open up either the source code or
executable for all the editors, game client, server, update client/server, etc.
End Select
End Sub
All the code under Case 8 will run whenever an NPC with its AI set to 8 acts. So how do we want this
NPC to behave? First, as with the summoned melee attacker (Case 7), we want to make sure that it's
only run by a summoned NPC with an owner:
End Select
End Sub
It will reset the action timer and abort the sub if the NPC doesn't have an owner. If the rest of your code
is well-designed, this sub should never be called by a non-summoned NPC anyway, but it's always
better to be safe than sorry.
Next, we want our NPC to look around for any other NPCs it should be attacking (for now, our NPC
will only attack other NPCs, as PvP is a little harder to do).
'*** Summoned Ranged Attacker ***
Case 8
End Sub
If you're not entirely sure what the NPC_AI_ClosestNPC sub does, it's easy enough to check (it's in
the same module). What this sub does is returns the index of the NPC closest to our NPC, inside the
range we specify. It also has options for if the NPC has to be hostile, if the NPC has to be attackable,
and if the NPC can't be owned by a certain player. If it finds no NPCs, it will return 0, so let's check for
that:
End Select
End Sub
So what do we want the NPC to do if there isn't anything to attack? We'll have it follow the user
around, because it's a summon. In this case, we can just copy+paste some code from Case 7 again:
'*** Summoned Ranged Attacker ***
Case 8
End Sub
That last bit of code might not make too much sense, because it's probably backwards from what you're
thinking. What these If statements are doing is checking if the NPC is already close enough to the
user, instead of checking if the NPC needs to move closer. So what we have so far, in pseudocode, is
basically:
If there is no valid target in range, Then:
If we're close enough to the user that we don't have to move, Then:
We don't have to do anything, so abort the routine.
However, if we aren't close enough to the user, we have to move towards him. Since it will
automatically exit the sub if the NPC is close enough, we can simply add the code without an Else
statement.
'*** Summoned Ranged Attacker ***
Case 8
'So let's set the direction toward the player, and try to move
tHeading = Server_FindDirection(NPCList(NPCIndex).Pos,
UserList(NPCList(NPCIndex).OwnerIndex).Pos)
End Sub
Now what we've done is set a variable called tHeading to the direction the user is in, using the
Server_FindDirection function. We then try to move using the NPC_MoveChar function.
NPC_MoveChar tries to move, and if it is successful (the NPC can move) it returns 1. Needless to say,
if it isn't, it returns 0. So let's assume we can't move in a direct line to the user. We're going to try and
move diagonally or to the side now (for the sake of saving space, I've cut off the top part of the code):
If Abs(CInt(NPCList(NPCIndex).Pos.X) -
CInt(UserList(NPCList(NPCIndex).OwnerIndex).Pos.X)) < 4 Then
If Abs(CInt(NPCList(NPCIndex).Pos.Y) -
CInt(UserList(NPCList(NPCIndex).OwnerIndex).Pos.Y)) < 4 Then
NPCList(NPCIndex).Counters.ActionDelay = timeGetTime + 500
Exit Sub
End If
End If
'So let's set the direction toward the player, and try to move
tHeading = Server_FindDirection(NPCList(NPCIndex).Pos,
UserList(NPCList(NPCIndex).OwnerIndex).Pos)
End Sub
That's pretty big, but simple. t1, t2, t3, and t4 represent the alternate directions we can move in. If
you trace through that code a bit, you shouldn't have much trouble gathering what it does.
Now we're going to actually try and move in those 4 directions.
Case SOUTHWEST
t1 = SOUTH
t2 = WEST
t3 = SOUTHEAST
t4 = NORTHWEST
Case NORTHWEST
t1 = WEST
t2 = NORTH
t3 = NORTHEAST
t4 = SOUTHWEST
End Select
'Try the alternate movements
If NPC_MoveChar(NPCIndex, t1) = 0 Then
If NPC_MoveChar(NPCIndex, t2) = 0 Then
If NPC_MoveChar(NPCIndex, t3) = 0 Then
If NPC_MoveChar(NPCIndex, t4) = 0 Then
'We still can't move, so just wait
NPCList(NPCIndex).Counters.ActionDelay =
timeGetTime + 1000
End If
End If
End If
End If
End Select
End Sub
You can probably figure out what this does by now. It tries moving in each alternate direction, and if it
still can't move, it will simply wait. We could implement some sort of advanced pathfinding algorithm
to get around obstacles, but let's just say our NPC is dumb :P
Case NORTHWEST
t1 = WEST
t2 = NORTH
t3 = NORTHEAST
Else
'Something was found, so now we get in position and attack!
'Get the position of the NPC
tPos = NPCList(i).Pos
End Select
End Sub
What we've done now is add the trailing End If statement for If NPC_MoveChar(NPCIndex,
tHeading) = 0 Then, and then aborted the sub. If we've gotten this far in the routine, we've either
moved or not and there are no enemies, so we don't need to do anything else. If you're a bit confused,
take a look at this updated pseudocode for our AI so far:
We've either moved or not by now, and there's no target, so abort the routine.
Else
We do have a target to attack, so get the target's position.
Now I'm going to post all the code for moving to the correct distance from the NPC. Don't worry, I'll
explain it.
Else
'Something was found, so now we get in position and attack!
'Get the position of the NPC
tPos = NPCList(i).Pos
End Sub
Lotta code right there. However, if you're keen, you'll have noticed it looks almost like the code we
used before (In fact, much of it IS the code we used before. I'm far too lazy to write it all out again.
Nothing wrong with a little Ctrl+C action). Let's use some more pseudocode to explain what this is
doing. Refer to this little snippet, and then back at the code, and see if you can piece together what the
code is doing:
If there is no valid target in range, Then:
If we're close enough to the user that we don't have to move, Then:
We don't have to do anything, so abort the routine.
End If
We've either moved or not by now, and there's no target, so abort the routine.
Else
We do have a target to attack, so get the target's position.
If we're closer than 3 tiles to the target, Then:
Set tHeading to the opposite direction of where the target is
Try to move in that direction. If we can't Then:
Try to move in an alternate path. If we still can't, Then:
We can't move, but we have a target, so attack.
End If
End If
We've either moved away or attacked, so abort the routine.
Making sense now? We're almost done, but we need some more code. What happens if we're already 3
tiles from the target? We want to go ahead and attack, so:
'Try the alternate moves
If NPC_MoveChar(NPCIndex, t1) = 0 Then
If NPC_MoveChar(NPCIndex, t2) = 0 Then
If NPC_MoveChar(NPCIndex, t3) = 0 Then
If NPC_MoveChar(NPCIndex, t4) = 0 Then
'We still can't move (cornered! ack!) so
attack!
NPC_AI_AttackNPC NPCIndex,
NPCList(NPCIndex).OwnerIndex
NPCList(NPCIndex).Counters.ActionDelay =
timeGetTime + NPCDelayFight
End If
End If
End If
End If
End If
Exit Sub
End If
End If
End Select
End Sub
By now, you probably have a good idea of what those last few lines are. For reference,
NPC_AI_AttackNPC returns a 1 if the attack is successful and a 0 if it wasn't. The ActionDelay
counter is there to make sure that the NPC attacks on-time - don't want him attacking too fast or too
slow.
Believe it or not, that's the end! Here's the completed pseudocode for AI number 8:
If there is no valid target in range, Then:
If we're close enough to the user that we don't have to move, Then:
We don't have to do anything, so abort the routine.
End If
We've either moved or not by now, and there's no target, so abort the routine.
Else
We do have a target to attack, so get the target's position.
If we're closer than 3 tiles to the target, Then:
Set tHeading to the opposite direction of where the target is
Try to move in that direction. If we can't Then:
Try to move in an alternate path. If we still can't, Then:
We can't move, but we have a target, so attack.
End If
End If
We've either moved away or attacked, so abort the routine.
End If
We're longer than 3 tiles away and we've gotten this far in the routine, so
attack.
If the attack was successful, Then:
Update the attack timer.
End If
And here's the completed AI code. Feel free to copy and paste into your own game, although if all you
do is copy+paste it without reading the tutorial you won't learn much.
'*** Summoned Ranged Attacker ***
'Note: only attacks NPCs for now. Fix later kthx.
Case 8
Else
'Something was found, so now we get in position and attack!
'Get the position of the NPC
tPos = NPCList(i).Pos
End If
VBGore comes with several NPC AIs already installed. AI number 2 makes the NPC walk around in a
random pattern. If the NPC is hostile then it will attack players, but if it is not hostile it will not fight
players, even when it has been attacked.
In this tutorial I'll show you how to modify AI number 2 so that NPCs defend themselves when
attacked.
'THESE ARRAYS MUST STAY DOWN HERE AT THE BOTTOM OF THE UDT!
VendItems() As Obj 'Information on the item the NPC is vending
'Attack
If NPCList(NPCIndex).Hostile Then b = NPC_AI_Attack(NPCIndex)
This will make the NPC fight back when someone hits it. If you also want to make them hostile when
hit by a range weapon add this code to Private Sub User_Attack_Ranged in the Users module:
'Play the sound of no weapon attacking
SfxID = UnequiptedSwingSfx
End If
Adding Graphics
Before you design your Grhs, it is recommended that you know how to optimize your textures for the
best performance.
Note that many file types are supported, from BMP, PNG, and JPG to weird extensions most of us have
never even heard of. To use other file extensions, just save as the different file extension and either
change the client and map editor to load the different file extension, or manually change the extension
to PNG (for example, .JPG to .PNG). Note that changing the extension does not have any impact on
the image, it just lets you change the format without changing the engine to look for a different format.
Graphic files are placed in the \Grh\ folder. You can name the file any number, as long as the number
doesn't already exist and does not contain any zeros before the number. Simple numbers like 1, 2, 41,
129, 320, all work. However, numbers like, 002, 0041, 010101, will not work. In the root directory, you
will find a program named ToolFreeNumber.exe. This tool will tell you the next available texture
numbers and grh numbers.
Using GrhRaw.txt
There are two things that identify a graphic, the File/Texture Number (such as 10.png or 210.png) and
Grh Number (defines the individual graphics inside a texture). To create the Grh Number, go to the
\Data2\GrhRaw.txt file and open it with Notepad or Wordpad. In here, you will find entries structured
in these two manners:
1) Grh#=<Frames(=1)>-<FileNumber>-<StartX>-<StartY>-<Width>-<Height>-(<Category>)
2) Grh#=<Frames(>1)>-#-#-#-#-#...-<Speed>-(<Category>)
Your Grh# is the ID number of your Grh. You often don't have to remember this unless you are writing
the GrhNumber directly into the code (like for the GUI) because you can browse through the
GrhNumbers in the map editor. Numbers are required to be unique. In other words, you cannot make
two entries for Grh 10. The compiler will warn you if you make duplicate entries.
At the end is the category. This is optional and is often ignored when making entries directly into
GrhRaw.txt. Categories are handled by the program ToolGrhCategorizer.exe. The rest of this guide
will ignore them, and it is recommended that you do the same when making entries into GrhRaw.txt
Method 1 is for single-frame (unanimated) graphics. Frames will always be 1 in this. FileNumber
refers to the .png file your graphic is in (such as for 20.png, you enter 20). StartX and StartY refer to the
starting pixel position where the graphic you want is, the width and height of the graphic you want is
the width and height of the graphic. For DirectDraw and BitBlt users, think of this as the SourceRect
since you are just defining the part of the image you wish to draw.
Method 2 is for multiple-frame graphics. In this case, Frames must be greater then 1. For each frame,
you must specify a GrhNumber. If you have 5 frames, then you will have 5 GrhNumbers specified after
that. At the end, you have your animation speed, which is how fast the frames elapse (higher = faster).
The speed has no real relative value, so you will want to experiment with how fast the different values
of speed are. Decimals are supported in speed. As an example, in the water animation, you have eight
As you can see, there is an 8 at the start for 8 frames, 8 GrhNumbers which define the 8 different
unanimated (single-frame) grhs, then the speed. A separate GrhNumber must be applied to the
animation that is separate from the other GrhNumbers. Grh3500 is now the animated water, while 318
to 325 is the separate frames of the water.
Another example:
Grh999=8-991-992-993-994-995-996-997-998-7
Grh999 is the Grh number you are assigning to the animation. 8 is the number of frames you have. 991,
992, ... 998 are the Grh numbers of the unanimated Grhs, specified by using Method 1. The last number
in the grounp, 7, is the speed at which the graphic animates.
Once you write the new graphic(s) into the GrhRaw.txt file, run GrhDatMaker.exe. This will compile
GrhRaw.txt into Grh.dat and Grh.ini, which contain the Grh information. This is automatically placed
in the \Data\ folder for you.
Make sure whenever you want to use the map editor which is not part of the client (the non-ingame
map editor) that you copy over the Grh folder along with the Grh.dat and Grh.ini to make sure the
graphics are up to date.
If you are uncomfortable editing the GrhRaw.txt, you can use the ToolGrhRawAssistant.exe to aid you.
Adding Signs
Sign text is stored completely client-side - there is absolutely no reference to it on the server. This is
because even just letting the server know what sign is on what tile is a huge consumption of RAM.
How much, exactly? On a 100x100 map, it would take 100x100x2 or 19 KBytes. It doesn't sound like
much, but spread over 1000s of maps, it adds up fast for an insignificant benefit.
There is only two simple steps required in working with signs. The first step is creating the sign text,
which is located in \Data\Signs.dat. Just open the file with Notepad or Wordpad. You will see the
following:
[SIGNS]
NumSigns=5
...
It is important to keep in mind how the engine will translate the sign and display it. The ""'s are
automatically added for you. The The sign says, text comes from the Messages file.
Useful Links
vbGORE Forums: If you need help with a topic that the user guide nor the vbGORE wiki can answer,
then the forums is a great place to find what you are looking for!
vbGOREmania Forums: Like above, if you can't find what you need on the vbGOREmania website,
then try the vbGOREmania forums!
StreamMyGame: StreamMyGame extends your monitor, keyboard, & mouse over a network so you
can see and play a game or application remotely. You may want to recommend this to your players so
they can play your game anywhere there is an Internet connection (even from their phone!)
PortableApps: A portable app is a computer program that you can carry around with you on a portable
device and use on any Windows computer. When your USB flash drive, portable hard drive, iPod or
other portable device is plugged in, you have access to your software and personal data just as you
would on your own PC. And when you unplug the device, none of your personal data is left behind.
Sprites/Music/More: This section of the vbGOREmania forums contains resources, such as music
and graphics, for your games. Below is just a sample of what has been posted!
• Miscellaneous Sounds
• Animation Editor
• Half Kaizer Graphics
• Google Language Tools
• KB Piano
• Sprite Generator
• Easy Music Composer
• Breeze Graphics
• Pixel Art Tutorials
• vbGORE tutorials / custom features (made by the community)
• vbGOREmania tutorials / custom features (all of these features are already in vbGOREmania's
latest version)
• Weebly: A good website hose for those who are not sure how to setup a website
Features
Quest Window This adds a visual quest log window that the player can interact with.
Guilds / Squads
There are guilds (AKA Factions) and squads (AKA Partys) in vbGOREmania. Players can start guilds
and assign ranks to guild members. Players with houses can also choose to lock their house to everyone
but guild members to setup a guild base/meeting place.
Equip Menu
Below the inventory is a small display of what the player has equiped. It is a useful feature for when
the player wants to reference what exactly he/she is wearing!
Status Window
A useful little window that displays the player's location (Map, x, y), Health, Mana, Stamina,
Experience, and Portrait.
Player Housing
You can set maps to be "ownable property." This means that a player can "purchase" this area from a
designated NPC (Servant). Once purchased, the player can later teleport back to this house at any time.
They may also "rest" in this map for instant healing (like at an Inn). They may also give items to the
Servant NPC to sell to players who visit their property. Items they put up for sale are sold at the item's
value + Premium (set by the player to be 5%, 10%, 15% of item value). So yes, the player can basically
have their own store! Players can also "lock" this property so that only friends, only guild members, or
only themselves can have access.
Since some players may eventually stop playing the game, the housing market can get a little out of
hand as the owners no longer play and thus never sell back their houses. That is why there is a time
limit (3 months by default) where if the owner does not visit their home and talk to the Servant, then
PVP Zones
Maps can be designated in the Map Editor as Player Vs Player areas, meaning that players can fight
each other. In game play, these areas have a skull in the upper right-hand corner to alert the player they
are in such an area.
Reflective Tiles
For extra cool eye candy, you can make certain tiles reflective. This can be done in the Map Editor.
When a player steps on such a tile, their reflection shows up on the tile beneath them.
Defense
Defense has been added as a stat. A must if you are going to protect yourself!
Job Skills
Players can now pursue blacksmithing, alchemy, and Crafting. Blacksmiths can make weapons and
armor, Craftsmen can make furniture, bows, etc, and Alchemist can make potions! All of these are
useful trades for making money and equipment needed for a players passage into greatness!
Windows Lock/Close
Players can lock windows/menus in place to avoid moving them by accident, and they can close them
with the click of a mouse.
Elemental Bonuses
Let's face it, in the real world, elements affect each other differently. So, why not have them in your
game so that players can creatue their own strategy as to how to beat that fire breathing dragon or that
ice giant? Knowing the right weapon to bring can make a big difference! Grab your fire shield!
Main Menu
There is now a main menu from which the player can access commonly accessed windows. Forget (or
simply not read the manual)? Well, just click on the Main Menu for easy access!
GM Tag
In the game chatroom, (GM) appears next to GM's names.
Friend/Ignore List
You can now keep track of your friends/enemies in your own buddy list!
Server Alerts
You can send a global message from the server to all players.
Control Panel
There is a control panel from which the developers of the game can access any editor, the client/server,
and more.
Chat Channels
The chatroom is broken down into Global, Map, Guild, Market, War, and Help.
• Global: Talk to the world
• Map: Talk to everyone on the same map
• Guild: Talk to other guild members
• Market: Chat with other people who are wanting to trade
• War: Chat with people wanting to dual or coordinate a guild war
• Help: Get help from other players
Editors
• Map Editor: Edit the maps/boards of the game
• Particle Editor: Edit/Create Particle effects
• House Editor: Setup player housing
Walk-Through Characters
Characters (players and NPCs) can now walk through each other.
Weather Rotates
The weather rotates periodically to one of three specified weather types specified in the map editor. In
the server, change the variable UpdateRate_Weather to change how fast weather changes.
Rearrange Stats
Players can decrease a stat and move their stat point to another one.
Downloading
First get a copy of the latest version of vbGORE or vbGOREmania.
Extracting
Once your download is done, it is time to extract the files. Go to the folder which you downloaded the
compressed version of vbGORE and right-click the file. Depending on what kind of unzipping software
you have, you will see different things. The typical thing to look for is "Extract" - click Extract To
Folder, Extract To..., Extract To <filename> or something similar. This will extract the contents of the
compressed folder to a new uncompressed folder.
Note that you do have to extract the files - do not just double-click the file. More information here.
What is MySQL
MySQL is a powerful multi-purpose database. It runs as a service on your computer, which means that
it will work in the background when your computer is running. Don't worry, it will use very little RAM
and no CPU if you don't use it. MySQL works by getting a query string from the client, then returns the
requested information. It uses a very simplistic language format for the query, but has very powerful
functions. Many games today uses a MSSQL or MySQL database, from Trickster to World of Warcraft.
Since vbGORE version 0.2.0, MySQL has been added to replace the editors and hard to work with file
formats. MySQL also allows for remote connections so you can edit from other computers without
moving any of the data, along with being able to read the information through web pages.
Downloading MySQL
A few files must be downloaded first. When you click on each link to download do not worry about any
of the other files that come up. Close out of the windows. You will get to them later.
1. Click to download MySQL. If and only if this download does not work for you, you may try an
alternative download from the MySQL 5.0 site here.
2. Click to download ODBC 3.51. If and only if this download does not work for you, you may try an
alternative download from the ODBC 3.51 site here.
Installing MySQL
1. The first thing you need to do is to remove ALL traces of MySQL if you installed it before. First,
remove it with Add / Remove Programs in the control panel. After that, go to where MySQL was
installed (default "C:\Program Files\MySQL") and delete MySQL manually.
2. Extract the ZIP file and run the MySQL setup.
3. After running the application, you should see the following page. Just hit Next through the pages -
the default settings are all you need.
4. When the installer finishes, make sure you tick the Configure the MySQL Server now box ticked,
then press Finish. If you don't configure the server now, you can always configure it later. A shortcut
should be placed in your start menu to it with a name similar to Configure MySQL instance.
Configure MySQL
1. A new application should pop up. Click Next to reach the following page, then tick the Detailed
Configuration option.
5. Click Next.
7. If you want to ever connect to your database remotely (from other computers), select Enable TCP/IP
Networking. If you only want to run it from the same computer the game server is on, you can leave
this unticked. It is recommended you do tick it for later usage.
9. Select Install As Windows Service. The service name does not matter - they all do the same. This will
allow MySQL to run in the background every time Windows loads.
If you have installed it already and reinstalled it you have to do several steps. Go to start>All
program>Mysql>MySQL Server Instance Config Wizard
Double Click on it and start it up. Just go through the default settings. Also, don't forget to change your
password(even if it is the same) during the config wizard.
MySQL Videos
Installing MySQL Video
Configuring MySQL
Videos By NotExistant (Arie Miller) sorry for bad quality I blame windows movie maker.
5. Right click the vbGORE database and click Restore from SQL dump browse for vbgore.sql and
press execute. After you press execute once, click close. Pressing execute will give you an error that
simply means you have already imported the data.
Important: If you get an error message saying "Error Code: 1050 - Table 'banned_ips' already exists"
or something like that, it means that you already imported the data either before, or you just did.
SQLyog is strange on its way of reporting a successful import, so it is very easy to do it without
realizing it. If you get this message, just move on, since you're done with this step.
Troubleshooting
Cannot create Windows service for MySQL
If you are getting an error message for MySQL 5.0 during the execute procedure, and the error is
"Cannot create Windows service for MySql. Error: 0" the usual problem is the install directory,
C:/Program Files/..... The space between Program & Files also prevents MySQL from creating/starting
service, so install MySQL server in C:/ itself (ex: C:/MYSQL).
Access Denied
Access denied simply means that the username and password you entered for the database was
invalid. This is a very common error people have on their first time trying to run vbGORE. The
password is the same password you entered into the MySQL Instance Configuration after
installing MySQL. The username is often left as root for the primary account.
These values can be changed in the server's configuration file, which is found in
root/ServerData/Server.ini on the following lines:
//MySQL account username (default is "root")
User=root
//Password for the username specified above for the database - same as the password
entered into the MySQL Instance Config
Password=test
If you try to save the file and you can't you'll have to do one of the steps below:
1. Ask the administrator of the computer to give you privileges.
2. Move the location of the vbgore folder to somewhere else like the desktop.
Keep in mind that the Host requires the external IP, not internal. You can get this IP by going on the
host machine and going to WhatIsMyIP.org or other similar sites if you do not already know the IP.
If you are hosting locally, the problem is most likely that you do not have the service running. The first
step is to make sure you have installed MySQL and run the MySQL Instance Configuration
successfully. If the service will still not load, you can load it manually through:
Right-click 'My Computer' -> 'Manage' -> 'Services and Applications' -> 'Services'
Find your MySQL service in this list (name usually starts with 'MySQL'), right-click it and click 'Start'
Unknown Database
Unknown Database means that you have connected to MySQL, but the database you specified does not
exist. By default, this is the vbgore database. Make sure that you have imported the vbgore.sql file into
the database with SQLyog, Navicat or your MySQL GUI of preference.
The name of the database can be changed in the root/ServerData/Server.ini file on the line:
//Name of the MySQL database (default is "vbgore")
Database=vbgore
If you do, then please copy your files from the Libraries folder (comes with the vbGORE(mania)
download) to your System32 folder (default C:\Windows\System32\). If you do not have a System32
folder, use your ...\System\ folder. If this does not work, you can try copying all the files into the same
folder all the EXEs are. If both of those fail, please read the below.
Those who get the error said above with a missing component do not have the file in the correct path or
you need to register it. Many installation programs can do this automatically, but with archived (zip,
rar, 7z, tar, etc) files that you extract, these files are not registered automatically and may not be
recognized automatically.
To register a file, you first need to find it's path. Most files should be located in ...\Libraries\ so start
with finding that folder. Look for the file that can not be found, then right-click it and click Properties.
In the Properties window, in the 2nd section down, you will see Location. Take the Location and
combine it with the file's name to get the full path. Example:
File path: C:\vbGORE\Libraries\ File name: Socket.ocx Complete file path:
C:\vbGORE\Libraries\Socket.ocx
Take this complete file path and go to Start -> Run to bring up the Run prompt. Enter the following:
where <filepath> is the Complete file path you acquired from the method above. When you are
finished, it should look something like this:
regsvr32 "C:\vbGORE\Libraries\Socket.ocx"
Make sure you keep the " " in there so the program knows it is all combined. Once you have that
entered, just press OK or press Enter and the registration should succeed! If it does not, it is more then
likely that you have entered the wrong file path.
Game Client
Learning The Game Controls
The control scheme for vbGORE, I admit, is not the greatest. You can change all the controls through
the source easily enough. In the following section is where you can find all the default controls. It is
important to check it out because it also gives you a better idea of what is in vbGOREmania. Please
note that most of these commands can be executed by the push of a button in the chat window's
command menu.
Movement
walk: left mouse click run: r
Misc.
Buy from NPC: Right-click NPC vendor, left-click item in item window to buy
Get item description: Right-click item in inventory/vendor window
Set description: "/desc <description>"
Get item off ground: space
Display Options
These commands are all used to modify, use, or display certain menus or displays.
Hide/Show Inventory: Ctrl + w
Hide/Show Quick Bar: Ctrl + q
Hide/Show Chat window: Ctrl + c
Reset GUI Positions: F10
Close Windows: Escape
Zoom View In: NumPad '8'
Zoom View Out: NumPad '2'
Display Mini-map: Tab
Talk
Command: Enter
The user may push enter to engage in chat or to enter commands that need to be entered through chat.
When done the user clicks enter again to submit the message.
Read Mail
Command: Right-click Mailbox
Allows the user to check their messages in their mailbox that are sent by other players or admins.
Private Message
Command: "/tell <name> <message>"
Allows you to send a message to given players name so that only you and that user may see the
message you have sent. This is often used for private chats or for messages only desired to be herd by
the two users.
Shout
Command: "/shout <message>"
Sends a message to everyone.
Guild Commands
Guild Chat
Command: "/g <message>"
Sends a message to everyone in the user's guild, if they are in a guild.
Create Guild
Command: "/creatg"
Allows the player to create their own guild. They must not be a part of a guild already.
Leave Guild
Command: "/leaveg"
Makes the user leave the guild they are in.
Invite to Guild
Command: "/invite <name>" Invites a user to join your guild. They must respond within 10 seconds to
join the guild.
Join Guild
Command: "/joing"
Accepts an invitation to a guild.
Guild Meeting
Command: "/gmeet"
Sends an invitation to all players in guild to attend a guild meeting
Party Commands
Party's are like temporary groups where you can quest/kill together and share rewards
Party Chat
Command: "/p <message>"
Sends a message to everyone in the user's party, if they are in a party.
Create Party
Command: "/creatp"
Allows the player to create their own party. They must not be a part of a party already.
Leave Party
Command: "/leavep"
Makes the user leave the party they are in.
Invite to Party
Command: "/pinvite <name>" Invites a user to join your party. They must respond within 10 seconds to
join the party.
Join Party
Command: "/joinp"
Accepts an invitation to a party.
Friend Commands
Remove Friend
Command: "/REMOVE FRIEND <friend name>"
Remove friend from friend list
Add Block
Command: "/BLOCK"
Add player to ignore list
Remove Block
Command: "/UNBLOCK"
Remove player from ignore list
Misc Commands
Who`s Online
Command: "/who"
Lists inside the communication (chat) box what players or users are currently online.
Look Left
Command: "/lookl"
When used your character will look to his/her left.
Look Right
Command: "/lookr"
When used your character will look to his/her right.
Blink
Command: "/blink"
When used your character will blink.
Emote
Command: "/me"
Allows the user to type a message and instead of displaying as something the player said it will display
it as what the users actions are. For example, typing the text:
/hi
<playername> says hi
Bank Balance
Command: "/balance"
Displays the amount of gold you have in your bank account. Must be near a banker NPC to use.
Trade
Command: "/Trade <name>"
Requests a trade with the player who's name was inserted.
Quit
Command: "/quit"
Closes the client.
Help
Command: "/help"
Brings up the help information, defined in the \ServerData\Help.ini file.
GM Commands
The following commands require the character to be marked as a GM. You need to edit vbGORE's
users table in the database to set a player as GM (GM = 1 for yes, GM = 0 for no).
By default all players start as GMs! To change this open the TCP Modules file in the Servers folder.
Look for line: 'This is for testing purposes only - remove this in any public release!
UserList(UserIndex).Flags.GMLevel = 0 (Change the 1 to 0)
Approach Player
Command: "/appr <name>"
Allows the GM to teleport or appear at the location of given player.
Map Warp
Command "/warp <mapID>"
Warps the GM to the map by index <mapID>. The GM is set on the very first non-blocked tile found.
Kick Player
Command: "/kick <name>"
Kicks the player out of the game or in other words disconnecting them from the game at that time.
Thrall
Command: "/thrall <npcnumber> <amount>"
Summons a number of NPCs by the NPC number. Thralled NPCs do not respawn.
Dethrall
Command: "/dethrall"
Kills all thralled NPCs in the screen.
Set GM Level
Command: "/setgm <name> <level>"
Sets user <name> to GM level <level>.
IP Banning
Command: "/banip <ip> <reason>"
Bans IP <ip> for reason <reason>. The reason must be specified. The IP must follow the format of
x.x.x.x, where x is any number between 0 and 255.
IP Unbanning
Command: "/unbanip <ip>"
Removes the IP ban from IP <ip>. The IP must follow the format of x.x.x.x, where x is any number
between 0 and 255.
Ban List
Command: "/banlist"
Displays a list of every IP and and the reason for the ban. Warning - with a lot of bans, this routine can
Click Warping
Command: "/clickwarp"
Toggles on and off click-warping. When toggled on, right-clicking a tile will warp you to it (or the
closest legal tile if the clicked on is not legal).
Item Search
Command: "/searchitem <name>"
Returns a list of items that contain the characters as written in the parameter <name>. List is ordered
by item ID.
SQL Query
Command: "/sql <query>"
Runs a SQL query as defined by the parameter <query> on the database. Information is reported back
to the GM running the command. Only certain operations are allowed to prevent abuse. By default, the
allowed operations are SELECT, SHOW, DESCRIBE, OPTIMIZE, REPAIR, ANALYZE, BACKUP
and FLUSH.
Kill
Command: "/kill"
Kills the PC or NPC that the user has targeted. Can not be used to kill yourself (to prevent accidental
self-killing). Nothing is rewarded to the GM using the command, nor will NPCs drop items.
Kill Map
Command: "/killmap"
Kills every NPC on the map that the GM using the command is on. Same conditions apply to the
killing as with using the /kill command.
Give Gold
Command: "/givegold <amount>"
Gives the GM <amount> gold.
Give Object
Command: "/giveobj <objindex> <amount>"
Gives the GM <amount> of object by index <objindex>. Recommended to use the /searchitem
command to find the object index.
Give Skills
Command: "/giveskill <username> <skillID>" (or /givespell)
Gives the user by name <username> the skill by ID <skillID>. The User_GiveSkill function is
used, so the same restrictions still apply that are in that, which is that the user must meet the valid
System Requirements
vbGORE is developed under Visual Basic 6, so it is bound to Windows-based operating systems or
using Wine under Linux. All information listed below are minimum requirements (and it can be
running slow, e.g.: run the server on a 3000mhz is very different than run the server at a pc with
minimum requirements).
Client Side:
Operating System: Windows 98 or later
Processor: 500mhz
RAM: 128 MB
Graphics Card: 16 MB with Direct3D 8 support
DirectX: 8.0 or higher
Disk Space: 50 MB free disk space
Server Side:
Operating System: Windows 98 or later
Processor: 800mhz (300mhz if you don't include the mysql and ODBC at the same computer)
RAM: 64 MB
Disk Space: 200 MB free disk space (includes space required for MySQL)
Database: MySQL 5.0 and ODBC 3.51
Changing Emoticons
An emoticon is a representation of emotions through characters or icons, such as :) and :(. In vbGORE,
emoticons are used to display a graphical animation of emotion above the character's head who used
the emoticon. These emoticons can be used on NPCs, too, to bring life to them.
Emoticons can be displayed, by default, by using the a combination of Control (Ctrl) + a number 0~9,
not using the numpad. Current emoticons are: 1- ... | 2- ! | 3- ? | 4- Red ! | 5- Heart |6- Cluster of hearts
| 7- Broken heart | 8- Spoon & Fork | 9- Turkey Leg | 0- !? | 12/16/07
Adding emoticon graphics is just the same as adding any other graphic to the engine.
Programming In Emoticons
The packet ID is handled by User_Emote. Do not get this confused with Comm_Emote, which is
Message Translations
The Messages in vbGORE refers to the messages that the client displays. These messages are for the
most part constant, sometimes with one or multiple variables in them in defined locations.
For example, the message:
Bandit appears to be no longer weakened.
When the server wants to send the text to a client, instead of sending the whole text as displayed in the
first example, a number is set along with any required variables. In our example, the number 1 will be
sent, followed by a string (being the NPC's name, "Bandit").
To edit the messages (or translate it), you need to work with the <yourlanguage>.ini that is located in
data/messages folder. It's important to remind that if you want to translate to a language, just copy the
original file, rename it, open, edit and save it.
You ultimately want to reach as large as a player-base as possible. This may mean encountering
players who speak a different language. I recommend using either Google Translator or WordMonkey.
How To Edit
The following rules will not break or change the way the translation functions, but are still important:
Grammar / Punctuation
Use as proper grammar and punctuation as possible. These translations are designed to be good
translations, not the quality an automatic translator gives you.
Number order
Please leave the number order in ascending order for organizational purposes.
The following are little tips and facts about the system that would be helpful to know:
Comments
Comments are signified by the -- in front of them. This is here just for reading purposes, though.
Please leave them in tact. Comments do not have to be translated, and it is recommended you do
not translate them unless you want to.
Getting stuck
If you get stuck on a translation, just skip it and make clear note that you did not translate it.
Unfinished translations should have a (Unfinished) tag in their header (ex: English
(Unfinished) ) to show that they are unfinished. At the very start, before the <pre> tag, write what
is left to be translated.
Formatting the code
Please use the <pre> and </pre> on this page at the very start and very end of the language
translation. This will put a box around the code. For an example, just refer to the currently
existing translations.
Server
<amount> and <objname> are replaced when the client reads the message from the server, and the
server must pass additional values.
After you add your messages, update _nummessages.ini with the highest message ID.
== On the server ==a
There are two ways messages are sent - either through a pre-cached byte array or by building the
message packet. Pre-cached messages can only be done for messages with no extra parameters, but are
faster and easier to write.
Pre-Cached
To add a message to the pre-cached message list, search the code for:
Const cMessages As String =
Anywhere in this huge string list, add the ID of your message. The code will take care of the rest for
you. You can now make a reference to that message by using:
cMessage(ID).Data()
Will send message 99 to the user. This is the exact same as using this code:
ConBuf.PreAllocate 2
ConBuf.Put_Byte DataCode.Server_Message
ConBuf.Put_Byte 99
Data_Send ToIndex, UserIndex, ConBuf.Get_Buffer
But using the cached message is a lot faster since the byte array is already made and the conversion
buffer doesn't have to be used as a medium to create it.
Non-Cached
Messages that have parameters must be created this way because of the extra fields they offer. You can
pass as many parameters of any type you want, but the client must know what to grab. For example,
Keep in mind you will have to denote where these parameters go in the message file, such as using <>
tags like vbGORE does by default. As long as the client knows what parameters are there, and what
they mean, you can send whatever you want.
On The Client
All the server message handling that you need to worry about happens in Sub Data_Server_Message.
For your message, add a new Case anywhere you want in the Select Case block, with the case
number being the ID number of your message.
If you do not have any parameters, like message 99, you can just go straight to handling the message.
Usually, this is just displaying the message in the message box:
Case 99
Engine_AddToChatTextBuffer Message(99), FontColor_Info
But if you have parameters, you must grab them out first before doing anything:
Case 63
Int1 = rBuf.Get_Integer
Str1 = rBuf.Get_String
TempStr = Replace$(Message(63), "<amount>", Int1)
Engine_AddToChatTextBuffer Replace$(TempStr, "<name>", Str1), FontColor_Info
As you can see, for each parameter, there is a Replace$() function. The unaltered message starts in
the variable Message(63). The altered message, the one that holds are variable replacements, is held
in the TempStr variable. As you can see, you simply just enter in the variable name you wish to
replace from your message, and the variable you wish to replace it with. For example, <amount> is
being replaced with Int1, which was our first parameter.
Monitoring Bandwidth
While adding and removing features, it is easy to unintentionally add extremely large packets or even
flood your own packets without even realizing it. It is also good to get an estimate on the rough
bytes/sec bandwidth you will have with a certain amount of players on so you can get a better idea on
Setting Up Wireshark
First off, it is recommended you do this with a public server, so set your server IP public and connect to
your server through the client with your external IP. Now, download Wireshark from the Wireshark
Download Page and install it. Load the program and click on the 2nd button on the toolbar that should
be captioned Show the capture options.... Next to the Capture Filter button, add the following line:
src port 10200 and src host <hostip>
...where <hostip> is your external IP. Now start capturing packets by pressing Start.
Packet Meanings
ACK
ACK stands for acknowledgment, which is part of the TCP structure. When a packet is sent, the
receiver of the packet sends and ACK back to tell that the packet was successfully received.
PSH
PSH is for Push, which is a packet that has data attached to it.
Len
Displays the amount of data sent in the packet. Just another way to see amount of data sent, but
from the Info bar.
Data
This is the actual information send from the server. As you notice, in comparison, the data to
overall bandwidth usage ratio if very, very bad, which is why we try to send packets as little as
possible.
Packet Buffering
vbGORE uses a custom buffering algorithm to smash together all those little packets under one header
and send it all at once, making the most out of the header size (along with it is just overall faster).
When you use Data_Send, it is actually going into a buffer of the users you specify for it to send to. It
is not until the end of the update loop for the user that the data is actually sent.
In v0.2.1, there is a "global wait" constant that can be set which will forcibly buffer for a certain period
of time. Such as if your server was running at 1000FPS, sending packets every millisecond is a total
waste, so you can set the value to 50, so it is like your packets are running at 20 FPS. That may sound
low, but think of any time you have played a game and you had a ping of 50. Did you complain? Hell
no! You were probably as giddy as a schoolgirl for such a low ping!
Packet Priorities
The packet priority system was invented (well maybe not invented, but have never heard or seen such a
system before) to combine those low-priority packets with those important packets. Just because they
are low-priority, it doesn't mean we don't want to send them, though - we are just not worried about the
time it takes for them to get there. It can be very tricky to decide what you want to use, and using
PP_None can be dangerous. Though this may help a bit:
Note that PP_None will always, as a last resort, end up attaching to the ping packet just since the
way it is structured (since the ping packet is PP_High). Be very careful with PP_None if you
remove the ping or lower the time!
PP_High
Use this for most all the packets. Try and think of what it'd be like if the packet got there about a
second later. What would it be like? If it was the server telling the client to play a sound or that a
character attacked, it wouldn't look good if it took over a second to show up, would it? No... no it
would not.
PP_Low
This will be your most commonly used "unimportant" packet state. Try to think when making a
The packet priorities in vbGORE is made very simple for the user. In the Data_Send routine, there is an
optional parameter at the end to set the packet priority. You can just ignore this value and it will
automatically be set to PP_HIGH.
Packet Structure
The packets for vbGORE are written in a byte array. A byte is the smallest sized variable you can have.
A byte array simply means a series of bytes put together. In a way, a string is like a byte array. Each
value of a byte can be 0 to 255, while each character in a string can be an ASCII character with the ID
of 0 to 255.
vbGORE makes creating the byte arrays easy for you with the DataBuffer class module. All you have
to do is get information out the same way you put it in. Each packet is structured, broadly, in the
following manner: <DataCode><DataInformation>
Your DataCode is a value from 0 to 255 which states what kind of function will take place. You can
recognize these functions by their Sub name, which start with "Data_" and end with the Datacode's
name. These functions can be anything - walking, casting spells, talking, etc. They simply just tell the
other computer what kind of packet it is.
According to the packet type, you have to get the data out accordingly. For example, if you have a
Move packet received on the server (that is, the DataCode = User_Move), your DataInformation is and
always will be one byte which states the direction the user is moving.
It is important you sync up the information of the Client and Server. You must never read data out of
the order you send it. I have made things easier for you by writing how every packet is structured under
the packet's recieve module (ie Data_Comm_Talk). The information looks like this:
'*********************************************
'Send data to chat buffer
'<Text(S)><FontColorID(B)>
'*********************************************
The first line tells what the sub does. In this case, we are using Data_Comm_Talk. As it says above,
this sends the recieved data to the chat buffer. The arguments the client sends are Text which is a String
and FontColorID which is a byte. You can tell if it is a string or byte by the (S) and (B). Below is the
list of the different identifiers:
(B) = Byte
Database
If you have have not already done so, please Setup the MySQL Database before viewing this section.
Field Descriptions
Note that there are editors (such as NPC Editor or Quest Editor), mentioned earlier, that you can use to
edit these fields with. If you are unsure of what your are doing, I recommend using the editors.
Banned Ips
The banned_ips table stores information on IP banning, along with the reasons why the IP was
banned. This only holds active bans, so any IPs listed in here will not be allowed in the game.
ip
Holds the banned IP.
reason
Mail
The mail table stores all the information on the messages currently in the game. When mail is deleted
from a user, it is deleted from here, too.
id
The unique identifier of the message. Using these numbers on the user characters, the game refers
to what mail they have. For example, if a user has 100 in one of their mail indexes, it will point to
the mail with the id of 100.
sub
Subject of the message.
by
The name of the player who created the message. Used for display purposes only when reading
the mail.
date
The date the message was created on.
msg
The body of the message.
new
If the message has been read or not by the receiver. 1 for is new, 0 for is not new.
objs
Holds information of all the objects in the mail. The first number, represents the unique ID of the
object (see objects). The second number represents the value of the item (or how many items).
Object parts (amount and ID) are split by a space, while objects as a whole are split by a line
break (vbCrLf, aka enter).
mail_lastid
The mail_lastid table is just used in conjunction with the mail table for writing mail.
lastid
Holds the last mail ID written to. This is a faster alternative to using a descending sort on the mail
to find the highest ID. Is only used for writing mail.
NPCs
The npcs table holds templates of what to create NPCs from. After being loaded from here, they can be
name
The name of the NPC.
descr
The description displayed when right-clicking the NPC.
ai
States which AI algorithm to use in the NPC_AI sub located in the server code.
chat
States the chat information the NPC uses. This refers to the NPC chat information in the
\Data\NPC Chat\ folder. Set to 0 to not use NPC chat.
respawnwait
The time it takes the NPC to respawn after killed, in milliseconds.
attackable
Tell us, if the NPC is attackable or not. 1 is Yes, 0 is No.
attackgrh
The GRH value of the attack.
attackrange
The range of the attack, used for ranged attacks, e.g with bows and arrows. If this value is 0 or 1,
the attack will be marked as a melee attack. If not, the range of the attack is based on tiles.
projectileroatespeed
How fast the projectile grh rotates on the client's screen (in no specific unit of measurement), if a
projectile.
hostile
If the NPC hostile or not (goes and attacks players). 0 is No, 1 is Yes.
quest
The quest ID of the NPC. 0 is no quest, any other number refers to the quest with the
corresponding ID in the quests table.
drops
The objects that the NPC drops when it dies. The first value is the object ID, second is the
amount of the item that is dropped, and the third is the chance, in percent, that the item will drop.
give_gold
The amount of Gold dropped, when the NPC is killed
objs_shop
The objects that the NPC sells. If this field is set to an empty string, the NPC will not act as a
vendor. Anything other value has to follow this format: The first value contains the ID of the
object sold, while the second value contains the amount of the objects in stock in the store (use -1
for infinite to ignore this feature). Each field is separated by a space, and each object is separated
by a line break.
char_hair
Holds the hair paper-doll values used on the NPC. Refers to the values found in \Data\Hair.dat.
char_head
Holds the head paper-doll values used on the NPC. Refers to the values found in
\Data\Head.dat.
char_body
Holds the body paper-doll values used on the NPC. Refers to the values found in
\Data\Body.dat.
char_weapon
Holds the weapon paper-doll values used on the NPC. Refers to the values found in
\Data\Weapon.dat.
char_wings
Holds the wings paper-doll values used on the NPC. Refers to the values found in
\Data\Wings.dat.
char_mount
Holds the mount paper-doll values used on the NPC. Refers to the values found in
\Data\Mounts.dat.
char_shield
Holds the shield paper-doll values used on the NPC. Refers to the values found in
\Data\Shield.dat.
char_heading
Holds the default heading the NPC is facing by numerical value. 1 = North, 2 = East, 3 = South, 4
= West, 5 = North-East, 6 = South-East, 7 = South-West, 8 = North-West.
Job
If AI is 10 (Job), what job menu to show?
char_headheading
Holds the default head heading (direction the NPC's head faces) by numerical value. Refer to the
above for the values.
stat_hitrate
Holds the hit rate of the NPC's attack. The higher the hit, the more likely the hit is to land. This
value is held in the server under the Agility stat, since the NPC does not use the Agility stat by
default. By default, the user's hit rate is calculated by Agil + (Str \ 4).
stat_mag
Holds the NPC's magic stat value which is used in calculations of magic power and damage. This
value works the same as the user's magic value, but is not modified by stats or items like the user.
stat_def
Holds the NPC's defense value, which determines damage reduction upon being attacked by
normal attacks. Magic attacks can use this value for reduction if they choose to do so. This value
works the same as the user's defense value, but is not modified by stats or items like the user.
stat_speed
Holds the NPC's speed value, which states how fast they move. This value works the same as the
user's speed value, but is not modified by stats or items like the user.
stat_hit_min
Holds the minimum hit damage the NPC does. This value works the same as the user's min hit
value, but is not modified by stats or items like the user.
stat_hit_max
Holds the maximum hit damage the NPC does. This value works the same as the user's max hit
value, but is not modified by stats or items like the user.
stat_range_min
Holds the minimum hit damage the NPC does with range attacks. This value works the same as
the user's min hit value, but is not modified by stats or items like the user.
stat_range_max
Holds the maximum range damage the NPC does with range attacks. This value works the same
as the user's max hit value, but is not modified by stats or items like the user.
stat_hp
Holds the maximum health the NPC has.
stat_sp
Holds the maximum stamina the NPC has.
Objects
id
The unique identifier of the object (points to the array index in the server's ObjData() array).
name
The name of the object.
price
The price of the object when purchased from a shop. Price when selling to a shop follows a
reduction equation based off of this value.
objtype
States what type of object it is. Each type is handled different. Only one object from each type
can be equipped at once (if it can be equipped). The object types can be found in the server's
Declares module for constants starting with OBJTYPE_.
• 1 – Use Once: After each usage, the item is lost. Common example is potions.
• 2 – Weapons: Set in the weapon slot of the character.
• 3 – Body armor: Set in the armor slot.
• 4 – Wings: Set in the wings slot.
• 5 – Use Infinite: Same as Use Once minus the removal after usage.
weapontype
If the object is a weapon (default value 2), then the type of weapon has to be specified. Although
not used in the vbGORE demo, it can be used to apply to class limitations and have different
modifier values. For example, a staff could be for mage only and the damage be based off of
Magic, while a sword can be for a warrior only and the damaged based off of strength. The
weapon type value and names can be found in the server's Declares module under Enum
WeaponType.
• 0 - Hand
• 1 – Staff
• 2 - Dagger
• 3 - Sword
• 4 - Throwing
weaponrange
classreq
Holds the class required to use the object. The values are stored bitwise, so to restrict multiple
classes, you have to use Class1 OR Class2 OR Class2... The values used are the ones set in the
ClassID type.
grhindex
Graphic of the item as shown in the inventory and on the ground.
usegrh
The objects Grh value, which is used to determine what Graphic the item will be represented by.
For "Use Once" objects, an graphic is displayed when used. For ranged weapons, it is the
projectile of the weapon (ninja star, arrow, bullet, etc). For melee weapons, it is the slash of the
weapon.
usesfx
The sound effect played when the object is used. If it is a weapon, it is when an attack is made.
For a use-once object, it is when the object is used.
projectilerotatespeed
If the weapon is a projectile or shoots projectiles (weaponrange > 1) and usegrh is defined, this
defines how fast the projectile rotates. Useful for throwing projectiles like ninja stars.
stacking
States how much the object can be stacked up. For non-stacking items, such as weapons and
armor, set the value as 1. Any value lower than 1 is reverted to the server default limit, which by
default, is 100 (specified in Const MaxObjAmount)
sprite_body
The GRH value, which show the objects Body Value. Used for paper dolling. Refer to the .dat file
of similar name (in this case, Body.dat) in the \Data\ folder. '-1' equals no graphic
sprite_weapon
Same as 'sprite_body', except for the weapon
sprite_shield
Same as 'sprite_body', except for the shield
sprite_mount
Same as 'sprite_body', except for the mount
sprite_hair
Same as 'sprite_body', except for the Hair
sprite_wings
Same as 'sprite_body', except for the Wings
replenish_hp
The amount of Health Points it restores
replenish_mp
The amount of Magic points it restores
replenish_sp
The amount of Speed points it restores
replenish_hp_percent
The percent amount of Health Points it restores. Max value is 100.
replenish_mp_percent
The percent amount of Magic Points it restores. Max value is 100.
replenish_sp_percent
The percent amount of Speed Points it restores. Max value is 100.
stat_str
The amount of Strength Points it adds to the player.
stat_agi
The amount of Agility Points it adds to the player.
stat_mag
The amount of Magic Points it adds to the player.
stat_def
The amount of Defence Points it adds to the player.
stat_speed
The amount of Speed Points it adds to the player.
stat_hit_min
The Minimum amount of HP it can take from a NPC, when attacked.
stat_hit_max
The Maximum amount of HP it can take from a NPC, when attacked.
stat_hp
stat_mp
The amount of Magic Points it adds to the player.
stat_sp
The amount of Speed Points it adds to the player.
stat_exp
The amount of Expirence Points it adds to the player.
stat_points
The amount of Stat Points it adds to the player.
stat_gold
The amount of Gold it adds to the player.
req_str
The required amount of strength to use the object.
req_agi
The required amount of agility to use the object.
req_mag
The required amount of magic to use the object.
req_lvl
The required level (stat ELV) to use the object.
NPC_Spawn
Index Of NPC to Spawn (For Furniture Items)
Quest
id
The unique ID of the quest
name
The name of the quest
text_start
The text shown in the Chat Box, when the player wants to start this quest.
text_accept
The text shown in the Chat Box, if the quest is accepted by the player.
text_incomplete
The text shown in the Chat Box, if the quest has been declined or failed by a player.
text_finish
Text shown in the Chat Box, if the quest has been fully completed by the player.
text_info
The information describing the quest when the user requests the quest information while having
the quest in their active quests list. By default, this can be done by typing /quest to view your list
of quests, then /quest #, where # is the ID of the quest in the user's list.
accept_req_level
The minimum level the user must be to accept the quest. The user must be this level, or higher.
accept_req_obj
The object index of the object the user must have to accept the quest. Set to 0 to not require
objects.
accept_req_objamount
If accept_req_obj is > 0, then the user must have more than or equal to this amount of the object
to accept the quest.
accept_req_finishquest
States the ID of the quest that must be finished before this quest can be accepted. Can be used to
make chains of quests. If value = 0, it will be ignored.
accept_reward_exp
The amount of experience the user gains when accepting the quest. Set to 0 for no accept
experience reward.
accept_reward_gold
The amount of gold the user gains when accepting the quest. Set to 0 for no accept gold reward.
accept_reward_obj
The object, by object index, the user receives when accepting the quest. The
accept_reward_objamount value must be set as > 0 for this to be used.
accept_reward_learnskill
The skill the user learns upon accepting the quest. Value defined by SkID (Skill ID). Set to 0 to
ignore.
finish_req_obj
The object, by object index, the user must have to successfully finish the quest. Set to 0 to ignore.
finish_req_objamount
The amount of the object defined in finish_req_obj the user must have to complete the quest.
Only used if finish_req_obj is > 0.
finish_req_killnpc
The index of the NPC that must be killed to complete the quest. Set to 0 to ignore.
finish_req_killnpcamount must be > 0 for this value to be used.
finish_req_killnpcamount
The amount of the NPC in finish_req_killnpc that must be killed. finish_req_killnpc must be > 0
for this value to be used.
finish_reward_exp
The amount of experience the user receives upon finishing the quest. Set to 0 for no experience
reward.
finish_reward_gold
The amount of gold the user receives upon finishing the quest. Set to 0 for no gold reward.
finish_reward_obj
The object the user receives upon finishing the quest. Set to 0 for no object reward.
finish_reward_objamount must be > 0 for this value to be used.
finish_reward_objamount
The amount of the reward object the user receives upon finishing a quest. finish_reward_obj must
be > 0 for this value to be used.
finish_reward_learnskill
The skill the user learns upon finishing the quest, as defined by the SkID (Skill ID).
Accounts
name
Player's account username
user1 - user5
The user's 5 character names. Players can have up to 5 characters per account
friends
The player's friend list
Blocks
The player's ignore list
Property
MapNumber
Map Number of property
Owner
Username of player who owns property
Value
Property Value/Worth
ItemsInStore
Items in the owner's store (accessed through a servant NPC)
LastVisit
Date of Owner's Last Visit
Furniture
Furniture on Map
WarpX
X coordinate of where user warps to when teleporting to house
WarpY
Y coordinate of where user warps to when teleporting to house
Premium
Premium charge on items in store
AccessLvl
Access Level for map
Adding Files
The first step to updating is to add files to be updated. All the update server (UpdateServer.exe) needs
to run is the exe itself along with the \UpdateFiles\ directory. In this directory, you will see a single
demo file if you have not changed anything that is basically a small read-me (in newer versions, it will
link you to this page). In this directory is where you want to put all the files you want updated.
Directory structure is read and preserved. The \UpdateFiles\ directory serves as the root directory of the
client. That means if you, for example, had MyFile.txt in \UpdateFiles\ directory directly, it will
download to the same directory the UpdateClient is in.
Server: \UpdateFiles\MyFile.txt
Client: \MyFile.txt
Server: \UpdateFiles\Grh\100.png
Client: \Grh\100.png
Server: \UpdateFiles\Data\NPCChat\english.txt
Client: \Data\NPCChat\english.txt
As you can see, you basically just want to copy over your copy of the client and all of its files into this
directory, then delete those that you do not want to keep up to date.
How It Works
When you run the server, you will notice a new folder pop up named \_Compressed\. What this folder
holds is a compressed version of a file, along with the MD5 hash of the original file, not the
compressed! This .md5 file is used for only one thing. When the server is run, instead of re-
compressing every single file, the MD5 hashes of the versions in the \_Compressed\ folder are
compared to the MD5 hashes of those in the \UpdateFiles\ folder. If the hash is the same, the file does
not need to be updated in the \_Compressed\ directory, which saves a lot of time. This allows you to
reboot the update server very quickly if it crashes, or only compress the files you change when you add
new ones.
The files in the \_Compressed\ folder are the actual ones that get sent to the client.
Compression
Two types of compression are used in the updater - LZMA and MAC. MAC, or Monkey Audio
Compression, is used on .wav format files while LZMA is used on every other file. The update server
and client will both just decide which one to use according to the file's suffix. If you have a graphic file
Event Structure
The first thing to happen is the update server is loaded. During this time, the following events take
place:
• All the files in the \UpdateFiles\ are found and their path stored
• A list of "short file paths" (the path of the file the \UpdateFiles\ directory) is created
• A list of the size of all the files is created
• A MD5 hash for each file is created
• A string is created that gets stored in the array ServerFileList() which contains the
"short path", file size and MD5 hash (in that order) of every single file, and is then turned into a
byte array and compressed with LZMA
• A loop is made that checks if any of the files in \_Compressed\ are not equal to or missing those
in \UpdateFiles\ and makes the compressed version if needed
• The server opens up the socket and is ready for connections
Now the server has most all the important information it needs in RAM. The ServerFileList()
contains all the information it needs to send to the client disincluding the files themselves.
When a client connects to the server:
• Server recognizes the connection, accepts it and sends the ServerFileList() array
• Client decrypts the ServerFileList() array and compares the information in that to the
files it has - if any file is has different information or is missing, a request is made to the server
to download the file
• Server receives a file download request (given the "short file path") and sends the client the file
• Once the client finishes downloading the file, it decompresses it and deletes the compressed
version
• Once the client goes through every file and confirms them all being valid, it disconnects from
the server
Compression In vbGORE
Compression algorithms, along with times to use the compression, varies greatly from game to game.
Some games use compression on textures to reduce the RAM usage at a cost of CPU usage, while other
games use compression to reduce the size of easy-to-compress (ie redundant data) files to reduce disk
space usage. In vbGORE, the only default usage of compression is in the update server, so that is where
we will be concentrating our information.
Compression Algorithms
The only compression algorithms we are going to be using in this article is the ones that come with
vbGORE. They are the following:
PAQ8l
PAQ8l is the March 8, 2007 edition of the PAQ compression series. It is one of the best
compression algorithms around, but also is easily the slowest and most memory intensive
compressions in this list. Only recommended for rare, special occasions.
LZMA
LZMA, or Lempel-Ziv-Markov chain-Algorithm, is an algorithm developed in 1998 and used in
7-Zip in the 7z format. It offers great compression at a decent speed. Its decompression is often a
few times faster than compression, though.
RLE
RLE, or Run-Length Encoding, is a very simple compression that takes runs of data (ie
AAAAAXAAA) and turns it into a shorter list (ie 5AX3A). This algorithm is very fast, though
slightly crippled from being implemented directly into the engine with VB.
RLE Looped
RLE Looped is the exact same as RLE, but the algorithm is run over and over until no more
compression can be achieved. The result is a slightly slower, yet very slightly better compression
than RLE.
Deflate64
Deflate64 is an enhanced version of Deflate, an algorithm that uses a combination of LZ77 and
Huffman encoding techniques to achieve compression. Although it has a very slow compression,
its decompression is very fast (can even reach over 100x faster than the compression). In result, it
makes a brilliant compression that is client-friendly.
Benchmarks
The following benchmarks are performed on an Intel T1300 1.66Ghz processor with 502MB of RAM
laptop. All encryption and decryption was done with the File Processor tool of vbGORE in compiled
mode.
The files compressed were all the files required by the client in the v0.5.2 release. This consisted of
231 files totaling at 15,473,310 bytes in size. Files were only compressed individually - no archiving.
Which To Use
Now that we know the benchmarks of the 5 algorithms, how do we decide which to use? First, we want
to take into consideration that compression time is not an important factor for the update server. It is
nice to have it compress fast, but I'm sure most people here wouldn't mind waiting an extra hour to gain
a bit more compression. The two important things to look at, then, is the size and decompression time.
Size has a heavier importance than decompression time, but PAQ8l is completely out until it can
manage compressing down to 5% of the original size. A full game distribution using PAQ8l is going to
run your decompression time into hours, if not days. If a client doesn't have over about 250MByes of
RAM to spare to the PAQ8l decompression process, you can expect the time to boost significantly
higher quickly.
RLE and RLE Looped are very fast, but their compression rate is way too weak, especially with RLE.
We'll hardly be saving any bandwidth with these two. That brings us down to the last two - LZMA and
Deflate64.
LZMA offers a better compression but at a slower decompression time. Though, 5.02 seconds to
decompress a series of so many files is hardly going to be a problem. For a full-sized game, this would
still take less than a few minutes for a complete update. The battle would be closer if Deflate64 had a
same compress time as LZMA, but the compression time is just insanely high compared to LZMA.
So in result, in my personal preference, the best algorithm to use for the update server would be
LZMA. If you really wanted to, PAQ8l can be used if you don't care that your users will have to suffer
a great downtime to extract the files. If you use PAQ8l, you better hope your updates are very small and
not frequent.
This section is dedicated to what you need to do when you want to release your game to make sure
everything is ready for others to use. Please note that these are just a few suggestions, and not
everything you should take into consideration. Make sure you always test your game extensively
before releasing it to the public.
Client
The client must have the external IP of the computer the server is running on hardcoded into it. Your
external IP can be acquired through websites dedicated to showing you your external IP, such as
WhatsMyIP.org. To set the IP, do the following things:
Open GameClient.vbp using Visual Studio 6. NOTEPAD WILL NOT WORK. Open TCP.bas and
under Sub initSocket
Find:
SoxID = frmMain.GOREsock.Connect(GetIPFromHost("127.0.0.1"), 10200)
Change it to:
SoxID = frmMain.GOREsock.Connect(GetIPFromHost("YOUR-IP"), PORT)
You shouldn't need change the port unless you have a firewall or a application blocking it, so, let the
port stay as 10200. For the IP, just replace the "YOUR-IP" with the IP that appeared at WhatIsMyIp.org
Once you have changed this, make sure you compile a new server exe! (Unless you plan to run your
server from the IDE, which usually a good idea, this way you can debug crashes, etc.)
Server
The server needs your internal IP so it knows what IP to bind to internally in case of situations of
multiple computers per single IP address (such as being behind a router, which most households are).
Normally, you can just set the internal ip as 0.0.0.0.
The IP for the server is stored in ...\ServerData\Server.ini. In the case you are using one server (which
is true in most cases), scroll down to [SERVER1], find IP and change it to the IP you got from above.
If the server did not bind to 0.0.0.0, then try your internal IP. To get this value, go to Start, select "Run",
type in cmd, and press enter. You will see a black screen with some white / offwhite text. Enter the
word ipconfig into this and press enter, and you will be presented with your IP Address, Subnet Mask,
and Default Gateway.
Using A DNS
You can use a DNS (such as www.mygame.com or mygame.somesite.com) instead of a raw IP address.
This allows you to not have to update the client every time your IP address changes. If you do not
already have a DNS of your own, you can use No-IP.com to get one for free. This DNS will only be for
replacing your client IP, not your server IP! Instead of entering your IP in the client now, you enter in
your DNS. For example:
Would become:
SoxID = GOREsock.Connect(GetIPFromHost("mygame.no-ip.com"), 10200)
You must make sure you update your DNS redirection IP every time your external IP changes, though.
This change can happen whenever your router reboots, so make sure to check after every time your
router shuts off.
Port Forwarding
If the server is on a computer behind a router, you will have to forward the ports used by the server in
your router. Also, if you have any firewall programs running on the server computer, you will have to
open the ports on those, too. More about port forwarding can be found at PortForward.com.
File Distribution
EditorMap
This is the remote program, that is used to edit all the maps related to your game.
EditorParticle
Helps you edit particle effects - requires you going through the code to edit the effects, though.
Used as a easier and faster way to view the effects. It's not really an editor.
GameClient
Runs the main game. You must have the server up to get past the login screen.
GameServer
Runs the main game server. The server will automatically initialize when loaded, so all you have
to do is open it up.
ToolColorCon
A simple program for converting between ARGB, RGB and Long values. This tool has been
intigrated into the Map Editor, which can be brought up by clicking the asterisk ( * ) next to color
input boxes.
ToolFreeNumber
Automatic finds for you the 15 smallest unused graphic file number and unused GRH value for
your convince.
ToolLogRemover
A tool that removes the current log files of the game.
ToolRebooter
When running, this tool automatically reboots the server if the GameServer crashes or stops
running for any reason.
ToolGrhCategorizer
This tool allows to sort all your GRH's graphics into different categorises for easier use in the
EditorMap.
ToolFolderCompress
An outdated/unused tool... compresses and decompresses a whole folder (use just as a reference).
ToolGrhDatMaker
Turns your Grh1.raw files into Grh.dat files, and calculates the values for your Grh.ini file.
ToolServerFPSViewer
Client Folders
These folders are needed by the client only:
Data
Holds general data of the game
Grh
Holds the graphic files
Music
Holds the game's music
Sfx
Holds the sound effect files
Server Folders
These folders are needed by the server only:
Backup
Contains backup map files from the server
Data2
Holds the server data
MapsEX
Holds more precise map information like object/npc placement, name, music info, etc.
ServerData
Holds general data for the server (such as MOTD)
UpdateFiles
Holds the files that will be sent to the client through the updater
To summarize; The client you distribute needs the following folders: Data, Grh, Music, Sfx, Maps It
will also need an EXE for your game (GameClient.exe by default - Make sure you have changed the IP
in this!) It's generally a good idea to include the config program, and if you have one set up, an updater
too. You will also need various DLLs, these can be found in a folder called "Libaries", either include
these along with the GameClient.exe or have the installer set them up. Make sure the
GoreSockClient.ocx is in there too.
Closing Remarks
Good luck on your game! Once you have a website up and going for your game, you can submit it to
vbGOREmania to posted to the Games Section.
Special thanks to Spodi who made vbGORE, on which vbGOREmania is based. Also thanks to the
vbGORE and vbGORE community for their contributions, especially those who contributed articles to
the vbGORE wiki, on which this guide is largely based.