# 范例集合

TIP

涵盖大部分接口的使用范例集合

return (function()

-- 地图常量数据
local Cfg = {
	map_size = 30,  --地图大小
	map_high = 5,   --城墙高度
	pool_width = 5, --水池竖宽
	pool_lenth = 15,--水池横长
	max_score = 35, --游戏分数
}

-- ItemID数据
local Items = {
	waterId = 4,   --水方块ID
	treatId = 8,   --加血方块ID
	floorId = 104, --地板方块ID

	fishCnt = 4,      --灯笼鱼
	fishIdx = 3600,   --灯笼鱼ID
	starCnt = 12,     --闪星数量
	starIdx = 997,    --闪星方块
	rewardCnt = 15,   --肘子数量
	rewardIdx = 12526,--大肘子ID

	redFlagId = 919,  --红旗ID
	blueFlagId = 920, --蓝旗ID

	mobsCnt = 7, --怪物数量/ID组
	mobsIdx = {3132, 3132, 3407},

	-- 测试方块trigger事件 --
	trigger_tx = 11311, --动物肥料
	trigger_x1 = 256,   --桃花树苗
	trigger_ty = 11055, --点火器
	trigger_y1 = 881,   --喷花烟花
	trigger_y2 = 931,   --蜡烛台
}
-- 系统相关数据
local Sys = {
	chatType = 1, --公告类型 1:系统公告
}
local Teams = {red=1, blue=2} --游戏队伍
local Battle = {win=1, lose=2, draw=3} --战斗结果
local LiveType = {all=-1,dead=0, alive=1} --玩家状态

-- 位置区域数据
local Pos = { --初始数据
	ix = 0, iy = 0, iz = 0, --默认出生点
	cx = 0, cz = 0, cr = 0, --雾圈原点/半径
}

-- 游戏数据
local Data = { --随游戏逻辑变更
	tickCount =  0,    -- tick计数
    newTicker = 20,	   -- 刷新时长
    glEffectId = -1,   -- 雾圈ID
    miniMarkId = -1,   -- 小地图标记
    markRadius = 100,  -- 地图标记半径
    isTimeout = false, -- 是否超时
	isGameEnd = false, -- 是否已结束
	isRuleInit = false,-- 游戏是否初始化
}

-- 游戏怪物数据
local Mobs = {
	objIds = {},--怪物objId
	gensCnt = 0,--攻击手数量
	deadCnt = 0,--已死量数量
}

-- 其他测试数据
local posBlocks = {} --正收益+5分
local negBlocks = {} --负收益/变鸡或变羊
local rewBlocks = {816, 739, 1035, 1057, 816}
local weaponIdx = {12005}--, 15000, 15501} --武器组ID
local itemBuffs = {12499, 12542, 12559}--测试Buff接口
local itemTools = {11311, 11500, 11055}--测试方块事件
local itemLamps = {881, 881, 931} --测试方块触发事件

local cgroupId1 = nil --生物组1/狼
local cgroupId2 = nil --生物组2/鱼

--[[
游戏玩法:寻找武器杀死野怪,并获取宝物积累分数,分高者胜出.
		 分数累计情况:1、获取宝物+1 杀死怪物+3 杀死对手+5 开启宝箱+7
		 游戏结束情况:1、游戏超时 2、怪物全被干掉 3、分数达到25
		 游戏其他效果:进入雾圈后debuff自动清除/踩上最上层草地后每秒加血
--]]

function ListenEvents_MiniDemo()
	--游戏事件---
	ScriptSupportEvent:registerEvent([=[Game.Start]=], Game_StartGame)
	ScriptSupportEvent:registerEvent([=[Game.Run]=], Game_Update)
	ScriptSupportEvent:registerEvent([=[Game.End]=], Game_GameEnd)
	ScriptSupportEvent:registerEvent([=[Game.TimeOver]=], Game_TimeOver)

	ScriptSupportEvent:registerEvent([=[Actor.Die]=], Actor_Die)
	--玩家事件---
	ScriptSupportEvent:registerEvent([=[Player.Init]=], Player_Inited)
	ScriptSupportEvent:registerEvent([=[Player.Die]=], Player_Dead)
	ScriptSupportEvent:registerEvent([=[Player.Revive]=], Player_Revive)
	ScriptSupportEvent:registerEvent([=[Player.AddItem]=], Player_AddItem)
	ScriptSupportEvent:registerEvent([=[Player.JoinTeam]=], Player_JoinTeam)

	--方块事件---
	ScriptSupportEvent:registerEvent_Block([=[Block.Add]=], Block_Added, {Items.redFlagId, Items.blueFlagId})
	ScriptSupportEvent:registerEvent_Block([=[Block.Remove]=], Block_Removed, {Items.redFlagId, Items.blueFlagId})
	ScriptSupportEvent:registerEvent_Block([=[Block.PlaceBy]=], Block_Placed, {rewBlocks[1]})
	ScriptSupportEvent:registerEvent_Block([=[Block.DestroyBy]=], Block_Destroy, rewBlocks)

	ScriptSupportEvent:registerEvent_Block([=[Block.Trigger]=], Block_TriggerBy, {881, 931})
	--ScriptSupportEvent:registerEvent_Block([=[Block.ActorCollide]=], Block_WalkedBy, rewBlocks)
	--ScriptSupportEvent:registerEvent_Block([=[Block.ActorWalking]=], Block_CollidedBy, {Items.treatId})
	ScriptSupportEvent:registerEvent_Block([=[Block.Fertilize]=], Block_FertilizedBy, {Items.trigger_x1})
end

-------------------------------自定义方法-------------------------------
function InitGameRule()
	Data.isRuleInit = true
	GameRule.EndTime = 9  --游戏时长
	GameRule.CurTime = 17.9  --当前时间
	GameRule.LifeNum = 3  --玩家生命
	GameRule.TeamNum = 2
	GameRule.MaxPlayers = 2

	GameRule.CameraDir = 1 --1:正视角
	GameRule.StartMode = 0 --0:房主开启
	GameRule.StartPlayers = 1
	-- GameRule.ScoreKillMob = 3 --击杀特定怪物+3分
	GameRule.ScoreKillPlayer = 5 --击杀玩家+5分
	GameRule.PlayerDieDrops = 1  --死亡掉落 1:true
	GameRule.DisplayScore = 1    --显示比分 1:true
