更新
This commit is contained in:
parent
40e1eb3462
commit
42dbc86b3a
BIN
excel/level.xlsx
BIN
excel/level.xlsx
Binary file not shown.
36
export.py
36
export.py
@ -11,16 +11,13 @@ if not os.path.exists(output_dir):
|
||||
|
||||
def parse_array_field(value, elem_type):
|
||||
"""
|
||||
解析数组类型字段,支持[1,2,3]或1,2,3写法,自动去除空格和空字符串。
|
||||
elem_type: 'int', 'float', 'string'等
|
||||
解析一维数组类型字段,支持[1,2,3]或1,2,3写法。
|
||||
"""
|
||||
if value is None:
|
||||
return []
|
||||
s = str(value).strip()
|
||||
# 支持带中括号写法
|
||||
if s.startswith("[") and s.endswith("]"):
|
||||
s = s[1:-1]
|
||||
# 支持英文逗号和中文逗号
|
||||
items = re.split(r'[,,]', s)
|
||||
result = []
|
||||
for v in items:
|
||||
@ -41,6 +38,32 @@ def parse_array_field(value, elem_type):
|
||||
result.append(v)
|
||||
return result
|
||||
|
||||
def parse_2d_array_field(value, elem_type):
|
||||
"""
|
||||
解析二维数组类型字段,支持[1,2],[3,4]或[[1,2],[3,4]]等写法。
|
||||
保证导出始终为双数组结构。
|
||||
"""
|
||||
if value is None or str(value).strip() == "":
|
||||
return []
|
||||
s = str(value).strip()
|
||||
# 去除最外层中括号
|
||||
if s.startswith("[[") and s.endswith("]]"):
|
||||
s = s[1:-1]
|
||||
# 按 '],[' 拆分
|
||||
parts = re.split(r'\]\s*,\s*\[', s)
|
||||
result = []
|
||||
for part in parts:
|
||||
part = part.strip("[] ")
|
||||
arr = parse_array_field(part, elem_type)
|
||||
result.append(arr)
|
||||
# 如果内容其实是一维数组(如单元格内容为1,2,3),也包一层
|
||||
if len(result) == 1 and not isinstance(result[0], list):
|
||||
result = [parse_array_field(s, elem_type)]
|
||||
# 如果内容为空但原始字符串非空,也包一层
|
||||
if not result and s:
|
||||
result = [parse_array_field(s, elem_type)]
|
||||
return result
|
||||
|
||||
for filename in os.listdir(excel_dir):
|
||||
if filename.endswith('.xlsx'):
|
||||
filepath = os.path.join(excel_dir, filename)
|
||||
@ -65,7 +88,10 @@ for filename in os.listdir(excel_dir):
|
||||
filtered_row = [row[i] if i < len(row) else None for i in valid_indices]
|
||||
row_dict = {}
|
||||
for h, t, v in zip(valid_headers, valid_types, filtered_row):
|
||||
if t.endswith("[]"):
|
||||
if t.endswith("[][]"):
|
||||
elem_type = t[:-4]
|
||||
row_dict[h] = parse_2d_array_field(v, elem_type)
|
||||
elif t.endswith("[]"):
|
||||
elem_type = t[:-2]
|
||||
row_dict[h] = parse_array_field(v, elem_type)
|
||||
else:
|
||||
|
@ -1,22 +1,22 @@
|
||||
[
|
||||
{"id":1,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[1,1,10,2,1,1,10,2]},
|
||||
{"id":2,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[1,1,10,2,1,1,10,2,1,1,10,2,1,1,10,2]},
|
||||
{"id":3,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[1,1,10,2,1,1,10,2]},
|
||||
{"id":4,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[1,1,10,2,1,1,10,2,1,1,10,2,1,1,10,2]},
|
||||
{"id":5,"type":2,"timeLimit":60,"atkBonus":1000,"hpBonus":1000,"wave":[1000]},
|
||||
{"id":6,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[1,1,10,2,1,1,10,2]},
|
||||
{"id":7,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[1,1,10,2,1,1,10,2,1,1,10,2,1,1,10,2]},
|
||||
{"id":8,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[1,1,10,2,1,1,10,2]},
|
||||
{"id":9,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[1,1,10,2,1,1,10,2,1,1,10,2,1,1,10,2]},
|
||||
{"id":10,"type":2,"timeLimit":60,"atkBonus":1000,"hpBonus":1000,"wave":[1000]},
|
||||
{"id":11,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[1,1,10,2,1,1,10,2]},
|
||||
{"id":12,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[1,1,10,2,1,1,10,2,1,1,10,2,1,1,10,2]},
|
||||
{"id":13,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[1,1,10,2,1,1,10,2]},
|
||||
{"id":14,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[1,1,10,2,1,1,10,2,1,1,10,2,1,1,10,2]},
|
||||
{"id":15,"type":2,"timeLimit":60,"atkBonus":1000,"hpBonus":1000,"wave":[1000]},
|
||||
{"id":16,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[1,1,10,2,1,1,10,2]},
|
||||
{"id":17,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[1,1,10,2,1,1,10,2,1,1,10,2,1,1,10,2]},
|
||||
{"id":18,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[1,1,10,2,1,1,10,2]},
|
||||
{"id":19,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[1,1,10,2,1,1,10,2,1,1,10,2,1,1,10,2]},
|
||||
{"id":20,"type":2,"timeLimit":60,"atkBonus":1000,"hpBonus":1000,"wave":[1000]}
|
||||
{"id":1,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[[10,1,1,10,2,1],[10,1,1,10,2,1]]},
|
||||
{"id":2,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[[10,1,1,10,2,1],[10,1,1,10,2,1],[10,1,1,10,2,1],[10,1,1,10,2,1]]},
|
||||
{"id":3,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[[10,1,1,10,2,1],[10,1,1,10,2,1]]},
|
||||
{"id":4,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[[10,1,1,10,2,1],[10,1,1,10,2,1],[10,1,1,10,2,1],[10,1,1,10,2,1]]},
|
||||
{"id":5,"type":2,"timeLimit":60,"atkBonus":1000,"hpBonus":1000,"wave":[[10,1000,1]]},
|
||||
{"id":6,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[[10,1,1,10,2,1],[10,1,1,10,2,1]]},
|
||||
{"id":7,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[[10,1,1,10,2,1],[10,1,1,10,2,1],[10,1,1,10,2,1],[10,1,1,10,2,1]]},
|
||||
{"id":8,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[[10,1,1,10,2,1],[10,1,1,10,2,1]]},
|
||||
{"id":9,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[[10,1,1,10,2,1],[10,1,1,10,2,1],[10,1,1,10,2,1],[10,1,1,10,2,1]]},
|
||||
{"id":10,"type":2,"timeLimit":60,"atkBonus":1000,"hpBonus":1000,"wave":[[10,1000,1]]},
|
||||
{"id":11,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[[10,1,1,10,2,1],[10,1,1,10,2,1]]},
|
||||
{"id":12,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[[10,1,1,10,2,1],[10,1,1,10,2,1],[10,1,1,10,2,1],[10,1,1,10,2,1]]},
|
||||
{"id":13,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[[10,1,1,10,2,1],[10,1,1,10,2,1]]},
|
||||
{"id":14,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[[10,1,1,10,2,1],[10,1,1,10,2,1],[10,1,1,10,2,1],[10,1,1,10,2,1]]},
|
||||
{"id":15,"type":2,"timeLimit":60,"atkBonus":1000,"hpBonus":1000,"wave":[[10,1000,1]]},
|
||||
{"id":16,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[[10,1,1,10,2,1],[10,1,1,10,2,1]]},
|
||||
{"id":17,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[[10,1,1,10,2,1],[10,1,1,10,2,1],[10,1,1,10,2,1],[10,1,1,10,2,1]]},
|
||||
{"id":18,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[[10,1,1,10,2,1],[10,1,1,10,2,1]]},
|
||||
{"id":19,"type":1,"timeLimit":null,"atkBonus":1000,"hpBonus":1000,"wave":[[10,1,1,10,2,1],[10,1,1,10,2,1],[10,1,1,10,2,1],[10,1,1,10,2,1]]},
|
||||
{"id":20,"type":2,"timeLimit":60,"atkBonus":1000,"hpBonus":1000,"wave":[[10,1000,1]]}
|
||||
]
|
@ -110,3 +110,5 @@ function Character:Died()
|
||||
self.Instance:Destroy()
|
||||
self = nil
|
||||
end
|
||||
|
||||
return Character
|
@ -41,9 +41,10 @@ end
|
||||
|
||||
function MobLib.new(MobInstance: Model): Mobs.Mob
|
||||
local HumanoidRootPart = MobInstance:FindFirstChild("HumanoidRootPart") :: BasePart
|
||||
local Enemy = MobInstance:FindFirstChild("Enemy") :: Humanoid
|
||||
local Enemy = MobInstance:WaitForChild("Enemy") :: Humanoid
|
||||
local MobConfig = MobInstance:FindFirstChild("MobConfig") and require(MobInstance:FindFirstChild("MobConfig"))
|
||||
if not HumanoidRootPart or not Enemy or not MobConfig then
|
||||
print(HumanoidRootPart, Enemy, MobConfig)
|
||||
error(("MobLib.new: Passed mob '%s' is missing vital components."):format(MobInstance.Name))
|
||||
end
|
||||
|
||||
|
@ -9,6 +9,8 @@ local Players = game:GetService("Players")
|
||||
--> Variables
|
||||
local Utils = require(ReplicatedStorage.Tools.Utils)
|
||||
local ArchiveProxy = require(ServerStorage.Proxy.ArchiveProxy)
|
||||
local MobsProxy = require(ServerStorage.Proxy.MobsProxy)
|
||||
local TypeList = require(ServerStorage.Base.TypeList)
|
||||
|
||||
--> Json
|
||||
local JsonLevel = require(ReplicatedStorage.Json.Level)
|
||||
@ -60,6 +62,48 @@ local function ExtraAddPlayerLevel(Player: Player, LevelData: table)
|
||||
end
|
||||
end
|
||||
|
||||
local EXCEPT_KEY = { "Task", "Mobs"}
|
||||
local function ChangeValue(Player: Player, Folder: Instance, LevelKey: string, LevelValue: any)
|
||||
if not Player or not Folder or not LevelKey or not LevelValue then return end
|
||||
local ValueInstance = Folder:FindFirstChild(LevelKey)
|
||||
if not ValueInstance then return end
|
||||
|
||||
local storeTable
|
||||
if Folder.Name == "Challenge" then
|
||||
storeTable = LevelProxy.pData[Player.UserId]
|
||||
else
|
||||
storeTable = ArchiveProxy.pData[Player.UserId][STORE_NAME].Progress
|
||||
end
|
||||
|
||||
storeTable[LevelKey] = LevelValue
|
||||
if not table.find(EXCEPT_KEY, LevelKey) then ValueInstance.Value = LevelValue end
|
||||
end
|
||||
|
||||
-- 怪物死亡,由初始化时传入
|
||||
local function OnMobDied(Player: Player, Mob: TypeList.Character)
|
||||
for _, mob in LevelProxy.pData[Player.UserId].Mobs do
|
||||
if mob ~= Mob then continue end
|
||||
|
||||
table.remove(LevelProxy.pData[Player.UserId].Mobs, mob)
|
||||
|
||||
-- 怪物清除判断
|
||||
local LevelData = Utils:GetJsonData(JsonLevel, LevelProxy.pData[Player.UserId].LevelId)
|
||||
if LevelProxy.pData[Player.UserId].SpawnWaveFinish and #LevelProxy.pData[Player.UserId].Mobs == 0 then
|
||||
if LevelProxy.pData[Player.UserId].NowWave < #LevelData["wave"] then
|
||||
-- 波数增长
|
||||
LevelProxy.pData[Player.UserId].NowWave = LevelProxy.pData[Player.UserId].NowWave + 1
|
||||
-- 新波次重置怪物生成状态标记
|
||||
local ChallengeFolder = LevelFolder:FindFirstChild("Challenge")
|
||||
ChangeValue(Player, ChallengeFolder, "SpawnWaveFinish", false)
|
||||
elseif LevelProxy.pData[Player.UserId].NowWave >= #LevelData["wave"] then
|
||||
-- 结束判断
|
||||
LevelProxy:ChallengeEnd(Player, true)
|
||||
end
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function LevelProxy:InitPlayer(Player: Player)
|
||||
@ -68,6 +112,7 @@ function LevelProxy:InitPlayer(Player: Player)
|
||||
local LevelFolder = Utils:CreateFolder(STORE_NAME, pData)
|
||||
local ProgressFolder = Utils:CreateFolder("Progress", LevelFolder)
|
||||
local DungeonFolder = Utils:CreateFolder("Dungeon", LevelFolder)
|
||||
local ChallengeFolder = Utils:CreateFolder("Challenge", LevelFolder)
|
||||
-- 当前关卡状态
|
||||
Utils:CreateFolder("Stats", LevelFolder)
|
||||
|
||||
@ -88,29 +133,108 @@ function LevelProxy:InitPlayer(Player: Player)
|
||||
for LevelKey, LevelValue in ArchiveProxy.pData[Player.UserId][STORE_NAME].Progress do
|
||||
CreateLevelInstance(Player, ProgressFolder, LevelKey, LevelValue)
|
||||
end
|
||||
|
||||
-- 本地内容初始化(关卡挑战信息,不存储)
|
||||
if not LevelProxy.pData then LevelProxy.pData = {} end
|
||||
if not LevelProxy.pData[Player.UserId] then LevelProxy.pData[Player.UserId] = {} end
|
||||
LevelProxy.pData[Player.UserId].Task = nil
|
||||
LevelProxy.pData[Player.UserId].Time = 0
|
||||
LevelProxy.pData[Player.UserId].LevelId = 0
|
||||
LevelProxy.pData[Player.UserId].MaxTime = 0
|
||||
LevelProxy.pData[Player.UserId].IsBoss = false
|
||||
LevelProxy.pData[Player.UserId].NowWave = 0
|
||||
LevelProxy.pData[Player.UserId].ShouldWave = 0
|
||||
LevelProxy.pData[Player.UserId].SpawnWaveFinish = false
|
||||
LevelProxy.pData[Player.UserId].Mobs = {}
|
||||
|
||||
-- 关卡挑战信息前端
|
||||
for key, value in LevelProxy.pData[Player.UserId] do
|
||||
if key == "Task" or key == "Mobs" then continue end
|
||||
CreateLevelInstance(Player, ChallengeFolder, key, value)
|
||||
end
|
||||
end
|
||||
|
||||
-- 挑战关卡(挑战副本用另一个函数)
|
||||
function LevelProxy:ChallengeLevel(Player: Player, LevelId: number)
|
||||
local LevelData = Utils:GetJsonData(JsonLevel, LevelId)
|
||||
if not LevelData then warn("Level Data not found", LevelId) return end
|
||||
-- 给前端传数据,做表现
|
||||
|
||||
-- 场景后端生成
|
||||
|
||||
-- 后端生成当前关卡状态数据
|
||||
local LevelFolder = GetPlayerLevelWorkspaceFolder(Player.UserId)
|
||||
local ChallengeFolder = LevelFolder:FindFirstChild("Challenge")
|
||||
if not ChallengeFolder then return end
|
||||
local levelTask = task.defer(function()
|
||||
ChangeValue(Player, ChallengeFolder, "IsBoss", LevelData.type == 1 and true or false)
|
||||
ChangeValue(Player, ChallengeFolder, "LevelId", LevelId)
|
||||
ChangeValue(Player, ChallengeFolder, "Time", 0)
|
||||
ChangeValue(Player, ChallengeFolder, "NowWave", 0)
|
||||
ChangeValue(Player, ChallengeFolder, "ShouldWave", 1)
|
||||
ChangeValue(Player, ChallengeFolder, "MaxTime", LevelData.timeLimit or 0)
|
||||
ChangeValue(Player, ChallengeFolder, "Mobs", {})
|
||||
|
||||
if LevelData.timeLimit then
|
||||
while task.wait(1) do
|
||||
ChangeValue(Player, ChallengeFolder, "Time", LevelProxy.pData[Player.UserId].Time + 1)
|
||||
|
||||
-- 关卡生成
|
||||
if LevelProxy.pData[Player.UserId].Wave < #LevelData.wave then
|
||||
ChangeValue(Player, ChallengeFolder, "Wave", LevelProxy.pData[Player.UserId].Wave + 1)
|
||||
end
|
||||
if LevelProxy.pData[Player.UserId].NowWave < LevelProxy.pData[Player.UserId].ShouldWave then
|
||||
ChangeValue(Player, ChallengeFolder, "NowWave", LevelProxy.pData[Player.UserId].NowWave + 1)
|
||||
local waveData = LevelData.wave[LevelProxy.pData[Player.UserId].NowWave]
|
||||
for i = 1, #waveData, 3 do
|
||||
local mobId = waveData[i + 1]
|
||||
local mobCount = waveData[i + 2]
|
||||
for _ = 1, mobCount do
|
||||
local mob = MobsProxy:CreateMob(Player, mobId, LevelData.atkBonus, LevelData.hpBonus, OnMobDied)
|
||||
table.insert(LevelProxy.pData[Player.UserId].Mobs, mob)
|
||||
end
|
||||
end
|
||||
ChangeValue(Player, ChallengeFolder, "SpawnWaveFinish", true)
|
||||
end
|
||||
-- 时间结束
|
||||
if LevelProxy.pData[Player.UserId].Time >= LevelData.timeLimit then
|
||||
self:ChallengeEnd(Player, false)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
ChangeValue(Player, ChallengeFolder, "Task", levelTask)
|
||||
end
|
||||
|
||||
-- 挑战结束
|
||||
function LevelProxy:ChallengeEnd(Player: Player)
|
||||
function LevelProxy:ChallengeEnd(Player: Player, result: boolean)
|
||||
local pData = Utils:GetPlayerDataFolder(Player)
|
||||
local LevelFolder = Utils:CreateFolder(STORE_NAME, pData)
|
||||
local ProgressFolder = Utils:CreateFolder("Progress", LevelFolder)
|
||||
-- 清除剩余怪物
|
||||
for _, mob in LevelProxy.pData[Player.UserId].Mobs do
|
||||
mob:Died()
|
||||
end
|
||||
LevelProxy.pData[Player.UserId].Mobs = {}
|
||||
|
||||
-- 判断玩家是否通关
|
||||
-- 通关后,没到最大关卡,关卡进度+1
|
||||
-- 到达最大关卡不做处理
|
||||
if result then
|
||||
ChangeValue(Player, ProgressFolder, "LevelId", LevelProxy.pData[Player.UserId].LevelId + 1)
|
||||
end
|
||||
end
|
||||
|
||||
function LevelProxy:OnPlayerRemoving(Player: Player)
|
||||
-- 关卡文件夹清除
|
||||
local PlayerLevelFolder = GetPlayerLevelWorkspaceFolder(Player.UserId)
|
||||
if PlayerLevelFolder then
|
||||
PlayerLevelFolder:Destroy()
|
||||
end
|
||||
-- 关卡存储数据清除
|
||||
if LevelProxy.pData[Player.UserId].Task then
|
||||
LevelProxy.pData[Player.UserId].Task:Cancel()
|
||||
end
|
||||
LevelProxy.pData[Player.UserId] = nil
|
||||
end
|
||||
|
||||
-- ReplicatedStorage.Remotes.PlayerRemoving.Event:Connect(function(PlayerUserId: string)
|
||||
|
@ -10,22 +10,24 @@
|
||||
|
||||
--> Services
|
||||
local Players = game:GetService("Players")
|
||||
local ServerStorage = game:GetService("ServerStorage")
|
||||
|
||||
--> Dependencies
|
||||
local MobList = require(script.Parent.MobList)
|
||||
local TypeList = require(ServerStorage.Base.TypeList)
|
||||
|
||||
--> Variables
|
||||
local DamageProxy = require(ServerStorage.Proxy.DamageProxy)
|
||||
local ActiveMobs = {}
|
||||
local AI = {}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- 获取两个单位之间的距离
|
||||
function AI:GetModelDistance(Unit1: Model, Unit2: Model): number
|
||||
function AI:GetModelDistance(Unit1: TypeList.Character, Unit2: TypeList.Character): number
|
||||
return (Unit1:GetPivot().Position - Unit2:GetPivot().Position).Magnitude
|
||||
end
|
||||
|
||||
function AI:GetClosestPlayer(Mob: any): (Player?, number?)
|
||||
function AI:GetClosestPlayer(Mob: TypeList.Character): (Player?, number?)
|
||||
local Closest = {Player = nil, Magnitude = math.huge}
|
||||
|
||||
local ActivePlayer -- We retain a reference to this, so they have to get further away from the mob to stop following, instead of the usual distance.
|
||||
@ -97,7 +99,13 @@ task.defer(function()
|
||||
if not Player then return end
|
||||
if AI:GetModelDistance(MobInstance, Player.Character) <= 5 then
|
||||
-- 调用伤害模块
|
||||
|
||||
DamageProxy:TakeDamage(MobInstance, Player.Character, {
|
||||
{
|
||||
Damage = 10,
|
||||
DamageType = DamageProxy.DamageType.PHYSICAL,
|
||||
DamageTag = DamageProxy.DamageTag.NORMAL
|
||||
}
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -11,9 +11,10 @@ local Utils = require(ReplicatedStorage.Tools.Utils)
|
||||
local PlayerInfoProxy = require(ServerStorage.Proxy.PlayerInfoProxy)
|
||||
local AI = require(script.AI)
|
||||
local Character = require(ServerStorage.Base.Character)
|
||||
local TypeList = require(ServerStorage.Base.TypeList)
|
||||
|
||||
--> Json
|
||||
local JsonMob = require(ReplicatedStorage.Json.Mob)
|
||||
local JsonMob = require(ReplicatedStorage.Json.Enemy)
|
||||
|
||||
--> Constants
|
||||
|
||||
@ -42,7 +43,7 @@ end
|
||||
local Mob = {}
|
||||
Mob.__index = Mob
|
||||
|
||||
function Mob.new(Player: Player, MobId: number)
|
||||
function Mob.new(Player: Player, MobId: number, OnMobDied: ((Player: Player, Mob: TypeList.Character) -> ())?)
|
||||
-- 获取玩家怪物目录
|
||||
local playerMobsFolder = GetPlayerMobsFolder(Player)
|
||||
if not playerMobsFolder then return end
|
||||
@ -64,6 +65,9 @@ function Mob.new(Player: Player, MobId: number)
|
||||
|
||||
-- 放入关卡中
|
||||
newMobModel.Parent = playerMobsFolder
|
||||
|
||||
-- 死亡函数
|
||||
if OnMobDied then Mob.OnDied = OnMobDied end
|
||||
|
||||
-- 接入统一AI
|
||||
self.Humanoid.MoveToFinished:Connect(function()
|
||||
@ -78,14 +82,18 @@ end
|
||||
|
||||
function Mob:Died()
|
||||
MobsProxy:RemoveMob(self.Player, self.Instance)
|
||||
if self.OnDied then self.OnDied(self.Player, self) end
|
||||
Character.Died(self)
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- 给玩家创建怪物
|
||||
function MobsProxy:CreateMob(Player: Player, MobId: number)
|
||||
local Mob = Mob.new(Player, MobId)
|
||||
function MobsProxy:CreateMob(Player: Player, MobId: number, AtkBonus: number?, HpBonus: number?, OnMobDied: ((Player: Player, Mob: TypeList.Character) -> ())?)
|
||||
local Mob = Mob.new(Player, MobId, OnMobDied)
|
||||
-- 关卡系数
|
||||
if AtkBonus then Mob:ChangeValue("attack", math.floor(Mob.attack * (AtkBonus / 1000))) end
|
||||
if HpBonus then Mob:ChangeValue("hp", math.floor(Mob.hp * (HpBonus / 1000))) end
|
||||
MobsProxy.pData[Player.UserId][Mob.Instance] = Mob
|
||||
return Mob
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user