DJMaxus
-
Posts
403 -
Joined
-
Last visited
Never
Content Type
Profiles
Forums
Calendar
Posts posted by DJMaxus
-
-
@ThereIsNoDomino_:
> Part Two works with OE too?
This one is CS:DE only, but it would only take a few modifications to get it work with EO. -
A quick alternative is that you could set it to where the gender changes with the tab key, just edit your "HandleMenuKeyPresses" sub.
-
Provide more details about the problem.
From what I can see, its probably your Pet declaration being 0 that is giving you this error. -
Yes there is, you can do just about anything you want with the source. Before tackling this feature, however, get the hang of the source first and try smaller things, you'll then be able to develop a good enough thought process to make the spell for yourself.
-
This is a tutorial for Crystalshire Developer's Edition. It's two tutorials in one topic. The first part will allow you to have paperdolling in your game, and the second part will allow you to have gender based paperdolling in your game. Don't think I saw a paperdolling tutorial on here for CS:DE so I thought I'd share mine.
_**How It Works:**_
Everyone knows how paperdolling works, but this gender based paperdoll will have you create two folders within the paperdolling folder. One called "male" one called "female" When a player equips an item, based on their gender, it will show the corresponding graphic from the specific folder. This way, "Heavy Steel Armor" will look different on Male characters than on Female characters, but will still be the same item. All you'll have to do is put the male graphic in the male folder, female graphic in the female folder, and they of course must be the same number. Simple.
_**Part One: Standard Paperdoll**_
* Follow part one only if you want just standard paperdolling in your project.
**All Client Side**
As you may have known, Paperdolling is already in CS:DE, we just have to render it.
In **modDirectX8**
Find : **Sub GDIRenderChar**
Underneath that entire sub, we're going to add this:
```
' Paperdoll show up in item editor
Public Sub GDIRenderPaperdoll(ByRef picBox As PictureBox, ByVal Sprite As Long)
Dim height As Long, Width As Long, sRECT As RECT
' exit out if doesn't exist
If Sprite <= 0 Or Sprite > Count_Paperdoll Then Exit Sub
height = 32
Width = 32
sRECT.top = 0
sRECT.bottom = sRECT.top + height
sRECT.left = 0
sRECT.Right = sRECT.left + Width
' Start Rendering
Call D3DDevice8.Clear(0, ByVal 0, D3DCLEAR_TARGET, 0, 1#, 0)
Call D3DDevice8.BeginScene
RenderTexture Tex_Paperdoll(Sprite), 0, 0, 0, 0, Width, height, Width, height
' Finish Rendering
Call D3DDevice8.EndScene
Call D3DDevice8.Present(sRECT, ByVal 0, picBox.hwnd, ByVal 0)
End Sub
```
In : **Sub DrawPlayer**
Find:```
RenderTexture Tex_Char(Sprite), ConvertMapX(x), ConvertMapY(y), rec.left, rec.top, rec.Width, rec.height, rec.Width, rec.height
```Underneath it Add:
```
' check for paperdolling
For i = 1 To UBound(PaperdollOrder)
If GetPlayerEquipment(Index, PaperdollOrder(i)) > 0 Then
If Item(GetPlayerEquipment(Index, PaperdollOrder(i))).Paperdoll > 0 Then
Call DrawPaperdoll(x, y, Item(GetPlayerEquipment(Index, PaperdollOrder(i))).Paperdoll, Anim, spritetop)
End If
End If
Next
```
Underneath the entire **DrawPlayer** sub, paste this:
```
Public Sub DrawPaperdoll(ByVal x2 As Long, ByVal y2 As Long, ByVal Sprite As Long, ByVal Anim As Long, ByVal spritetop As Long)
Dim rec As GeomRec
If Sprite < 1 Or Sprite > Count_Paperdoll Then Exit Sub
With rec
.top = spritetop * (D3DT_TEXTURE(Tex_Paperdoll(Sprite)).height / 4)
.height = (D3DT_TEXTURE(Tex_Paperdoll(Sprite)).height / 4)
.left = Anim * (D3DT_TEXTURE(Tex_Paperdoll(Sprite)).Width / 4)
.Width = (D3DT_TEXTURE(Tex_Paperdoll(Sprite)).Width / 4)
End With
' Clip to screen
If y2 < 0 Then
With rec
.top = .top - y2
End With
y2 = 0
End If
If x2 < 0 Then
With rec
.left = .left - x2
End With
x2 = 0
End If
RenderTexture Tex_Paperdoll(Sprite), ConvertMapX(x2), ConvertMapY(y2), rec.left, rec.top, rec.Width, rec.height, rec.Width, rec.height
End Sub
```
In **Sub DrawGDI**
Find:```
GDIRenderItem frmEditor_Item.picItem, frmEditor_Item.scrlPic.value
```
Underneath it add this:
```
GDIRenderPaperdoll frmEditor_Item.picPaperdoll, frmEditor_Item.scrlPaperdoll.value
```
That's it for standard paperdolling. You now have paperdolling in your project.
_**Part Two: Gender Based Paperdoll**_
* Follow part one first, then follow this for gender based paperdolling
First thing you're going to want to do is create two folders in your "paperdolls" folder. One called "male" and one called "female"
**Server Side**
In **modServerTCP**
Find : **Function PlayerData**
Find:
```
For i = 1 To Stats.Stat_Count - 1
Buffer.WriteLong GetPlayerStat(index, i)
Next
```
Underneath it add:
```
Buffer.WriteLong GetPlayerSex(index)
```
In **modPlayer**
Add this to the bottom:
```
Function GetPlayerSex(ByVal index As Long) As Long
If index <= 0 Or index > MAX_PLAYERS Then Exit Function
GetPlayerSex = Player(index).Sex
End Function
```
**Client Side**
In **modDirectX8**
Near the top of the entire module, find this:
```
Public Tex_Paperdoll() As Long
```
And replace it with this:
```
Public Tex_Paperdoll_M() As Long
Public Tex_Paperdoll_F() As Long
```
Find:
```
Public Const Path_Paperdoll As String = "\data files\graphics\paperdolls\"
```
And replace it with this:
```
Public Const Path_Paperdoll_M As String = "\data files\graphics\paperdolls\male\"
Public Const Path_Paperdoll_F As String = "\data files\graphics\paperdolls\female\"
```
In **EngineCacheTextures**
Find:
```
' Paperdoll Textures
Count_Paperdoll = 1
Do While FileExist(App.path & Path_Paperdoll & Count_Paperdoll & ".png")
ReDim Preserve Tex_Paperdoll(0 To Count_Paperdoll)
Tex_Paperdoll(Count_Paperdoll) = SetTexturePath(App.path & Path_Paperdoll & Count_Paperdoll & ".png")
Count_Paperdoll = Count_Paperdoll + 1
Loop
Count_Paperdoll = Count_Paperdoll - 1
```
And Replace it with this:
```
' Male Paperdoll Textures
Count_Paperdoll = 1
Do While FileExist(App.Path & Path_Paperdoll_M & Count_Paperdoll & ".png")
ReDim Preserve Tex_Paperdoll_M(0 To Count_Paperdoll)
Tex_Paperdoll_M(Count_Paperdoll) = SetTexturePath(App.Path & Path_Paperdoll_M & Count_Paperdoll & ".png")
Count_Paperdoll = Count_Paperdoll + 1
Loop
Count_Paperdoll = Count_Paperdoll - 1
' Female Paperdoll Textures
Count_Paperdoll = 1
Do While FileExist(App.Path & Path_Paperdoll_F & Count_Paperdoll & ".png")
ReDim Preserve Tex_Paperdoll_F(0 To Count_Paperdoll)
Tex_Paperdoll_F(Count_Paperdoll) = SetTexturePath(App.Path & Path_Paperdoll_F & Count_Paperdoll & ".png")
Count_Paperdoll = Count_Paperdoll + 1
Loop
Count_Paperdoll = Count_Paperdoll - 1
```
Replace **Sub GDIRenderPaperdoll** with this one:
```
' Paperdoll show up in item editor
Public Sub GDIRenderPaperdoll(ByRef picBox As PictureBox, ByVal Sprite As Long)
Dim height As Long, Width As Long, sRECT As RECT
' exit out if doesn't exist
If Sprite <= 0 Or Sprite > Count_Paperdoll Then Exit Sub
height = 32
Width = 32
sRECT.top = 0
sRECT.bottom = sRECT.top + height
sRECT.left = 0
sRECT.Right = sRECT.left + Width
' Start Rendering
Call D3DDevice8.Clear(0, ByVal 0, D3DCLEAR_TARGET, 0, 1#, 0)
Call D3DDevice8.BeginScene
RenderTexture Tex_Paperdoll_M(Sprite), 0, 0, 0, 0, Width, height, Width, height
' Finish Rendering
Call D3DDevice8.EndScene
Call D3DDevice8.Present(sRECT, ByVal 0, picBox.hwnd, ByVal 0)
End Sub
```
In **Sub DrawPlayer**
Find this line:
```
Call DrawPaperdoll(x, y, Item(GetPlayerEquipment(Index, PaperdollOrder(i))).Paperdoll, Anim, spritetop)
```
Replace it with this line:
```
Call DrawPaperdoll(Index, x, y, Item(GetPlayerEquipment(Index, PaperdollOrder(i))).Paperdoll, Anim, spritetop)
```
In **modTypes**
In **Private Type PlayerRec**
Find:
```
name As String
```
Underneath it add:
```
Sex As Byte
```
Replace **Sub DrawPaperdoll** with this one:
```
Public Sub DrawPaperdoll(ByVal index As Long, ByVal x2 As Long, ByVal y2 As Long, ByVal Sprite As Long, ByVal Anim As Long, ByVal spritetop As Long)
Dim rec As GeomRec
Dim G_Paperdoll As Long
If Sprite < 1 Or Sprite > Count_Paperdoll Then Exit Sub
If GetPlayerSex(index) = SEX_MALE Then
G_Paperdoll = Tex_Paperdoll_M(Sprite)
Else
G_Paperdoll = Tex_Paperdoll_F(Sprite)
End If
With rec
.top = spritetop * (D3DT_TEXTURE(G_Paperdoll).height / 4)
.height = (D3DT_TEXTURE(G_Paperdoll).height / 4)
.left = Anim * (D3DT_TEXTURE(G_Paperdoll).Width / 4)
.Width = (D3DT_TEXTURE(G_Paperdoll).Width / 4)
End With
' Clip to screen
If y2 < 0 Then
With rec
.top = .top - y2
End With
y2 = 0
End If
If x2 < 0 Then
With rec
.left = .left - x2
End With
x2 = 0
End If
RenderTexture G_Paperdoll, ConvertMapX(x2), ConvertMapY(y2), rec.left, rec.top, rec.Width, rec.height, rec.Width, rec.height
End Sub
```
In **modDatabase**
Add This to the very bottom:
```
Function GetPlayerSex(ByVal Index As Long) As Long
' If debug mode, handle error then exit out
If Options.Debug = 1 Then On Error GoTo errorhandler
If Index > MAX_PLAYERS Then Exit Function
GetPlayerSex = Player(Index).Sex
' Error handler
Exit Function
errorhandler:
HandleError "GetPlayerPK", "modDatabase", Err.Number, Err.Description, Err.Source, Err.HelpContext
Err.Clear
Exit Function
End Function
Sub SetPlayerSex(ByVal Index As Long, ByVal Sex As Long)
' If debug mode, handle error then exit out
If Options.Debug = 1 Then On Error GoTo errorhandler
If Index > MAX_PLAYERS Then Exit Sub
Player(Index).Sex = Sex
' Error handler
Exit Sub
errorhandler:
HandleError "SetPlayerPK", "modDatabase", Err.Number, Err.Description, Err.Source, Err.HelpContext
Err.Clear
Exit Sub
End Sub
```
In **modHandleData**
Find : **Sub HandlePlayerData**
Find:
```
For x = 1 To Stats.Stat_Count - 1
SetPlayerStat i, x, Buffer.ReadLong
Next
```
Underneath it add this:
```
Call SetPlayerSex(i, Buffer.ReadLong)
```
That should be everything. You now have gender based paperdolling in your game. This is copy pasted right out of my project so if I missed anything let me know. Hope this helps you further your project. If you have any questions feel free to ask. -
255, the max size of Byte I believe.
-
What adjustments have you made to your source regarding items?
-
Search for "Public Const MAP_MORAL_SAFE As Byte = 1" in your server and add something under it like "Public Const MAP_MORAL_PVP As Byte = 2" or whatever the next number is. You then need to search for an example of checking map morals, add a new check for the PvP map, and what will happen once a player(s) is on the map.
-
There's probably a Transformation snippet in the Source Tutorial section.
-
@Santa:
> You have been a good boy this year so I have granted you Administrative powers.
But Santa, he wanted Moderator powers. Thanks, you ruined another Thanksgiving. -
They don't show up because CS:DE supports .png while EO does not. The format was also modified to support the general RMVX RTP sprites. If you want to change EO to 3 sprites per row, you would have to modify your DirectDraw module. It's just easier to find a RMVX to RMXP Sprite converter.
-
@Vindicate:
> Thanks so much for this edit and props to all the people whos coding went into it, imo the best of the best.
Makes me feel good. ;] -
Change the MAX_LEVELS constant on both the server and client.
-
And that highlighted line was..?
-
What all did you do to your map? Change anything in the source? Using EO or CS:DE?
What was that exact line that was highlighted? -
@coolkidmoa1:
> whats IDE?
What line is highlighted in VB6? -
What line is highlighted in the IDE
-
Yes you will need visual basic to change that.
-
In your PlayerAttackPlayer sub on your server, use GiveInvItem to give the player the item you created once one player kills another. Determine the item by its ID.
-
@psyDelic:
> What do you do for the wild & trails to other towns, hunting?
When I make a path running north or south, I'll make X much larger than Y, and vice versa for east and west. For a route open to exploration, you'll want to have the dimensions about 10 or 20 tiles apart from each other. I make routes around 50 - 70 as well. You'll want to place a few of them (2-5) in between towns. -
Depends on what you're making. Before you make the map, think about the location. Is it a town? A village? How many people populate it? Is it just a road? A city?
I'll usually make my small towns and villages around 50 - 70, larger towns around 70 - 90, and cities around 80 - 95 with multiple maps for different parts of the city.
That's just me though. -
Oh yeah that's right. That explains a whole lot then.
@Marsh:
> 360 leak is out. Cant wait till this download is done.
>
> Pretty sure its legit.
Sweet. -
To put items into the bank, open the bank and double click on the item in your inventory.
-
What weather tutorial? It's probably for an old version of Mirage.
Link?
[CS:DE] Character Customization (Gender & Hair)
in Source
Posted
_**How It Works:**_
This will allow you to choose the Gender and Hair of your character when you are creating them. After you have selected a class, you are able to cycle between hair and gender options for your character using buttons. Hair is a separate declaration and will appear independent from the sprite, it can be changed throughout the game. This is just a simple customization you could refer to so that you can add extra customization options if you wish. Please see attachments for the buttons you'll need to use this tutorial. To fully utilize this tutorial, you should have a set of base characters for use with your project, if anything, you can just extract the gender part out of this tutorial and forget about the hair part.
_**Screenshots:**_
>! ![](http://img543.imageshack.us/img543/8045/hairone.png)
>! ![](http://img851.imageshack.us/img851/5172/hare2.png)
>! ![](http://img14.imageshack.us/img14/7545/hayaire.png)
_**The Code:**_
==============
**Server Side**
==============
First let's add the "Hair" declaration to the PlayerRec
In **modTypes**
Find : **Private Type PlayerRec**
Find:
```
Level As Byte
```
Underneath it Add:
```
Hair As Long
```
In **modConstants**
Change **MAX_BUTTONS** Value to equal 39 instead of 35
In **modPlayer**
We're going to add a function and sub that will return the value of and set the hair, could be used for other source edits in the future.
Find: **Function GetPlayerLevel**
Above that entire function, add this:
```
Function GetPlayerHair(ByVal index As Long) As Long
If index <= 0 Or index > MAX_PLAYERS Then Exit Function
GetPlayerHair = Player(index).Hair
End Function
Sub SetPlayerHair(ByVal index As Long, ByVal Hair As Long)
If index <= 0 Or index > MAX_PLAYERS Then Exit Sub
Player(index).Hair = Hair
End Sub
```
In **modDatabase**
Find the **AddChar** Sub
We're going to modify our AddChar sub so it can know which hair will be sent from the client, look for this on the same line as the name of the sub:
```
ByVal Sprite As Long
```
Directly after it on the same line, we're going to add this:
```
, ByVal Hair As Long
```
That whole line should look like this:
```
Sub AddChar(ByVal index As Long, ByVal Name As String, ByVal Sex As Byte, ByVal ClassNum As Long, ByVal Sprite As Long, ByVal Hair As Long)
```
This will set the hair for the player on the server so it can be saved, in the same sub find this:
```
Player(index).Level = 1
```
Underneath it, add this:
```
Player(index).Hair = Hair
```
The next two additions we'll make are so that the server saves the hair value.
In the **SavePlayer** sub,
Find:
```
PutVar filename, "ACCOUNT", "Level", Val(Player(index).Level)
```
Underneath it add this:
```
PutVar filename, "ACCOUNT", "Hair", Val(Player(index).Hair)
```
In the **LoadPlayer** sub,
Find:
```
Player(index).Level = Val(GetVar(filename, "ACCOUNT", "Level"))
```
Underneath it add this:
```
Player(index).Hair = Val(GetVar(filename, "ACCOUNT", "Hair"))
```
Now we handle the sub that actually receives player data from the client. We need to tell it to read the hair value.
In **modHandleData**
Find the **HandleAddChar** sub.
Find:
```
Dim Sprite As Long
```
Underneath it add this:
```
Dim Hair As Long
```
Find:
```
Sprite = Buffer.ReadLong
```
Underneath it add this:
```
Hair = Buffer.ReadLong
```
Now we tell the AddChar sub to include hair as well
Find:
```
Call AddChar(index, Name, Sex, Class, Sprite)
```
Replace it with:
```
Call AddChar(index, Name, Sex, Class, Sprite, Hair)
```
In **modServerTCP**
Find the **PlayerData** function
Here, were going to send our saved hair value back to the client so it can load it every time.
Find:
```
Buffer.WriteLong GetPlayerLevel(index)
```
Underneath it add this:
```
Buffer.WriteLong GetPlayerHair(index)
```
That's it for server side! On to the client.
==============
**Client Side**
==============
Doing the same thing as the server here…
In **modTypes**
Find : **Private Type PlayerRec**
Find:
```
Level As Byte
```
Underneath it Add:
```
Hair As Long
```
In **modClientTCP**
Here we'll modify our SendAddChar to include a hair value to send to the server.
Replace the entire **SendAddChar** sub with this:
```
Public Sub SendAddChar(ByVal name As String, ByVal Sex As Long, ByVal ClassNum As Long, ByVal Sprite As Long, ByVal Hair As Long)
Dim Buffer As clsBuffer
' If debug mode, handle error then exit out
If Options.Debug = 1 Then On Error GoTo errorhandler
Set Buffer = New clsBuffer
Buffer.WriteLong CAddChar
Buffer.WriteString name
Buffer.WriteLong Sex
Buffer.WriteLong ClassNum
Buffer.WriteLong Sprite
Buffer.WriteLong Hair
SendData Buffer.ToArray()
Set Buffer = Nothing
' Error handler
Exit Sub
errorhandler:
HandleError "SendAddChar", "modClientTCP", Err.Number, Err.Description, Err.Source, Err.HelpContext
Err.Clear
Exit Sub
End Sub
```
In **modDatabase**
Now we'll add two subs that return or set the hair value.
Add this to the bottom:
```
Function GetPlayerHair(ByVal index As Long) As Long
' If debug mode, handle error then exit out
If Options.Debug = 1 Then On Error GoTo errorhandler
If index > MAX_PLAYERS Then Exit Function
GetPlayerHair = Player(index).Hair
' Error handler
Exit Function
errorhandler:
HandleError "GetPlayerSprite", "modDatabase", Err.Number, Err.Description, Err.Source, Err.HelpContext
Err.Clear
Exit Function
End Function
Sub SetPlayerHair(ByVal index As Long, ByVal Hair As Long)
' If debug mode, handle error then exit out
If Options.Debug = 1 Then On Error GoTo errorhandler
If index > MAX_PLAYERS Then Exit Sub
Player(index).Hair = Hair
' Error handler
Exit Sub
errorhandler:
HandleError "SetPlayerSprite", "modDatabase", Err.Number, Err.Description, Err.Source, Err.HelpContext
Err.Clear
Exit Sub
End Sub
```
In **modGlobals**
Adding in declarations that hold our gender and hair constants, can't remember if the "newCharSex" already exists or not, if it does, ignore it and don't add it.
Find:
```
' New char
Public newCharSprite As Long
Public newCharClass As Long
```
Underneath it add this:
```
Public newCharSex As Long
Public newCharHair As Long
```
In **modGeneral**
Find the **MenuState** sub
We send our hair constant to the server with our modified SendAddChar sub. Also, we tell it to select the gender we've picked at character creation.
Find:
```
Call SendAddChar(sChar, SEX_MALE, newCharClass, newCharSprite)
```
And Replace it with:
```
Call SendAddChar(sChar, newCharSex, newCharClass, newCharSprite, newCharHair)
```
In **modHandleData**
Find the **HandlePlayerData** sub,
Here we receive the saved hair constant from the server.
Find:
```
Call SetPlayerLevel(i, Buffer.ReadLong)
```
Underneath it, add this:
```
Call SetPlayerHair(i, Buffer.ReadLong)
```
Add this to the bottom of the entire modGeneral module:
```
Public Sub ChangeGender()
If newCharSex = SEX_MALE Then
newCharSex = SEX_FEMALE
Else
newCharSex = SEX_MALE
End If
End Sub
```
Now we add the graphical functions of hair.
In **modDirectX8**
Find:
```
Public Tex_Fader As Long
```
Underneath it add:
```
' Hair
Public Tex_Hair() As Long
```
Find:
```
Public Count_Fog As Long
```
Underneath it add this:
```
Public Count_Hair As Long
```
Find:
```
Public Const Path_Fog As String = "\data files\graphics\fog\"
```
Underneath it add:
```
Public Const Path_Hair As String = "\data files\graphics\characters\hair\"
```
Find:
```
' Surfaces
Count_Surface = 1
Do While FileExist(App.Path & Path_Surface & Count_Surface & ".png")
ReDim Preserve Tex_Surface(0 To Count_Surface)
Tex_Surface(Count_Surface).Path = App.Path & Path_Surface & Count_Surface & ".png"
Count_Surface = Count_Surface + 1
Loop
Count_Surface = Count_Surface - 1
```
Underneath it add this:
```
' Hair Textures
Count_Hair = 1
Do While FileExist(App.Path & Path_Hair & Count_Hair & ".png")
ReDim Preserve Tex_Hair(0 To Count_Hair)
Tex_Hair(Count_Hair) = SetTexturePath(App.Path & Path_Hair & Count_Hair & ".png")
Count_Hair = Count_Hair + 1
Loop
Count_Hair = Count_Hair - 1
```
Find your **DrawPlayer** sub
Find:
```
RenderTexture Tex_Char(Sprite), ConvertMapX(x), ConvertMapY(y), rec.left, rec.top, rec.Width, rec.height, rec.Width, rec.height
```
Underneath it add this:
```
DrawHair x, y, GetPlayerHair(index), Anim, spritetop
```
Underneath the entire **DrawPlayer** sub, add this:
```
Public Sub DrawHair(ByVal x2 As Long, ByVal y2 As Long, ByVal Hair As Long, ByVal Anim As Long, ByVal spritetop As Long)
Dim rec As GeomRec
If Hair < 1 Or Hair > Count_Hair Then Exit Sub
With rec
.top = spritetop * (D3DT_TEXTURE(Tex_Hair(Hair)).height / 4)
.height = (D3DT_TEXTURE(Tex_Hair(Hair)).height / 4)
.left = Anim * (D3DT_TEXTURE(Tex_Hair(Hair)).Width / 4)
.Width = (D3DT_TEXTURE(Tex_Hair(Hair)).Width / 4)
End With
' Clip to screen
If y2 < 0 Then
With rec
.top = .top - y2
End With
y2 = 0
End If
If x2 < 0 Then
With rec
.left = .left - x2
End With
x2 = 0
End If
RenderTexture Tex_Hair(Hair), ConvertMapX(x2), ConvertMapY(y2), rec.left, rec.top, rec.Width, rec.height, rec.Width, rec.height
End Sub
```
Up next, we will be moving some things around in the New Character screen, as well as adding in our buttons and defining what they do.
Find your **DrawNewChar** sub
Find:
```
' sprite preview
sprite = Class(newCharClass).MaleSprite(newCharSprite)
'EngineRenderRectangle Tex_Char(sprite), x + 235, y + 123, 32, 0, 32, 32, 32, 32, 32, 32
RenderTexture Tex_Char(sprite), x + 235, y + 123, 32, 0, 32, 32, 32, 32
```
Replace it with this:
```
RenderChar
RenderTexture Tex_Hair(newCharHair), x + 265, y + 120, 32, 0, 32, 32, 32, 32
```
This sub will render the correct sprite based on gender on character creation. Above the entire **DrawNewChar** sub, add this:
```
Public Sub RenderChar()
Dim Sprite As Long
Dim x As Long
Dim y As Long
x = GUIWindow(GUI_MAINMENU).x
y = GUIWindow(GUI_MAINMENU).y
If newCharSex = SEX_MALE Then
Sprite = Class(newCharClass).MaleSprite(newCharSprite)
Else
Sprite = Class(newCharClass).FemaleSprite(newCharSprite)
End If
RenderTexture Tex_Char(Sprite), x + 265, y + 120, 32, 0, 32, 32, 32, 32
End Sub
```
Time to draw our four buttons. Back in the **DrawNewChar** sub, were going to **add this just above the last "End If"**
```
' position
For buttonnum = 36 To 39
x = GUIWindow(GUI_MAINMENU).x + Buttons(buttonnum).x
y = GUIWindow(GUI_MAINMENU).y + Buttons(buttonnum).y
Width = Buttons(buttonnum).Width
height = Buttons(buttonnum).height
' render accept button
If Buttons(buttonnum).state = 2 Then
' we're clicked boyo
'EngineRenderRectangle Tex_Buttons_c(Buttons(buttonnum).PicNum), x, y, 0, 0, width, height, width, height, width, height
RenderTexture Tex_Buttons(Buttons(buttonnum).PicNum), x, y, 0, 0, Width, height, Width, height
ElseIf (GlobalX >= x And GlobalX <= x + Buttons(buttonnum).Width) And (GlobalY >= y And GlobalY <= y + Buttons(buttonnum).height) Then
' we're hoverin'
'EngineRenderRectangle Tex_Buttons_h(Buttons(buttonnum).PicNum), x, y, 0, 0, width, height, width, height, width, height
RenderTexture Tex_Buttons(Buttons(buttonnum).PicNum), x, y, 0, 0, Width, height, Width, height
' play sound if needed
If Not lastButtonSound = buttonnum Then
Play_Sound Sound_ButtonHover
lastButtonSound = buttonnum
End If
Else
' we're normal
'EngineRenderRectangle Tex_Buttons(Buttons(buttonnum).PicNum), x, y, 0, 0, width, height, width, height, width, height
RenderTexture Tex_Buttons(Buttons(buttonnum).PicNum), x, y, 0, 0, Width, height, Width, height
' reset sound if needed
If lastButtonSound = buttonnum Then lastButtonSound = 0
End If
Next
```
In **modGeneral**
Find the **InitialiseGUI** sub
This is where we defined our buttons, their sizes and position. At the very bottom of the sub but above "End Sub", were going to add in our new buttons:
```
' main - Select Gender Left
With Buttons(36)
.state = 0 'normal
.x = 175
.y = 114
.Width = 19
.height = 19
.visible = True
.PicNum = 23
End With
' main - Select Gender Right
With Buttons(37)
.state = 0 'normal
.x = 211
.y = 114
.Width = 19
.height = 19
.visible = True
.PicNum = 24
End With
' main - Select Hair Left
With Buttons(38)
.state = 0 'normal
.x = 175
.y = 141
.Width = 19
.height = 19
.visible = True
.PicNum = 23
End With
' main - Select Gender Right
With Buttons(39)
.state = 0 'normal
.x = 211
.y = 141
.Width = 19
.height = 19
.visible = True
.PicNum = 24
End With
```
In **modInput**
Find the **MainMenu_MouseDown** sub
This will check if we're clicking a button.
Add this at the bottom before "End Sub"
```
For i = 36 To 39
x = GUIWindow(GUI_MAINMENU).x + Buttons(i).x
y = GUIWindow(GUI_MAINMENU).y + Buttons(i).y
' check if we're on the button
If (GlobalX >= x And GlobalX <= x + Buttons(i).Width) And (GlobalY >= y And GlobalY <= y + Buttons(i).height) Then
Buttons(i).state = 2 ' clicked
End If
Next
```
Find the **MainMenu_MouseUp** sub
This will check if we clicked a button and what the button will do once we've clicked it.
Find:
```
' reset buttons
resetClickedButtons
```
Above it, add this:
```
' Character Customization Buttons
' find out which button we're clicking
For i = 36 To 39
x = GUIWindow(GUI_MAINMENU).x + Buttons(i).x
y = GUIWindow(GUI_MAINMENU).y + Buttons(i).y
' check if we're on the button
If (GlobalX >= x And GlobalX <= x + Buttons(i).Width) And (GlobalY >= y And GlobalY <= y + Buttons(i).height) Then
If Buttons(i).state = 2 Then
' do stuffs
Select Case i
Case 36
If curMenu = MENU_NEWCHAR Then
' do eet
ChangeGender
RenderChar
End If
Case 37
If curMenu = MENU_NEWCHAR Then
' do eet
ChangeGender
RenderChar
End If
Case 38
If curMenu = MENU_NEWCHAR Then
' Select Hair
newCharHair = newCharHair - 1
If newCharHair < 0 Then
newCharHair = Count_Hair
End If
End If
Case 39
If curMenu = MENU_NEWCHAR Then
' Cycle Hair
newCharHair = newCharHair + 1
If newCharHair > Count_Hair Then
newCharHair = 1
End If
End If
End Select
' play sound
Play_Sound Sound_ButtonClick
End If
End If
Next
```
_**Non-Code Work:**_
1\. In your graphics folder, create a new folder in your "characters" folder called "hair"
2\. Add 26.png to your /graphics/gui/ folder and replace the old one
3\. Add 23.png and 24.png to your graphics/gui/buttons/ folder.
I think that's it but I'm not sure. I have a bad habit of adding in things then forgetting what all I did to get it working, if you have trouble with the tutorial, have any questions, or find I left something out, let me know. Congrats, you now have a basic character customization screen. I hope this helps you further your project, and I hope its understandable enough for you to add your own customization options. I'll try to do my tutorials with a bit more explanation in the future.