end
function InitCenterPoint()
	-- 获取出生点,并以此设置地图中心
	local ret, x,y,z = Spawnport:getSpawnPoint()
	Pos.ix = x
	Pos.iy = y
	Pos.iz = z
	--地平面的y轴坐标为7
	if y==0 then Pos.iy = 6 end
end

function InitGamePlayer(isTestMode)
	--获取本地玩家信息
	local ret, playerId = Player:getMainPlayerUin()
	if ret==ErrorCode.OK then Backpack:clearAllPack(playerId) end

	local teamId = isClient and Teams.blue or Teams.red
	local result = Player:setTeam(playerId, teamId) --主机默认为红队
	if result==ErrorCode.OK then ResetPosition(playerId, teamId) end

	GainItems(playerId) --默认给玩家的道具

	if isTestMode then --枪械测试
		-- local itemId, itemCnt = 12247, 1 --彩蛋枪
		-- Player:gainItems(playerId, itemId, itemCnt, 1)
		-- local itemId, itemCnt = 12249, 1*64--子弹
		-- Player:gainItems(playerId, itemId, itemCnt, 1)
		local itemId, itemCnt = 15004, 1 --狙击枪
		Player:gainItems(playerId, itemId, itemCnt, 1)
		local itemId, itemCnt = 15003, 1*64--子弹
		Player:gainItems(playerId, itemId, itemCnt, 2)
	end

	--设置饱食度小于90,防止自动加血
	local ret, foodLv = Player:getFoodLevel(playerId)
	if ret==ErrorCode.OK and foodLv>90 then
		--Player:setFoodLevel(playerId, 70)
	end
end

function InitGameMap(length, isTestMode)
	local blockId = 1 --设置游戏围栏
	local map_high = Cfg.map_high
	if isTestMode then map_high = 3 end
	for yPos = Pos.iy+1, Pos.iy+map_high do
		for xPos = Pos.ix-length, Pos.ix+length do
			Block:setBlockAll(xPos, yPos, Pos.iz-length, blockId);
			Block:setBlockAll(xPos, yPos, Pos.iz+length, blockId);
		end

		for zPos = Pos.iz-length, Pos.iz+length do
			Block:setBlockAll(Pos.ix-length, yPos, zPos, blockId);
			Block:setBlockAll(Pos.ix+length, yPos, zPos, blockId);
		end
	end

	local yPos = Pos.iy+map_high --给最上层围栏设置缺口
	for xPos = Pos.ix-length, Pos.ix+length, 2 do
		Block:destroyBlock(xPos, yPos, Pos.iz-length, false)
		Block:destroyBlock(xPos, yPos, Pos.iz+length, false)
	end
	for zPos = Pos.iz-length, Pos.iz+length, 2 do
		Block:destroyBlock(Pos.ix-length, yPos, zPos, false)
		Block:destroyBlock(Pos.ix+length, yPos, zPos, false)
	end

	if not isTestMode then --测试模式不创建地板
		if Items.floorId ~= 0 then --设置地板方块
			for xPos = Pos.ix-length, Pos.ix+length do
				for zPos = Pos.iz-length, Pos.iz+length do
					Block:setBlockAll(xPos, Pos.iy, zPos, Items.floorId)--bId为1时无法生成怪物
				end
			end
		end
	end

	InitSmallPool(); --设置中央水池
	if not isTestMode then --测试时选择创建
		InitHpTreeAndTotem(0, -5);--治疗树
		InitTeamCity(Teams.red); --红队复活点
		InitTeamCity(Teams.blue);--蓝队复活点
	end
end

--获取某区域内可放置道具的点
function getPosition(x1,x2,z1,z2,yp,isUp)
	x1 = x1 or Pos.ix-Cfg.map_size+1
	x2 = x2 or Pos.ix+Cfg.map_size-1
	z1 = z1 or Pos.iz-Cfg.map_size+1
	z2 = z2 or Pos.iz+Cfg.map_size-1
	yp = yp or Pos.iy+1  --地面/水里
	isUp = isUp==nil and true or isUp--默认true

	local count = 1
	local xPos, zPos = 0, 0
	local ret, blkId = 0, 0
	while true do
		count = count + 1
		xPos = math.random(x1, x2)
		zPos = math.random(z1, z2)

		ret, blkId = Block:getBlockID(xPos, yp, zPos)
		if ret==ErrorCode.OK and blkId==0 then
			if isUp then --地表方块需同时判断下是否有支撑
				local ret2, blkId2 = Block:getBlockID(xPos, yp-1, zPos)
				if ret2==ErrorCode.OK and blkId2~=Items.waterId then break end
			else --只判断当前是否有方块占着
				if xPos~=0 and zPos~=0 then break end
			end
		end
		if not isUp and blkId==Items.waterId then break end --是否在水里

		--防止参数有误导致死循环
		if count>99 then
			print("Position Error x===>>>")
			return nil
		end
	end
	return xPos, zPos
end

function InitTeamCity(teamId)
	--获取起始出生点
	local xPos, yPos, zPos = Pos.ix, Pos.iy+1, Pos.iz

	if teamId==Teams.red then xPos = Pos.ix-(Cfg.map_size-2) end
	if teamId==Teams.blue then xPos = Pos.ix+(Cfg.map_size-2) end

	local fixDist = 0 --小门朝向
	local flagFix = 0
	local homeIdx, reveIdx = 0, 0
	if teamId==Teams.red then
		fixDist = 2
		flagFix = 1
		homeIdx, reveIdx = 919, 991
	elseif teamId==Teams.blue then
		fixDist = -2
		flagFix = -1
		homeIdx, reveIdx = 920, 992
	end
	if homeIdx==0 or reveIdx==0 then return end

	Block:setBlockAll(xPos, yPos, zPos, reveIdx, 0) -- 复活点
	Block:placeBlock(homeIdx, xPos+fixDist, yPos+2, zPos+flagFix, 1) --队旗点

	--设置战队保护区
	local blockId = 101
	for yIdx = yPos, yPos+1 do
		for xIdx = xPos-2, xPos+2, 4 do --外边缘1
			for zIdx = zPos-2, zPos+2 do
				Block:placeBlock(blockId, xIdx, yIdx, zIdx, 3)
			end
		end

		for zIdx = zPos-2, zPos+2, 4 do --外边缘2
			for xIdx = xPos-2, xPos+2 do
				Block:placeBlock(blockId, xIdx, yIdx, zIdx, 3)
			end
		end
	end

	local doorId = 857 --开个小门
	Block:destroyBlock(xPos+fixDist, yPos, zPos, false)
	Block:destroyBlock(xPos+fixDist, yPos+1, zPos, false)
	Block:destroyBlock(xPos+fixDist, yPos, zPos-flagFix, false)
	Block:destroyBlock(xPos+fixDist, yPos+1, zPos-flagFix, false)

	Block:placeBlock(doorId, xPos+fixDist, yPos, zPos-flagFix, 3)
	--]]

	-- if teamId==Teams.red then --工具箱/红队
	-- 	Block:placeBlock(881, xPos+3, yPos, zPos+1)
	-- else --工具箱/蓝队
	-- 	Block:placeBlock(881, xPos-3, yPos, zPos-1)
	-- end
