前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >组队和公会系统的功能实现

组队和公会系统的功能实现

作者头像
深雾
发布2020-07-10 10:33:44
2.3K0
发布2020-07-10 10:33:44
举报
文章被收录于专栏:工具类工具类

放一起讲是觉得这两个功能比较类似,区别是公会数据保存在数据库里

组队数据结构

服务器队伍类,组队数据仅在内存中使用,如果做成支付宝种树,叠猫猫那类持久组队,可以新建张数据表

代码语言:javascript
复制
function TeamMgr:Init()
	self.teamlist = {}
	self.singlePersion = {}
end

玩家队伍数据

代码语言:javascript
复制
local Team = oo.class()
local _TEAM_MEM_NUM = 5 --一个队伍最多有5个成员,包括仙君和玩家--

function Team:ctor(teamid,player,targetid)
	self.teamid = teamid
	self.leader = player
	self.targetid = targetid
	self.cfgid = math.floor(targetid / 1000)
	self.index =  targetid % 1000
	self.isAuto = 1--是否进行自动匹配	 
	if self.targetid == 0 then
		self.isAuto = 0--是否进行自动匹配
	end
	self.memlist = {player}
	self.xianjunlist = {}
	self.levelRange = {0,1000}
	--self.xianjunStar = 0
end

组队功能

组队事件

注册onJoinTeam入队和onLeaveTeam离队方法

代码语言:javascript
复制
function TeamPerson:ctor(player,targetid)
	self.player = player
	self.targetid = targetid
	self.cfgid = math.floor(targetid / 1000)
end

function TeamPerson:init()	
	self.config = server.configCenter.TeamTargetConfig[self.cfgid]
	if not self.config then 
		return false
	end	
	self.m_joinTeamE = self.player:SubEvent(server.enEvent.PlayerEvnt.EVENTID_ENTITY_JION_TEAM,self.onJoinTeam,self)
	self.m_leaveTeamE = self.player:SubEvent(server.enEvent.PlayerEvnt.EVENTID_ENTITY_LEAVE_TEAM,self.onLeaveTeam,self)
	return true
end
--示例
function TeamPerson:onLeaveTeam(args)
	if args.entityID ~= self.player.entityID then
		return
	end
	--删除定时器
	if self.del_timer  then 
		lua_app.del_timer(self.del_timer)
		self.del_timer =  nil
	end 
end

创建队伍

代码语言:javascript
复制
function TeamMgr:createTeam(player,targetid)
	if player.prop.teamid ~= 0 then --已经有队伍不能再次创建
		return false
	end
	local teamid =  _Cur_TeamID + 1
	local team =  Team.new(teamid,player,targetid)
	if team and team:init(true) then
		_Cur_TeamID = teamid
		self.teamlist[teamid] = team
	else
		return false
	end
	--触发入队事件
	local args = {}
	args.entityID = player.entityID  --创建队伍
	args.teamid = teamid
	args.EventID = server.enEvent.PlayerEvnt.EVENTID_ENTITY_JION_TEAM
	player:FireEvent(args.EventID,args)
	local function  _matchTeam()
		if self.matchTime then
			lua_app.del_timer(self.matchTime)
		end
		if next(self.singlePersion) then
			self:doMatch() 
		end
		self.matchTime =  lua_app.add_timer(5000, _matchTeam)
	end
	if not self.matchTime then
		self.matchTime =  lua_app.add_timer(5000, _matchTeam)
	end
	--存在目标的的可以进行发送超链接
	if targetid and targetid > 0 then
		local info = team:getTargetInfo()		
		local players = {}
		for _, actor in pairs(server.playerCenter:GetOnlinePlayers()) do
			if actor.prop.level >= team.levelRange[1] and 
			actor.prop.level <= team.levelRange[2] then
				table.insert(players,actor)
			end
		end
	server.chatCenter:SendLink2SomePalyers(1320,player,players,info.activeName,info.rangeName,
		{server.ChatLinkType.team,teamid,player.entityID,"申请组队"})
	end 
	return true
end

申请加入队伍

与客户端通信协议

代码语言:javascript
复制
--[[
#请求加入队伍
cs_team_jointeam 17002 {
	request { 
	teamid	0 : integer
	}
}

]]
function server.cs_team_jointeam(socketid, msg)
    local player = server.playerCenter:GetPlayerBySocket(socketid)
    server.teamMgr:joinTeam(msg.teamid,player.entityID)
end

