Merge branch 'develop' of https://git.brew.monster/Unity/perfect-world-unity into feature/produce-equipment
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 1.1 MiB |
@@ -0,0 +1,130 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cfa464036967d9746abcfa0608211b2e
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 0
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 0
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f3553c5fdd68230c6a591df1fde22cf360896fc818007787595189f0cc036b5c
|
||||
size 69312
|
||||
oid sha256:eadad766c90d9a2f8f33468f1b6b21e6fd78e55f555200887eb9f6198720424a
|
||||
size 76688
|
||||
|
||||
@@ -919,6 +919,53 @@ public static class generate_item_temp
|
||||
itemdataman.set_to_classid(DATA_TYPE.DT_FASHION_ESSENCE, data, -1);
|
||||
return 0;
|
||||
}
|
||||
public static int generate_taskdice<RAND_CLASS>(uint id, ID_SPACE idspace, out byte[] data, out uint size, RAND_CLASS cls)
|
||||
{
|
||||
DATA_TYPE datatype = DATA_TYPE.DT_INVALID;
|
||||
data = new byte[0];
|
||||
size = 0;
|
||||
object obj = itemdataman._edm.get_data_ptr(id, idspace, ref datatype);
|
||||
if(obj == null || datatype != DATA_TYPE.DT_TASKDICE_ESSENCE)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
TASKDICE_ESSENCE ess = (TASKDICE_ESSENCE)obj;
|
||||
size = (uint)(Marshal.SizeOf(typeof(item_data)) + Marshal.SizeOf(typeof(TASKDICE_ESSENCE)));
|
||||
data = new byte[size];
|
||||
int offset = 0;
|
||||
WriteUInt(data, ref offset, id);
|
||||
WriteUInt(data, ref offset, 1);
|
||||
WriteInt(data, ref offset, ess.pile_num_max);
|
||||
WriteInt(data, ref offset, 0);
|
||||
WriteUInt(data, ref offset, ess.proc_type);
|
||||
WriteInt(data, ref offset, (int)DATA_TYPE.DT_TASKDICE_ESSENCE);
|
||||
if(ess.has_guid == 1)
|
||||
{
|
||||
int g1,g2;
|
||||
itemdataman.get_item_guid(id,out g1,out g2);
|
||||
WriteInt(data, ref offset, g1);
|
||||
WriteInt(data, ref offset, g2);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteInt(data, ref offset, 0);
|
||||
WriteInt(data, ref offset, 0);
|
||||
}
|
||||
WriteInt(data, ref offset, 0);
|
||||
WriteInt(data, ref offset, 0);
|
||||
|
||||
int content_length = 0;
|
||||
int content_length_ptr = offset;
|
||||
WriteInt(data, ref offset, 0);
|
||||
int item_content = offset;
|
||||
WriteInt(data, ref offset, 0);
|
||||
content_length = (int)(size - offset);
|
||||
WriteInt(data, ref content_length_ptr, content_length);
|
||||
WriteInt(data, ref item_content, offset);
|
||||
|
||||
itemdataman.set_to_classid(DATA_TYPE.DT_TASKDICE_ESSENCE, data, -1);
|
||||
return 0;
|
||||
}
|
||||
public static int generate_tasknormalmatter<RAND_CLASS>(uint id, ID_SPACE idspace, out byte[] data, out uint size, RAND_CLASS cls,
|
||||
GEN_ADDON_MODE normal_addon ,item_tag_t tag,List<int> sa_list = null)
|
||||
{
|
||||
|
||||
@@ -469,6 +469,9 @@ namespace BrewMonster
|
||||
case DATA_TYPE.DT_FASHION_ESSENCE:
|
||||
ret = generate_item_temp.generate_fashion_item(id, ID_SPACE.ID_SPACE_ESSENCE, out item, out size, SPECIFIC.SPECIFIC_RAND, tag);
|
||||
break;
|
||||
case DATA_TYPE.DT_TASKDICE_ESSENCE:
|
||||
ret = generate_item_temp.generate_taskdice(id, ID_SPACE.ID_SPACE_ESSENCE, out item, out size, SPECIFIC.SPECIFIC_RAND);
|
||||
break;
|
||||
case DATA_TYPE.DT_TASKNORMALMATTER_ESSENCE:
|
||||
ret = generate_item_temp.generate_tasknormalmatter(id,ID_SPACE.ID_SPACE_ESSENCE,
|
||||
out item,out size,SPECIFIC.SPECIFIC_RAND,GEN_ADDON_MODE.ADDON_LIST_SHOP,tag);
|
||||
|
||||
@@ -1508,16 +1508,16 @@ namespace BrewMonster
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
|
||||
public byte[] file_model; // Model file path
|
||||
|
||||
public string FileModel => ByteToStringUtils.ByteArrayToCP936String(file_model);
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
|
||||
public byte[] file_model2; // Second model file path
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
|
||||
public byte[] file_matter; // Material file path
|
||||
|
||||
public string FileMatter => ByteToStringUtils.ByteArrayToCP936String(file_matter);
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
|
||||
public byte[] file_icon; // Icon file path
|
||||
|
||||
public string FileIcon => ByteToStringUtils.ByteArrayToCP936String(file_icon);
|
||||
public int price; // Price
|
||||
public int shop_price; // Shop price
|
||||
|
||||
@@ -1785,9 +1785,10 @@ namespace BrewMonster
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
|
||||
public byte[] file_matter; // matter file path
|
||||
|
||||
public string FileMatter { get { return ByteToStringUtils.ByteArrayToCP936String(file_matter); } }
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
|
||||
public byte[] file_icon; // icon file path
|
||||
public string FileIcon { get { return ByteToStringUtils.ByteArrayToCP936String(file_icon); } }
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct TaskList
|
||||
|
||||
@@ -819,7 +819,7 @@ namespace PerfectWorld.Scripts.Managers
|
||||
/// <summary>
|
||||
/// Read maker information from binary data
|
||||
/// </summary>
|
||||
private void ReadMakerInfo(CECDataReader dr)
|
||||
protected void ReadMakerInfo(CECDataReader dr)
|
||||
{
|
||||
// Debug: Log the bytes at current position before reading
|
||||
// We need to check what bytes are actually at the reader position
|
||||
|
||||
@@ -1,20 +1,228 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.IO;
|
||||
using BrewMonster;
|
||||
using ModelRenderer.Scripts.Common;
|
||||
using ModelRenderer.Scripts.GameData;
|
||||
using UnityEngine;
|
||||
using PerfectWorld.Scripts.Managers;
|
||||
using BrewMonster.Network;
|
||||
using BrewMonster.Scripts.Managers;
|
||||
using BrewMonster.Scripts;
|
||||
using CSNetwork.GPDataType;
|
||||
using System.Runtime.InteropServices;
|
||||
namespace PerfectWorld.Scripts.Managers
|
||||
{
|
||||
public class EC_IvtrFlysword : EC_IvtrItem
|
||||
|
||||
/// <summary>
|
||||
/// Flysword Item (Phi kiem).
|
||||
/// </summary>
|
||||
public class EC_IvtrFlysword : EC_IvtrEquip
|
||||
{
|
||||
|
||||
protected int m_iCurTime; // Current time counter in ms
|
||||
protected IVTR_ESSENCE_FLYSWORD m_Essence;
|
||||
protected FLYSWORD_ESSENCE m_pDBEssence;
|
||||
/// <summary>
|
||||
/// Not create logic yet (add summary later)
|
||||
/// Flysword Item (Phi kiem)
|
||||
/// </summary>
|
||||
/// <param name="tid">Template id</param>
|
||||
/// <param name="expire_date">Expire date</param>
|
||||
public EC_IvtrFlysword(int tid, int expire_date) : base(tid, expire_date)
|
||||
{
|
||||
m_iCID = (int)InventoryClassId.ICID_FLYSWORD;
|
||||
|
||||
// Get database data
|
||||
elementdataman pDB = ElementDataManProvider.GetElementDataMan();
|
||||
DATA_TYPE DataType = DATA_TYPE.DT_INVALID;
|
||||
m_pDBEssence = (FLYSWORD_ESSENCE)pDB.get_data_ptr((uint)tid, ID_SPACE.ID_SPACE_ESSENCE, ref DataType);
|
||||
m_iPileLimit = m_pDBEssence.pile_num_max;
|
||||
m_iPrice = m_pDBEssence.price;
|
||||
m_iShopPrice = m_pDBEssence.shop_price;
|
||||
m_iProcType = (int)m_pDBEssence.proc_type;
|
||||
m_i64EquipMask = EC_IvtrType.EQUIP_MASK64_FLYSWORD;
|
||||
m_bUseable = true;
|
||||
m_bNeedUpdate = false;
|
||||
}
|
||||
|
||||
public EC_IvtrFlysword(EC_IvtrFlysword other) : base(other)
|
||||
{
|
||||
m_iCurTime = other.m_iCurTime;
|
||||
m_Essence = other.m_Essence;
|
||||
m_pDBEssence = other.m_pDBEssence;
|
||||
MadeFrom = other.MadeFrom;
|
||||
Maker = other.Maker;
|
||||
}
|
||||
|
||||
public override bool SetItemInfo(byte[] pInfoData, int iDataLen)
|
||||
{
|
||||
// Note: because fly sword isn't an absolute equipment, so skip
|
||||
// CECIvtrEquip::SetItemInfo().
|
||||
|
||||
if (pInfoData == null || iDataLen == 0)
|
||||
{
|
||||
m_bNeedUpdate = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
CECDataReader dr = new CECDataReader(pInfoData, iDataLen);
|
||||
|
||||
m_Essence = new IVTR_ESSENCE_FLYSWORD(dr.ReadData(Marshal.SizeOf<IVTR_ESSENCE_FLYSWORD>()));
|
||||
base.ReadMakerInfo(dr);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError("CECIvtrFlySword::SetItemInfo, data read error (" + e.GetType() + ")");
|
||||
return false;
|
||||
}
|
||||
|
||||
LevelReq = m_Essence.require_level;
|
||||
m_bNeedUpdate = false;
|
||||
m_iCurTime = m_Essence.cur_time * 1000;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override string GetIconFile()
|
||||
{
|
||||
return m_pDBEssence.FileIcon;
|
||||
}
|
||||
protected override string GetNormalDesc(bool bRepair)
|
||||
{
|
||||
if (m_bNeedUpdate)
|
||||
return string.Empty;
|
||||
|
||||
m_strDesc = "";
|
||||
|
||||
// Try to build item description
|
||||
CECStringTab pDescTab = EC_Game.GetItemDesc();
|
||||
CECHostPlayer pHost = EC_Game.GetGameRun().GetHostPlayer();
|
||||
int white = (int)DescriptipionMsg.ITEMDESC_COL_WHITE;
|
||||
int red = (int)DescriptipionMsg.ITEMDESC_COL_RED;
|
||||
int namecol = DecideNameCol();
|
||||
|
||||
if (m_iCount > 1)
|
||||
AddDescText(namecol, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NAMENUMBER), GetName(), m_iCount);
|
||||
else
|
||||
AddDescText(namecol, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NAME), GetName());
|
||||
|
||||
AddIDDescText();
|
||||
|
||||
AddBindDescText();
|
||||
|
||||
// Is destroying?
|
||||
AddDestroyingDesc((int)m_pDBEssence.id_drop_after_damaged, m_pDBEssence.num_drop_after_damaged);
|
||||
|
||||
AddExpireTimeDesc();
|
||||
|
||||
// level
|
||||
AddDescText(white, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_LEVEL), m_Essence.level);
|
||||
|
||||
// whether can be improved
|
||||
if (IsImprovable())
|
||||
AddDescText((int)DescriptipionMsg.ITEMDESC_COL_GREEN,true,pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_FLYSWORD_IMPROVE),m_Essence.improve_level,GetMaxImproveLevel());
|
||||
else
|
||||
AddDescText(white,true,pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_FLYSWORD_NOIMPROVED));
|
||||
|
||||
// Normal fly speed bonus
|
||||
if (m_Essence.speed_increase > 0)
|
||||
AddDescText(white, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_ADDFLYSPEED), m_Essence.speed_increase);
|
||||
|
||||
// Quick fly speed bonus
|
||||
if (m_Essence.speed_increase2 > 0)
|
||||
AddDescText(white, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_ADDFLYSPEED2), m_Essence.speed_increase2);
|
||||
|
||||
// Remain time
|
||||
if (GetMaxTime() > 0)
|
||||
AddDescText(white, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_REMAINTIME), GetCurTime(), GetMaxTime());
|
||||
|
||||
// Profession requirement
|
||||
AddProfReqDesc((uint)m_Essence.profession);
|
||||
|
||||
// Level requirement
|
||||
if (LevelReq > 0)
|
||||
{
|
||||
int col = pHost.GetMaxLevelSofar() >= LevelReq ? white : red;
|
||||
AddDescText(col, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_LEVELREQ), LevelReq);
|
||||
}
|
||||
|
||||
// Element consume
|
||||
// AddDescText(white, true, pDescTab->GetWideString(ITEMDESC_ELEMENTTIME), m_Essence.time_per_element);
|
||||
|
||||
// Price
|
||||
AddPriceDesc(white, bRepair);
|
||||
|
||||
AddMakerDesc();
|
||||
|
||||
// Suite description
|
||||
AddSuiteDesc();
|
||||
|
||||
// Extend description
|
||||
AddExtDescText();
|
||||
|
||||
return m_strDesc;
|
||||
}
|
||||
// Get max time
|
||||
protected int GetMaxTime()
|
||||
{
|
||||
return (int)m_Essence.max_time;
|
||||
}
|
||||
|
||||
// Get max element number
|
||||
protected int GetMaxElement()
|
||||
{
|
||||
return (int)((float)m_Essence.max_time / m_Essence.time_per_element + 0.5f);
|
||||
}
|
||||
|
||||
// Get time each element equal to
|
||||
protected int GetElementTime()
|
||||
{
|
||||
return m_Essence.time_per_element;
|
||||
}
|
||||
// Get number of element if time is filled to full. This is just the number
|
||||
// of element which has been used
|
||||
protected int GetUsedElementNum()
|
||||
{
|
||||
return (int)((m_Essence.max_time - GetCurTime()) / (float)m_Essence.time_per_element);
|
||||
}
|
||||
|
||||
// Get drop model for shown
|
||||
protected string GetDropModel()
|
||||
{
|
||||
return m_pDBEssence.FileMatter;
|
||||
}
|
||||
public override bool IsRare()
|
||||
{
|
||||
return base.IsRare() || m_Essence.level >= 6;
|
||||
}
|
||||
protected bool IsImprovable()
|
||||
{
|
||||
return m_pDBEssence.max_improve_level > 0 && m_pDBEssence.improve_config[0].require_item_num > 0;
|
||||
}
|
||||
protected bool CanBeImproved()
|
||||
{
|
||||
if(m_pDBEssence.max_improve_level <=0) return false;
|
||||
|
||||
if(m_Essence.improve_level>= GetMaxImproveLevel()) return false;
|
||||
|
||||
return m_pDBEssence.improve_config[m_Essence.improve_level].require_item_num > 0;
|
||||
}
|
||||
protected int GetMaxImproveLevel()
|
||||
{
|
||||
int maxL = m_pDBEssence.improve_config.Length;
|
||||
int i = 0;
|
||||
for (i = 0; i < maxL; i++)
|
||||
{
|
||||
if(m_pDBEssence.improve_config[i].require_item_num == 0)
|
||||
break;
|
||||
}
|
||||
return Mathf.Min(m_pDBEssence.max_improve_level, i);
|
||||
}
|
||||
|
||||
protected int GetCurTime() { return m_Essence.cur_time; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -194,8 +194,82 @@ namespace PerfectWorld.Scripts.Managers
|
||||
}
|
||||
private string GetRidingPetDesc(bool bRepair)
|
||||
{
|
||||
Debug.Log("GetRidingPetDesc. This is not implemented yet.");
|
||||
return "";
|
||||
if (m_bNeedUpdate)
|
||||
return "";
|
||||
|
||||
m_strDesc = string.Empty;
|
||||
|
||||
// Try to build item description
|
||||
CECStringTab pDescTab = EC_Game.GetItemDesc();
|
||||
CECHostPlayer pHost = EC_Game.GetGameRun().GetHostPlayer();
|
||||
|
||||
int white = (int)DescriptipionMsg.ITEMDESC_COL_WHITE;
|
||||
int red = (int)DescriptipionMsg.ITEMDESC_COL_RED;
|
||||
int namecol = DecideNameCol();
|
||||
|
||||
// Item name: always use the name in template
|
||||
if (m_iCount > 1)
|
||||
AddDescText(namecol, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NAMENUMBER), m_pDBEssence.name/* GetName() */, m_iCount);
|
||||
else
|
||||
AddDescText(namecol, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NAME), m_pDBEssence.name/* GetName() */);
|
||||
|
||||
AddIDDescText();
|
||||
|
||||
AddBindDescText();
|
||||
|
||||
AddExpireTimeDesc();
|
||||
|
||||
// ������ɫ��Ϣ
|
||||
if (m_pPetEssence.id != 0 && m_pPetEssence.require_dye_count > 0)
|
||||
{
|
||||
if (m_iScaleType == (int)ScaleType.SCALE_BUY)
|
||||
{
|
||||
AddDescText(white, false, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_COLOR));
|
||||
AddDescText(white, true, " ???");
|
||||
}
|
||||
else
|
||||
{
|
||||
Color clr = new Color(255, 255, 255);
|
||||
if (RIDINGPET.GetColor(m_Essence.color, clr))
|
||||
clr = RIDINGPET.GetDefaultColor();
|
||||
string strColor = string.Format("^{0:X2}{1:X2}{2:X2}", clr.r, clr.g, clr.b);
|
||||
AddDescText(white, false, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_COLOR));
|
||||
m_strDesc += " ";
|
||||
AddDescText(-1, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_COLORRECT), strColor);
|
||||
}
|
||||
}
|
||||
|
||||
// Food type requirement
|
||||
AddFoodTypeDesc();
|
||||
|
||||
if (m_pPetEssence.id != 0)
|
||||
{
|
||||
// Pet level
|
||||
AddDescText(white, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_PETLEVEL), m_Essence.level);
|
||||
|
||||
// Move speed
|
||||
float fSpeed = m_pPetEssence.speed_a + (m_Essence.level - 1) * m_pPetEssence.speed_b;
|
||||
AddDescText(-1, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_MOVESPEED), fSpeed);
|
||||
|
||||
// Profession requirement
|
||||
AddProfReqDesc(m_pPetEssence.character_combo_id);
|
||||
}
|
||||
|
||||
// Level requirement
|
||||
int iLevelReq = Mathf.Max((int)m_Essence.level, m_Essence.req_level);
|
||||
if (iLevelReq > 0)
|
||||
{
|
||||
int col = pHost.GetMaxLevelSofar() >= iLevelReq ? white : red;
|
||||
AddDescText(col, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_LEVELREQ), iLevelReq);
|
||||
}
|
||||
|
||||
// Price
|
||||
AddPriceDesc(white, bRepair);
|
||||
|
||||
// Extend description
|
||||
AddExtDescText();
|
||||
|
||||
return m_strDesc;
|
||||
}
|
||||
private string GetCombatPetDesc(bool bRepair)
|
||||
{
|
||||
|
||||
@@ -1,19 +1,84 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.IO;
|
||||
using BrewMonster;
|
||||
using ModelRenderer.Scripts.Common;
|
||||
using ModelRenderer.Scripts.GameData;
|
||||
using UnityEngine;
|
||||
using PerfectWorld.Scripts.Managers;
|
||||
using BrewMonster.Network;
|
||||
using BrewMonster.Scripts.Managers;
|
||||
using BrewMonster.Scripts;
|
||||
using CSNetwork.GPDataType;
|
||||
using System.Runtime.InteropServices;
|
||||
namespace PerfectWorld.Scripts.Managers
|
||||
{
|
||||
/// <summary>
|
||||
/// Task Dice Item (Tui qua random).
|
||||
/// This is a part of IvtrTaskItem(C++)
|
||||
/// </summary>
|
||||
public class EC_IvtrTaskDice : EC_IvtrItem
|
||||
{
|
||||
protected TASKDICE_ESSENCE m_pDBEssence;
|
||||
|
||||
/// <summary>
|
||||
/// Not create logic yet (add summary later)
|
||||
/// Task Dice Item
|
||||
/// </summary>
|
||||
/// <param name="tid">Template id</param>
|
||||
/// <param name="expire_date">Expire date</param>
|
||||
public EC_IvtrTaskDice(int tid, int expire_date) : base(tid, expire_date)
|
||||
/// <param name="tid"></param>
|
||||
/// <param name="expire_date"></param>
|
||||
public EC_IvtrTaskDice(int tid, int expire_date) : base(tid, expire_date)
|
||||
{
|
||||
}
|
||||
m_iCID = (int)InventoryClassId.ICID_TASKDICE;
|
||||
elementdataman pDB = ElementDataManProvider.GetElementDataMan();
|
||||
DATA_TYPE DataType = DATA_TYPE.DT_INVALID;
|
||||
m_pDBEssence = (TASKDICE_ESSENCE)pDB.get_data_ptr((uint)tid, ID_SPACE.ID_SPACE_ESSENCE, ref DataType);
|
||||
m_iPileLimit = m_pDBEssence.pile_num_max;
|
||||
m_iPrice = 0;
|
||||
m_iShopPrice = 0;
|
||||
m_iProcType = (int)m_pDBEssence.proc_type;
|
||||
m_bUseable = true;
|
||||
m_bNeedUpdate = false;
|
||||
}
|
||||
|
||||
public EC_IvtrTaskDice(EC_IvtrTaskDice other) : base(other)
|
||||
{
|
||||
m_pDBEssence = other.m_pDBEssence;
|
||||
}
|
||||
public override bool SetItemInfo(byte[] pInfoData, int iDataLen)
|
||||
{
|
||||
base.SetItemInfo(pInfoData, iDataLen);
|
||||
return true;
|
||||
}
|
||||
public override string GetIconFile()
|
||||
{
|
||||
return m_pDBEssence.FileIcon;
|
||||
}
|
||||
protected override string GetNormalDesc(bool bRepair)
|
||||
{
|
||||
m_strDesc = "";
|
||||
// Try to build item description
|
||||
CECStringTab pDescTab = EC_Game.GetItemDesc();
|
||||
int white = (int)DescriptipionMsg.ITEMDESC_COL_WHITE;
|
||||
int namecol = DecideNameCol();
|
||||
|
||||
if (m_iCount > 1)
|
||||
AddDescText(namecol, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NAMENUMBER), GetName(), m_iCount);
|
||||
else
|
||||
AddDescText(namecol, true, pDescTab.GetWideString((int)DescriptipionMsg.ITEMDESC_NAME), GetName());
|
||||
AddIDDescText();
|
||||
AddExpireTimeDesc();
|
||||
|
||||
AddPriceDesc(white, bRepair);
|
||||
|
||||
// Extend description
|
||||
AddExtDescText();
|
||||
|
||||
return m_strDesc;
|
||||
}
|
||||
public override string GetDropModel()
|
||||
{
|
||||
return m_pDBEssence.FileMatter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,16 +160,28 @@ namespace BrewMonster.Scripts.Managers
|
||||
};
|
||||
public struct IVTR_ESSENCE_FLYSWORD
|
||||
{
|
||||
// TODO : implement data later
|
||||
// int cur_time;
|
||||
// int max_time;
|
||||
// short require_level;
|
||||
// char level;
|
||||
// char improve_level;
|
||||
// int profession;
|
||||
// size_t time_per_element;
|
||||
// float speed_increase;
|
||||
// float speed_increase2;
|
||||
public int cur_time;
|
||||
public int max_time;
|
||||
public short require_level;
|
||||
public char level;
|
||||
public char improve_level;
|
||||
public int profession;
|
||||
public int time_per_element;
|
||||
public float speed_increase;
|
||||
public float speed_increase2;
|
||||
public IVTR_ESSENCE_FLYSWORD(byte[] data)
|
||||
{
|
||||
CECDataReader dr = new (data, data.Length);
|
||||
cur_time = dr.ReadInt();
|
||||
max_time = dr.ReadInt();
|
||||
require_level = dr.ReadShort();
|
||||
level = (char)dr.ReadByte();
|
||||
improve_level = (char)dr.ReadByte();
|
||||
profession = dr.ReadInt();
|
||||
time_per_element = dr.ReadInt();
|
||||
speed_increase = dr.ReadFloat();
|
||||
speed_increase2 = dr.ReadFloat();
|
||||
}
|
||||
};
|
||||
public struct IVTR_ESSENCE_WING
|
||||
{
|
||||
|
||||
@@ -81,6 +81,7 @@ namespace BrewMonster
|
||||
|
||||
protected int m_iBoothState = 0; // Booth state. 0, none; 1, prepare; 2, open booth; 3, visite other's booth
|
||||
public int m_idFRole = GNETRoles._R_UNMEMBER; // ID of player's faction role
|
||||
|
||||
protected int m_idCountry = 0; // ¹úÕ½ÕóÓª id
|
||||
public static int MAX_REINCARNATION = 2;
|
||||
protected List<int> m_aCurEffects = new List<int>(); // Current effects
|
||||
@@ -1905,4 +1906,42 @@ namespace BrewMonster
|
||||
enumSkinShowArmet,
|
||||
enumSkinShowHand,
|
||||
};
|
||||
/// <summary>
|
||||
/// Place holder for riding pet. Not test logic yet.
|
||||
/// </summary>
|
||||
public struct RIDINGPET
|
||||
{
|
||||
public int id;
|
||||
public ushort color;
|
||||
|
||||
public RIDINGPET(bool isReset = true)
|
||||
{
|
||||
id = 0;
|
||||
color = 0;
|
||||
}
|
||||
|
||||
public bool GetColor(Color clr)
|
||||
{
|
||||
// ��ȡ��ǰ����Ⱦɫ��ɫ
|
||||
return id>0 && GetColor(color, clr);
|
||||
}
|
||||
|
||||
public static bool GetColor(ushort c, Color clr)
|
||||
{
|
||||
// ��ѯ��ǰ����Ƿ�Ⱦ��ɫ�����Ⱦ��ɫ�����ر�Ⱦ֮�����ɫ
|
||||
bool bRet = false;
|
||||
if ((c & (1<<(8-1))) != 0)
|
||||
{
|
||||
// unsigned short ��λΪ1ʱ����ʾȾ��ɫ����ʱ�ɻ�ȡ��ɫ
|
||||
clr = new Color(((c) & (0x1f << 10)) >> 7, ((c) & (0x1f << 5)) >> 2, ((c) & 0x1f) << 3);
|
||||
bRet = true;
|
||||
}
|
||||
return bRet;
|
||||
}
|
||||
|
||||
public static Color GetDefaultColor()
|
||||
{
|
||||
return new Color(255, 255, 255);
|
||||
}
|
||||
};
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,23 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using CSNetwork.Protocols.RPCData;
|
||||
|
||||
namespace CSNetwork.Protocols
|
||||
{
|
||||
public class createrole : Protocol
|
||||
{
|
||||
public int Userid { get; set; }
|
||||
public int Localsid { get; set; }
|
||||
public uint Localsid { get; set; }
|
||||
public RoleInfo Roleinfo { get; set; }
|
||||
public Octets Referid { get; set; }
|
||||
|
||||
public createrole() : base(ProtocolType.PROTOCOL_CREATEROLE)
|
||||
{
|
||||
Referid = new Octets();
|
||||
Roleinfo = new RoleInfo();
|
||||
}
|
||||
|
||||
public override Protocol Clone() => new createrole
|
||||
{
|
||||
Userid = Userid,
|
||||
Localsid = Localsid,
|
||||
Roleinfo = Roleinfo?.Clone(),
|
||||
Referid = new Octets(Referid.ToArray())
|
||||
};
|
||||
|
||||
@@ -25,13 +29,23 @@ namespace CSNetwork.Protocols
|
||||
{
|
||||
os.Write(Userid);
|
||||
os.Write(Localsid);
|
||||
if (Roleinfo != null)
|
||||
{
|
||||
Roleinfo.Marshal(os);
|
||||
}
|
||||
else
|
||||
{
|
||||
new RoleInfo().Marshal(os);
|
||||
}
|
||||
os.Write(Referid);
|
||||
}
|
||||
|
||||
public override void Unmarshal(OctetsStream os)
|
||||
{
|
||||
Userid = os.ReadInt32();
|
||||
Localsid = os.ReadInt32();
|
||||
Localsid = os.ReadUInt32();
|
||||
Roleinfo = new RoleInfo();
|
||||
Roleinfo.Unmarshal(os);
|
||||
Referid = os.ReadOctets();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using CSNetwork.Protocols.RPCData;
|
||||
|
||||
namespace CSNetwork.Protocols
|
||||
{
|
||||
public class createrole_re : Protocol
|
||||
{
|
||||
public int result { get; set; }
|
||||
public int roleid { get; set; }
|
||||
public uint localsid { get; set; }
|
||||
public RoleInfo roleinfo { get; set; }
|
||||
public int refretcode { get; set; }
|
||||
|
||||
public createrole_re() : base(ProtocolType.PROTOCOL_CREATEROLE_RE)
|
||||
{
|
||||
roleinfo = new RoleInfo();
|
||||
}
|
||||
|
||||
public override Protocol Clone() => new createrole_re
|
||||
{
|
||||
result = result,
|
||||
roleid = roleid,
|
||||
localsid = localsid,
|
||||
roleinfo = roleinfo?.Clone(),
|
||||
refretcode = refretcode
|
||||
};
|
||||
|
||||
public override void Marshal(OctetsStream os)
|
||||
{
|
||||
os.Write(result);
|
||||
os.Write(roleid);
|
||||
os.Write(localsid);
|
||||
if (roleinfo != null)
|
||||
{
|
||||
roleinfo.Marshal(os);
|
||||
}
|
||||
else
|
||||
{
|
||||
new RoleInfo().Marshal(os);
|
||||
}
|
||||
os.Write(refretcode);
|
||||
}
|
||||
|
||||
public override void Unmarshal(OctetsStream os)
|
||||
{
|
||||
result = os.ReadInt32();
|
||||
roleid = os.ReadInt32();
|
||||
localsid = os.ReadUInt32();
|
||||
roleinfo = new RoleInfo();
|
||||
roleinfo.Unmarshal(os);
|
||||
refretcode = os.ReadInt32();
|
||||
}
|
||||
|
||||
public override int PriorPolicy() => 101;
|
||||
|
||||
public override bool SizePolicy(int size) => size <= 8192;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3640555d366b4e34bbefbbf040f7f339
|
||||
@@ -35,7 +35,8 @@ namespace CSNetwork.Protocols.RPCData
|
||||
os.Write(pos);
|
||||
os.Write(count);
|
||||
os.Write(max_count);
|
||||
os.Write(data);
|
||||
// Server-side expects an Octets field here; null will crash encoding.
|
||||
os.Write(data ?? new Octets());
|
||||
os.Write(proctype);
|
||||
os.Write(expire_date);
|
||||
os.Write(guid1);
|
||||
|
||||
@@ -69,9 +69,10 @@ namespace CSNetwork.Protocols.RPCData
|
||||
os.Write(occupation);
|
||||
os.Write(level);
|
||||
os.Write(level2);
|
||||
os.Write(name);
|
||||
os.Write(custom_data);
|
||||
os.WriteList(equipment);
|
||||
// Avoid null Octets/List crashing protocol.Encode()
|
||||
os.Write(name ?? new Octets());
|
||||
os.Write(custom_data ?? new Octets());
|
||||
os.WriteList(equipment ?? new List<GRoleInventory>());
|
||||
os.Write(status);
|
||||
os.Write(delete_time);
|
||||
os.Write(create_time);
|
||||
@@ -80,12 +81,12 @@ namespace CSNetwork.Protocols.RPCData
|
||||
os.Write(posy);
|
||||
os.Write(posz);
|
||||
os.Write(worldtag);
|
||||
os.Write(custom_status);
|
||||
os.Write(charactermode);
|
||||
os.Write(custom_status ?? new Octets());
|
||||
os.Write(charactermode ?? new Octets());
|
||||
os.Write(referrer_role);
|
||||
os.Write(cash_add);
|
||||
os.Write(reincarnation_data);
|
||||
os.Write(realm_data);
|
||||
os.Write(reincarnation_data ?? new Octets());
|
||||
os.Write(realm_data ?? new Octets());
|
||||
}
|
||||
|
||||
public void Unmarshal(OctetsStream os)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using BrewMonster;
|
||||
using BrewMonster;
|
||||
using BrewMonster.Common;
|
||||
using CSNetwork;
|
||||
using CSNetwork.C2SCommand;
|
||||
@@ -171,6 +171,12 @@ namespace BrewMonster.Network
|
||||
{
|
||||
Instance._gameSession.SelectRoleAsync(roleInfo, callback);
|
||||
}
|
||||
|
||||
public static void CreateRoleAsync(RoleInfo roleInfo, Octets referId, Action<RoleInfo> callback = null)
|
||||
{
|
||||
Instance._gameSession.CreateRoleAsync(roleInfo, referId, callback);
|
||||
}
|
||||
|
||||
public static void EnterWorldAsync(RoleInfo roleInfo, Action callback = null)
|
||||
{
|
||||
Debug.Log("EnterWorldAsync !!!!! nay ");
|
||||
|
||||
@@ -0,0 +1,249 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using BrewMonster.Network;
|
||||
using CSNetwork;
|
||||
using CSNetwork.GPDataType;
|
||||
using CSNetwork.Protocols;
|
||||
using CSNetwork.Protocols.RPCData;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using BrewMonster.Scripts;
|
||||
|
||||
namespace BrewMonster.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// UI screen for creating a new character.
|
||||
/// Equivalent to CDlgCreateGenderName + CDlgCreateProfession in C++.
|
||||
/// </summary>
|
||||
public class CreateCharacterScreen : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private GameObject professionSelectionPanel;
|
||||
[SerializeField] private Button[] professionButtons;
|
||||
[SerializeField] private Button maleGenderButton;
|
||||
[SerializeField] private Button femaleGenderButton;
|
||||
[SerializeField] private TMP_InputField nameInputField;
|
||||
[SerializeField] private Button confirmButton;
|
||||
[SerializeField] private Button cancelButton;
|
||||
[SerializeField] private Button backButton;
|
||||
|
||||
private int _currentProfession = -1;
|
||||
private int _currentGender = -1;
|
||||
|
||||
private Action<RoleInfo> _onCreateComplete;
|
||||
private Action _onCancel;
|
||||
|
||||
// Static array matching s_bShowMale[NUM_PROFESSION] from original C++ code (EC_ProfConfigs.cpp)
|
||||
// true = show male, false = show female
|
||||
private static readonly bool[] s_bShowMale = new bool[]
|
||||
{
|
||||
true, // 0: Warrior (武侠)
|
||||
false, // 1: Mage (法师)
|
||||
false, // 2: Priest (巫师)
|
||||
false, // 3: Assassin (妖精)
|
||||
true, // 4: Orc (妖兽)
|
||||
true, // 5: Monk (刺客)
|
||||
true, // 6: Elf (羽芒)
|
||||
false, // 7: Elf (羽灵)
|
||||
true, // 8: Ling (剑灵)
|
||||
false, // 9: Ling (魅灵)
|
||||
true, // 10: Oboro (夜影)
|
||||
false, // 11: Oboro (月仙)
|
||||
};
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (confirmButton != null)
|
||||
confirmButton.onClick.AddListener(OnConfirmClicked);
|
||||
if (cancelButton != null)
|
||||
cancelButton.onClick.AddListener(OnCancelClicked);
|
||||
if (backButton != null)
|
||||
backButton.onClick.AddListener(OnCancelClicked);
|
||||
|
||||
if (maleGenderButton != null)
|
||||
maleGenderButton.onClick.AddListener(() => OnGenderSelected(GENDER.GENDER_MALE));
|
||||
if (femaleGenderButton != null)
|
||||
femaleGenderButton.onClick.AddListener(() => OnGenderSelected(GENDER.GENDER_FEMALE));
|
||||
|
||||
// Setup profession buttons
|
||||
if (professionButtons != null)
|
||||
{
|
||||
for (int i = 0; i < professionButtons.Length && i < 12; i++)
|
||||
{
|
||||
int prof = i; // Capture for closure
|
||||
if (professionButtons[i] != null)
|
||||
professionButtons[i].onClick.AddListener(() => OnProfessionSelected(prof));
|
||||
}
|
||||
}
|
||||
|
||||
if (nameInputField != null)
|
||||
{
|
||||
nameInputField.onSubmit.AddListener((text) => { if (CanConfirm()) OnConfirmClicked(); });
|
||||
}
|
||||
}
|
||||
|
||||
public void Show(Action<RoleInfo> onCreateComplete, Action onCancel)
|
||||
{
|
||||
_onCreateComplete = onCreateComplete;
|
||||
_onCancel = onCancel;
|
||||
_currentProfession = -1;
|
||||
_currentGender = -1;
|
||||
|
||||
gameObject.SetActive(true);
|
||||
|
||||
if (nameInputField != null)
|
||||
{
|
||||
nameInputField.text = "";
|
||||
nameInputField.Select();
|
||||
}
|
||||
|
||||
UpdateConfirmButtonState();
|
||||
}
|
||||
|
||||
public void Hide()
|
||||
{
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
private void OnProfessionSelected(int profession)
|
||||
{
|
||||
if (profession < 0 || profession >= (int)Profession.NUM_PROFESSION)
|
||||
return;
|
||||
|
||||
_currentProfession = profession;
|
||||
|
||||
// Update UI to show selected profession
|
||||
if (professionButtons != null)
|
||||
{
|
||||
for (int i = 0; i < professionButtons.Length; i++)
|
||||
{
|
||||
if (professionButtons[i] != null)
|
||||
{
|
||||
// Visual feedback for selected profession
|
||||
var colors = professionButtons[i].colors;
|
||||
colors.normalColor = (i == profession) ? Color.yellow : Color.white;
|
||||
professionButtons[i].colors = colors;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-select gender based on profession (matching original C++ logic from EC_ProfConfigs.cpp)
|
||||
// This matches the s_bShowMale array in CanShowOnCreate function
|
||||
int autoGender = GetDefaultGenderForProfession(profession);
|
||||
OnGenderSelected(autoGender);
|
||||
|
||||
UpdateConfirmButtonState();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default gender for a profession based on the original C++ logic.
|
||||
/// Matches the s_bShowMale array from EC_ProfConfigs.cpp CanShowOnCreate function.
|
||||
/// </summary>
|
||||
private int GetDefaultGenderForProfession(int profession)
|
||||
{
|
||||
if (profession >= 0 && profession < s_bShowMale.Length)
|
||||
{
|
||||
return s_bShowMale[profession] ? GENDER.GENDER_MALE : GENDER.GENDER_FEMALE;
|
||||
}
|
||||
|
||||
// Fallback to male if profession is invalid
|
||||
return GENDER.GENDER_MALE;
|
||||
}
|
||||
|
||||
private void OnGenderSelected(int gender)
|
||||
{
|
||||
if (gender != GENDER.GENDER_MALE && gender != GENDER.GENDER_FEMALE)
|
||||
return;
|
||||
|
||||
_currentGender = gender;
|
||||
|
||||
// Update UI to show selected gender
|
||||
if (maleGenderButton != null)
|
||||
{
|
||||
var colors = maleGenderButton.colors;
|
||||
colors.normalColor = (gender == GENDER.GENDER_MALE) ? Color.yellow : Color.white;
|
||||
maleGenderButton.colors = colors;
|
||||
}
|
||||
|
||||
if (femaleGenderButton != null)
|
||||
{
|
||||
var colors = femaleGenderButton.colors;
|
||||
colors.normalColor = (gender == GENDER.GENDER_FEMALE) ? Color.yellow : Color.white;
|
||||
femaleGenderButton.colors = colors;
|
||||
}
|
||||
|
||||
UpdateConfirmButtonState();
|
||||
}
|
||||
|
||||
private void OnConfirmClicked()
|
||||
{
|
||||
if (!CanConfirm())
|
||||
return;
|
||||
|
||||
string characterName = nameInputField != null ? nameInputField.text : "";
|
||||
if (string.IsNullOrWhiteSpace(characterName))
|
||||
{
|
||||
Debug.LogWarning("Character name cannot be empty");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create RoleInfo using helper method
|
||||
RoleInfo roleInfo = GameSession.CreateNewRoleInfo(characterName, _currentProfession, _currentGender);
|
||||
|
||||
// Create role via network
|
||||
Debug.Log($"Calling CreateRoleAsync for character: {characterName}, profession: {_currentProfession}, gender: {_currentGender}");
|
||||
UnityGameSession.CreateRoleAsync(roleInfo, new Octets(), (createdRole) =>
|
||||
{
|
||||
if (createdRole != null)
|
||||
{
|
||||
Debug.Log($"Character created successfully: {characterName}, RoleID: {createdRole.roleid}");
|
||||
Hide();
|
||||
_onCreateComplete?.Invoke(createdRole);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"Failed to create character: {characterName}. Check GameSession logs for error details.");
|
||||
// TODO: Show error message to user
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void OnCancelClicked()
|
||||
{
|
||||
Hide();
|
||||
_onCancel?.Invoke();
|
||||
}
|
||||
|
||||
private bool CanConfirm()
|
||||
{
|
||||
if (_currentProfession < 0 || _currentProfession >= (int)Profession.NUM_PROFESSION)
|
||||
return false;
|
||||
|
||||
if (_currentGender != GENDER.GENDER_MALE && _currentGender != GENDER.GENDER_FEMALE)
|
||||
return false;
|
||||
|
||||
string name = nameInputField != null ? nameInputField.text : "";
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void UpdateConfirmButtonState()
|
||||
{
|
||||
if (confirmButton != null)
|
||||
{
|
||||
confirmButton.interactable = CanConfirm();
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
// Update confirm button state in case name changes
|
||||
if (nameInputField != null && nameInputField.isFocused)
|
||||
{
|
||||
UpdateConfirmButtonState();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa9de023137e92348983cee3c59d620b
|
||||
@@ -1,193 +1,282 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BrewMonster.Network;
|
||||
using CSNetwork.Protocols;
|
||||
using CSNetwork.Protocols.RPCData;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace BrewMonster.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// Login Flow:
|
||||
/// 1. Enter username and password
|
||||
/// 2. Click login button
|
||||
/// 3. Login success, get the list of characters
|
||||
/// 4. Open the select character screen
|
||||
/// </summary>
|
||||
public class LoginScreenUI : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private TMP_InputField _usernameInputField;
|
||||
[SerializeField] private TMP_InputField _passwordInputField;
|
||||
[SerializeField] private Button _loginButton;
|
||||
[SerializeField] private SelecScreenCharacter _selectCharacterScreen;
|
||||
|
||||
private List<RoleInfo> _roleInfos;
|
||||
bool isDoneWorldRender = false;
|
||||
bool isDoneNPCRender = false;
|
||||
private SynchronizationContext context;
|
||||
public AudioClip loginBGM;
|
||||
void Start()
|
||||
{
|
||||
AudioManager.Instance.PlayBGM(loginBGM, 1.5f);
|
||||
_loginButton.onClick.AddListener(OnLoginButtonClicked);
|
||||
context = SynchronizationContext.Current;
|
||||
|
||||
_usernameInputField.text = PlayerPrefs.GetString("username", "");
|
||||
_passwordInputField.text = PlayerPrefs.GetString("password", "");
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
if (_roleInfos != null)
|
||||
{
|
||||
_selectCharacterScreen.InitScreen(_roleInfos, OnClickSelectCharacter);
|
||||
_roleInfos = null;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (Input.GetKeyUp(KeyCode.LeftAlt))
|
||||
{
|
||||
_usernameInputField.text = "test004";
|
||||
_passwordInputField.text = "123456";
|
||||
}
|
||||
|
||||
if (Input.GetKeyUp(KeyCode.Tab))
|
||||
{
|
||||
_usernameInputField.text = "test002";
|
||||
_passwordInputField.text = "123456";
|
||||
OnLoginButtonClicked();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public async void OnLoginButtonClicked()
|
||||
{
|
||||
BMLogger.Log("OnLoginButtonClicked");
|
||||
string username = _usernameInputField.text;
|
||||
string password = _passwordInputField.text;
|
||||
// UnityGameSession.SetConnectionInfo("103.182.22.52", 29000);
|
||||
UnityGameSession.SetConnectionInfo("103.51.120.195", 29000);
|
||||
PlayerPrefs.SetString("username", username);
|
||||
PlayerPrefs.SetString("password", password);
|
||||
PlayerPrefs.Save();
|
||||
await UnityGameSession.Login(username, password, OnLoginComplete);
|
||||
_selectCharacterScreen.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback when the login is complete.
|
||||
/// Then get the list of characters
|
||||
/// </summary>
|
||||
private void OnLoginComplete(bool result)
|
||||
{
|
||||
if (!result)
|
||||
{
|
||||
BMLogger.LogError("Login failed");
|
||||
return;
|
||||
}
|
||||
|
||||
UnityGameSession.GetRoleListAsync(OnGetRoleListComplete);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback when the list of characters is retrieved.
|
||||
/// Then move to the select character screen
|
||||
/// </summary>
|
||||
private void OnGetRoleListComplete(List<RoleInfo> roleInfos)
|
||||
{
|
||||
_roleInfos = roleInfos;
|
||||
}
|
||||
|
||||
private void OnClickSelectCharacter(RoleInfo roleInfo)
|
||||
{
|
||||
UnityGameSession.SelectRoleAsync(roleInfo, OnSelectRoleComplete);
|
||||
}
|
||||
|
||||
private void OnSelectRoleComplete(RoleInfo roleInfo)
|
||||
{
|
||||
context.Post(_ =>
|
||||
{
|
||||
isDoneWorldRender = false;
|
||||
isDoneNPCRender = false;
|
||||
Action actLoadChar = () =>
|
||||
{
|
||||
if (!isDoneNPCRender || !isDoneWorldRender)
|
||||
{
|
||||
return;
|
||||
}
|
||||
};
|
||||
SceneLoader.SceneLoadProcess = SceneLoadProcess.Loading;
|
||||
SceneLoader.LoadingProgress = 0;
|
||||
LoadingSceneController.Instance.ShowLoadingScene(true);
|
||||
#if TESTFAST
|
||||
string nameScene = "LoginScene";
|
||||
SceneManager.UnloadSceneAsync(nameScene);
|
||||
isDoneNPCRender = true;
|
||||
isDoneWorldRender = true;
|
||||
actLoadChar?.Invoke();
|
||||
UnityGameSession.EnterWorldAsync(roleInfo, OnEnterWorldComplete);
|
||||
#else
|
||||
string nameScene = "NPCRender";
|
||||
UnityGameSession.Instance.LoadScene(nameScene, LoadSceneMode.Single, (value) =>
|
||||
{
|
||||
isDoneNPCRender = value;
|
||||
actLoadChar?.Invoke();
|
||||
});
|
||||
nameScene = "a61";
|
||||
UnityGameSession.Instance.LoadScene(nameScene, LoadSceneMode.Additive, (value) =>
|
||||
{
|
||||
isDoneWorldRender = value;
|
||||
actLoadChar?.Invoke();
|
||||
UnityGameSession.EnterWorldAsync(roleInfo, OnEnterWorldComplete);
|
||||
|
||||
});
|
||||
#endif
|
||||
}, null);
|
||||
}
|
||||
|
||||
private async void OnEnterWorldComplete()
|
||||
{
|
||||
await Task.Delay(2000);
|
||||
// Request all known packages: 0=Inventory,1=Equipment,2=Task
|
||||
UnityGameSession.RequestAllInventoriesAsync(() => { /*BMLogger.Log("Sent Inventory Detail Requests (all packs)");*/ }, 0, 1, 2);
|
||||
await Task.Delay(1000);
|
||||
UnityGameSession.RequestCheckSecurityPassWd("");
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
|
||||
//private void OnInventoryReceived(List<InventoryItem> inventoryData)
|
||||
//{
|
||||
// _inventoryUI.DisplayInventory(inventoryData);
|
||||
//}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
if (_usernameInputField == null)
|
||||
{
|
||||
// find childrend with name "username"
|
||||
_usernameInputField = transform.Find("username").GetComponent<TMP_InputField>();
|
||||
}
|
||||
|
||||
if (_passwordInputField == null)
|
||||
{
|
||||
// find childrend with name "password"
|
||||
_passwordInputField = transform.Find("password").GetComponent<TMP_InputField>();
|
||||
}
|
||||
|
||||
if (_loginButton == null)
|
||||
{
|
||||
// find childrend with name "LoginBtn"
|
||||
_loginButton = transform.Find("LoginBtn").GetComponent<Button>();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BrewMonster.Network;
|
||||
using CSNetwork.Protocols;
|
||||
using CSNetwork.Protocols.RPCData;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace BrewMonster.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// Login Flow:
|
||||
/// 1. Enter username and password
|
||||
/// 2. Click login button
|
||||
/// 3. Login success, get the list of characters
|
||||
/// 4. Open the select character screen
|
||||
/// </summary>
|
||||
public class LoginScreenUI : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private TMP_InputField _usernameInputField;
|
||||
[SerializeField] private TMP_InputField _passwordInputField;
|
||||
[SerializeField] private Button _loginButton;
|
||||
[SerializeField] private SelecScreenCharacter _selectCharacterScreen;
|
||||
|
||||
private List<RoleInfo> _roleInfos;
|
||||
private List<RoleInfo> _currentRoles;
|
||||
private RoleInfo _pendingCreatedRole;
|
||||
bool isDoneWorldRender = false;
|
||||
bool isDoneNPCRender = false;
|
||||
private SynchronizationContext context;
|
||||
public AudioClip loginBGM;
|
||||
void Start()
|
||||
{
|
||||
AudioManager.Instance.PlayBGM(loginBGM, 1.5f);
|
||||
_loginButton.onClick.AddListener(OnLoginButtonClicked);
|
||||
context = SynchronizationContext.Current;
|
||||
|
||||
_usernameInputField.text = PlayerPrefs.GetString("username", "");
|
||||
_passwordInputField.text = PlayerPrefs.GetString("password", "");
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
if (_roleInfos != null)
|
||||
{
|
||||
_selectCharacterScreen.InitScreen(_roleInfos, OnClickSelectCharacter, OnCreateCharacterComplete);
|
||||
_roleInfos = null;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (Input.GetKeyUp(KeyCode.LeftAlt))
|
||||
{
|
||||
_usernameInputField.text = "test004";
|
||||
_passwordInputField.text = "123456";
|
||||
}
|
||||
|
||||
if (Input.GetKeyUp(KeyCode.Tab))
|
||||
{
|
||||
_usernameInputField.text = "test002";
|
||||
_passwordInputField.text = "123456";
|
||||
OnLoginButtonClicked();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public async void OnLoginButtonClicked()
|
||||
{
|
||||
BMLogger.Log("OnLoginButtonClicked");
|
||||
string username = _usernameInputField.text;
|
||||
string password = _passwordInputField.text;
|
||||
// UnityGameSession.SetConnectionInfo("103.182.22.52", 29000);
|
||||
UnityGameSession.SetConnectionInfo("103.51.120.195", 29000);
|
||||
PlayerPrefs.SetString("username", username);
|
||||
PlayerPrefs.SetString("password", password);
|
||||
PlayerPrefs.Save();
|
||||
await UnityGameSession.Login(username, password, OnLoginComplete);
|
||||
_selectCharacterScreen.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback when the login is complete.
|
||||
/// Then get the list of characters
|
||||
/// </summary>
|
||||
private void OnLoginComplete(bool result)
|
||||
{
|
||||
if (!result)
|
||||
{
|
||||
BMLogger.LogError("Login failed");
|
||||
return;
|
||||
}
|
||||
|
||||
UnityGameSession.GetRoleListAsync(OnGetRoleListComplete);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback when the list of characters is retrieved.
|
||||
/// Then move to the select character screen
|
||||
/// </summary>
|
||||
private void OnGetRoleListComplete(List<RoleInfo> roleInfos)
|
||||
{
|
||||
if (roleInfos == null)
|
||||
{
|
||||
BMLogger.LogError("OnGetRoleListComplete: roleInfos is null");
|
||||
// Keep whatever is currently shown; don't overwrite UI state with null.
|
||||
return;
|
||||
}
|
||||
|
||||
// Merge pending created role in case backend list hasn't updated yet.
|
||||
if (_pendingCreatedRole != null)
|
||||
{
|
||||
bool exists = false;
|
||||
for (int i = 0; i < roleInfos.Count; i++)
|
||||
{
|
||||
if (roleInfos[i].roleid == _pendingCreatedRole.roleid)
|
||||
{
|
||||
exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!exists)
|
||||
{
|
||||
// Copy list so we don't mutate a list owned elsewhere.
|
||||
var merged = new List<RoleInfo>(roleInfos.Count + 1);
|
||||
merged.AddRange(roleInfos);
|
||||
merged.Add(_pendingCreatedRole);
|
||||
roleInfos = merged;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Backend now includes the role; clear pending.
|
||||
_pendingCreatedRole = null;
|
||||
}
|
||||
}
|
||||
|
||||
BMLogger.Log($"OnGetRoleListComplete: roles={roleInfos.Count}");
|
||||
_roleInfos = roleInfos;
|
||||
_currentRoles = roleInfos;
|
||||
}
|
||||
|
||||
private void OnClickSelectCharacter(RoleInfo roleInfo)
|
||||
{
|
||||
UnityGameSession.SelectRoleAsync(roleInfo, OnSelectRoleComplete);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback when a new character is created.
|
||||
/// Refreshes the role list and keeps the character selection screen visible.
|
||||
/// </summary>
|
||||
private void OnCreateCharacterComplete(RoleInfo createdRole)
|
||||
{
|
||||
BMLogger.Log("Character created, refreshing role list...");
|
||||
if (_selectCharacterScreen != null)
|
||||
{
|
||||
_selectCharacterScreen.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
// Ensure the newly created role is visible immediately even if the server role list
|
||||
// hasn't updated yet.
|
||||
if (createdRole != null)
|
||||
{
|
||||
_pendingCreatedRole = createdRole;
|
||||
if (_currentRoles == null)
|
||||
{
|
||||
_currentRoles = new List<RoleInfo>();
|
||||
}
|
||||
|
||||
bool exists = false;
|
||||
for (int i = 0; i < _currentRoles.Count; i++)
|
||||
{
|
||||
if (_currentRoles[i].roleid == createdRole.roleid)
|
||||
{
|
||||
exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!exists)
|
||||
{
|
||||
_currentRoles.Add(createdRole);
|
||||
}
|
||||
|
||||
_roleInfos = _currentRoles;
|
||||
}
|
||||
else
|
||||
{
|
||||
BMLogger.LogError("OnCreateCharacterComplete: createdRole is null (create-role callback returned null)");
|
||||
}
|
||||
|
||||
// NOTE:
|
||||
// Immediately requesting the role list after create has been observed to disconnect
|
||||
// in some server builds. We rely on the createdRole callback to update UI instantly.
|
||||
// A server sync can be done later (e.g., next time you open this screen / re-login).
|
||||
}
|
||||
|
||||
private void OnSelectRoleComplete(RoleInfo roleInfo)
|
||||
{
|
||||
context.Post(_ =>
|
||||
{
|
||||
isDoneWorldRender = false;
|
||||
isDoneNPCRender = false;
|
||||
Action actLoadChar = () =>
|
||||
{
|
||||
if (!isDoneNPCRender || !isDoneWorldRender)
|
||||
{
|
||||
return;
|
||||
}
|
||||
};
|
||||
SceneLoader.SceneLoadProcess = SceneLoadProcess.Loading;
|
||||
SceneLoader.LoadingProgress = 0;
|
||||
LoadingSceneController.Instance.ShowLoadingScene(true);
|
||||
#if TESTFAST
|
||||
string nameScene = "LoginScene";
|
||||
SceneManager.UnloadSceneAsync(nameScene);
|
||||
isDoneNPCRender = true;
|
||||
isDoneWorldRender = true;
|
||||
actLoadChar?.Invoke();
|
||||
UnityGameSession.EnterWorldAsync(roleInfo, OnEnterWorldComplete);
|
||||
#else
|
||||
string nameScene = "NPCRender";
|
||||
UnityGameSession.Instance.LoadScene(nameScene, LoadSceneMode.Single, (value) =>
|
||||
{
|
||||
isDoneNPCRender = value;
|
||||
actLoadChar?.Invoke();
|
||||
});
|
||||
nameScene = "a61";
|
||||
UnityGameSession.Instance.LoadScene(nameScene, LoadSceneMode.Additive, (value) =>
|
||||
{
|
||||
isDoneWorldRender = value;
|
||||
actLoadChar?.Invoke();
|
||||
UnityGameSession.EnterWorldAsync(roleInfo, OnEnterWorldComplete);
|
||||
|
||||
});
|
||||
#endif
|
||||
}, null);
|
||||
}
|
||||
|
||||
private async void OnEnterWorldComplete()
|
||||
{
|
||||
await Task.Delay(2000);
|
||||
// Request all known packages: 0=Inventory,1=Equipment,2=Task
|
||||
UnityGameSession.RequestAllInventoriesAsync(() => { /*BMLogger.Log("Sent Inventory Detail Requests (all packs)");*/ }, 0, 1, 2);
|
||||
await Task.Delay(1000);
|
||||
UnityGameSession.RequestCheckSecurityPassWd("");
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
|
||||
//private void OnInventoryReceived(List<InventoryItem> inventoryData)
|
||||
//{
|
||||
// _inventoryUI.DisplayInventory(inventoryData);
|
||||
//}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
if (_usernameInputField == null)
|
||||
{
|
||||
// find childrend with name "username"
|
||||
_usernameInputField = transform.Find("username").GetComponent<TMP_InputField>();
|
||||
}
|
||||
|
||||
if (_passwordInputField == null)
|
||||
{
|
||||
// find childrend with name "password"
|
||||
_passwordInputField = transform.Find("password").GetComponent<TMP_InputField>();
|
||||
}
|
||||
|
||||
if (_loginButton == null)
|
||||
{
|
||||
// find childrend with name "LoginBtn"
|
||||
_loginButton = transform.Find("LoginBtn").GetComponent<Button>();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fd9306e92f60c254aba22e7fa622d485
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -578,7 +578,10 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
characterItemPrefab: {fileID: 5263746738484752443, guid: 726ee9eade6587245ac1b55d2335e9b9, type: 3}
|
||||
addCharacterItemPrefab: {fileID: 5263746738484752443, guid: a0b31ed0940ec9942b243a0b8cec8ad3, type: 3}
|
||||
parentItems: {fileID: 2643174602035272289}
|
||||
createCharacterButton: {fileID: 0}
|
||||
createCharacterScreen: {fileID: 0}
|
||||
--- !u!1 &7510180475820570348
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -717,7 +720,7 @@ GameObject:
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
m_IsActive: 0
|
||||
--- !u!224 &6444858493086001938
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a0b31ed0940ec9942b243a0b8cec8ad3
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -6948,7 +6948,7 @@ namespace BrewMonster
|
||||
for(i = 0; i < m_pEquipPack.GetSize(); i++)
|
||||
{
|
||||
var pItem = m_pEquipPack.GetItem(i);
|
||||
if(pItem == null || (pItem is not EC_IvtrWeapon && pItem is not EC_IvtrArmor))
|
||||
if(pItem == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ using CSNetwork.Protocols.RPCData;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using BrewMonster;
|
||||
|
||||
namespace BrewMonster.UI
|
||||
@@ -9,16 +10,121 @@ namespace BrewMonster.UI
|
||||
public class SelecScreenCharacter : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private GameObject characterItemPrefab;
|
||||
[SerializeField] private GameObject addCharacterItemPrefab;
|
||||
[SerializeField] private RectTransform parentItems;
|
||||
[SerializeField] private Button createCharacterButton;
|
||||
[SerializeField] private CreateCharacterScreen createCharacterScreen;
|
||||
|
||||
public void InitScreen(List<RoleInfo> roleInfos, Action<RoleInfo> OnClickItemChar)
|
||||
private Action<RoleInfo> _onClickItemChar;
|
||||
private Action<RoleInfo> _onCreateCharacterComplete;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
|
||||
foreach (RoleInfo info in roleInfos)
|
||||
if (createCharacterButton != null)
|
||||
{
|
||||
CharacterItemUI item = Instantiate(characterItemPrefab, parentItems).GetComponent<CharacterItemUI>();
|
||||
item.InitItem(info, OnClickItemChar);
|
||||
createCharacterButton.onClick.AddListener(OnCreateCharacterClicked);
|
||||
}
|
||||
}
|
||||
|
||||
public void InitScreen(List<RoleInfo> roleInfos, Action<RoleInfo> OnClickItemChar, Action<RoleInfo> onCreateCharacterComplete = null)
|
||||
{
|
||||
_onClickItemChar = OnClickItemChar;
|
||||
_onCreateCharacterComplete = onCreateCharacterComplete;
|
||||
|
||||
// Clear existing items
|
||||
if (parentItems != null)
|
||||
{
|
||||
foreach (Transform child in parentItems)
|
||||
{
|
||||
Destroy(child.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
// Create character items
|
||||
if (roleInfos != null)
|
||||
{
|
||||
foreach (RoleInfo info in roleInfos)
|
||||
{
|
||||
if (characterItemPrefab != null && parentItems != null)
|
||||
{
|
||||
CharacterItemUI item = Instantiate(characterItemPrefab, parentItems).GetComponent<CharacterItemUI>();
|
||||
item.InitItem(info, OnClickItemChar);
|
||||
}
|
||||
}
|
||||
|
||||
// If number of roles < 8, spawn addCharacterItemPrefab and hide createCharacterButton
|
||||
if (roleInfos.Count < 8)
|
||||
{
|
||||
// Hide the createCharacterButton
|
||||
if (createCharacterButton != null)
|
||||
{
|
||||
createCharacterButton.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
// Spawn addCharacterItemPrefab
|
||||
if (addCharacterItemPrefab != null && parentItems != null)
|
||||
{
|
||||
GameObject addCharacterItem = Instantiate(addCharacterItemPrefab, parentItems);
|
||||
// Set up click handler for the add character item
|
||||
Button addButton = addCharacterItem.GetComponent<Button>();
|
||||
if (addButton == null)
|
||||
{
|
||||
addButton = addCharacterItem.GetComponentInChildren<Button>();
|
||||
}
|
||||
if (addButton != null)
|
||||
{
|
||||
addButton.onClick.RemoveAllListeners();
|
||||
addButton.onClick.AddListener(OnCreateCharacterClicked);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Show the createCharacterButton if we have 8 or more roles
|
||||
if (createCharacterButton != null)
|
||||
{
|
||||
createCharacterButton.gameObject.SetActive(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If roleInfos is null, show createCharacterButton
|
||||
if (createCharacterButton != null)
|
||||
{
|
||||
createCharacterButton.gameObject.SetActive(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCreateCharacterClicked()
|
||||
{
|
||||
if (createCharacterScreen != null)
|
||||
{
|
||||
gameObject.SetActive(false);
|
||||
createCharacterScreen.Show(OnCreateCharacterComplete, OnCreateCharacterCancel);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCreateCharacterComplete(RoleInfo newRole)
|
||||
{
|
||||
if (createCharacterScreen != null)
|
||||
{
|
||||
createCharacterScreen.Hide();
|
||||
}
|
||||
|
||||
gameObject.SetActive(true);
|
||||
_onCreateCharacterComplete?.Invoke(newRole);
|
||||
}
|
||||
|
||||
private void OnCreateCharacterCancel()
|
||||
{
|
||||
if (createCharacterScreen != null)
|
||||
{
|
||||
createCharacterScreen.Hide();
|
||||
}
|
||||
|
||||
gameObject.SetActive(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user