2025-01-04 23:00:19 +08:00

718 lines
32 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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版本编码
--[[
地图编号1位72进制 -- 占位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版本解码
--[[
地图编号1位72进制 -- 占位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 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------