end

--设置治疗树/图腾
function InitHpTreeAndTotem(cx, cz)
	cx = cx or 0
	cz = cz or 0

	--四种怪物对应四种坦克类型
	local totemIds = {745, 901, 903, 908}
	local x1, y1, z1 = Pos.ix-5, Pos.iy+1, Pos.iz-Cfg.map_size+5

	for idx, valId in ipairs(totemIds) do
		if math.mod(idx, 3)==0 then
			x1 = Pos.ix-3
			z1 = Pos.iz+Cfg.map_size-5
		end
	 	Block:placeBlock(valId, x1, y1, z1)
	 	x1 = x1 + 6
	end

	--设置治疗树/草地
	local floorId = 100--草地
	local xPos1, xPos2, yPos = 0, 0, 0
	for idx = 1, 3 do
		yPos = Pos.iy + idx
		xPos1 = Pos.ix+cx-Cfg.pool_width-2 + idx
		xPos2 = Pos.ix+cx+Cfg.pool_width+2 - idx
		for zPos = Pos.iz+cz-2, Pos.iz+cz+2 do
			Block:placeBlock(floorId, xPos1, yPos, zPos)
			Block:placeBlock(floorId, xPos2, yPos, zPos)
		end
	end

	for zPos = Pos.iz+cz-2, Pos.iz+cz+2 do
		for xPos = xPos1+1, xPos2-1 do--上层草地
			Block:placeBlock(floorId, xPos, yPos, zPos)
		end
		for xPos = xPos1, xPos2 do--下层草地
			Block:placeBlock(101, xPos, yPos-1, zPos)
		end
	end

	local ret1 = Block:setBlockAll(xPos1-1, yPos-1, Pos.iz+cz+2, 103)
	local ret2 = Block:setBlockAll(xPos2+1, yPos-1, Pos.iz+cz-2, 103)
	--生成树苗/测试施肥事件/此处placeBlock会失败,因树苗无法放置在草块上
	local ret1 = Block:placeBlock(Items.trigger_x1, xPos1-1, yPos, Pos.iz+cz+2)
	local ret2 = Block:placeBlock(Items.trigger_x1, xPos2+1, yPos, Pos.iz+cz-2)
	--print("HpTree====================>>>", ret1, ret2)

	for zPos = Pos.iz+cz-2, Pos.iz+cz+2 do
		for xPos = Pos.ix+cx-2, Pos.ix+cx+2 do--加血区域
			--treatPos[#treatPos+1] = {xPos, yPos, zPos}
			Block:setBlockAll(xPos, yPos, zPos, Items.treatId)
		end
	end

	local direct = 4
	local tyPos = 0 --设置树干
	for idx = 1, 5 do --树高为5
		tyPos = yPos + idx
		Block:placeBlock(200, Pos.ix+cx, tyPos, Pos.iz+cz, direct)
	end

	--设置树叶/四层树叶
	local leafId = 218
	direct = 0 --第4层树叶
	for xPos = Pos.ix+cx-1, Pos.ix+cx+1 do
		for zPos = Pos.iz+cz-1, Pos.iz+cz+1 do
			Block:placeBlock(leafId, xPos, tyPos-1, zPos, direct)
		end
		direct = direct + 2
	end
	direct = 0 --第5层树叶
	for xPos = Pos.ix+cx-2, Pos.ix+cx+2 do
		for zPos = Pos.iz+cz-2, Pos.iz+cz+2 do
			Block:placeBlock(leafId, xPos, tyPos, zPos, direct)
		end
		direct = direct + 2
	end
	direct = 0
	for xPos = Pos.ix+cx-1, Pos.ix+cx+1 do
		for zPos = Pos.iz+cz-1, Pos.iz+cz+1 do
			Block:placeBlock(leafId, xPos, tyPos, zPos, direct)
		end
		direct = direct + 2
	end
	direct = 0 --第6层树叶
	for xPos = Pos.ix+cx-1, Pos.ix+cx+1 do
		for zPos = Pos.iz+cz-1, Pos.iz+cz+1 do
			Block:placeBlock(leafId, xPos, tyPos+1, zPos, direct)
		end
		direct = direct + 2
	end
	direct = 4 --最上层树叶
	Block:placeBlock(leafId, Pos.ix+cx, tyPos+2, Pos.iz+cz, direct)
	--]]

	--治疗圈位置/半径
	Pos.cx, Pos.cz, Pos.cr = Pos.ix + cx, Pos.iz + cz, 4*1.2
end

--绘制小地图标记
function drawMiniMark(isNew, x1, x2, z1, z2, rx, mType)
	if Data.miniMarkId >= 0 and not mType then --清理旧标记
		MapMark:deleteShape(Data.miniMarkId)
	elseif Data.miniMarkId==-1 or isNew then --重新绘制标记
		local ret = ErrorCode.FAILED

		local markType = MAPMARK_TYPE.MMARK_CIRCLE
		if mType==1 then markType = MAPMARK_TYPE.MMARK_LINE end
		if mType==2 then markType = MAPMARK_TYPE.MMARK_RECTANGLE end

		ret, Data.miniMarkId = MapMark:newShape(markType,false,255,255,255)
		if ret~=ErrorCode.OK then Data.miniMarkId = -1 end
	end

	if Data.miniMarkId >= 0 and not isNew then
		if mType == 1 then--线形标记
			MapMark:setShapeColor(Data.miniMarkId, 255, 0, 0)
			MapMark:updateLine(Data.miniMarkId, x1, z1, x2, z2)
		elseif mType == 2 then--矩形标记
			MapMark:setShapeColor(Data.miniMarkId, 255, 0, 0)
			MapMark:updateRectangle(Data.miniMarkId, x1, z1, x2-x1, z2-z1)
		else --圆形标记
			MapMark:setShapeColor(Data.miniMarkId, 255, 0, 0)
			MapMark:updateCircle(Data.miniMarkId, x1, z1, rx)
		end
		MapMark:showShape(Data.miniMarkId, true)
	end
