718 lines
32 KiB
Lua
Raw Normal View History

2025-01-18 21:26:02 +08:00
PlacementModeConfig = PlacementModeConfig or {}
require('Script.Common.ue_enum_custom')
-- 放置模式ModeID
PlacementModeConfig.PlaceModeID = 1002;
-- 游玩模式ModeID
PlacementModeConfig.PlayModeID = 1001;
-- 当前编解码使用的版本
PlacementModeConfig.PlaceCodeVersion = 1;
-- 当玩家没有保存地图的情况下使用默认地图
PlacementModeConfig.GlobalDefaultPlaceCode = "1141E0P0000021J0M0000021I0M0100021H0M0200021G0M0300021F0M0400021E0M0500021D0M0600021C0M0700021B0M0800021B0N0800021D0N0600021A0M0900021A0L0900000@0W0100001E0Q0100001D0L0100001E0M0100000@0E0100001E0L0100001E0O0100000@0F0100000@0G0100000@0H0100000@0Z0100000@0Y0100001E0N0100000@0X0100000@0V0100000@0I0100001E0R0100001E0S0100001D0S010001180N000001180Q0000011B0T0000011B0K00000";
-- 放置物带有的ActorTag
PlacementModeConfig.PlaceItemTag = "PlaceItem"
-- Path --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Manager
PlacementModeConfig.PlaceManagerPath = UGCGameSystem.GetUGCResourcesFullPath('Asset/Blueprint/PlaceItems/BP_PlaceModeManager.BP_PlaceModeManager_C')
-- ItemBase
PlacementModeConfig.PlaceItemBasePath = UGCGameSystem.GetUGCResourcesFullPath('Asset/Blueprint/PlaceItems/BP_PlaceItemBase.BP_PlaceItemBase_C')
-- 跑图的阻挡体Actor
PlacementModeConfig.PassagewayBlockPath = UGCGameSystem.GetUGCResourcesFullPath('Asset/Blueprint/SceneActor/PlaceMode/BP_PassagewayBlock.BP_PassagewayBlock_C')
-- 可放置范围Actor
PlacementModeConfig.PlaceableAreaPath = UGCGameSystem.GetUGCResourcesFullPath('Asset/Blueprint/SceneActor/PlaceMode/BP_PlaceableArea.BP_PlaceableArea_C')
-- 预览材质
PlacementModeConfig.PreviewMatPath = UGCGameSystem.GetUGCResourcesFullPath('Asset/Material/PlaceMat/MAT_ClientPreview.MAT_ClientPreview')
-- 防线路径
PlacementModeConfig.LineOfDefensePath = UGCGameSystem.GetUGCResourcesFullPath('Asset/Blueprint/SceneActor/PlaceMode/BP_LineOfDefense.BP_LineOfDefense_C')
-- Path End ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
PlacementModeConfig.PlacingAttr = {
-- 采用对象池放置时可以减少性能开销,但不能设置为不可移动因此不能攀爬
IsObjectPoolPlace = false;
-- 放置时单位点之间的距离
PositionSpacing = 100;
-- 设置旋转时的单位旋转间隔
RotationSpacing = 90;
-- 初始位置(即未放置时的单位位置)
SpawnPos = {X = 0, Y = 0, Z = -3000};
-- 保存的地图上限
MaxSavedMapNum = 6;
-- 保存的放置物命名utf-8字符串长度限制
PlaceMapNameLengthLimit = 6;
-- 代码长度上限
MaxPlaceCodeLen = 800;
----------------------------TraceParam
-- 启用检测时的绘制
EnableDrawDebug = false;
-- 检测位置的时间间隔
CheckPosTimeInterval = 0.0;
-- 检测位置的距离
TraceDis = 2000;
-- 检测移除Item的距离
TraceRemoveDis = 5000;
-- 移除时检测位置的时间间隔
CheckRemoveItemTimeInterval = 0.2;
-- 检测放置的碰撞类型
TraceObjType = {ECollisionChannel.ECC_WorldStatic, ECollisionChannel.ECC_WorldDynamic};
-- 检测移除的碰撞类型
RemoveTraceObjType = {ECollisionChannel.ECC_WorldStatic, ECollisionChannel.ECC_WorldDynamic,};
-- 可放置的颜色
CanPlaceColor = {R=0.000000,G=1.000000,B=0.838520,A=1.000000};
-- 不可放置的颜色
CanNotPlaceColor = {R=1.000000,G=0.000000,B=0.000000,A=1.000000};
----------------------------TraceParam End
----------------------------PlaceValue
-- 基础放置量
BasePlaceValue = 100;
-- 最大放置量
MaxPlaceValue = 300;
-- 每级增加放置量
LevelUpPlaceValue = 2;
----------------------------PlaceValue End
---------------------------- LineOfDefense
-- 每名玩家需要通过防线的次数
NumOfPlayerBreakingThroughDefenseLine = 3;
-- 击杀得分
KillAddScore = 2;
-- 助攻得分
AssistAddScore = 1;
-- 防守成功得分
DefendSucceedAddScore = 30;
-- 进入防线得分
EnterDefenseLineAddScore = 10;
-- 距离防线2D半径内不可放置物体
LineOfDefenseRadius = 300;
-- 高度不能在防线范围内
LineOfDefenseHeight = 500;
---------------------------- LineOfDefense End
-- Shop ---------------------------------------------------------
---------------------------- subscription ratio
-- 金币兑换Exp的比例
RatioGoldToExp = 1;
-- 金砖兑换金币的比例
RatioGoldBrickToGold = 10;
-- 绿洲币兑换金砖比例
RatioOasisCoinToGoldBrick = 1;
---------------------------- subscription ratio End
-- 金砖购买名
GoldBrickName = "GoldBrick";
-- 单次购买数量
BuyGoldBrickCount = 100;
-- Shop ---------------------------------------------------------
}
-- Enum ----------------------------------------------------------------------------------------------
-- 放置模式类型
PlacementModeConfig.EPlaceMode = {
None = 1;
PlaceMode = 2;
RemoveMode = 3;
}
-- 放置是否成功的回调类型
PlacementModeConfig.EPlaceCallback = {
Succeed = 1;
InsufficientPlaceValue = 2;
InsufficientNumberOfItem = 3;
LocationNotWithinRange = 4;
}
-- 加载已保存放置物的类型
PlacementModeConfig.LoadPlaceItemsType = {
None = 0,
Default = 1,
SavedMap = 2,
}
-- 放置地图类型
PlacementModeConfig.PlaceMapType = {
RelicDefenseLine = 1;
}
-- 得分类型
PlacementModeConfig.AddScoreType = {
KillAddScore = 1; -- 击杀得分
AssistAddScore = 2; -- 助攻得分
DefendSucceedAddScore = 3; -- 防守成功得分
EnterDefenseLineAddScore = 4; -- 进入防线得分
Dead = 5; -- 玩家死亡
}
-- 放置代码导入反馈类型
PlacementModeConfig.EPlaceDecodeCallback = {
Succeed = 1; -- 导入成功
VersionError = 2; -- 版本代码出错
CodeLengthError = 3; -- 代码长度异常
MapCodeError = 4; -- 地图类型错误
PlacePosRangeError = 5; -- 放置点位不在范围内
CharRangeError = 5; -- 代码字符存在异常字符
PlaceItemTypeError = 6; -- 放置物类型异常
}
-- 解锁物体类型
PlacementModeConfig.EUnlockType = {
None = 1;
Level = 2;
Gold = 3;
GoldBrick = 4;
}
-- Enum End ------------------------------------------------------------------------------------------
-- 放置失败的回调名
PlacementModeConfig.PlaceCallbackName = {
[PlacementModeConfig.EPlaceCallback.Succeed] = "放置成功";
[PlacementModeConfig.EPlaceCallback.InsufficientPlaceValue] = "放置空间不足";
[PlacementModeConfig.EPlaceCallback.InsufficientNumberOfItem] = "物品数量不足";
[PlacementModeConfig.EPlaceCallback.LocationNotWithinRange] = "该位置不在可放置范围内";
}
-- 地图信息
PlacementModeConfig.MapInfo = {
[PlacementModeConfig.PlaceMapType.RelicDefenseLine] = {
MapName = "遗迹防线";
-- 跑图测试的时间上限
BreakThroughTestTime = 20;
MapPlacingRange = {X = 2000, Y = 2000, Z = 2000};
DefaultPlaceCode = "1141E0P0000021J0M0000021I0M0100021H0M0200021G0M0300021F0M0400021E0M0500021D0M0600021C0M0700021B0M0800021B0N0800021D0N0600021A0M0900021A0L0900000@0W0100001E0Q0100001D0L0100001E0M0100000@0E0100001E0L0100001E0O0100000@0F0100000@0G0100000@0H0100000@0Z0100000@0Y0100001E0N0100000@0X0100000@0V0100000@0I0100001E0R0100001E0S0100001D0S010001180N000001180Q0000011B0T0000011B0K00000";
}
}
-- Item
PlacementModeConfig.ItemInfo = {
[EPlaceItemType.SmallBunker] = {
Name = "小型掩体";
Desc = "可以挡子弹或作为踏板。";
ItemPath = UGCGameSystem.GetUGCResourcesFullPath('Asset/Blueprint/PlaceItems/Items/SmallBunker/BP_SmallBunker.BP_SmallBunker_C');
PreviewItemPath = UGCGameSystem.GetUGCResourcesFullPath('Asset/Blueprint/PlaceItems/Items/SmallBunker/BP_Preview_SmallBunker.BP_Preview_SmallBunker_C');
SelectTex = UGCGameSystem.GetUGCResourcesFullPath('Asset/Texture/PlaceItem/T_SmallBunker.T_SmallBunker');
MaxCount = 50;
InitialCount = 20;
Cost = 2;
RemovePointToActor = false; -- 若为true则移除指针指向Actor根位置反之则指向边框的中心点
IncrementInfo = {
UnlockType = PlacementModeConfig.EUnlockType.Gold;
Cost = 500;
};
UnlockInfo = {
UnlockType = PlacementModeConfig.EUnlockType.None;
}
},
[EPlaceItemType.BigBunker] = {
Name = "大型掩体";
Desc = "比小型掩体大很多,可以阻挡敌人前进,在无协助攀爬的情况下无法直接爬上去。";
ItemPath = UGCGameSystem.GetUGCResourcesFullPath('Asset/Blueprint/PlaceItems/Items/BigBanker/BP_BigBunker.BP_BigBunker_C');
PreviewItemPath = UGCGameSystem.GetUGCResourcesFullPath('Asset/Blueprint/PlaceItems/Items/BigBanker/BP_Preview_BigBunker.BP_Preview_BigBunker_C');
SelectTex = UGCGameSystem.GetUGCResourcesFullPath('Asset/Texture/PlaceItem/T_BigBunker.T_BigBunker');
MaxCount = 10;
InitialCount = 4;
Cost = 5;
RemovePointToActor = false; -- 若为true则移除指针指向Actor根位置反之则指向边框的中心点
IncrementInfo = {
UnlockType = PlacementModeConfig.EUnlockType.Gold;
Cost = 1000;
};
UnlockInfo = {
UnlockType = PlacementModeConfig.EUnlockType.None;
}
},
[EPlaceItemType.Slope] = {
Name = "斜坡木板";
Desc = "可快速走到一定的高度。";
ItemPath = UGCGameSystem.GetUGCResourcesFullPath('Asset/Blueprint/PlaceItems/Items/Slope/BP_Slope.BP_Slope_C');
PreviewItemPath = UGCGameSystem.GetUGCResourcesFullPath('Asset/Blueprint/PlaceItems/Items/Slope/BP_Preview_Slope.BP_Preview_Slope_C');
SelectTex = UGCGameSystem.GetUGCResourcesFullPath('Asset/Texture/PlaceItem/T_Slope.T_Slope');
MaxCount = 40;
InitialCount = 15;
Cost = 2;
RemovePointToActor = false; -- 若为true则移除指针指向Actor根位置反之则指向边框的中心点
IncrementInfo = {
UnlockType = PlacementModeConfig.EUnlockType.Gold;
Cost = 500;
};
UnlockInfo = {
UnlockType = PlacementModeConfig.EUnlockType.None;
}
},
[EPlaceItemType.Launch] = {
Name = "蹦床";
Desc = "弹射玩家到一定的高度。";
ItemPath = UGCGameSystem.GetUGCResourcesFullPath('Asset/Blueprint/PlaceItems/Items/Launch/BP_Launch.BP_Launch_C');
PreviewItemPath = UGCGameSystem.GetUGCResourcesFullPath('Asset/Blueprint/PlaceItems/Items/Launch/BP_Preview_Launch.BP_Preview_Launch_C');
SelectTex = UGCGameSystem.GetUGCResourcesFullPath('Asset/Texture/PlaceItem/T_Launch.T_Launch');
MaxCount = 4;
InitialCount = 0;
Cost = 10;
RemovePointToActor = true; -- 若为true则移除指针指向Actor根位置反之则指向边框的中心点
IncrementInfo = {
UnlockType = PlacementModeConfig.EUnlockType.Gold;
Cost = 1500;
};
UnlockInfo = {
UnlockType = PlacementModeConfig.EUnlockType.Level;
Cost = 3;
}
},
[EPlaceItemType.LandMine] = {
Name = "地雷";
Desc = "进攻玩家走入范围内会发生爆炸造成80点伤害,10s冷却。";
ItemPath = UGCGameSystem.GetUGCResourcesFullPath('Asset/Blueprint/PlaceItems/Items/LandMine/BP_LandMine.BP_LandMine_C');
PreviewItemPath = UGCGameSystem.GetUGCResourcesFullPath('Asset/Blueprint/PlaceItems/Items/LandMine/BP_Preview_LandMine.BP_Preview_LandMine_C');
SelectTex = UGCGameSystem.GetUGCResourcesFullPath('Asset/Texture/PlaceItem/T_LandMine.T_LandMine');
MaxCount = 6;
InitialCount = 1;
Cost = 15;
RemovePointToActor = true; -- 若为true则移除指针指向Actor根位置反之则指向边框的中心点
IncrementInfo = {
UnlockType = PlacementModeConfig.EUnlockType.Gold;
Cost = 3000;
};
UnlockInfo = {
UnlockType = PlacementModeConfig.EUnlockType.None;
};
-- 其他参数
Param = { Damage = 80; CoolingTime = 10;}
},
[EPlaceItemType.Flamethrower] = {
Name = "喷火装置";
Desc = "对范围8m内最近的敌人造成范围伤害。";
ItemPath = UGCGameSystem.GetUGCResourcesFullPath('Asset/Blueprint/PlaceItems/Items/Flamethrower/BP_Flamethrower.BP_Flamethrower_C');
PreviewItemPath = UGCGameSystem.GetUGCResourcesFullPath('Asset/Blueprint/PlaceItems/Items/Flamethrower/BP_Preview_Flamethrower.BP_Preview_Flamethrower_C');
SelectTex = UGCGameSystem.GetUGCResourcesFullPath('Asset/Texture/PlaceItem/T_Framethrower.T_Framethrower');
MaxCount = 2;
InitialCount = 0;
Cost = 20;
RemovePointToActor = true; -- 若为true则移除指针指向Actor根位置反之则指向边框的中心点
IncrementInfo = {
UnlockType = PlacementModeConfig.EUnlockType.Gold;
Cost = 5000;
};
UnlockInfo = {
UnlockType = PlacementModeConfig.EUnlockType.Level;
Cost = 8;
};
-- 其他参数
Param = { Damage = 10; }
},
}
-- 得分数值
PlacementModeConfig.ScoreVal = {
[PlacementModeConfig.AddScoreType.KillAddScore] = 2; -- 击杀得分
[PlacementModeConfig.AddScoreType.AssistAddScore] = 1; -- 助攻得分
[PlacementModeConfig.AddScoreType.DefendSucceedAddScore] = 30; -- 防守成功得分
[PlacementModeConfig.AddScoreType.EnterDefenseLineAddScore] = 10; -- 进入防线得分
[PlacementModeConfig.AddScoreType.Dead] = 0; -- 玩家死亡
}
-- 得分名称
PlacementModeConfig.AddScoreName = {
[PlacementModeConfig.AddScoreType.KillAddScore] = "淘汰得分";
[PlacementModeConfig.AddScoreType.AssistAddScore] = "助攻得分";
[PlacementModeConfig.AddScoreType.DefendSucceedAddScore] = "防守成功";
[PlacementModeConfig.AddScoreType.EnterDefenseLineAddScore] = "突破得分";
}
PlacementModeConfig.UnlockName = {
[PlacementModeConfig.EUnlockType.None] = "";
[PlacementModeConfig.EUnlockType.Level] = "等级";
[PlacementModeConfig.EUnlockType.Gold] = "金币";
[PlacementModeConfig.EUnlockType.GoldBrick] = "金砖";
}
-- Function ============================================================================================================================================================================================
--- 获取放置控制器Manager
PlacementModeConfig.GetPlaceManager = function()
if not UE.IsValid(PlacementModeConfig.PlaceManager) then
PlacementModeConfig.PlaceManager = UGCSystemLibrary.GetUniqueInstanceFromPath(PlacementModeConfig.PlaceManagerPath)
end
return PlacementModeConfig.PlaceManager
end
--- 获取放置模式的父类Class
PlacementModeConfig.GetPlaceItemBaseClass = function()
if PlacementModeConfig.PlaceItemBaseClass == nil then
PlacementModeConfig.PlaceItemBaseClass = UE.LoadClass(PlacementModeConfig.PlaceItemBasePath)
end
return PlacementModeConfig.PlaceItemBaseClass
end
--- 是否为放置模式
PlacementModeConfig.IsPlaceMode = function()
return PlacementModeConfig.PlaceModeID == UGCMultiMode.GetModeID()
end
--- 通过当前在线的进攻玩家数,进行判断应该突破防线的次数
function PlacementModeConfig.GetNumOfBreakingThroughDefenseLine()
local PCNum = #UGCGameSystem.GetAllPlayerController()
return (PCNum - 1) * PlacementModeConfig.PlacingAttr.NumOfPlayerBreakingThroughDefenseLine
end
--- 获取放置物解锁条件信息
function PlacementModeConfig.GetPlaceItemUnlockInfo(PlaceItemType)
local PlaceItemInfo = PlacementModeConfig.ItemInfo[PlaceItemType]
if PlaceItemInfo then
return PlaceItemInfo.UnlockInfo.UnlockType, PlaceItemInfo.UnlockInfo.Cost
end
end
--- 获取放置物增量条件信息
function PlacementModeConfig.GetPlaceItemIncrementInfo(PlaceItemType)
local PlaceItemInfo = PlacementModeConfig.ItemInfo[PlaceItemType]
if PlaceItemInfo then
return PlaceItemInfo.IncrementInfo.UnlockType, PlaceItemInfo.IncrementInfo.Cost
end
end
--- 获取最大放置量
function PlacementModeConfig.GetPlaceMaxValue(InPlayerKey)
local Exp = ArchiveDataConfig.GetPlayerArchiveDataFromType(InPlayerKey, ArchiveDataConfig.EArchiveType.Exp)
Exp = Exp and Exp or 0
local Level = LevelConfig.GetLevel(Exp)
return PlacementModeConfig.PlacingAttr.BasePlaceValue + (Level - 1) * PlacementModeConfig.PlacingAttr.LevelUpPlaceValue
end
--- 设置所有放置机关的激活
function PlacementModeConfig.ActiveAllPlaceItem(IsActive)
local SceneAllPlaceItems = GameplayStatics.GetAllActorsOfClass(UGCGameSystem.GameState, PlacementModeConfig.GetPlaceItemBaseClass(), {})
for i, v in pairs(SceneAllPlaceItems) do
v:SetActive(IsActive)
end
end
--- 获取玩家可放置某物体的数量
function PlacementModeConfig.GetPlayerPlaceItemCount(PlayerKey, InItemType)
local ItemIncrement = ArchiveDataConfig.GetPlayerArchiveDataFromType(PlayerKey, ArchiveDataConfig.EArchiveType.ItemIncrement)
local ItemInfo = PlacementModeConfig.ItemInfo[InItemType]
if ItemIncrement and ItemIncrement[InItemType] then
return math.clamp(ItemIncrement[InItemType] + ItemInfo.InitialCount, 0, ItemInfo.MaxCount)
end
return ItemInfo.InitialCount
end
--- 获取放置代码中含有的物体数量
function PlacementModeConfig.GetPlaceCodeHaveItemCont(InCode)
local PlaceItemCount = {}
local DecodeResType, MapType, PlaceItemInfo = PlacementModeConfig.PlaceCodeDecode(InCode)
if DecodeResType == PlacementModeConfig.EPlaceDecodeCallback.Succeed then
for i, v in pairs(PlaceItemInfo) do
if PlaceItemCount[v.PlaceItemType] then
PlaceItemCount[v.PlaceItemType] = PlaceItemCount[v.PlaceItemType] + 1
else
PlaceItemCount[v.PlaceItemType] = 1
end
end
end
return DecodeResType, PlaceItemCount, PlaceItemInfo
end
--- 判断该代码是否满足该玩家可用的需求
---@return CanUse, PlaceCount, DecodeResType
function PlacementModeConfig.CheckPlayerCanUsePlaceCode(InCode, InPlayerKey)
local DecodeResType, PlaceItemCount, PlaceItemInfo = PlacementModeConfig.GetPlaceCodeHaveItemCont(InCode)
if DecodeResType == PlacementModeConfig.EPlaceDecodeCallback.Succeed then
local PlaceCount = 0
local CanPlace = true
for PlaceItemType, Count in pairs(PlaceItemCount) do
if CanPlace and PlacementModeConfig.GetPlayerPlaceItemCount(InPlayerKey, PlaceItemType) < Count then
CanPlace = false
end
PlaceCount = PlaceCount + PlacementModeConfig.ItemInfo[PlaceItemType].Cost * Count
end
if not CanPlace then
return false, PlaceCount, DecodeResType, PlaceItemInfo
end
if PlaceCount > PlacementModeConfig.GetPlaceMaxValue(InPlayerKey) then
return false, PlaceCount
end
return true, PlaceCount, DecodeResType, PlaceItemInfo
end
return false, 0, DecodeResType, PlaceItemInfo
end
function PlacementModeConfig.GetSimpleLineOfDefense()
if not UE.IsValid(PlacementModeConfig.SimpleLineOfDefense) then
PlacementModeConfig.SimpleLineOfDefense = UGCSystemLibrary.GetUniqueInstanceFromPath(PlacementModeConfig.LineOfDefensePath)
end
return PlacementModeConfig.SimpleLineOfDefense
end
-- 格式化坐标和旋转 ----------------------------------------------------------------------------------------------------------------------------------------------
---@param Vec FVector
PlacementModeConfig.VectorToUnitVector = function(Vec)
return {
X = KismetMathLibrary.Round(Vec.X / PlacementModeConfig.PlacingAttr.PositionSpacing),
Y = KismetMathLibrary.Round(Vec.Y / PlacementModeConfig.PlacingAttr.PositionSpacing),
Z = KismetMathLibrary.Round(Vec.Z / PlacementModeConfig.PlacingAttr.PositionSpacing),
}
end
---@param Vec FVector
PlacementModeConfig.UnitVectorToVector = function(Vec)
return {
X = Vec.X * PlacementModeConfig.PlacingAttr.PositionSpacing,
Y = Vec.Y * PlacementModeConfig.PlacingAttr.PositionSpacing,
Z = Vec.Z * PlacementModeConfig.PlacingAttr.PositionSpacing,
}
end
---@param Rot FRotator
PlacementModeConfig.RotatorToUnitRotator = function(Rot)
return {
Roll = KismetMathLibrary.Round((Rot.Roll % 360) / PlacementModeConfig.PlacingAttr.RotationSpacing),
Pitch = KismetMathLibrary.Round((Rot.Pitch % 360) / PlacementModeConfig.PlacingAttr.RotationSpacing),
Yaw = KismetMathLibrary.Round((Rot.Yaw % 360) / PlacementModeConfig.PlacingAttr.RotationSpacing),
}
end
---@param Rot FRotator
PlacementModeConfig.UnitRotatorToRotator = function(Rot)
return {
Roll = Rot.Roll * PlacementModeConfig.PlacingAttr.RotationSpacing,
Pitch = Rot.Pitch * PlacementModeConfig.PlacingAttr.RotationSpacing,
Yaw = Rot.Yaw * PlacementModeConfig.PlacingAttr.RotationSpacing,
}
end
-- 格式化坐标和旋转 End ------------------------------------------------------------------------------------------------------------------------------------------
-- 单例预览材质 -------------------------------------------------------------------------------------------------------------------------------------------------
--- 获取放置时的动态材质
function PlacementModeConfig.GetPreviewDynamicMat()
if PlacementModeConfig.DynamicMaterial == nil then
local PreviewMat = UE.LoadObject(PlacementModeConfig.PreviewMatPath)
PlacementModeConfig.DynamicMaterial = KismetMaterialLibrary.CreateDynamicMaterialInstance(UGCGameSystem.GameState, PreviewMat);
end
return PlacementModeConfig.DynamicMaterial
end
--- 设置是否可放置
PlacementModeConfig.bCanPlace = true
function PlacementModeConfig.SetCanPlace(InCanPlace)
if InCanPlace ~= PlacementModeConfig.bCanPlace then
PlacementModeConfig.bCanPlace = InCanPlace
--- 设置预览放置物动态材质的颜色
if PlacementModeConfig.bCanPlace then
PlacementModeConfig.GetPreviewDynamicMat():SetVectorParameterValue("Diff_Light", PlacementModeConfig.PlacingAttr.CanPlaceColor)
else
PlacementModeConfig.GetPreviewDynamicMat():SetVectorParameterValue("Diff_Light", PlacementModeConfig.PlacingAttr.CanNotPlaceColor)
end
end
end
-- 单例预览材质 End ---------------------------------------------------------------------------------------------------------------------------------------------
-- 导出/导入放置代码 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- 采用72进制作为编码
PlacementModeConfig.base72_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!@#$%^&*()"
PlacementModeConfig.StrToBase72 = {["0"] = 0, ["1"] = 1, ["2"] = 2, ["3"] = 3, ["4"] = 4, ["5"] = 5, ["6"] = 6, ["7"] = 7, ["8"] = 8, ["9"] = 9, ["A"] = 10, ["B"] = 11, ["C"] = 12, ["D"] = 13, ["E"] = 14, ["F"] = 15, ["G"] = 16, ["H"] = 17, ["I"] = 18, ["J"] = 19, ["K"] = 20, ["L"] = 21, ["M"] = 22, ["N"] = 23, ["O"] = 24, ["P"] = 25, ["Q"] = 26, ["R"] = 27, ["S"] = 28, ["T"] = 29, ["U"] = 30, ["V"] = 31, ["W"] = 32, ["X"] = 33, ["Y"] = 34, ["Z"] = 35, ["a"] = 36, ["b"] = 37, ["c"] = 38, ["d"] = 39, ["e"] = 40, ["f"] = 41, ["g"] = 42, ["h"] = 43, ["i"] = 44, ["j"] = 45, ["k"] = 46, ["l"] = 47, ["m"] = 48, ["n"] = 49, ["o"] = 50, ["p"] = 51, ["q"] = 52, ["r"] = 53, ["s"] = 54, ["t"] = 55, ["u"] = 56, ["v"] = 57, ["w"] = 58, ["x"] = 59, ["y"] = 60, ["z"] = 61, ["!"] = 62, ["@"] = 63, ["#"] = 64, ["$"] = 65, ["%"] = 66, ["^"] = 67, ["&"] = 68, ["*"] = 69, ["("] = 70, [")"] = 71, }
PlacementModeConfig.Base72ToStr = { [0] = "0", [1] = "1", [2] = "2", [3] = "3", [4] = "4", [5] = "5", [6] = "6", [7] = "7", [8] = "8", [9] = "9", [10] = "A", [11] = "B", [12] = "C", [13] = "D", [14] = "E", [15] = "F", [16] = "G", [17] = "H", [18] = "I", [19] = "J", [20] = "K", [21] = "L", [22] = "M", [23] = "N", [24] = "O", [25] = "P", [26] = "Q", [27] = "R", [28] = "S", [29] = "T", [30] = "U", [31] = "V", [32] = "W", [33] = "X", [34] = "Y", [35] = "Z", [36] = "a", [37] = "b", [38] = "c", [39] = "d", [40] = "e", [41] = "f", [42] = "g", [43] = "h", [44] = "i", [45] = "j", [46] = "k", [47] = "l", [48] = "m", [49] = "n", [50] = "o", [51] = "p", [52] = "q", [53] = "r", [54] = "s", [55] = "t", [56] = "u", [57] = "v", [58] = "w", [59] = "x", [60] = "y", [61] = "z", [62] = "!", [63] = "@", [64] = "#", [65] = "$", [66] = "%", [67] = "^", [68] = "&", [69] = "*", [70] = "(", [71] = ")", }
-- 十进制转换为72进制的函数
---@param n 十进制数
---@param CompletingDigits 需要补全的数字为nil则不补全
function PlacementModeConfig.DToBase72(n, CompletingDigits)
local result = ""
if n == 0 then
result = "0"
else
local base = 72
-- UGCLogSystem.Log("[PlacementModeConfig_DToBase72] n:%s", tostring(n))
while n > 0 do
local remainder = n % base
-- UGCLogSystem.Log("[PlacementModeConfig_DToBase72]---- n:%s", tostring(n))
result = PlacementModeConfig.Base72ToStr[remainder] .. result
n = math.floor(n / base)
end
end
if CompletingDigits then
while string.len(result) < CompletingDigits do
result = "0" .. result
end
end
return result
end
-- 72进制转换为十进制的函数
function PlacementModeConfig.base72ToD(base72Str)
local Res = 0
local LenStr = string.len(base72Str)
for i = 1, LenStr, 1 do
local chr = string.sub(base72Str, LenStr - i + 1, LenStr - i + 1)
Res = Res + PlacementModeConfig.StrToBase72[chr] * 72 ^ (i - 1)
end
-- 四舍五入
return math.floor(Res + 0.5)
end
function PlacementModeConfig.PlaceCodeEncode(InMapType)
return PlacementModeConfig.PlaceCodeVersionFuncList[PlacementModeConfig.PlaceCodeVersion].Encode(InMapType)
end
--- 对放置代码进行验证并解码
---@return " EPlaceDecodeCallback, MapType, PlaceItemInfo = {PlaceItemType = PlaceItemType, UnitPos = UnitPos, UnitRot = UnitRot}"
function PlacementModeConfig.PlaceCodeDecode(PlaceCode)
local CodeLen = string.len(PlaceCode)
-- 检验字符范围是否在72个字符内
for i = 1, CodeLen do
local CodeStr = string.sub(PlaceCode, i, i)
if PlacementModeConfig.StrToBase72[CodeStr] == nil then
return PlacementModeConfig.EPlaceDecodeCallback.CharRangeError
end
end
-- 检验版本和地图的字符长度
if CodeLen < 2 or CodeLen > PlacementModeConfig.PlacingAttr.MaxPlaceCodeLen then
return PlacementModeConfig.EPlaceDecodeCallback.CodeLengthError
end
local Version = PlacementModeConfig.StrToBase72[string.sub(PlaceCode, 1, 1)]
local CodeFuncList = PlacementModeConfig.PlaceCodeVersionFuncList[Version]
-- 检验版本是否出错
if CodeFuncList == nil then
return PlacementModeConfig.EPlaceDecodeCallback.VersionError
end
return CodeFuncList.Decode(PlaceCode)
end
-- V1版本编码
--[[
172 -- 占位1位
(1,6(XYZ各2位)3(RPY各1位)) -- 占位10位
]]
function PlacementModeConfig.PlaceCodeEncode_V01(MapType)
-- 编码版本 此函数版本为1
local ResString = PlacementModeConfig.Base72ToStr[1]
-- 地图占1位
ResString = ResString .. PlacementModeConfig.Base72ToStr[MapType]
-- 对场景中所有已激活的放置物进行编码
local SceneAllPlaceItems = GameplayStatics.GetAllActorsOfClass(UGCGameSystem.GameState, PlacementModeConfig.GetPlaceItemBaseClass(), {})
for i, v in pairs(SceneAllPlaceItems) do
-- 判断该物体是否激活
if v:GetIsPlaced() then
local AddStr = ""
-- 编码物体类型
local ItemType = v:GetPlaceItemType()
AddStr = AddStr .. PlacementModeConfig.DToBase72(ItemType)
--UGCLogSystem.Log("[PlacementModeConfig_PlaceCodeEncode_V01]_1 ResString:%s", ResString)
-- 编码物体位置和旋转
local Pos, Rot = v:GetPlacePosAndRot()
--UGCLogSystem.LogTree("[PlacementModeConfig_PlaceCodeEncode_V01] Pos", Pos)
--UGCLogSystem.LogTree("[PlacementModeConfig_PlaceCodeEncode_V01] Rot", Rot);
AddStr = AddStr .. PlacementModeConfig.DToBase72(Pos.X, 2)
AddStr = AddStr .. PlacementModeConfig.DToBase72(Pos.Y, 2)
AddStr = AddStr .. PlacementModeConfig.DToBase72(Pos.Z, 2)
--UGCLogSystem.Log("[PlacementModeConfig_PlaceCodeEncode_V01]_2 ResString:%s", ResString)
AddStr = AddStr .. PlacementModeConfig.DToBase72(Rot.Roll)
AddStr = AddStr .. PlacementModeConfig.DToBase72(Rot.Pitch)
AddStr = AddStr .. PlacementModeConfig.DToBase72(Rot.Yaw)
--UGCLogSystem.Log("[PlacementModeConfig_PlaceCodeEncode_V01]_3 ResString:%s", ResString)
ResString = ResString .. AddStr
UGCLogSystem.Log("[PlacementModeConfig_PlaceCodeEncode_V01]_4 Len:%d, AddStr:%s",string.len(AddStr), AddStr)
UGCLogSystem.Log("[PlacementModeConfig_PlaceCodeEncode_V01]_5 Len:%d, ResString:%s",string.len(ResString), ResString)
end
end
return ResString
end
-- V1版本解码
--[[
172 -- 占位1位
(1,6(XYZ各2位)3(RPY各1位)) -- 占位10位
]]
function PlacementModeConfig.PlaceCodeDecode_V01(PlaceCode)
local LenPlaceCode = string.len(PlaceCode)
UGCLogSystem.Log("[PlacementModeConfig_PlaceCodeDecode_V01] LenPlaceCode:%s", tostring(LenPlaceCode))
-- 验证长度
if ((LenPlaceCode - 2) % 10) ~= 0 then
return PlacementModeConfig.EPlaceDecodeCallback.CodeLengthError
end
local Index = 2
local ReadCodeStr = function(InNum)
local Res = string.sub(PlaceCode, Index, Index + (InNum - 1))
Index = Index + InNum
return Res
end
local MapType = PlacementModeConfig.StrToBase72[ReadCodeStr(1)]
-- 验证Map类型是否符合
if PlacementModeConfig.MapInfo[MapType] == nil then
return PlacementModeConfig.EPlaceDecodeCallback.MapCodeError
end
-- 可放置范围
local MapPlacingRange = PlacementModeConfig.MapInfo[MapType].MapPlacingRange
local ResPlaceItemInfo = {}
for i = 1, math.floor((LenPlaceCode - 2) / 10 + 0.5) do
local PlaceItemType = PlacementModeConfig.base72ToD(ReadCodeStr(1))
if PlacementModeConfig.ItemInfo[PlaceItemType] == nil then
return PlacementModeConfig.EPlaceDecodeCallback.PlaceItemTypeError
end
local UnitX = PlacementModeConfig.base72ToD(ReadCodeStr(2))
local UnitY = PlacementModeConfig.base72ToD(ReadCodeStr(2))
local UnitZ = PlacementModeConfig.base72ToD(ReadCodeStr(2))
-- 检验放置范围是否异常
if UnitX > MapPlacingRange.X or UnitY > MapPlacingRange.Y or UnitZ > MapPlacingRange.Z then
return PlacementModeConfig.EPlaceDecodeCallback.PlacePosRangeError
end
local UnitPos = {X = UnitX, Y = UnitY, Z = UnitZ}
local UnitRot = {
Roll = PlacementModeConfig.StrToBase72[ReadCodeStr(1)],
Pitch = PlacementModeConfig.StrToBase72[ReadCodeStr(1)],
Yaw = PlacementModeConfig.StrToBase72[ReadCodeStr(1)]
}
ResPlaceItemInfo[#ResPlaceItemInfo + 1] = {PlaceItemType = PlaceItemType, UnitPos = UnitPos, UnitRot = UnitRot}
end
return PlacementModeConfig.EPlaceDecodeCallback.Succeed, MapType, ResPlaceItemInfo
end
-- 开头为编码的版号 -- 占位1位
PlacementModeConfig.PlaceCodeVersionFuncList = {
[1] = {Encode = PlacementModeConfig.PlaceCodeEncode_V01, Decode = PlacementModeConfig.PlaceCodeDecode_V01},
}
-- 导出/导入放置代码 End ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------