服务器验证队伍信息

代码语言:javascript
复制
function TeamMgr:joinTeam(teamid,entityID)
	local player  = server.gameEntityCenter:GetEntityByID(entityID)
	if not player then
		return false
	end
	local team = self.teamlist[teamid]
	if not team then
		--链接已经失效
		server.chatCenter:sendTipMsg(1321,player.dbid)
		return false
	end
	if player.prop.teamid ~= 0 then
		server.sendErr(player, "你已经有队伍了")
		return false
	end
	--判断是否满组队伍的要求
	if not team:canJoinTeam(player) then
		server.chatCenter:sendTipMsg(1322,player.dbid,tostring(team.levelRange[1]))
		return false
	end
	if team:GetMemberCount() >= _MaxCount then
		server.chatCenter:sendTipMsg(1321,player.dbid)
		return false
	end
	return team:joinTeam(player)
end

玩家队伍类处理

代码语言:javascript
复制
function Team:joinTeam(player)
	if player.prop.teamid ~= 0 then
		return false
	end
	if self:GetMemberCount() >= 3 then
		return false
	end
	--加入者在战斗中
	if player.prop.status == server.enDef.entityStatus.fighting then
		return false
	end
	--队长在战斗中
	if self.leader.prop.status == server.enDef.entityStatus.fighting then
		return false
	end
	local targetEntity =  self.memlist[#self.memlist]
	if not server.mapMgr:Fly(player.entityID,targetEntity.prop.mapID,targetEntity.prop.sceneID,targetEntity.prop.x,targetEntity.prop.y,true) then
		return false
	end
	table.insert(self.memlist,player)
	player.prop.teamid = self.teamid
	self:resetXianJun()
	self:Broadcast("sc_team_info",{data = self:packMsg()})
	local args = {}
	args.entityID = player.entityID  --加入队伍的实体id
	args.teamid = self.teamid
	args.EventID = server.enEvent.PlayerEvnt.EVENTID_ENTITY_JION_TEAM
	for _,mem in pairs(self.memlist) do
		mem:FireEvent(args.EventID,args)
	end
	return true
end

邀请加入队伍

代码语言:javascript
复制
function TeamMgr:inviteJoinTeam(player,beinviteid)
	local team = self:getTeam(player.prop.teamid)
	if not team then
		server.sendErr(self.player, "你还没有队伍,无法邀请别人")
		return false
	end
	local beinviter = server.playerCenter:GetPlayerByDBID(beinviteid)
	--local beinviter = server.gameEntityCenter:GetEntityByID(beinviteid)	
	if not beinviter or beinviter.prop.teamid ~= 0 then
		server.sendErr(self.player, "被邀请的人不存在,或者被邀请者已经有队伍了")
		return false
	end 
	if not team:canJoinTeam(beinviter) then 
		server.chatCenter:sendTipMsg(1323,player.dbid,tostring(team.levelRange[1]))
		return false
	end 
	--通知被邀请
	local msg  =  {}
	msg.inviteid =  player.dbid
	msg.inviteTeamid = player.prop.teamid
	msg.targetid = team.targetid
	msg.inviteName = player.prop.name
	beinviter:sendReq("sc_team_invite",msg)
	return true
end

响应邀请

teamid 0 : integer #响应的队伍id inviteid 1 : integer #邀请者的dbid isConfirm 2 : integer #同意 1, 拒绝0

代码语言:javascript
复制
function TeamMgr:responeInvite(teamid,inviteid,beInviteEnityid,isconfirm)
	--local inviter = server.gameEntityCenter:GetEntityByID(inviteid)	
	local inviter = server.playerCenter:GetPlayerByDBID(inviteid)
	if not  inviter or inviter.prop.teamid ~= teamid then
		return false
	end
	local team = self.teamlist[teamid]
	if not team then
		return false
	end
	local beinviter = server.gameEntityCenter:GetEntityByID(beInviteEnityid)	
	if not beinviter  or beinviter.prop.teamid ~= 0 then
		return false
	end
	if not team:canJoinTeam(beinviter) then 
		lua_app.log_info("忙活了半天,还是不能加入队伍, 被邀请者等级不符合条件,或者队长在战斗中")
		return false
	end
	if isconfirm == 1 then
		team:joinTeam(beinviter)
		return  true
	end
	--对邀请者发送 被邀请者拒绝入队的提示
	server.sendErr(inviter,beinviter.prop.name.."拒绝加入队伍")
	return true
end

踢出队伍

代码语言:javascript
复制
function TeamMgr:kickMem(player,entityID)
	local kickPlayer = server.gameEntityCenter:GetEntityByID(entityID)
	if not  kickPlayer then
		return false
	end
	local teamid = player.prop.teamid
	if teamid ~= kickPlayer.prop.teamid then
		return false
	end
	local team = self.teamlist[teamid]
	if not team then
		return false
	end
	if not team:isLeader(player.entityID) then
		server.sendErr(self.player, "你不是队长,没有踢人的权限")
		return false
	end
	local ret =  team:kickTeam(player,kickPlayer)
	if ret then 
		local teamPsersion  =  self.singlePersion[entityID]
		if teamPsersion  then
			teamPsersion:sendMyInfo()
		end
	end
	return ret
end

玩家组队类踢出

代码语言:javascript
复制
function Team:kickTeam(leader,beKicker)
	if leader.dbid ~=  self.leader.dbid then
		return false
	end
	if beKicker.prop.teamid ~=  self.teamid then
		return false
	end
	if leader.entityID ~= self.leader.entityID then
		return false
	end
	local args = {}
	args.entityID = beKicker.entityID  --离开队伍的的实体id
	args.EventID = server.enEvent.PlayerEvnt.EVENTID_ENTITY_LEAVE_TEAM
	args.teamid = self.teamid
	for _,mem in pairs(self.memlist) do
		mem:FireEvent(args.EventID,args)
	end
	for i = 1,#self.memlist do 
		if self.memlist[i].entityID == beKicker.entityID then
			table.remove(self.memlist,i)
			break
		end
	end
	beKicker.prop.teamid = 0
	--直接向客服端发送离开队伍
	local leavemsg = {}
	beKicker:sendReq("sc_team_leave",leavemsg)
	--重新甚至队伍的仙君信息
	self:resetXianJun()
	self:Broadcast("sc_team_info",{data = self:packMsg()})
end

离开队伍

代码语言:javascript
复制
function TeamMgr:leaveTeam(player)
	local teamid = player.prop.teamid
	local team = self.teamlist[teamid]
	if not team then
		player.prop.teamid = 0
		server.sendErr(self.player, "你没有队伍,无需离队")
		return false
	end
	local ret =  team:leaveTeam(player)
	if ret then 
		--主动离队要删除自己的自动匹配
		self:deletePerson(player.entityID)
	end 
	return ret
end

玩家组队类离开队伍

代码语言:javascript
复制
function Team:leaveTeam(player)
	if player.prop.teamid ~= self.teamid then
		return false
	end
	local args = {}
	args.entityID = player.entityID  --离开队伍的实体id
	args.EventID = server.enEvent.PlayerEvnt.EVENTID_ENTITY_LEAVE_TEAM
	args.teamid = self.teamid
	args.preStatus = server.enDef.teamStatues.mem
	if self:isLeader(player.entityID) then
		args.preStatus = server.enDef.teamStatues.leader
	end
	for _,mem in pairs(self.memlist) do
		mem:FireEvent(args.EventID,args)
	end
	--确定可以离队了,先清掉队伍id吧
	player.prop.teamid =  0
	player.prop.leaderSign = 0
	--直接向客服端发送离开队伍
	local leavemsg = {}
	player:sendReq("sc_team_leave",leavemsg)
	--战斗中允许直接离队,先这样吧
	if self.leader.entityID == player.entityID then
		--离队的是队长
		local mem = {}
		for i = 2 ,#self.memlist do 
			table.insert(mem,self.memlist[i])
		end
		self.memlist =  mem
		if #self.memlist > 0 then
			self.leader = self.memlist[1]
			self.leader.prop.leaderSign = 1
			local largs = {}
			largs.newLeader = self.leader.entityID  --新的队长
			largs.oldLeader = player.entityID --老的队长 ,此处队长可能已经不再队伍里面了
			largs.EventID = server.enEvent.PlayerEvnt.EVENTID_ENTITY_BE_TEAM_LEADER
			largs.teamid = self.teamid
			for _,mem in pairs(self.memlist) do
				mem:FireEvent(largs.EventID,largs)
			end
		else 
			--队伍解散了
			server.teamMgr:deleteTeam(self.teamid)
			player.prop.teamid =  0
			return true
		end
	else
		for i =  2 ,#self.memlist do 
			if self.memlist[i].entityID == player.entityID then
				table.remove(self.memlist,i)
				break
			end
		end
	end
	self:resetXianJun()
	self:Broadcast("sc_team_info",{data = self:packMsg()})
end

获取组队目标下的队伍列表

代码语言:javascript
复制
function TeamMgr:getAndSendTeamList(player,targetid)
	if not targetid then
		return false
	end 
	local msg =  {}
	local cfgid = math.floor(targetid / 1000)
	--获取目标相同的所有,可以匹配的队伍
	for teamid,team in pairs(self.teamlist) do 
		if team.cfgid == cfgid and team:GetMemberCount() < 3 then
			local teammsg =  team:packTeamShowMsg()
			table.insert(msg,teammsg)
		end
	end
	if #msg > 0 then
		player:sendReq("sc_team_list",{targetid =  targetid,teamlist = msg})
		table.print(msg)
		return true
	end
end

更改组队设置

targetid 0 : integer #如果是队长该id为cfgid*1000 +index ,如果是队员改id直接是 cfgid isAuto 1 : integer #设置自动匹配或者取消自动匹配

代码语言:javascript
复制
function TeamMgr:setAutoMatch(player,targetid,isAuto)
	local teamid = player.prop.teamid
	if teamid == 0 then
		if not isAuto then
			self:deletePerson(player.entityID)
			return true
		end
		local teamPsersion  =  self.singlePersion[player.entityID]
		if teamPsersion  and teamPsersion.release then
			teamPsersion:release()
			self.singlePersion[player.entityID] = nil
		end
		local persion =  TeamPerson.new(player,targetid)
		if not persion or not persion:init() then
			return false
		end
		self.singlePersion[player.entityID] = persion
		return true
	end
	--如果有队伍
	local team = self.teamlist[teamid]
	if not team then
		player.prop.teamid = 0 
		return false
	end
	if not team:isLeader(player.entityID) then
		return false
	end
    return team:setTarget(targetid,isAuto)
end

玩家组队类设置

代码语言:javascript
复制
function Team:setTarget(targetid,isAuto)
	if #self.memlist >= 3 then
		return false
	end
	if self.isAuto == isAuto and self.targetid == targetid then
		--没有任何变化,不用继续去处理了
		return true
	end
	self.isAuto  = isAuto
	if self.targetid == targetid then
		local msg = {targetid = self.targetid ,isAuto = self.isAuto}
		self:Broadcast("sc_team_target", msg)
		return true
	end
	self.targetid = targetid 
	local cfgid = math.floor(targetid / 1000)
	local index =  targetid % 1000	
	if self.targetid > 0 then
		self.config = server.configCenter.TeamTargetConfig[cfgid]
		if not self.config then
			return false
		end
		--等级段
		local range = self.config.levelrange[index]
		if not range then 
			return false
		end
		if range[0] == -1 then
			if index <=  1 then
				return false
			end
			local prerange =  self.config.levelrange[index -1]
			local minlvl =  self.player.prop.level - 5 
			minlvl =  math.max(minlvl,prerange[0] + 5)
			self.levelRange[1] =  minlvl
			self.levelRange[2] =  range[2]
		else 
			self.levelRange[1] = range[1]
			self.levelRange[2] =  range[2]
		end
		local info = self:getTargetInfo()
		local players = {}
		for _, player in pairs(server.playerCenter:GetOnlinePlayers()) do
			if player.prop.level >= self.levelRange[1] and 
				player.prop.level <= self.levelRange[2] then
				table.insert(players,player)
			end 
		end
		--发送超链接
		server.chatCenter:SendLink2SomePalyers(1320,self.leader,players,info.activeName,info.rangeName,				{server.ChatLinkType.team,self.teamid,self.leader.entityID,"申请组队"})
	else 
		self.levelRange = {0,1000}
		self.isAuto = 0
		self.config = nil
	end
	self.targetid = targetid 
	self.cfgid = cfgid
	self.index =  index	
	local msg = {targetid = self.targetid ,isAuto = self.isAuto}
	--广播目标改变信息	
	self:Broadcast("sc_team_target",msg)
	return true
end

公会基本结构

公会和组队类似不多讲了,只是数据保存在公会表中

公会数据

玩家实体信息保存公会id和活动数据

代码语言:javascript
复制
		{ "guildid" 	 		,"bigint(20)"		,0		,"公会ID" },
		{ "guildcontribute" 	,"bigint(20)"		,0		,"公会贡献" },
		{ "guild_data"					,"mediumblob"		,{
			skillinfo = {skills = {}},
			fuli	  =  {},
			pray	  =  {},
		}		,"玩家公会数据" },

公会表保存公会信息

代码语言:javascript
复制
guild = {
	columns = {
		{ "dbid"			,"bigint(20)"		,0		,"公会id" },
		{ "name"			,"varchar(128)"		,""		,"公会名称" },
		{ "serverid" 		,"int(11)"			,0		,"公会创建所在服务器" },
		{ "changename_count","int(11)"			,0		,"剩余改名次数" },
		{ "players"			,"mediumblob"		,{}		,"公会成员表" },
		{ "level"			,"int(11)"			,0		,"帮派等级" },
		{ "notice"			,"varchar(256)"		,""		,"帮派签名" },
		{ "fund"			,"int(11)"			,0		,"帮派资金" },
		{ "fuliawardtips"	,"mediumblob"		,{}		,"福利抽奖传闻列表" },
		{ "partnerswapbit"  ,"mediumblob"       ,{}     ,"仙君碎片交换区"},
		{ "partnerswaphis"  ,"mediumblob"       ,{}     ,"仙君交换历史数据"},
	},
	prikey = { "dbid" },
	comment = "公会表",
	initdbid = "platonly",
},

公会管理类

初始加载信息,对应guild表

代码语言:javascript
复制
function Guild:Init(cache)
	self.cache = cache
	self:RefrushData()	
end

function Guild:RefrushData()
	self.dbid = self.cache.dbid
	self.players = {}
	self.admin = {}
	for _, v in ipairs(self.cache.players) do
		self.players[v.playerid] = v
		if v.office ~= _Office.Mem then
			if v.office == _Office.Leader then
				self.leader = self.players[v.playerid]
			end
			self.admin[v.playerid] = v
		end
	end
	self.summary = {
			id = self.dbid,
			level = self.cache.level,
			playercount = #self.cache.players,
			name = self.cache.name,
			leaderinfo = self.leader,
			notice = self.cache.notice
		}
end

创建公会

代码语言:javascript
复制
function Guild:Create(data)
	data.serverid = server.serverID
	self.cache = server.mysqlBlob:CreateDmg(tbname,data,true)
	self:RefrushData()
	self.sceneid = server.mapMgr:createMap(GuildConfig.MapID, self.cache.dbid)
	self.guildmapid = GuildConfig.MapID
	self.guildRobberCtrl = GuildRobberCtrl.new()
	self.guildRobberCtrl:Create(self.dbid, self.sceneid)
end

玩家公会类

对应数据guild_data,主管管理活动信息

代码语言:javascript
复制
local GuildCtrl = oo.class()

function GuildCtrl:ctor(player)
	self.player = player
	self.guildSkill = GuildSkill.new(player,self)
	self.guildFuLi =  GuildFuLi.new(player,self)
	self.guildPray =  GuildPray.new(player,self)
end

function GuildCtrl:onCreate()
	self:onLoad()
end

function GuildCtrl:onLoad()
	self.cache = self.player.cache.guild_data
	self:Init(self.cache)
end

公会活动示例

代码语言:javascript
复制
--帮派祈愿
local GuildPray = oo.class()

local MAX_TASKID = 3

function GuildPray:ctor(player, guildctrl)
	self.player = player
	self.guildctrl = guildctrl
end

function GuildPray:Init(datas)
	self.cache = datas.pray or {}
	self.cache.offerGoods = self.cache.offerGoods or {}
	self.cache.circleCount = self.cache.circleCount  or 0
	self.cache.iscomplete = self.cache.iscomplete or 0
	self.cache.updatetime = self.cache.updatetime or 0
end

function GuildPray:onJoinGuild(guild)
	local playerinfo = guild:GetPlayerInfo(self.player.dbid)
	if not playerinfo then
		return
	end
	self:Refresh()
	self:SendClientMsg()
end

公会和组队功能应该也很比较有参考意义

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-06-28 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 组队数据结构
    • 玩家队伍数据
    • 组队功能
      • 组队事件
        • 创建队伍
          • 申请加入队伍
            • 邀请加入队伍
              • 响应邀请
                • 踢出队伍
                  • 离开队伍
                    • 获取组队目标下的队伍列表
                      • 更改组队设置
                      • 公会基本结构
                        • 公会数据
                          • 公会管理类
                            • 玩家公会类
                              • 公会活动示例
                          领券
                          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档