end

--地图中生成水池
function InitSmallPool(pWid, pLen)
	pWid = pWid and pWid or Cfg.pool_width
	pLen = pLen and pLen or Cfg.pool_lenth

	local xwid, zwid = pWid, pLen

	for yPos = Pos.iy-1, Pos.iy do--挖坑
		for xPos = Pos.ix-(xwid-1), Pos.ix+(xwid-1) do
			for zPos = Pos.iz-(zwid-1), Pos.iz+(zwid-1) do
				Block:destroyBlock(xPos, yPos, zPos, false)
			end
		end
	end
	for xPos = Pos.ix-xwid, Pos.ix+xwid do--内边缘
		for zPos = Pos.iz-zwid, Pos.iz+zwid do
			Block:destroyBlock(xPos, Pos.iy, zPos, false)
		end
	end

	for yPos = Pos.iy-1, Pos.iy do--生成水池
		for xPos = Pos.ix-xwid, Pos.ix+xwid do
			for zPos = Pos.iz-zwid, Pos.iz+zwid do
				Block:placeBlock(4, xPos, yPos, zPos, 3)
			end
		end
	end

	-- 外边缘1
	local blockId = 104--方块Id
	for zPos = Pos.iz-zwid-2, Pos.iz+zwid+2, 2*zwid+4 do
		for xPos = Pos.ix-xwid-2, Pos.ix+xwid+2 do
			Block:placeBlock(blockId, xPos, Pos.iy+1, zPos, 3)
		end
	end
	-- 外边缘2
	for xPos = Pos.ix-xwid-2, Pos.ix+xwid+2, 2*xwid+4 do
		for zPos = Pos.iz-zwid-2, Pos.iz+zwid+2 do
			Block:placeBlock(blockId, xPos, Pos.iy+1, zPos, 3)
		end
	end
end

