Guild System
From VbGORE Visual Basic Online RPG Engine
The guild system is quite basic. It extends the group chat (that, and replaces it). So, what happens is when you run the commands to make a group, you'll actually make a guild. I also added new commands to assign rank and kick a user from the guild. And /ginfo will return the guild name and the users (Rank User (Lvl)). And group members nearby will share xp when pursuing combat. Also, you can't attack fellow members of the guild.
This sets up the foundation for more guild stuff. Btw, if anyone improves on this, It would be much appreciated if you share the improvements.
Contents |
Client
We'll start with the Client Side:
DataIDs.bas Find "User_Group_Make As Byte" and below it add this:
<vb> User_Group_Kick As Byte
User_Group_Assign As Byte</vb>
Then find ".Server_KeepAlive = 121" and below it add
<vb> .User_Group_Kick = 123 'Kicks a user from group
.User_Group_Assign = 124 'Assigns rank to user in group</vb>
If those numbers are in use, just change them to some other free number.
Input.bas
Go to Input_HandleCommands and find "ElseIf Input_GetCommand("/CREATEG")"
Change that block of code to the following:
<vb> ElseIf Input_GetCommand("/CREATEG") Or Input_GetCommand("/MAKEG") Or Input_GetCommand("/NEWG") Then
s = Input_GetBufferArgs
If s = vbNullString Then GoTo CleanUp
sndBuf.Put_Byte DataCode.User_Group_Make
sndBuf.Put_String s</vb>
and below this add:
<vb> ElseIf Input_GetCommand("/KICK") Then
s = Input_GetBufferArgs
If s = vbNullString Then GoTo CleanUp
sndBuf.Put_Byte DataCode.User_Group_Kick
sndBuf.Put_String s
ElseIf Input_GetCommand("/ASSIGN") Then
s = Input_GetBufferArgs
If s = vbNullString Then GoTo CleanUp
sndBuf.Put_Byte DataCode.User_Group_Assign
sndBuf.Put_String s</vb>
Server
Declares.bas Note, you can alter the group settings. just find "'Group settings" in this file. I suggest increasing the max users at least. the default 15 is a bit small.
Find "Type GroupData" and add to it this:
<vb> Name As String</vb>
Find "Type User" and add to it:
<vb> Group As String 'Name of user's group
GroupRank As Integer 'Rank of user in group (See GroupRanks)</vb>
above the "Type User" line, add this:
<vb>Public GroupRanks(1 To 6) As String</vb>
FileIO.bas go to Load_User and add to the variable declarations at the beginning this:
<vb>Dim GroupInstance As Integer</vb>
Now find "UserList(UserIndex).Stats.ModStat(SID.MaxSTA)" and below that line add:
<vb> UserList(UserIndex).Group = DB_RS!Group
UserList(UserIndex).GroupRank = DB_RS!GroupRank</vb>
just a bit below that is an "End With" line. below that line add this:
<vb> 'Join/make User's group
If Len(UserList(UserIndex).Group) > 0 Then
GroupInstance = -1
For i = 1 To NumGroups
If GroupData(i).Name = UserList(UserIndex).Group Then
GroupInstance = i
Exit For
End If
Next i
If GroupInstance = -1 Then
'No instance of group found; Create the group
i = Group_Create(UserIndex)
If i > 0 Then
GroupData(i).NumUsers = 1
ReDim GroupData(i).Users(1 To 1)
GroupData(i).Users(1) = UserIndex
UserList(UserIndex).GroupIndex = i
End If
Else
'Instance found; join the group
Group_AddUser UserIndex, GroupInstance
UserList(UserIndex).GroupIndex = GroupInstance
End If
End If</vb>
go to Save_User and find "DB_RS!stat_sp_max = .Stats.BaseStat(SID.MaxSTA)" and below it add this:
<vb> DB_RS!Group = .Group
DB_RS!GroupRank = .GroupRank</vb>
Groups.bas at the very beginning, add this sub:
<vb>Public Sub Init_GroupRanks()
GroupRanks(1) = "General" GroupRanks(2) = "Captain" GroupRanks(3) = "Lieutenant" GroupRanks(4) = "Sergeant" GroupRanks(5) = "Corporal" GroupRanks(6) = "Recruit"
End Sub</vb>
You can make your ranking system whatever you want. I made it so that the user who makes the guild becomes the "General." The General can enact any guild function (i.e. kick, assign rank, etc.). You can of course alter this and give various ranks different privileges.
TCP.bas
Add the following subs:
<vb>Sub Data_User_Group_Assign(ByRef rBuf As DataBuffer, ByVal UserIndex As Integer) '***************************************************************** 'Assign a rank to user from group '<Name(S)> '***************************************************************** Dim tNameRank() As String Dim tName As String Dim tRank As Integer Dim tIndex As Integer Dim Command As String
'get command from buffer Command = rBuf.Get_String
'Get the name and rank
tNameRank = Split(Command, " ")
If UBound(tNameRank) <> 1 Then
' improper command syntaxx
Exit Sub
Else
If Val(tNameRank(1)) > 0 And Val(tNameRank(1)) < UBound(GroupRanks) And Len(tNameRank(0)) > 0 Then
tName = tNameRank(0)
tRank = tNameRank(1)
Else
'invalid values for name and or rank
Exit Sub
End If
End If
'Make sure the user is in a group
If UserList(UserIndex).GroupIndex = 0 Then
Data_Send ToIndex, UserIndex, cMessage(113).Data()
Exit Sub
End If
'Make sure the user is the leader of the group
If Not UserList(UserIndex).GroupRank = 1 Then
Data_Send ToIndex, UserIndex, cMessage(113).Data()
Exit Sub
End If
'Get the user's index
tIndex = User_NameToIndex(tName)
'Make sure the user is already part of this group
If UserList(tIndex).GroupIndex = UserList(UserIndex).GroupIndex Then
UserList(tIndex).GroupRank = tRank
End If
End Sub
Sub Data_User_Group_Kick(ByRef rBuf As DataBuffer, ByVal UserIndex As Integer) '***************************************************************** 'Kick a user from group '<Name(S)> '***************************************************************** Dim tName As String Dim tIndex As Integer
'Get the name
tName = rBuf.Get_String
'Make sure the user is in a group
If UserList(UserIndex).GroupIndex = 0 Then
Data_Send ToIndex, UserIndex, cMessage(113).Data()
Exit Sub
End If
'Make sure the user is the leader of the group
If Not UserList(UserIndex).GroupRank = 1 Then
Data_Send ToIndex, UserIndex, cMessage(113).Data()
Exit Sub
End If
'Get the user's index
tIndex = User_NameToIndex(tName)
'Make sure the user is already part of this group
If UserList(tIndex).GroupIndex = UserList(UserIndex).GroupIndex Then
Group_RemoveUser tIndex, UserList(tIndex).GroupIndex
UserList(tIndex).Group = ""
UserList(tIndex).GroupRank = 0
End If
End Sub</vb>
Locate "Data_User_Group_Info" and change it to this:
<vb>Sub Data_User_Group_Info(ByVal UserIndex As Integer) '***************************************************************** 'User requests the information of their group '<> 'More info: http://www.vbgore.com/GameServer.TCP.Data_User_Group_Info '***************************************************************** Dim i As Byte
'Check if the user is in a group
If UserList(UserIndex).GroupIndex = 0 Then
Data_Send ToIndex, UserIndex, cMessage(123).Data()
Exit Sub
End If
ConBuf.Clear
'----- Generate the info to return to the user -----
'Group Name:
ConBuf.Allocate 9
ConBuf.Put_Byte DataCode.Comm_Talk
ConBuf.Put_String UserList(UserIndex).Group
ConBuf.Put_Byte DataCode.Comm_FontType_Group
'Members List (with level and rank)
'Returned as: Rank Name (lvl)
For i = 1 To GroupData(UserList(UserIndex).GroupIndex).NumUsers
ConBuf.Allocate 9
ConBuf.Put_Byte DataCode.Comm_Talk
ConBuf.Put_String "* " & GroupRanks(UserList(GroupData(UserList(UserIndex).GroupIndex).Users(i)).GroupRank) & " " & UserList(GroupData(UserList(UserIndex).GroupIndex).Users(i)).Name & "(" & UserList(GroupData(UserList(UserIndex).GroupIndex).Users(i)).Stats.BaseStat(SID.ELV) & ")"
ConBuf.Put_Byte DataCode.Comm_FontType_Group
Next i
'Create the group text packet
If ConBuf.HasBuffer Then Data_Send ToIndex, UserIndex, ConBuf.Get_Buffer
End Sub</vb>
Locate "Data_User_Group_Join" and add the following to the end of it:
<vb> UserList(UserIndex).Group = GroupData(UserList(UserIndex).GroupIndex).Name
UserList(UserIndex).GroupRank = 6 'set rank to recruit by default</vb>
Locate "Data_User_Group_Leave" and add the following to the bottom of it:
<vb> UserList(UserIndex).Group = ""
UserList(UserIndex).GroupRank = 0</vb>
Locate "Data_User_Group_Make" and change it to this:
<vb>Sub Data_User_Group_Make(ByRef rBuf As DataBuffer, ByVal UserIndex As Integer) '***************************************************************** 'User wants to create a new group '<> 'More info: http://www.vbgore.com/GameServer.TCP.Data_User_Group_Make '***************************************************************** Dim i As Byte Dim GroupName As String
'Make sure the user isn't already in a group
If UserList(UserIndex).GroupIndex > 0 Then Exit Sub
'Get name of new group
GroupName = rBuf.Get_String
'Make sure that group does not already exist
DB_RS.Open "SELECT DISTINCT users.Group FROM users WHERE `Group`='" & GroupName & "'", DB_Conn, adOpenStatic, adLockOptimistic
If Not DB_RS.EOF Then
DB_RS.Close
Exit Sub
End If
DB_RS.Close
'Create the group
i = Group_Create(UserIndex)
If i > 0 Then
Data_Send ToIndex, UserIndex, cMessage(116).Data()
GroupData(i).NumUsers = 1
ReDim GroupData(i).Users(1 To 1)
GroupData(i).Users(1) = UserIndex
GroupData(i).Name = GroupName
UserList(UserIndex).GroupIndex = i
UserList(UserIndex).Group = GroupName
UserList(UserIndex).GroupRank = 1
End If
End Sub</vb>
Users.bas Locate User_Attack. Find the line "'Look for user". change that block of code to this:
<vb> 'Look for user
If MapInfo(AttackPos.Map).Data(AttackPos.X, AttackPos.Y).UserIndex > 0 Then
TargetIndex = MapInfo(AttackPos.Map).Data(AttackPos.X, AttackPos.Y).UserIndex
If UserList(TargetIndex).GroupIndex <> UserList(UserIndex).GroupIndex Then
Log "User_Attack: Found a user to attack", CodeTracker '//\\LOGLINE//\\
Damage = User_AttackUser(UserIndex, TargetIndex)
If ObjData.UseGrh(UserList(UserIndex).WeaponEqpObjIndex) > 0 Then
ConBuf.PreAllocate 12
ConBuf.Put_Byte DataCode.Combo_SlashSoundRotateDamage
ConBuf.Put_Integer UserList(UserIndex).Char.CharIndex
ConBuf.Put_Integer UserList(TargetIndex).Char.CharIndex
ConBuf.Put_Long ObjData.UseGrh(UserList(UserIndex).WeaponEqpObjIndex)
ConBuf.Put_Byte UseSfx
Else
ConBuf.PreAllocate 8
ConBuf.Put_Byte DataCode.Combo_SoundRotateDamage
ConBuf.Put_Integer UserList(UserIndex).Char.CharIndex
ConBuf.Put_Integer UserList(TargetIndex).Char.CharIndex
ConBuf.Put_Byte UseSfx
End If
If Damage > 32000 Then ConBuf.Put_Integer 32000 Else ConBuf.Put_Integer Damage
Data_Send ToPCArea, UserIndex, ConBuf.Get_Buffer
User_AttackUser_ApplyDamage UserIndex, TargetIndex, Damage
Exit Sub
End If
End If</vb>
Go to your frmMain code. Go to Form_Load. Find "'Show the form - displays in the "loading" state". above that add this:
<vb> 'Initialize Group Ranks
Init_GroupRanks</vb>
Go to OnDataArrival and find "Case .User_Use: Data_User_Use rBuf, Index" below that add this:
<vb> Case .User_Group_Kick: Data_User_Group_Kick rBuf, Index
Case .User_Group_Assign: Data_User_Group_Assign rBuf, Index</vb>
MySQL Database
Go to your users table. Open it to add new columns. Add these two columns:
- Group
- DataType: tinytext - Comment: Group Name
- GroupRank
- DataType: tinyint - len: 4 - Default: 0 - Not Null?: checked - Comment: Rank in Guild
That's it (unless I missed something. If you get an error, let me know and I'll post what I overlooked).
Guild Commands
/INVITE <name> invites player to join guild
/LEAVEG leave the guild
/JOING accept an invite to join a guild
/ASSIGN <name> <#> assignes rank to a player
/KICK <name> kicks player from guild.
/CREATEG <name> /MAKEG <name> /NewG <name> all the above make a new guild with the specified name
/G <message> send message to guild members
/GINFO
/GROUPI
gets info about your guild (members, their ranks, and the guild name)
in the Input_HandleCommands, I changed GROUPI to GUILDI. that's optional of course.
This tutorial is made by: GoreMania