--在一定区域内初始化道具
function InitGameItems(bxsize)
	-- 获取起起始出生点
	local x, y, z = Pos.ix, Pos.iy+1, Pos.iz

	-- 位置区域
	local x1, x2 = Pos.ix-bxsize+1, Pos.ix+bxsize-1
	local z1, z2 = Pos.iz-bxsize+1, Pos.iz+bxsize-1

	for idx = 1, Items.rewardCnt do --Item大肘子
		local xPos, zPos = getPosition(x1,x2,z1,z2)
		World:spawnItem(xPos, y, zPos, Items.rewardIdx)
	end
	for idx = 1, Items.rewardCnt do --Item动物肥料
		local xPos, zPos = getPosition(x1,x2,z1,z2)
		World:spawnItem(xPos, y, zPos, Items.rewardIdx)
	end

	-- 设置大宝剑掉落位置
	for idx=1, #weaponIdx do
		-- local xPos1 = math.random(x1, x2)
		-- local zPos1 = math.random(z1, z2)
		local xPos1, zPos1 = getPosition(x1,x2,z1,z2)
		World:spawnItem(xPos1, y, zPos1, weaponIdx[idx])
	end

	-- 设置BuffItem位置
	for idx=1, #itemBuffs do
		-- local xPos1 = math.random(x1, x2)
		-- local zPos1 = math.random(z1, z2)
		local xPos1, zPos1 = getPosition(x1,x2,z1,z2)
		World:spawnItem(xPos1, y, zPos1, itemBuffs[idx])
	end
	-- 设置ToolItem位置
	for idx=1, #itemTools do
		local itemId = itemTools[idx]
		for jdx = 1, 5 do --数量
			local xPos1, zPos1 = getPosition(x1,x2,z1,z2)
			World:spawnItem(xPos1, y, zPos1, itemId)
		end
	end

	for idx = 1, #rewBlocks do --方块碰撞区
		local blockId = rewBlocks[idx]
		local direct = idx~=1 and 3 or 4
		local xPos0, zPos0 = getPosition(x1,x2,z1,z2)
		Block:placeBlock(blockId, xPos0, y, zPos0, direct)

		--设置正负收益方块
		local randx = math.random(1, 10)
		if randx<=5 and #posBlocks<2 or idx==1 then
			posBlocks[#posBlocks+1] = blockId
		else
			negBlocks[#negBlocks+1] = blockId
		end
	end

	for idx = 1, #itemLamps do --方块触发区
		local xPos0, zPos0 = getPosition(x1,x2,z1,z2)
		Block:placeBlock(itemLamps[idx], xPos0, y, zPos0, 3)
	end

	for idx = 1, Items.starCnt do --方块触发区
		local xPos0, zPos0 = getPosition(x1,x2,z1,z2)
		Block:placeBlock(Items.starIdx, xPos0, y, zPos0, 3)
	end
end

--在一定区域内初始化怪物
function InitGameMobs(bxsize)
	-- 获取起起始出生点
	local x, y, z = Pos.ix, Pos.iy+1, Pos.iz

	-- 位置区域
	local x1, x2 = Pos.ix-bxsize+1, Pos.ix+bxsize-1
	local z1, z2 = Pos.iz-bxsize+1, Pos.iz+bxsize-1

	-- 生成怪物并设置位置
	for idx=1, Items.mobsCnt do
		local xPos, zPos = getPosition(x1,x2,z1,z2)
		local cIdx = math.mod(idx, #Items.mobsIdx)
		cIdx = cIdx~=0 and cIdx or #Items.mobsIdx
		local curMobId = Items.mobsIdx[cIdx]
		local ret, objIds = World:spawnCreature(xPos, y, zPos, curMobId)

		if objIds and type(objIds)=="table" then
			for idx = 1, #objIds do --遍历设置攻击手属性
				local attrType = MODATTRIB_TYPE.MODATTR_MOVE_SPEED
				local ret, value = Creature:getModAttrib(objIds[idx], attrType)
				print('MODATTR_MOVE_SPEED-------------------->>>', value)
				local result = Creature:addModAttrib(objIds[idx], attrType, 1)
				if result == ErrorCode.OK then print('增加怪物移动速度') end

				Mobs.objIds[#Mobs.objIds+1] = objIds[idx]
				if curMobId == Items.mobsIdx[1] then
					Mobs.gensCnt = Mobs.gensCnt + 1 --攻击手
				else -- 生物组1->狼群
					Trigger.CreatureGroup:addCreatureToGroup(objIds[idx], cgroupId1)
				end
			end
		end
	end

	--设置怪物属性
	for idx = 1, #Mobs.objIds do
		local mobObjId = Mobs.objIds[idx]
		local isMob = Actor:isMob(mobObjId)
		if isMob==ErrorCode.OK then --确实是怪物
			local ret, actorId = Creature:getActorID(mobObjId)
			if actorId == Items.mobsIdx[3] then--狼
				Creature:setPanic(mobObjId, true)
				Creature:setAIActive(mobObjId, true)
				local result = Creature:setOxygenNeed(mobObjId, false)
			end
		end
	end

	local xwid, zwid, count = 7-1, 12-1, 3
	for idx = 1, count do --水池范围生成鱼类
		-- local xPos = math.random(Pos.ix-xwid, Pos.ix+xwid)
		-- local zPos = math.random(Pos.iz-zwid, Pos.iz+zwid)
		x1,x2,z1,z2 = Pos.ix-xwid, Pos.ix+xwid,Pos.iz-zwid, Pos.iz+zwid
		local xPos,zPos = getPosition(x1,x2,z1,z2, Pos.iy, false)
		local ret, objIds = World:spawnCreature(xPos, y-1, zPos, Items.fishIdx)

		if objIds and type(objIds)=="table" then
			for idx = 1, #objIds do --生物组2->鱼群
				Trigger.CreatureGroup:addCreatureToGroup(objIds[idx], cgroupId2)
			end
		end
	end
	print("GensX===================>>>", Mobs.gensCnt)
end

--计算游戏结果
function Battle_Ended(teamId, retType)
	--local isPlayerValid = Player:isMainPlayerValid()#已取消
	--if isPlayerValid ~= ErrorCode.OK then return end

	if teamId == Teams.red then
		-- 设置红队游戏结果
		Team:setTeamResults(Teams.red, retType)
		Team:setTeamPlayersResults(Teams.red, retType)
		-- 设置蓝队游戏结果
		local blueRet = (retType==Battle.win and Battle.lose) or Battle.win
		Team:setTeamResults(Teams.blue, blueRet)
		Team:setTeamPlayersResults(Teams.blue, blueRet)
		print("Battle1 ================>>>", teamId, retType, blueRet)
	elseif teamId == Teams.blue then
		-- 设置蓝队游戏结果
		Team:setTeamResults(Teams.blue, retType)
		Team:setTeamPlayersResults(Teams.blue, retType)
		-- 设置红队游戏结果
		local redRet = (retType==Battle.win and Battle.lose) or Battle.win
		Team:setTeamResults(Teams.red, redRet)
		Team:setTeamPlayersResults(Teams.red, redRet)
		print("Battle2 ================>>>", teamId, retType, redRet)
	end

	ShowGBattleUI() --设置战斗总结界面
end

--游戏结算界面
function ShowGBattleUI()
	-- 设置排行/分数
	local ret, rank = Player:getGameRanking()
	if not rank or rank==0 then rank = 1 end
    local ret, score = Player:getGameScore()

    -- 队伍数量及成员量
    local ret1, teamNum = Team:getNumTeam()
    local ret2, redNum = Team:getTeamPlayers(Teams.red)
    local ret3, blueNum = Team:getTeamPlayers(Teams.blue)
  	local totalPlayers = 1
  	if ret2==ErrorCode.OK and ret3==ErrorCode.OK then
  		totalPlayers = redNum+blueNum
  	end

  	local ret, txtTitle = Game:getDefString(rank==1 and 8028 or 8029)
  	local ret, txtTRank = Game:getDefString(8032)
  	local ret, txtRanker = Game:getDefString(8030)
  	local ret, txtDefeat = Game:getDefString(3176)
	UI:setGBattleUI('left_title', txtTRank..tostring(rank))--第1/1
	UI:setGBattleUI('right_title', "/"..totalPlayers)
	UI:setGBattleUI('left_desc', txtTitle)--大吉大利/继续努力
	UI:setGBattleUI('left_little_desc', txtRanker..tostring(rank))--排名
	UI:setGBattleUI('right_little_desc', txtDefeat..tostring(score))--得分
	UI:setGBattleUI('battle_btn', false)
	UI:setGBattleUI('result', false)
	UI:setGBattleUI('result_bkg', false)
	UI:setGBattleUI('reopen', true)
end

--重置玩家位置
function ResetPosition(playerId, teamId)
	if playerId<0 or teamId<0 then return end

	if teamId == Teams.red then      --红队出生/复活点
		local ret = Player:setPosition(playerId, Pos.ix-(Cfg.map_size-2)+0.5, 7, Pos.iz+0.5)
	elseif teamId == Teams.blue then --蓝队出生/复活点
		local ret = Player:setPosition(playerId, Pos.ix+(Cfg.map_size-2)+0.5, 7, Pos.iz+0.5)
	end
end

--初始玩家道具
function GainItems(playerId)
	--给玩家一把短刀做防御,优先快捷栏
	local itemId, itemCnt = 12003, 1 --短刀
	local ret = Backpack:enoughSpaceForItem(playerId, itemId, itemCnt)
	if ret==ErrorCode.OK then Player:gainItems(playerId, itemId, itemCnt, 1) end

	local itemId, itemCnt = 11001, 1 --木斧
	local ret = Backpack:enoughSpaceForItem(playerId, itemId, itemCnt)
	if ret==ErrorCode.OK then Player:gainItems(playerId, itemId, itemCnt, 1) end

	local itemId, itemCnt = 200, 1 --果木
	local ret = Backpack:enoughSpaceForItem(playerId, itemId, itemCnt)
	if ret==ErrorCode.OK then Player:gainItems(playerId, itemId, itemCnt, 1) end

	local itemId, itemCnt = 230, 1 --南瓜
	local ret = Backpack:enoughSpaceForItem(playerId, itemId, itemCnt)
	if ret==ErrorCode.OK then Player:gainItems(playerId, itemId, itemCnt, 1) end

	local itemId, itemCnt = 817, 2
	local isDayTx = World:isDaytime() --白天:true 黑夜:false
	local result = Backpack:enoughSpaceForItem(playerId, itemId, itemCnt)

	if result==ErrorCode.OK and not isDayTx then --如果是夜晚给俩火炬
		Player:gainItems(playerId, itemId, itemCnt, 1)
	end
end

--设置玩家分数
function PlayerAddScore(playerId, addScore)
	if playerId <= 0 then return end

	local ret, currScore = Player:getGameScore(playerId)
	if ret==ErrorCode.OK then
		local playScore = currScore+addScore
		if addScore < 0 then --设置玩家分数
			playScore = math.max(0, playScore)
		end
		Player:setGameScore(playerId, playScore)
	end

	local ret, teamId = Player:getTeam(playerId)
	if ret==ErrorCode.OK and teamId>0 then
		local ret, teamScore = Team:getTeamScore(teamId)
		if addScore < 0 then --设置队伍分数
			teamScore = math.max(0, addScore+teamScore)
			Team:setTeamScore(teamId, teamScore)
		else
			Team:addTeamScore(teamId, addScore)
		end
	end
end

--重置tick次数
function IsCanTick(isTick)
	isTick = isTick or true
	if isTick then Data.tickCount = Data.tickCount+1 end

	if Data.tickCount>=Data.newTicker then
		Data.tickCount = 0
		return true
	end

	return false
end

-------------------------------游戏事件-------------------------------
Game_EnterRoom = function()
    -- 玩法地图不会调该方法,测试需开房间
	InitGameRule() --初始化相关游戏规则

	--重置游戏数据
	Data.tickCount = 0
	Data.isGameEnd = false
	Mobs.gensCnt = 0
	Mobs.deadCnt = 0

	local renderType = 1--小地图显示模式 1:旋转视角 2:全图俯视
	local result = UI:setMinimapRenderMode(renderType)

	-- 设置一个标志位
	local result = Game:setScriptVar(1, 99)
	if result==ErrorCode.OK then
		result = Game:sendScriptVars2Client()
	end
end

Game_StartGame = function()
	if not Data.isRuleInit then InitGameRule() end

	InitCenterPoint() --初始化地图中心点
	local isTestMode = false --测试模式
	InitGameMap(Cfg.map_size, isTestMode)
	InitGameMobs(Cfg.map_size)  --初始化游戏怪物
	InitGameItems(Cfg.map_size) --初始化游戏道具

	InitGamePlayer(isTestMode) --初始化玩家信息

	local x1, x2 = Pos.ix-Data.markRadius, Pos.ix+Data.markRadius
	local z1, z2 = Pos.iz-Data.markRadius, Pos.iz+Data.markRadius
	drawMiniMark(true, x1,x2,z1,z2, 0,2) --绘制小地图
	--drawMiniMark(true, Pos.ix,Pos.iz,0,0, Data.markRadius,3)

	local ret, text = Game:getDefString(3068)
	Chat:sendChat(text, Sys.chatType)
end

Game_Update = function()
	if Data.isGameEnd or Data.isTimeout then return end
	if IsCanTick()==false then return end

	Data.markRadius = Data.markRadius-1
	if Data.miniMarkId > 0 then --标记还存在
		if Data.markRadius > 0 then --刷新小地图标记
			local x1, x2 = Pos.ix-Data.markRadius, Pos.ix+Data.markRadius
			local z1, z2 = Pos.iz-Data.markRadius, Pos.iz+Data.markRadius
			drawMiniMark(false, x1, x2, z1, z2, 0, 2)
			--drawMiniMark(false, Pos.ix,Pos.iz,0,0, Data.markRadius,3)
		elseif Data.markRadius <= 0 then
			MapMark:showShape(Data.miniMarkId, false)
			MapMark:deleteShape(Data.miniMarkId)
			Data.miniMarkId = -1
		end
	end
	--[==[
	if Data.glEffectId >= 0 then --进入小圈后去掉全部debuff
		local ret, playerId = Player:getMainPlayerUin()
		if ret==ErrorCode.OK and playerId>0 then
			local ret, x,y,z = Player:getPosition(playerId)
			if ret == ErrorCode.OK then
				if (x-Pos.cx)*(x-Pos.cx)+(z-Pos.cz)*(z-Pos.cz) < Pos.cr*Pos.cr then
					Player:clearAllBadBuff(playerId)--去掉debuff
					local ret, buffN, buffLt = Player:getBuffList(playerId)
					if ret==ErrorCode.OK and buffNum>=3 then

					end
				end
			end
			--[[
			local ret, actorHp = Actor:getHP(playerId)
			if ret==ErrorCode.OK and actorHp<=15 then
				local ret = Actor:tryMoveToPos(playerId, Pos.cx, Pos.iy+1, Pos.cz, 5.0)
				print("Move=============>>>", ret)
			end
			--]]
		end
	end
	--]==]

	--/1、怪物已经全被干掉
	if Mobs.gensCnt>0 and Mobs.deadCnt>=Mobs.gensCnt then
		Data.isGameEnd = true
		Game:doGameEnd()
		return
	end

	--/2、分数达到某值则结束游戏/GameRule设置有问题
	if Cfg.max_score > 0 then
		for teamId in pairs({Teams.red, Teams.blue}) do
			local ret, score = Team:getTeamScore(teamId)
			if ret==ErrorCode.OK and score>=Cfg.max_score then
				Data.isGameEnd = true
				Game:doGameEnd()
				return
			end
		end
	end

	-- 单人模式下不计算存活规则
	local ret1, btNum = Team:getTeamPlayers(Teams.blue)
	if ret1==ErrorCode.OK or btNum==0 then return end
	local ret2, rtNum = Team:getTeamPlayers(Teams.red)
	if ret2==ErrorCode.OK or rtNum==0 then return end

	--/3、玩家无存活则游戏结束
	local ret1, raNum = Team:getTeamPlayers(Teams.red, LiveType.alive)
	local ret2, baNum = Team:getTeamPlayers(Teams.blue, LiveType.alive)
	if ret1 ~= ErrorCode.OK or ret2 ~= ErrorCode.OK then return end

	if raNum==0 and baNum==0 then
		Data.isGameEnd = true
		Game:doGameEnd()
		return
	end
end

Game_GameEnd = function()
	print("GameEnd1 ================>>>Func")
	local ret1, rxScore = Team:getTeamScore(Teams.red)
	local ret2, bxScore = Team:getTeamScore(Teams.blue)

	print("GameEnd2 ================>>>", ret1, ret2, rxScore, bxScore)
	if ret1==ErrorCode.FAILED or ret2==ErrorCode.FAILED then return end

	local result = rxScore >= bxScore
	local isClient = true --主客机标志

	if result then --红队/主队胜利
		Battle_Ended(Teams.red, Battle.win)
		if not isClient then --主队胜利提示
			local ret, txtInfox = Game:getDefString(270)
			Chat:sendChat(txtInfox,  Sys.chatType)
		else --客队失败提示
			local ret, txtInfox = Game:getDefString(271)
			Chat:sendChat(txtInfox,  Sys.chatType)
		end
	else
		Battle_Ended(Teams.blue, Battle.win)
		if not isClient then --主队失败提示
			local ret, txtInfox = Game:getDefString(271)
			Chat:sendChat(txtInfox,  Sys.chatType)
		else --客队胜利提示
			local ret, txtInfox = Game:getDefString(270)
			Chat:sendChat(txtInfox,  Sys.chatType)
		end
	end
end

Game_TimeOver = function()
	--超时比得分,高分获胜
	Data.isTimeout = true
end

-------------------------------玩家事件-------------------------------
Player_Inited = function(trigger_obj)
	local playerId = trigger_obj['eventobjid']
	if not Data.isRuleInit then InitGameRule() end

	-- 进入房间开始游戏前时调用
	local ret, val = Game:getScriptVar(1)
	if ret==ErrorCode.OK then end
end

-- 干掉对方玩家可+5分/已在GameRule里设置
Player_Dead = function(trigger_obj)
	local playerId = trigger_obj['eventobjid']
	local killedBy = trigger_obj['toobjid']

	if playerId <= 0 then return end

	PlayerAddScore(playerId, -5) --死亡-5分
end

Player_Revive = function(trigger_obj)
	local playerId = trigger_obj['eventobjid']

	--复活保护BUFF<BuffId要除1000>/GameRule可设置
	local buffId = math.floor(999002/1000)
	Player:addBuff(playerId, buffId, 2, 10000)

	local buffId1 = math.floor(27003/1000)
	Player:addBuff(playerId, buffId1, 2, 500000)

	local ret, teamId = Player:getTeam(playerId)
	if ret~=ErrorCode.OK or teamId<=0 then return end
	ResetPosition(playerId, teamId) --回到复活点复活

	--设置饱食度/防止血量自增
	Player:setFoodLevel(playerId, 70)

	-- 默认给玩家一把短刀(ItemId:12003)防御
	local itemId, itemCnt = 12003, 1
	local ret = Backpack:enoughSpaceForItem(playerId, itemId, itemCnt)
	if ret==ErrorCode.OK then Player:gainItems(playerId, itemId, itemCnt, 1) end
end

Player_JoinTeam = function(trigger_obj)
	local playerId = trigger_obj['eventobjid']

    -- 流程有问题,暂时无法设置多人组,默认1人组
	local ret, teamId = Player:getTeam(playerId)
	if ret==ErrorCode.OK and teamId>0 then
		ResetPosition(playerId, teamId) --设置队伍位置
	end
end

local itemCount = 0
Player_AddItem = function(trigger_obj)
	local itemId = trigger_obj['itemid']
	local itemNum = trigger_obj['itemnum']
	local playerId = trigger_obj['eventobjid']

	if itemId==Items.rewardIdx and playerId>0 then
		PlayerAddScore(playerId, itemNum*1)
	end

	if itemId == Items.rewardIdx then
		local result, state = World:getCameraEditState()
		if result==ErrorCode.OK then print('当前视角编辑状态:', state) end
		--[[
		state = CameraEditState.CAMERA_EDIT_STATE_EDIT
		local result = World:setCameraEditState(state)
		print('已成功设置视角编辑状态?', result==ErrorCode.OK and '成功' or '失败')
		--]]
		local result, config = World:getCustomCameraConfig()
		if result==ErrorCode.OK and config~=nil then --自定义视角
			config:setOption(CAMERA_OPTION_INDEX_CONFIG_SET, CCG_FLATVIEW)
		end

		local actorType = 0 --OBJ_TYPE_MONSTER
		local x1, y1, z1 = -5, 1, -5
		local x2, y2, z2 = 15, 9, 15
		local ret, num, array = World:getActorsByBox(actorType, x1,y1,z1, x2,y2,z2)
		if ret == ErrorCode.OK then print('Creature ===>> ', num, array) end

		local aliveType = LiveType.all
		local ret, num, array = World:getAllPlayers(aliveType)
		if ret == ErrorCode.OK then print('Actors ===>> ', num, array) end

		local aliveType = LiveType.alive
		local ret, playerId = World:randomOnePlayer(aliveType)
		if ret == ErrorCode.OK then print('Player ===>> ', playerId) end

		local result = World:despawnActor(Mobs.objIds[1])
		if result == ErrorCode.OK then print('Despawn Actorx ===>> ', result) end
	end

	-- local modx = math.mod(itemCount, 3)
	-- if modx==0 then CheckBackpackAPI('SC', itemId) end
	-- if modx==1 then CheckBackpackAPI('BC', itemId) end
	-- if modx==2 then CheckBackpackAPI('EC', itemId) end
	itemCount = itemCount + 1
end

-------------------------------怪物事件-------------------------------
-- 伤害源为玩家或怪物
Actor_Die = function(trigger_obj)
	print("Monster_Dead==========>>>", trigger_obj)
	local mobId, actorId = trigger_obj['eventobjid'], trigger_obj['toobjid']

	local addScore = 0 --额外加分情况
	local ret, defId = Creature:getActorID(mobId)

	if defId==Items.mobsIdx[1] then --弓手
		addScore = 2
		Mobs.deadCnt = Mobs.deadCnt+1
		print('FFc=======>>>', Mobs.deadCnt)
	elseif defId==Items.fishIdx then --灯笼鱼
		addScore = 5
	end

	if addScore==0 then return end

	local result = Actor:isPlayer(actorId)
	if result==ErrorCode.OK then--怪物被玩家干掉
		PlayerAddScore(actorId, addScore)
		return
	end

	--被玩家驯服的动物干掉
	local result = Actor:isMob(actorId)
	if result==ErrorCode.OK then
		local ret, playerId = Creature:getTamedOwnerID(actorId)
		if ret==ErrorCode.OK and playerId>0 then
			PlayerAddScore(playerId, addScore)
		end
	end
end

-------------------------------方块事件-------------------------------
--生成战旗后添加雾圈效果
Block_Added = function(trigger_obj)
	print("Block_Added==========>>>", trigger_obj)
	local blockId = trigger_obj['blockid']
	local x, y, z = trigger_obj['x'], trigger_obj['y'], trigger_obj['z']

	if blockId==919 or blockId==920 then
		if Data.glEffectId >= 0 then return end
		local ret, glEffectId = Game:addRenderGlobalEffect("particles/Fog.ent")
		if ret==ErrorCode.OK and glEffectId >= 0 then
			Data.glEffectId = glEffectId
			Game:setRenderGlobalEffectPos(Data.glEffectId, Pos.cx, 0, Pos.cz)
			Game:setRenderGlobalEffectScale(Data.glEffectId, Pos.cr/4.0, 0.045, Pos.cr/4.0)
		end
	end
end

--战旗被摧毁后雾圈消失/治疗效果消失
Block_Removed = function(trigger_obj)
	print('Block_removed===========>>>', trigger_obj)
	local blockId = trigger_obj['blockid']
	local x, y, z = trigger_obj['x'], trigger_obj['y'], trigger_obj['z']

	if Data.glEffectId >= 0 then --删除雾圈效果
		 local ret = Game:removeRenderGlobalEffect(Data.glEffectId)
		 if ret == ErrorCode.OK then Data.glEffectId = -1 end
	end
end

--将南瓜灯放置到对应的队旗旁+12fen
Block_PlacedBy = function(trigger_obj)
	print('Block_placed===========>>>', trigger_obj)
	local blockId = trigger_obj['blockid']
	local x, y, z = trigger_obj['x'], trigger_obj['y'], trigger_obj['z']
end

--获取宝箱并将其打掉的队伍可+7分
Block_DestroyBy = function(trigger_obj)
	print("Block_DestroyBy===========>>>", trigger_obj)
	local blockId = trigger_obj['blockid']
	local actorId = trigger_obj['eventobjid']
	local x, y, z = trigger_obj['x'], trigger_obj['y'], trigger_obj['z']

	if actorId > 0 then
		if blockId == posBlocks[1] then--罐子
			PlayerAddScore(actorId, 7)
		elseif blockId == posBlocks[2] then--南瓜灯
			PlayerAddScore(actorId, 12)
		end
	end
end

--点燃台灯+10分/点燃烟花+20分
Block_TriggerBy = function(trigger_obj)
	print("Block_trigger===========>>>", trigger_obj)
	local blockId = trigger_obj['blockid']
	local actorId = trigger_obj['eventobjid']
	local x, y, z = trigger_obj['x'], trigger_obj['y'], trigger_obj['z']

	if blockId==itemLamps[1] then--烟花
		PlayerAddScore(actorId, 20)
	elseif blockId==itemLamps[2] or blockId==itemLamps[3] then
		PlayerAddScore(actorId, 10)
	end
end
--[==[
--碰撞区撞到方块会触发变身效果
Block_CollidedBy = function(trigger_obj)
	print("Block_Collided===========>>>", trigger_obj)
	local blockId = trigger_obj['blockid']
	local actorId = trigger_obj['eventobjid']
	local x, y, z = trigger_obj['x'], trigger_obj['y'], trigger_obj['z']

	local result = Actor:isPlayer(actorId)
	if result ~= ErrorCode.OK then return end --非玩家触发

	local buffId, buffLv = 0, 1
	if blockId == negBlocks[1] then--变鸡Buff
		buffId = math.floor(1003001/1000)
	elseif blockId == negBlocks[2] then--变羊Buff
		buffId = math.floor(1005001/1000)
	end
	if buffId == 0 then return end

	local ret = Player:hasBuff(actorId, buffId)
	if ret == ErrorCode.OK then --设置buff时长/60秒
		local ret, ticks = Player:getBuffLeftTick(actorId, buffId)
		print('TT===========>>>', ret, ticks)
		if ret==ErrorCode.OK and ticks<=60*20 then
			Player:addBuff(actorId, buffId, buffLv, 60*20)
		end
	else
		Player:addBuff(actorId, buffId, buffLv, 60*20)
	end
end

--加血区每秒加1生命值
Block_WalkedBy = function(trigger_obj)
	print("Block_walking===========>>>", trigger_obj)
	local blockId = trigger_obj['blockid']
	local actorId = trigger_obj['eventobjid']
	local x, y, z = trigger_obj['x'], trigger_obj['y'], trigger_obj['z']
	if Data.glEffectId == -1 then return end

	local result = Actor:isPlayer(actorId)
	if result ~= ErrorCode.OK then return end --非玩家触发

	if blockId == Items.treatId then
		local ret1, maxHp = Player:getMaxHP(actorId)
		if ret1 ~= ErrorCode.OK then return end
		local ret2, curHp = Player:getHP(actorId)
		if ret2 ~= ErrorCode.OK then return end

		if curHp < maxHp then --加血
			local ret = Player:addHP(actorId, 1)
		end
	end
end
--]==]
Block_FertilizedBy = function(trigger_obj)
	print("Block_fertilized===========>>>", trigger_obj)
	local blockId = trigger_obj['blockid']
	local actorId = trigger_obj['eventobjid']
	local x, y, z = trigger_obj['x'], trigger_obj['y'], trigger_obj['z']
end

ListenEvents_MiniDemo();
end)()
上次更新: 2021/4/12 20:37:37