备份CatanBuilding瘦身独立工程

This commit is contained in:
JSD\13999
2026-05-26 16:15:54 +08:00
commit 2d0e6a61b7
12001 changed files with 2431925 additions and 0 deletions

View File

@@ -0,0 +1,216 @@
using asap.core;
using cfg;
using DG.Tweening;
using System.Collections.Generic;
using System.Collections;
using UnityEngine;
using UnityEngine.Assertions;
public class Block : MonoBehaviour
{
private Rigidbody2D _rb;
private BoxCollider2D _bc;
public BlockState State;
private bool _freezable = false;
private Tables _tables;
private InfiniteBuildingConf _cfg;
public int Idx;
public IEventAggregator EventAggregator;
public bool Freezable => _freezable;
//private Transform _focus;
public Rigidbody2D Rb => _rb;
private List<Furniture> _furnitureList;
private class Furniture
{
public readonly GameObject Go;
public readonly Vector3 TargetScale;
public Furniture(GameObject go, Vector3 targetScale)
{
Go = go;
TargetScale = targetScale;
}
}
public float Height
{
get
{
if (_tables.TbConstructionUnits.DataMap.ContainsKey(Idx)) return _tables.TbConstructionUnits[Idx].Height;
Debug.LogError($"Block index {Idx} is not in the table.");
return 0;
}
}
public float Width => _bc.size.x;
public float WorldHeight => transform.position.y + _bc.offset.y + _bc.size.y / 2;
public bool IsCurrentBlockStill
=> Rb.velocity.magnitude <= _cfg.blockFreezeVelocity
&& Mathf.Abs(Rb.angularVelocity) <= _cfg.blockFreezeAngularVelocity
&& _acc.magnitude <= _cfg.blockFreezeAcc
&& Mathf.Abs(_angularAcc) <= _cfg.blockFreezeAngularAcc;
public int FallPoint
{
get
{
Assert.IsTrue(_tables.TbConstructionUnits.DataMap.ContainsKey(Idx),
$"Block index {Idx} is not in the table.");
return _tables.TbConstructionUnits[Idx].FallPoint;
}
}
public int StackPoint
{
get
{
Assert.IsTrue(_tables.TbConstructionUnits.DataMap.ContainsKey(Idx),
$"Block index {Idx} is not in the table.");
return _tables.TbConstructionUnits[Idx].StackPoint;
}
}
private void Awake()
{
_rb = GetComponent<Rigidbody2D>();
_bc = GetComponent<BoxCollider2D>();
_tables = GContext.container.Resolve<Tables>();
}
private Vector2 previousVelocity, _acc;
private float previousAngularVelocity, _angularAcc;
public Vector2 Acc => _acc;
public float AngularAcc => _angularAcc;
private void Start()
{
previousAngularVelocity = _rb.angularVelocity;
previousVelocity = _rb.velocity;
}
private void FixedUpdate()
{
_acc = (_rb.velocity - previousVelocity) / Time.fixedDeltaTime;
_angularAcc = (_rb.angularVelocity - previousAngularVelocity) / Time.fixedDeltaTime;
previousVelocity = _rb.velocity;
previousAngularVelocity = _rb.angularVelocity;
}
public void InitHangingBlock(BlockState s, int idx, IEventAggregator ea, InfiniteBuildingConf config)
{
State = BlockState.Hanging;
_furnitureList = new List<Furniture>();
GetFurnitures(transform, 0, _furnitureList);
State = s;
Idx = idx;
EventAggregator = ea;
_cfg = config;
foreach (var fur in _furnitureList)
SetFurnitureScale(fur, 0);
}
public void InitRecordBlock(InfiniteBuildingConf config)
{
_cfg = config;
_furnitureList = new List<Furniture>();
GetFurnitures(transform, 0, _furnitureList);
}
private void OnCollisionEnter2D(Collision2D collision)
{
//Debug.Log($"<color=red>Play audio from {gameObject.name} to {collision.gameObject.name}</color>");
int a = gameObject.GetHashCode();
int b = collision.gameObject.GetHashCode();
if (a > b)
(a, b) = (b, a);
string hash = string.Format("{0}{1}", a, b);
EventAggregator.Publish(new EventInfiniteBuildingCollisionSound(hash));
if (_freezable == false && State == BlockState.Free)
EventAggregator.Publish(new EventInfiniteBuildingFirstCollision(this));
_freezable = true;
}
private void OnCollisionExit2D(Collision2D collision)
{
//Debug.Log($"<color=blue>Detach audio from {gameObject.name} to {collision.gameObject.name}</color>");
}
private int targetDepth = 2;
private void GetFurnitures(Transform parent, int currentDepth, List<Furniture> result)
{
if (currentDepth == targetDepth)
{
result.Add(new Furniture(parent.gameObject, parent.gameObject.transform.localScale));
return;
}
foreach (Transform child in parent)
{
GetFurnitures(child, currentDepth + 1, result);
}
}
private void SetFurnitureScale(Furniture f, float scale)
{
if (!f.Go.name.StartsWith("B999_glass"))
f.Go.transform.localScale = f.TargetScale * scale;
}
public void PlayFurnitureAnimation()
{
foreach (var fur in _furnitureList)
{
if (fur.Go.name.StartsWith("B999_glass"))
StartCoroutine(GlassTransfer(fur));
else
fur.Go.transform.DOScale(fur.TargetScale,
Random.Range(_cfg.animationDurationRange.x, _cfg.animationDurationRange.y));
}
}
private IEnumerator GlassTransfer(Furniture f)
{
yield return new WaitForSeconds(_cfg.animationDurationRange.y);
Material mat = f.Go.GetComponent<MeshRenderer>().material;
float t = 0;
while (t <= _cfg.animationDurationRange.z)
{
t += Time.deltaTime;
mat.SetColor("_EmissionColor", Color.Lerp(Color.black, _cfg.glassColor,
t / _cfg.animationDurationRange.z));
yield return null;
}
}
public void LitBlock()
{
foreach (var fur in _furnitureList)
{
if (fur.Go.name.StartsWith("B999_glass"))
fur.Go.GetComponent<MeshRenderer>().material
.SetColor("_EmissionColor", _cfg.glassColor);
}
}
public void Drop()
{
//_djl.breakForce = 0;
//_djr.breakForce = 0;
State = BlockState.Free;
Rb.drag = 0;
//DestroyCountDown();
}
public void Rest()
{
//_cts.Cancel();
//_cts.Dispose();
State = BlockState.Resting;
//_rb.velocity = Vector3.zero;
//_rb.isKinematic = true;
//Debug.Log(_focus.position);
//Debug.Log(Height);
//_rb.MovePosition(new Vector2(_rb.position.x, _focus.position.y));
//OnRest?.Invoke(delta);
}
//public void DestroySelf()
//{
// Debug.Log($"awsl {gameObject}");
// try
// {
// _cts?.Cancel();
// _cts?.Dispose();
// }
// catch(ObjectDisposedException e)
// {
// Debug.Log($"source disposed: {e}");
// }
// if (_state == BlockState.Free)
// OnDestroy?.Invoke();
// Destroy(gameObject);
//}
}
public enum BlockState
{
Hanging, Free, Resting, Locked
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0ba06163a44f9bd40a3df71c58a8be15
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,17 @@
using asap.core;
using UnityEngine;
public class BlockDeathNotifier : MonoBehaviour
{
private EventAggregator _eventAggregator;
public void Init(EventAggregator e)
{
_eventAggregator = e;
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.TryGetComponent(out Block b))
_eventAggregator.Publish(new EventInfiniteBuildingBlockDeath(b.State));
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e7483ff4d84b7f8458273fd57fdb8fb4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,338 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
using cfg;
using asap.core;
using UnityEngine.ResourceManagement.AsyncOperations;
public class BlockManager : MonoBehaviour
{
private Dictionary<string, GameObject> _blockPrefabs = new Dictionary<string, GameObject>();
//[SerializeField] private BoxCollider2D _deathWall;
[SerializeField] List<Block> _blocks = new List<Block>();
[SerializeField] private Transform _focus;
public Block CurrentBlock;
private TbConstructionBasicUnits _blockTypesTable;
private TbConstructionUnits _blocksTable;
private TbConstructionHeightEvent _heightEventTable;
private InfiniteBuildingConf _cfg;
private InfiniteBuildingData _data;
private EventAggregator _eventAggregator;
private List<AsyncOperationHandle> _prefabOps;
public List<Block> Blocks => _blocks;
private void Start()
{
_blockTypesTable = GContext.container.Resolve<Tables>().TbConstructionBasicUnits;
_blocksTable = GContext.container.Resolve<Tables>().TbConstructionUnits;
_prefabOps = new List<AsyncOperationHandle>();
}
private void OnDestroy()
{
foreach (var op in _prefabOps)
Addressables.Release(op);
}
public void Init(InfiniteBuildingConf cfg, InfiniteBuildingData data, EventAggregator ea)
{
_cfg = cfg;
_data = data;
_eventAggregator = ea;
_heightEventTable = GContext.container.Resolve<Tables>().TbConstructionHeightEvent;
}
/// <summary>
/// Get prefab according to PrefabID, will be used in init and block generation
/// </summary>
/// <param name="id">name of the prefab in addressables</param>
/// <returns>the prefab GameObject</returns>
private async System.Threading.Tasks.Task<GameObject> GetBlockPrefab(string id)
{
if (_blockPrefabs.TryGetValue(id, out var prefab))
return prefab;
_prefabOps.Add(Addressables.LoadAssetAsync<object>(id));
var go = (GameObject) await _prefabOps[^1].Task;
_blockPrefabs.Add(id, go);
return go;
}
private int GetRandomIDFromWeightTable(Dictionary<int, float> weightTable)
{
Dictionary<int, float> weightSum = new Dictionary<int, float>();
float sum = 0;
foreach (var e in weightTable)
{
sum += e.Value;
weightSum.Add(e.Key, sum);
}
float randomNum = UnityEngine.Random.Range(0, sum);
foreach (var e in weightSum)
{
if (randomNum <= e.Value)
{
return e.Key;
}
}
Debug.LogError($"Random ID not available. WeightTable entries count: {weightTable.Count}.");
return -1;
}
public async System.Threading.Tasks.Task<Block> GenerateBlock(Vector3 spawnPos, bool isFirst = false)
{
Block generatedBlock;
Dictionary<int, float> weightTable = new Dictionary<int, float>();
//_crane.ResetPosition();
//await Awaiters.NextFrame;
int type, block;
foreach (var bt in _blockTypesTable.DataList)
{
weightTable.Add(bt.ID, bt.Weight);
}
type = GetRandomIDFromWeightTable(weightTable);
weightTable.Clear();
foreach (int blockID in _blockTypesTable[type].UnitList)
{
if (_data.Lvl < _blocksTable[blockID].UnlockedHeight)
continue;
weightTable.Add(blockID, _blocksTable[blockID].Weight);
}
block = GetRandomIDFromWeightTable(weightTable);
if (isFirst && _data.LastHangingBlock != -1)
{
block = _data.LastHangingBlock;
_data.LastHangingBlock = -1;
}
TbConstructionInfiniteInit initTable = GContext.container.Resolve<Tables>().TbConstructionInfiniteInit;
if (_data.Lvl < initTable.DataList.Count)
block = GContext.container.Resolve<Tables>().TbConstructionInfiniteInit.DataList[_data.Lvl].UnitID;
#if UNITY_EDITOR
if (_cfg.NextBlockToSpawn != -1 && _blocksTable.DataMap.ContainsKey(_cfg.NextBlockToSpawn))
block = _cfg.NextBlockToSpawn;
#endif
string id = _blocksTable[block].Prefab;
GameObject prefab = await GetBlockPrefab(id);
//GameObject prefab = await GetBlockPrefab("block_000");//Get test prefab
//Debug.Log($"<color=red>{_crane.transform.position}</color>");
//Debug.Log($"<color=red>{_cfg.blockSpawnOffset}</color>");
generatedBlock = Instantiate(prefab, spawnPos + _blocksTable[block].Height * Vector3.down,
prefab.transform.rotation, transform).GetComponent<Block>();
generatedBlock.InitHangingBlock(BlockState.Hanging, block, _eventAggregator, _cfg);
generatedBlock.Rb.angularDrag = GetDataByIBLvl(_data.Lvl, _heightEventTable.DataList).AngularDrag;
generatedBlock.Rb.drag = GetDataByIBLvl(_data.Lvl, _heightEventTable.DataList).LinearDrag;
//_currentBlock.SetParams(_cfg, _deathWall.name, block, _focus);
//generatedBlock.OnRest += async d => await OnBlockRest(d);
//generatedBlock.OnDestroy += async () => await OnBlockDestroy();
//_currentBlock.AttachJoints(_crane);
//_crane.AttachJoints(generatedBlock);
//await _crane.Descend();
//if (doSwitchState)
// _stateMachine.SetState(EInfiniteBuildingState.PlayerCtrl);
return generatedBlock;
}
private async System.Threading.Tasks.Task<GameObject> GenerateBlock(InfiniteBuildingData.BlockRecord record, IEventAggregator ea)
{
GameObject b = Instantiate(await GetBlockPrefab(record.PrefabID),
new Vector3(record.Pos.x, record.Pos.y, _cfg.blockDepth), Quaternion.identity, transform);
b.GetComponent<Rigidbody2D>().isKinematic = true;
b.GetComponent<Rigidbody2D>().velocity = Vector2.zero;
b.GetComponent<Block>().Idx = record.ID;
b.GetComponent<Block>().EventAggregator = ea;
//_blocks[^1].SetParams(_cfg, _deathWall.name, record.id, _focus);
return b;
}
public int GetExcellentScore()
{
int fallingBlockScore = _blocksTable[CurrentBlock.Idx].FallPoint;
int stackedBlockScore = _blocks is { Count: > 0 } ? _blocksTable[_blocks[^1].Idx].StackPoint : 0;
// Debug.Log($"<color=red>Incoming: {fallingBlockScore}, stacked: {stackedBlockScore}</color>");
return fallingBlockScore + stackedBlockScore;
}
public bool TrySnap()
{
if (_blocks is not { Count: > 0 })
{
if (Mathf.Abs(CurrentBlock.Rb.position.x - _focus.position.x) > _cfg.snapThresh)
return false;
CurrentBlock.Rb.MovePosition(new Vector2(_focus.position.x, CurrentBlock.Rb.position.y));
return true;
}
if (Mathf.Abs(CurrentBlock.Rb.position.x - _blocks[^1].Rb.position.x) > _cfg.snapThresh)
return false;
CurrentBlock.Rb.MovePosition(new Vector2(_blocks[^1].Rb.position.x, CurrentBlock.Rb.position.y));
return true;
}
public async void AlignBlocks(IEventAggregator ea)
{
Block b;
for (int j = _blocks.Count - 1; j >= 0; j--)
{
b = _blocks[j];
//_blocks.RemoveAt(j);
if (b != null)
Destroy(b.gameObject);
}
Vector3 pivot = _focus.position;
for (int i = _data.Record.Count - 1; i >= 0; i--)
{
InfiniteBuildingData.BlockRecord r = _data.Record[i];
b = Instantiate(await GetBlockPrefab(r.PrefabID),
pivot + r.Height * Vector3.down,
Quaternion.identity, transform).GetComponent<Block>();
pivot += r.Height * Vector3.down;
//_blocks[_data.Record.Count - 1 - i] = b;
_blocks[i] = b;
b.Rb.isKinematic = true;
b.Rb.velocity = Vector2.zero;
b.Idx = r.ID;
b.EventAggregator = ea;
}
for (int i = _blocks.Count - 1; i >= 0; i--)
{
b = _blocks[i];
if (b.WorldHeight < _focus.position.y + _cfg.blockDestroyOffset)
{
_blocks.RemoveAt(i);
Destroy(b.gameObject);
}
else if (b.WorldHeight < _focus.position.y + _cfg.blockRestingOffset)
{
b.Rb.isKinematic = true;
b.State = BlockState.Locked;
}
else
{
b.Rb.isKinematic = false;
b.State = BlockState.Resting;
}
}
//for (int i = 0; i < _blocks.Count; i++)
//{
// if (_blocks[i] == null)
// continue;
// _blocks[i].Rb.MovePosition(new Vector2(0, _data.Record[i].pos.y));
//}
}
private float _blockDestructionTimer = 1000f;
public void BlockFallFixedUpdate()
{
float rot = CurrentBlock.Rb.rotation;
_blockDestructionTimer -= Time.fixedDeltaTime;
if (_blockDestructionTimer < 0)
{
_eventAggregator.Publish(new EventInfiniteBuildingFail());
return;
}
if (!CurrentBlock.Freezable || !CurrentBlock.IsCurrentBlockStill)
return;
if ((rot <= _cfg.blockDestroyThreshAngle && rot > -_cfg.blockDestroyThreshAngle)
|| (rot >= 180 - _cfg.blockDestroyThreshAngle && rot <= 180)
|| (rot >= -180 && rot <= -180 + _cfg.blockDestroyThreshAngle))
_eventAggregator.Publish(new EventInfiniteBuildingSucceed());
else
_eventAggregator.Publish(new EventInfiniteBuildingFail());
}
public void StartDestroyCountDown()
{
//Debug.Log("111111111111111");
_blockDestructionTimer = _cfg.blockDestroyDelay;
}
public void ResetDestroyCountDown()
{
_blockDestructionTimer = float.PositiveInfinity;
}
public void AddCurrentBlock()
{
_blocks.Add(CurrentBlock);
}
private void CurrentBlockFail()
{
Debug.Log("Build failure.");
}
/// <summary>
/// Lock or clear blocks according to their height, need focus updated first
/// </summary>
public void LockOrClearBlocks(bool isFilterOnly = false)
{
for (int i = _blocks.Count - 1; i >= 0; i--)
{
Block b = _blocks[i];
if (b.WorldHeight < _cfg.blockDestroyOffset + _focus.position.y)
{
_blocks.RemoveAt(i);
Destroy(b.gameObject);
}
else if (b.WorldHeight < _cfg.blockRestingOffset + _focus.position.y )
{
b.Rb.velocity = Vector2.zero;
b.Rb.rotation = 0;
b.Rb.angularVelocity = 0;
b.Rb.isKinematic = true;
}
else if (!isFilterOnly)
b.Rb.isKinematic = false;
}
}
/// <summary>
/// Clear stage, generate blocks according to data, and reset focus position
/// </summary>
/// <returns>Task</returns>
public async System.Threading.Tasks.Task RebuildAllBlocks()
{
//clear the act
if (CurrentBlock != null)
Destroy(CurrentBlock.gameObject);
await RebuildBlocks();
}
/// <summary>
/// reset stage, bug leave the current block alone
/// </summary>
/// <returns></returns>
public async System.Threading.Tasks.Task RebuildBlocks(bool doesLockAll = false)
{
Block b;
for (int j = _blocks.Count - 1; j >= 0; j--)
{
b = _blocks[j];
_blocks.RemoveAt(j);
if (b != null)
Destroy(b.gameObject);
}
//regenerate
_focus.position = new Vector3(_focus.position.x, 0, _focus.position.z);
foreach (var record in _data.Record)
{
b = (await GenerateBlock(record, _eventAggregator)).GetComponent<Block>();
b.InitRecordBlock(_cfg);
b.LitBlock();
_blocks.Add(b);
if (_focus.position.y < b.WorldHeight)
_focus.position = new Vector3(_focus.position.x, b.WorldHeight, _focus.position.z);
}
for (int i = _blocks.Count - 1; i >= 0; i--)
{
b = _blocks[i];
if (b.WorldHeight < _focus.position.y + _cfg.blockDestroyOffset)
{
_blocks.RemoveAt(i);
Destroy(b.gameObject);
}
else if (b.WorldHeight < _focus.position.y + _cfg.blockRestingOffset || doesLockAll)
{
b.Rb.isKinematic = true;
b.State = BlockState.Locked;
}
else
{
b.Rb.isKinematic = false;
b.State = BlockState.Resting;
}
}
}
private ConstructionHeightEvent GetDataByIBLvl(int lvl, List<ConstructionHeightEvent> dataList)
{
for (int i = 0; i < dataList.Count - 1; i++)
{
if (lvl < dataList[i + 1].Height)
return dataList[i];
}
return dataList[^1];
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 07289b2d3209cfa409936717be62c45d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,118 @@
using DG.Tweening;
using UnityEngine;
using System.Collections.Generic;
using cfg;
using asap.core;
using PlayFab.GroupsModels;
public class CameraCtrl : MonoBehaviour
{
private Transform _focus;
private float _blockDepth, _skyLoopTriggerheight, _skyLoopOffsetDelta;
private MeshRenderer _sky;
private Material _skyMat;
private InfiniteBuildingConf _cfg;
private InfiniteBuildingData _data;
private List<int> _lvlThresh;
private List<float> _depth, _yOffset;
private TbConstructionHeightEvent _tableHeightEvent;
private readonly string MatOffsetKey = "_Offset";
//[SerializeField]private CinemachineVirtualCamera _cam;
/* public Vector3 LowerLimit
{
get
{
Vector3 pos = Camera.main.ViewportToWorldPoint(
new Vector3(0.5f, 0, _blockDepth - transform.position.z));
//Debug.Log(pos);
return pos;
}
}
*/
public float CamDepth
{
get { return GetDataByIBLvl<float>(_data.Lvl, _lvlThresh, _depth); }
}
public void Init(Transform focus, InfiniteBuildingConf cfg, MeshRenderer sky,
InfiniteBuildingData data)
{
_tableHeightEvent = GContext.container.Resolve<Tables>().TbConstructionHeightEvent;
_focus = focus;
_blockDepth = cfg.blockDepth;
_sky = sky;
_skyMat = sky.sharedMaterial;
_skyLoopTriggerheight = cfg.skyLoopTriggerHeight;
_skyLoopOffsetDelta = cfg.skyLoopOffsetDelta;
if (focus.position.y >= cfg.skyLoopTriggerHeight)
{
Vector3 pos = _sky.transform.position;
_sky.transform.position = new Vector3(pos.x, transform.position.y, pos.z);
}
_cfg = cfg;
_data = data;
_lvlThresh = new List<int>();
_depth = new List<float>();
_yOffset = new List<float>();
foreach (var c in _tableHeightEvent.DataList)
{
_lvlThresh.Add(c.Height);
_depth.Add(c.CameraDepth);
_yOffset.Add(c.CameraYOffest);
}
transform.position = new Vector3(0,
focus.position.y + GetDataByIBLvl<float>(_data.Lvl, _lvlThresh, _yOffset),
focus.position.z - CamDepth);
if (_focus.position.y >= _skyLoopTriggerheight)
_sky.transform.position =
new Vector3(0, transform.position.y, _sky.transform.position.z);
_skyMat.SetVector(MatOffsetKey, Vector4.zero);
}
public void FollowFocus(float duration = 0.5f)
{
transform.DOMove(new Vector3(0,
_focus.position.y + GetDataByIBLvl<float>(_data.Lvl, _lvlThresh, _yOffset),
transform.position.z), duration);
if (_focus.position.y < _skyLoopTriggerheight)
return;
_sky.transform.DOMove(new Vector3(0, transform.position.y, _sky.transform.position.z),
duration);
//Vector2 oldOffset = _skyMat.GetTextureOffset("_Texture2D");
//Debug.Log(oldOffset);
//_skyMat.DOOffset(oldOffset + Vector2.up * _skyLoopOffsetDelta, duration);
Vector2 offset = _skyMat.GetVector(MatOffsetKey);
float t = 0;
DOTween.To(() => t, (value) => t = value, _skyLoopOffsetDelta, duration)
.OnUpdate(() => _skyMat.SetVector(MatOffsetKey, offset + t * Vector2.up)).OnComplete(() =>
{
var v = _skyMat.GetVector(MatOffsetKey);
while (v.y > 0.5f) v.y -= 1f;
while (v.y < -0.5f) v.y += 1f;
_skyMat.SetVector(MatOffsetKey, v);
});
}
private T GetDataByIBLvl<T>(int lvl, List<int> lvlThresh, List<T> dataList)
{
if (lvlThresh.Count != dataList.Count)
{
Debug.LogError($"lvlTresh count {lvlThresh.Count} does not" +
$"match dataList count {dataList.Count}");
return default(T);
}
for (int i = 0; i < lvlThresh.Count - 1; i++)
{
if (lvl < lvlThresh[i + 1])
return dataList[i];
}
return dataList[^1];
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4d4602d0c872ad44db4dadd40e89a12e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,27 @@
using asap.core;
using cfg;
using GameCore;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class CampInfoPanel : MonoBehaviour
{
private TMP_Text _textPrice;
private RewardItemNew _reward;
private Button _btnClose;
private void Awake()
{
_btnClose = transform.Find("btn_close").GetComponent<Button>();
_textPrice = transform.Find("root/info2/btn_construct2/text_cost").GetComponent<TMP_Text>();
_reward = transform.Find("root/info4/reward").GetComponent<RewardItemNew>();
}
private void Start()
{
_btnClose.onClick.AddListener(() => UIManager.Instance.DestroyUI(UITypes.CampInfoPanel));
_textPrice.text = ((int) (GContext.container.Resolve<Tables>().TbMapData.DataMap[114].ConstrutionCost
* GContext.container.Resolve<Tables>().TbConstructionInfiniteConfig.CashMagList[0])).ToString();
_reward.SetData(GContext.container.Resolve<PlayerItemData>().GetItemDataOne(
GContext.container.Resolve<Tables>().TbConstructionInfiniteReward[1].DropID));
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 95d373774d7918a4ab3dda76290aa9d0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,36 @@
using UnityEngine.UI;
using TMPro;
using asap.core;
using cfg;
public class CampSettlementPanel : BasePanel
{
private Button _btnClose, _btnRetry, _btnAlign;
private TMP_Text _textAlignCost;
//public Action Retry, Align;
private IEventAggregator _eventAggregator;
private void Awake()
{
_btnClose = transform.Find("root_fail/btn_close").GetComponent<Button>();
_btnRetry = transform.Find("root_fail/station_advert/btn_retry/btn_green").GetComponent<Button>();
_btnAlign = transform.Find("root_fail/station_advert/btn_fix/btn_green").GetComponent <Button>();
_textAlignCost = transform.Find("root_fail/station_advert/btn_fix/cost/text_num").GetComponent<TMP_Text>();
}
public void Init(IEventAggregator ea)
{
_eventAggregator = ea;
_textAlignCost.text = ConvertTools.GetNumberString(
GContext.container.Resolve<Tables>().TbConstructionInfiniteConfig.ResetCost);
}
protected override void Start()
{
_btnClose.onClick.AddListener(
() => _eventAggregator.Publish(new EventInfiniteBuildingRetry()));
_btnRetry.onClick.AddListener(
() => _eventAggregator.Publish(new EventInfiniteBuildingRetry()));
_btnAlign.onClick.AddListener(
() => _eventAggregator.Publish(new EventInfiniteBuildingAlign()));
base.Start();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8d480c71be6942b48b397d885f4bf847
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,306 @@
using UnityEngine.UI;
using game;
using asap.core;
using GameCore;
using UnityEngine;
using TMPro;
using cfg;
using DG.Tweening;
using UniRx;
//using System.Threading;
public class CampSkyscraperPanel : BasePanel
{
private Button _btnClose, _btnLeft, _btnConstruct, _btnInfo, _btnConstructGray;
//public Action OnClickConstruct, OnClickBtnClose;
public GameObject fxRating, goCombo;
private TMP_Text _textPrice, _textIBLvl, _textStepProgress, _textPriceGray, _comboText1, _comboText2, _comboText3;
TMP_Text text_cost_buff, text_old;//, text_cost_buffGray, text_oldGray;
private InfiniteBuildingData _ibd;
private ulong _price;
private Image _bar;
private RewardItemNew _reward, _flyMoney;
private Tables _tables;
private PlayerData _pd;
private PlayerItemData _pid;
private Animation _rewardAni, _lvlUpAni;
private TbConstructionInfiniteReward _rewardTable;
private EventAggregator _eventAggregator;
CanvasGroup canvasGroup;
private void Awake()
{
//Debug.Log($"<color=red>UI thread id: {Thread.CurrentThread.ManagedThreadId}</color>");
_btnClose = transform.Find("safearea/DownPanel/btn_close").GetComponent<Button>();
_btnLeft = transform.Find("safearea/DownPanel/btn_left").GetComponent<Button>();
_btnConstruct = transform.Find("safearea/DownPanel/btn_construct").GetComponent<Button>();
_btnConstructGray = transform.Find("safearea/DownPanel/btn_construct_gray").GetComponent<Button>();
fxRating = transform.Find("safearea/MiddlePanel/FX_info_piercing").gameObject;
_textPrice = transform.Find("safearea/DownPanel/btn_construct/text_cost").GetComponent<TMP_Text>();
_textPriceGray = transform.Find("safearea/DownPanel/btn_construct_gray/text_cost").GetComponent<TMP_Text>();
text_cost_buff = transform.Find("safearea/DownPanel/btn_construct/text_cost_buff").GetComponent<TMP_Text>();
text_old = transform.Find("safearea/DownPanel/btn_construct/text_cost_buff/text_old").GetComponent<TMP_Text>();
//text_cost_buffGray = transform.Find("safearea/DownPanel/btn_construct_gray/text_cost_buff").GetComponent<TMP_Text>();
//text_oldGray = transform.Find("safearea/DownPanel/btn_construct_gray/text_cost_buff/text_old").GetComponent<TMP_Text>();
_textIBLvl = transform.Find("top_area/level/icon_grade/text_grade").GetComponent<TMP_Text>();
_bar = transform.Find("safearea/MiddlePanel/skyscraper_target/bar").GetComponent<Image>();
_reward = transform.Find("safearea/MiddlePanel/skyscraper_target/reward").GetComponent<RewardItemNew>();
_btnInfo = transform.Find("top_area/level").GetComponent<Button>();
_textStepProgress = transform.Find("safearea/MiddlePanel/skyscraper_target/text_progress").GetComponent<TMP_Text>();
_rewardAni = transform.Find("safearea/MiddlePanel/skyscraper_target").GetComponent<Animation>();
//_lvlUpAni = transform.Find("fx_anim_campskyscraper_levelup_d_01")
_lvlUpAni = transform.Find("top_area/particle/fx_ui_campskyscraper_levelup_01 1").GetComponent<Animation>();
_flyMoney = transform.Find("RewardFlyPanel/reward").GetComponent<RewardItemNew>();
_pd = GContext.container.Resolve<PlayerData>();
_tables = GContext.container.Resolve<Tables>();
_pid = GContext.container.Resolve<PlayerItemData>();
_rewardTable = GContext.container.Resolve<Tables>().TbConstructionInfiniteReward;
goCombo = transform.Find("safearea/MiddlePanel/combo").gameObject;
_comboText1 = goCombo.transform.Find("text_num1").GetComponent<TMP_Text>();
_comboText2 = goCombo.transform.Find("text_num2").GetComponent<TMP_Text>();
_comboText3 = goCombo.transform.Find("text_num3").GetComponent<TMP_Text>();
canvasGroup = transform.GetComponent<CanvasGroup>();
}
protected override void Start()
{
//GContext.container.Resolve<CampData>().IsCanSkyscraper
//建造按钮是否置灰 !IsCanSkyscraper
bool t = GContext.container.Resolve<CampDataMM>().IsCanSkyscraper;
//t = false;
_btnConstruct.gameObject.SetActive(t);
_btnConstructGray.gameObject.SetActive(!t);
//Init();
base.Start();
GContext.OnEvent<RestartShowHomeUIEvent>().Subscribe(_ =>
{
canvasGroup.alpha = 1;
canvasGroup.blocksRaycasts = true;
}).AddTo(disposables);
GContext.OnEvent<HideHomePanelEvent>().Subscribe(_ =>
{
canvasGroup.alpha = 0;
canvasGroup.blocksRaycasts = false;
}).AddTo(disposables);
GContext.OnEvent<ChangeLanguageEvent>().Subscribe(OnChangeLanguage).AddTo(disposables);
}
private void OnClickClose()
{
//OnClickBtnClose?.Invoke();
GContext.Publish(new UnloadActToNextAct());
}
private int target;
public void Init(InfiniteBuildingData ibd, EventAggregator ea)
{
_ibd = ibd;
int price = SetPrice();
_textPriceGray.text = ConvertTools.GetNumberString(price);
_textIBLvl.text = _ibd.Lvl.ToString();
target = _tables.TbConstructionInfiniteReward[_ibd.StepLvl].Step;
_textStepProgress.text = LocalizationMgr.GetFormatTextValue("UI_CampPanel_9", string.Format("{0}/{1}", _ibd.Step, target));
_bar.fillAmount = (float)_ibd.Step / (float)target;
_reward.SetData(_pid.GetItemDataOne(_rewardTable[_ibd.StepLvl].DropID));
_eventAggregator = ea;
}
void OnChangeLanguage(ChangeLanguageEvent changeLanguageEvent)
{
_textStepProgress.text = LocalizationMgr.GetFormatTextValue("UI_CampPanel_9", string.Format("{0}/{1}", _ibd.Step, target));
}
public async System.Threading.Tasks.Task<bool> UpdateUIWhenSuccess()
{
if (_ibd == null)
{
Debug.LogError("Infinite building data is null in UI sript.");
return false;
}
PlayLvlUpAnimation();
target = _rewardTable[_ibd.StepLvl].Step;
if (_ibd.Step < target)
{
_bar.DOFillAmount((float)_ibd.Step / (float)target, 0.5f).onComplete +=
() => _textStepProgress.text = LocalizationMgr.GetFormatTextValue("UI_CampPanel_9", string.Format("{0}/{1}", _ibd.Step, target));
SetPrice();
//_textStepProgress.text = string.Format("Step {0}/{1}", target, target);
return false;
}
_textStepProgress.text = LocalizationMgr.GetFormatTextValue("UI_CampPanel_9", string.Format("{0}/{1}", _ibd.Step, target));
await _bar.DOFillAmount(1, 0.5f).AsyncWaitForCompletion();
return true;
//step target achieved!!!
}
private async System.Threading.Tasks.Task PlayLvlUpAnimation()
{
_lvlUpAni.gameObject.SetActive(false);
_lvlUpAni.gameObject.SetActive(true);
await System.Threading.Tasks.Task.Delay(1000 * 55 / 60);
int lvl = int.Parse(_textIBLvl.text);
DOTween.To(() => lvl, value => lvl = value, _ibd.Lvl, 0.3f)
.OnUpdate(() => { _textIBLvl.text = lvl.ToString(); });
//_textIBLvl.text = _ibd.Lvl.ToString();
}
public async System.Threading.Tasks.Task ReceiveReward()
{
_rewardAni.Play("campskyscraper_target");
await System.Threading.Tasks.Task.Delay(1000 * 92 / 60);
int dropID = _rewardTable[_ibd.StepLvl].DropID;
_pid.AddItemByDrop(dropID, true);
GContext.Publish(new ShowData());
_eventAggregator.Publish(new EventInfiniteBuildingGetReward(dropID));
_bar.fillAmount = 0;
_ibd.Step -= target;
_ibd.StepLvl++;
_ibd.StepLvl = ((_ibd.StepLvl - 1) % _rewardTable.DataList.Count) + 1;
target = _rewardTable[_ibd.StepLvl].Step;
//Debug.Log($"<color=red>stepLvl: {_ibd.StepLvl}," +
// $"dropID: {_pid.GetItemDataOne(_rewardTable[_ibd.StepLvl].DropID)}</color>");
_reward.SetData(_pid.GetItemDataOne(_rewardTable[_ibd.StepLvl].DropID));
_textStepProgress.text = LocalizationMgr.GetFormatTextValue("UI_CampPanel_9", string.Format("{0}/{1}", _ibd.Step, target));
SetPrice();
_ibd.UploadData();
}
int SetPrice()
{
int price = _ibd.ConstructPrice;
var buffTimeData = GContext.container.Resolve<BuffDataCenter>().GetWeelyBuffTimeData<ConstructionCost>();
bool isConstructionCost = buffTimeData != null;
text_cost_buff.gameObject.SetActive(isConstructionCost);
_textPrice.gameObject.SetActive(!isConstructionCost);
if (isConstructionCost)
{
text_old.text = ConvertTools.GetNumberString(price);
_price = (ulong)(price * (1 - buffTimeData.Param));
text_cost_buff.text = ConvertTools.GetNumberString(_price);
}
else
{
_price = (ulong)price;
_textPrice.text = ConvertTools.GetNumberString(price);
}
return price;
}
async void InBuildAct()
{
var campData = GContext.container.Resolve<CampDataMM>();
ILoadResourceService loadResourceService = GContext.container.Resolve<ILoadResourceService>();
bool isCanEnter = await loadResourceService.Loads(campData.AllPrefabs);
if (isCanEnter)
{
GContext.Publish(new UnloadActToNextAct("BuildAct"));
}
else
{
var panel = await UIManager.Instance.ShowUI(UITypes.CloudTransitionPanel);
panel.GetComponent<CloudTransitionPanel>().SetBtn(true, () => GContext.Publish(new UnloadActToNextAct("BuildAct")));
//var panel = await UIManager.Instance.ShowUI(UITypes.FishingDownLoadPopupPanel);
//panel.GetComponent<FishingDownLoadPopupPanel>().SetBtn(null, () => GContext.Publish(new UnloadActToNextAct("BuildAct")));
}
}
public void PlayComboFx(int comboCount)
{
if (comboCount <= 1)
return;
goCombo.SetActive(false);
switch (comboCount)
{
case > 10:
_comboText3.text = comboCount.ToString();
_comboText1.gameObject.SetActive(false);
_comboText2.gameObject.SetActive(false);
_comboText3.gameObject.SetActive(true);
break;
case > 5:
_comboText2.text = comboCount.ToString();
_comboText1.gameObject.SetActive(false);
_comboText2.gameObject.SetActive(true);
_comboText3.gameObject.SetActive(false);
break;
default:
_comboText1.text = comboCount.ToString();
_comboText1.gameObject.SetActive(true);
_comboText2.gameObject.SetActive(false);
_comboText3.gameObject.SetActive(false);
break;
}
goCombo.SetActive(true);
}
/// <summary>
/// Play the rating fx.
/// </summary>
/// <param name="rating">0 for nothing, 1 for good, 2 for fantastic.</param>
public void PlayRatingFx(int rating)
{
if (rating == 0)
return;
fxRating.gameObject.SetActive(false);
fxRating.transform.Find("1").gameObject.SetActive(rating == 2);
fxRating.transform.Find("2").gameObject.SetActive(rating == 1);
fxRating.gameObject.SetActive(true);
}
public async System.Threading.Tasks.Task PlayCashFlyAnimation(int count)
{
// PerfectAni.SetActive(false);
// PerfectAni.SetActive(true);
_flyMoney.gameObject.SetActive(true);
_flyMoney.SetRewardPopupData(new ItemData(1002, count));
_flyMoney.GetComponent<Animation>().Play("reward_common_open");
await System.Threading.Tasks.Task.Delay(16 * 1000 / 60);
_flyMoney.GetComponent<Animation>().Play("reward_common_close");
await System.Threading.Tasks.Task.Delay(16 * 1000 / 60);
await _flyMoney.ParticleAttractor();
_flyMoney.gameObject.SetActive(false);
GContext.Publish(new ResAddEvent(1002));
}
public void ActivateBtns()
{
//if (!_btnConstruct.gameObject.activeSelf)
// return;
_btnConstruct.onClick.AddListener(OnClickPlay);
_btnConstructGray.onClick.AddListener(
() => ToastPanel.Show(LocalizationMgr.GetText("UI_ToastPanel_77")));
_btnClose.onClick.AddListener(OnClickClose);
_btnLeft.onClick.AddListener(InBuildAct);
//_btnConstruct.onClick.AddListener(OnClickPlay);
_btnInfo.onClick.AddListener(() => UIManager.Instance.ShowUI(UITypes.CampInfoPanel));
}
public void DeactivateBtns()
{
_btnConstruct.onClick.RemoveAllListeners();
_btnConstructGray.onClick.RemoveAllListeners();
_btnClose.onClick.RemoveAllListeners();
_btnLeft.onClick.RemoveAllListeners();
_btnInfo.onClick.RemoveAllListeners();
}
private void OnClickPlay()
{
//Debug.Log("Play!!!!!!!!!!!");
_btnConstruct.gameObject.GetComponent<Animator>().Play("clicked");
if ((ulong)_pd.gold >= _price)
{
_btnConstruct.onClick.RemoveAllListeners();
_pd.SetGold(_pd.gold - _price);
GContext.Publish(new ResAddEvent(1002));
_eventAggregator.Publish(new EventInfiniteBuildingConstruct(_price));
}
else
{
ToastPanel.Show(LocalizationMgr.GetText("UI_CampPanel_8"));
}
}
#if UNITY_EDITOR
//private void OnGUI()
//{
// GUI.Box(new Rect(20, 110, 200, 20), _btnConstruct.isActiveAndEnabled.ToString());
//}
#endif
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3e0a4de406af4d04799275c431df2e63
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,193 @@
using UnityEngine;
using DG.Tweening;
using System.Collections.Generic;
using System.Collections;
using cfg;
using asap.core;
public class CraneCtrl : MonoBehaviour
{
private DistanceJoint2D _djL, _djR;
[SerializeField] private Rigidbody2D _rb;
private Vector2 _direction = Vector2.zero, _craneAnchorOffset;
private float _driftOffset, _craneCycleHalfDistance,
_blockAnchorCoefficient, _lineThickness, _blockDepth;
private Block _currentBlock = null;
private bool _maxDistanceOnly, _hasAutoDistance, _needKicking = false;
private Transform _focus;
private List<int> _LvlThresh;
private List<float> _craneHeightRise, _craneHeightDescend, _craneCycleTime, _craneRiseTime;
private InfiniteBuildingData _data;
[SerializeField] private LineRenderer _lineL, _lineR;
private TbConstructionHeightEvent _tableHeightEvent;
private IEventAggregator _eventAggregator;
private float CraneRiseTime { get => GetDataByIBLvl<float>(_data.Lvl, _LvlThresh, _craneRiseTime); }
public Rigidbody2D Rb { get => _rb; }
private float CraneAcc {
get
{
float t = GetDataByIBLvl<float>(_data.Lvl, _LvlThresh, _craneCycleTime) / 4;
return 2 * _craneCycleHalfDistance / t / t;
}
}
private float CraneMaxSpeed
{
get
{
float t = GetDataByIBLvl<float>(_data.Lvl, _LvlThresh, _craneCycleTime) / 4;
return 2 * _craneCycleHalfDistance / t;
}
}
public void Init(InfiniteBuildingConf config, Transform focus, InfiniteBuildingData data, IEventAggregator ea)
{
_eventAggregator = ea;
_tableHeightEvent = GContext.container.Resolve<Tables>().TbConstructionHeightEvent;
_craneCycleTime = new List<float>();
_LvlThresh = new List<int>();
_craneHeightRise = new List<float>();
_craneHeightDescend = new List<float>();
_craneRiseTime = new List<float>();
foreach (var c in _tableHeightEvent.DataList)
{
_craneCycleTime.Add(c.CraneCycleTime);
_LvlThresh.Add(c.Height);
_craneHeightRise.Add(c.CraneHeightRise);
_craneHeightDescend.Add(c.CraneHeightToFocus);
_craneRiseTime.Add(c.CraneRiseTime);
}
_craneCycleHalfDistance = config.craneCycleHalfDistance;
_craneAnchorOffset = config.craneAnchorOffset;
_blockAnchorCoefficient = config.blockAnchorCoefficient;
_maxDistanceOnly = config.maxDistanceOnly;
_hasAutoDistance = config.hasAutoDistance;
_driftOffset = config.blockDriftOffset;
_lineThickness = config.craneLineThickness;
_blockDepth = config.blockDepth;
_focus = focus;
_data = data;
_lineL.startWidth = _lineL.endWidth = _lineR.startWidth = _lineR.endWidth = _lineThickness;
}
public void PlayerCtrlFixedUpdate()
{
if (_rb.position.x < 0)
_direction = Vector2.right;
else
_direction = Vector2.left;
if (_needKicking)
{
_needKicking = false;
_rb.velocity = Mathf.Lerp(0, CraneMaxSpeed,
1 - Mathf.Abs(_rb.position.x) / _craneCycleHalfDistance)
*_direction;
//Debug.Log($"Kick!!!!!!!!!!{_rb.velocity}");
}
_rb.velocity += CraneAcc * Time.fixedDeltaTime * _direction;
//draw line
if (_djL != null && _djR != null && _lineL != null && _lineR != null
&& _lineL.gameObject.activeSelf && _lineR.gameObject.activeSelf
&& _currentBlock != null)
SetJointPosition();
}
public void Kick()
{
_needKicking = true;
}
public void AttachJoints(Block block)
{
_currentBlock = block;
_djL = gameObject.AddComponent<DistanceJoint2D>();
_djR = gameObject.AddComponent<DistanceJoint2D>();
if (_djL == null || _djR == null || _lineL == null || _lineR == null)
{
Debug.LogError($"Components not generated for {gameObject}");
}
_lineL.gameObject.SetActive(true);
_lineR.gameObject.SetActive(true);
SetJointPosition();
_djL.anchor = new Vector2(-_craneAnchorOffset.x, _craneAnchorOffset.y);
_djR.anchor = _craneAnchorOffset;
_djL.connectedBody = block.Rb;
_djR.connectedBody = block.Rb;
_djL.connectedAnchor = new Vector2(-block.Width * _blockAnchorCoefficient / 2, block.Height);
_djR.connectedAnchor = new Vector2(block.Width * _blockAnchorCoefficient / 2, block.Height);
_djL.maxDistanceOnly = _maxDistanceOnly;
_djR.maxDistanceOnly = _maxDistanceOnly;
_djL.autoConfigureDistance = _hasAutoDistance;
_djR.autoConfigureDistance = _hasAutoDistance;
_djL.breakAction = JointBreakAction2D.Destroy;
_djR.breakAction = JointBreakAction2D.Destroy;
if (!_hasAutoDistance)
{
float jd = Mathf.Sqrt(
(block.Width * 0.5f * _blockAnchorCoefficient)
* (block.Width * 0.5f * _blockAnchorCoefficient)
+ _driftOffset * _driftOffset);
_djL.distance = jd;
_djR.distance = jd;
}
}
public IEnumerator DropBlockAndRise()
{
_eventAggregator.Publish(new EventInfiniteBuildingPlayAudio("BlockFall"));
_eventAggregator.Publish(new EventInfiniteBuildingPlayAudio("CraneRise"));
_currentBlock = null;
_rb.velocity = Vector2.zero;
_djL.breakForce = 0;
_djR.breakForce = 0;
_lineL.gameObject.SetActive(false);
_lineR.gameObject.SetActive(false);
yield return new WaitForFixedUpdate();
//await Task.Delay((int)(Time.deltaTime * 1000 * 2));
float h = GetDataByIBLvl<float>(_data.Lvl, _LvlThresh, _craneHeightRise);
_rb.DOMoveY(_focus.position.y + h, CraneRiseTime);
//await Rise();
}
public void ResetPosition()
{
transform.position = new Vector3(0, _focus.position.y +
GetDataByIBLvl<float>(_data.Lvl, _LvlThresh, _craneHeightRise), _blockDepth);
}
public async System.Threading.Tasks.Task Descend()
{
// ResetPosition();
_eventAggregator.Publish(new EventInfiniteBuildingPlayAudio("CraneDescend"));
await _rb.DOMoveY(_focus.position.y +
GetDataByIBLvl<float>(_data.Lvl, _LvlThresh, _craneHeightDescend),
CraneRiseTime).AsyncWaitForCompletion();
}
//public async Task Rise(float duration = 0.5f)
//{
// _rb.velocity = Vector2.zero;
// await _rb.DOMoveY(_focus.position.y +
// GetDataByIBLvl<float>(_data.Lvl, _LvlThresh, _craneHeightRise),
// duration).AsyncWaitForCompletion();
//}
private void SetJointPosition()
{
Vector3 cranePointL = gameObject.transform.position + (Vector3)_djL.anchor;
Vector3 cranePointR = gameObject.transform.position + (Vector3)_djR.anchor;
Vector3 blockPointL = _currentBlock.transform.position + Quaternion.AngleAxis(
_currentBlock.Rb.rotation, Vector3.forward) * (Vector3)_djL.connectedAnchor;
Vector3 blockPointR = _currentBlock.transform.position + Quaternion.AngleAxis(
_currentBlock.Rb.rotation, Vector3.forward) * (Vector3)_djR.connectedAnchor;
_lineL.SetPositions(new Vector3[] { cranePointL, blockPointL });
_lineR.SetPositions(new Vector3[] { cranePointR, blockPointR });
}
private T GetDataByIBLvl<T>(int lvl, List<int> lvlThresh, List<T> dataList)
{
if (lvlThresh.Count != dataList.Count)
{
Debug.LogError($"lvlTresh count {lvlThresh.Count} does not" +
$"match dataList count {dataList.Count}");
return default(T);
}
for (int i = 0; i < lvlThresh.Count - 1; i++)
{
if (lvl < lvlThresh[i + 1])
return dataList[i];
}
return dataList[^1];
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 13702d906a14554478d2807d74039cca
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,806 @@
using System.Collections.Generic;
using UnityEngine;
using asap.core;
using UnityEngine.AddressableAssets;
using GameCore;
using cfg;
using UniRx;
using UnityEngine.ResourceManagement.AsyncOperations;
using Game;
public class InfiniteBuildingAct : AGameAct
{
private PlayerData _playerData;
private InfiniteBuildingData _data;
private InfiniteBuildingConf _cfg;
private class FSM : AFSM<EInfiniteBuildingState>
{
}
private IFSM<EInfiniteBuildingState> _sm;
private FSMHandler<IFSM<EInfiniteBuildingState>, EInfiniteBuildingState> _smHandler;
[SerializeField] private CraneCtrl _crane;
[SerializeField] private BlockManager _blockManager;
private Tables _tables;
[SerializeField] private CameraCtrl _cam;
private const int blockDepth = 20;
private CampSkyscraperPanel _mainPanel;
[SerializeField] private Transform _focus;
[SerializeField] private BlockDeathNotifier _deathWall;
private PlayerItemData _playerItemData;
private readonly EventAggregator _eventAggregator = new EventAggregator();
private float BlockRestingHeight => _cfg.blockRestingOffset + _focus.position.y;
[SerializeField] private MeshRenderer _skyLoop;
private HashSet<string> _collisionSounds;
private int _EVConstructionState, _EVRetryType, _EVHookRewardGot, _EVCashRewardGot, _EVRating, _EVCombo;
private ulong _EVCost, _EVCashBack;
[SerializeField] GameObject _light;
GameObject Building999Main;
private CompositeDisposable _disposables = new CompositeDisposable();
//IDisposable disposable;
private const string ComboKey = "InfiniteBuildingCombo";
public override async System.Threading.Tasks.Task<bool> StartAsync()
{
Building999Main = transform.GetChild(0).gameObject;
//Debug.Log($"<color=red>Main thread id: {Thread.CurrentThread.ManagedThreadId}</color>");
_collisionSounds = new HashSet<string>();
_data = new InfiniteBuildingData();
_sm = new FSM();
_smHandler = new FSMHandler<IFSM<EInfiniteBuildingState>, EInfiniteBuildingState>(this, _sm);
_cfg = (InfiniteBuildingConf)await Addressables.LoadAssetAsync<System.Object>("InfiniteBuildingConf").Task;
_playerData = GContext.container.Resolve<PlayerData>();
_tables = GContext.container.Resolve<Tables>();
_playerItemData = GContext.container.Resolve<PlayerItemData>();
_disposables.Add(GContext.OnEvent<InGradeAquariumEvent>().Subscribe(OnInAquariumEnevt));
_disposables.Add(GContext.OnEvent<EventMainBGM>().Subscribe(OnEventMainBGM));
GContext.OnEvent<MapShowEvent>().Subscribe(e =>
{
SetMapShow(e.isShow);
}).AddTo(_disposables);
_data.DownloadData(_playerData.InfiniteBuildingData);
// Debug.Log($"<color=red>Debug in progress!!!!!!!!!!!!!!!!</color>");
// _data.DownloadData("0,0,1,-1");
//_data.DownloadData("1199,0,1,-1," +
// "209,-0.9679986,1191.69006," +
// "212,-0.9312674,1192.70402," +
// "1201,-0.1499511,1193.71932," +
// "103,-0.288533,1195.73021," +
// "211,-0.03252038,1196.74632," +
// "203,-0.06627272,1197.76019," +
// "201,0.08355299,1198.77346," +
// "101,-0.3572269,1199.79065");
_crane.Init(_cfg, _focus, _data, _eventAggregator);
_eventAggregator.GetEvent<EventInfiniteBuildingAlign>()
.Subscribe(async _ => await TryAlignBlocks()).AddTo(_disposables);
_eventAggregator.GetEvent<EventInfiniteBuildingRetry>()
.Subscribe(_ =>
{
_EVRetryType = 1;
_sm.SetState(EInfiniteBuildingState.InitLoop);
UIManager.Instance.DestroyUI(UITypes.CampSettlementPanel);
}).AddTo(_disposables);
_eventAggregator.GetEvent<EventInfiniteBuildingConstruct>()
.Subscribe(e =>
{
_sm.SetState(EInfiniteBuildingState.BlockFall);
_EVCost = e.ConstructionCost;
}).AddTo(_disposables);
_eventAggregator.GetEvent<EventInfiniteBuildingBlockDeath>()
.Subscribe(e => HandleBlockDeath(e)).AddTo(_disposables);
_eventAggregator.GetEvent<EventInfiniteBuildingFail>()
.Subscribe(_ => _sm.SetState(EInfiniteBuildingState.Failure)).AddTo(_disposables);
_eventAggregator.GetEvent<EventInfiniteBuildingSucceed>()
.Subscribe(_ => _sm.SetState(EInfiniteBuildingState.Success)).AddTo(_disposables);
_eventAggregator.GetEvent<EventInfiniteBuildingPlayAudio>()
.Subscribe(async e => await PlayAudio(e.AudioName)).AddTo(_disposables);
_eventAggregator.GetEvent<EventInfiniteBuildingCollisionSound>()
.Subscribe(e => OnCollisionSound(e.Hash)).AddTo(_disposables);
_eventAggregator.GetEvent<EventInfiniteBuildingFirstCollision>()
.Subscribe(e => HandleFirstCollision(e.block)).AddTo(_disposables);
_eventAggregator.GetEvent<EventInfiniteBuildingGetReward>()
.Subscribe(e => HandleReceiveReward(e)).AddTo(_disposables);
await LoadAudioClips();
PlayBGM();
//Debug.Log($"<color=red>{_pd.InfiniteBuildingData}</color>");
_mainPanel = (await UIManager.Instance.ShowUI(UITypes.CampSkyscraperPanel))
.GetComponent<CampSkyscraperPanel>();
_mainPanel.Init(_data, _eventAggregator);
BoxCollider2D initBC =
transform.Find("Building999Main/static/B999_initial/Collision2D").GetComponent<BoxCollider2D>();
_focus.position = initBC.transform.position + new Vector3(initBC.offset.x, initBC.offset.y) +
initBC.size.y / 2f * Vector3.up;
_blockManager.Init(_cfg, _data, _eventAggregator);
await _blockManager.RebuildAllBlocks();
_deathWall.Init(_eventAggregator);
GetFX();
_sm.SetState(EInfiniteBuildingState.Init);
return await base.StartAsync();
}
void SetMapShow(bool isShow)
{
if (Building999Main != null)
{
Building999Main.SetActive(isShow);
}
}
void OnInAquariumEnevt(InGradeAquariumEvent e)
{
Debug.Log("OnInAquariumEnevt");
if (_light != null)
{
_light.SetActive(e.type == 1);
}
}
void OnEventMainBGM(EventMainBGM e)
{
PlayBGM();
}
public override async System.Threading.Tasks.Task StopAsync()
{
UIManager.Instance.DestroyUI(UITypes.CampSkyscraperPanel);
await base.StopAsync();
}
private void FixedUpdate()
{
if (_sm == null)
return;
if (_sm.State == EInfiniteBuildingState.PlayerCtrl
#if UNITY_EDITOR
&& !_cfg.FreezeCrane
#endif
)
{
_crane.PlayerCtrlFixedUpdate();
}
#if UNITY_EDITOR
float v = 0.2f;
if (Input.GetKeyDown(KeyCode.A) && _sm.State == EInfiniteBuildingState.PlayerCtrl)
{
_crane.Rb.position += v * Vector2.left;
}
if (Input.GetKeyUp(KeyCode.D) && _sm.State == EInfiniteBuildingState.PlayerCtrl)
{
_crane.Rb.position += v * Vector2.right;
}
#endif
else if (_sm.State == EInfiniteBuildingState.BlockFall)
{
_blockManager.BlockFallFixedUpdate();
}
}
private void LateUpdate()
{
_collisionSounds?.Clear();
}
protected override void OnDestroy()
{
Debug.Log("Act Destroyed!");
}
#if UNITY_EDITOR
private void OnGUI()
{
if (_sm != null)
GUI.Box(new Rect(20, 40, 200, 20), _sm.State.ToString());
//Debug.DrawLine(new Vector3(-10, _cam.LowerLimit.y, blockDepth),
//new Vector3(10, _cam.LowerLimit.y, blockDepth), Color.red);
if (_blockManager.CurrentBlock != null)
{
GUI.Box(new Rect(20, 60, 200, 20), $"Acc: {_blockManager.CurrentBlock.Acc.magnitude}");
GUI.Box(new Rect(20, 90, 200, 20), $"Angular Acc: {_blockManager.CurrentBlock.AngularAcc}");
}
else
{
GUI.Box(new Rect(20, 60, 200, 20), $"Empty");
GUI.Box(new Rect(20, 90, 200, 20), $"Empty");
}
}
private void OnDrawGizmos()
{
if (_focus != null && _cfg != null)
Debug.DrawLine(new Vector3(-10, BlockRestingHeight, blockDepth),
new Vector3(10, BlockRestingHeight, blockDepth), Color.red);
//Debug.DrawLine(new Vector3(-20, _cam.LowerLimit.y, blockDepth),
// new Vector3(-20, _cam.LowerLimit.y, blockDepth), Color.red);
}
#endif
private void UpdateLastHangingBlock()
{
_data.LastHangingBlock = _blockManager.CurrentBlock.Idx;
_data.UploadData();
}
private void UpdateData(int lvlDelta = 0)
{
_data.Lvl += lvlDelta;
_data.Record = new List<InfiniteBuildingData.BlockRecord>();
foreach (var block in _blockManager.Blocks)
{
//Debug.Log($"{block}");
//Debug.Log($"{block.Rb.position}");
//Debug.Log($"{block.transform.position}");
_data.Record.Add(new InfiniteBuildingData.BlockRecord(block.Idx, block.Rb.position));
}
_data.UploadData();
}
protected override void OnStopped()
{
//_data.LastHangingBlock = _blockManager.CurrentBlock.Idx;
//UpdateData();
foreach (var e in _audioClips)
{
Addressables.Release(e.Value.Op);
}
_disposables.Dispose();
base.OnStopped();
}
public void HandleBlockDeath(EventInfiniteBuildingBlockDeath e)
{
PlayFX("collapse", _focus.position + _cfg.fxCollapse);
if (_sm.State != EInfiniteBuildingState.BlockFall)
{
PlayFX("replay",
Camera.main.ViewportToWorldPoint(new Vector3(0.5f, 1f, _cfg.blockDepth)));
_blockManager.RebuildBlocks(true);
return;
}
if (e.stateBeforeDeath == BlockState.Free)
_eventAggregator.Publish(new EventInfiniteBuildingFail());
if (e.stateBeforeDeath == BlockState.Resting)
{
_eventAggregator.Publish(new EventInfiniteBuildingFail());
PlayFX("replay",
Camera.main.ViewportToWorldPoint(new Vector3(0.5f, 1f, Camera.main.nearClipPlane)));
_blockManager.RebuildAllBlocks();
}
}
private async System.Threading.Tasks.Task TryAlignBlocks()
{
int alignCost = _tables.TbConstructionInfiniteConfig.ResetCost;
if (_playerData.diamond < alignCost)
{
//Debug.LogWarning("inssuficient diamond");
GameObject ui = await UIManager.Instance.ShowUI(UITypes.LackOfResourceConfirmPopupPanel);
//ui.GetComponent<CampSettlementPanel>().Init(_eventAggregator);
return;
}
_EVRetryType = 2;
PlayAudio("Reset");
PlayFX("reset", Camera.main.ViewportToWorldPoint(new Vector3(0.5f, 0f, _cfg.blockDepth)));
_playerData.AddDiamond(-alignCost);
_blockManager.AlignBlocks(_eventAggregator);
UpdateData();
_sm.SetState(EInfiniteBuildingState.InitLoop);
UIManager.Instance.DestroyUI(UITypes.CampSettlementPanel);
}
private void HandleFirstCollision(Block b)
{
//Debug.Log($"name: {b.name}");
PlayFX("fall", b.transform.position + _cfg.fxFall);
_blockManager.StartDestroyCountDown();
//PlayAudio("BlockFall");
}
private void HandleReceiveReward(EventInfiniteBuildingGetReward e)
{
var drop = _tables.TbDrop[e.DropID];
if (drop.DropList.DropIDList[0] == 1001)
_EVHookRewardGot = drop.DropList.DropCountList[0];
else if (drop.DropList.DropIDList[0] == 1002)
_EVCashRewardGot = _playerItemData.GetExtraCoinMag(drop.DropList.DropCountList[0]);
}
private int GetConstructionPrice()
{
int price = _data.ConstructPrice;
var buffTimeData = GContext.container.Resolve<BuffDataCenter>().GetWeelyBuffTimeData<ConstructionCost>();
bool isConstructionCost = buffTimeData != null;
if (isConstructionCost)
{
price = (int)(price * (1 - buffTimeData.Param));
}
return price;
}
private int GetRating()
{
int excellentScore = _blockManager.GetExcellentScore();
if (excellentScore >= _tables.TbConstructionInfiniteConfig.GoodRankClamp[0] &&
excellentScore <= _tables.TbConstructionInfiniteConfig.GoodRankClamp[1])
{
Debug.Log($"<color=red>Good.</color>");
return 1;
}
// else if (excellentScore >= _tables.TbConstructionInfiniteConfig.GreatRankClamp[0] &&
// excellentScore <= _tables.TbConstructionInfiniteConfig.GreatRankClamp[1])
// Debug.Log($"<color=red>Great.</color>");
if (excellentScore >= _tables.TbConstructionInfiniteConfig.FantasticRankClamp[0] &&
excellentScore <= _tables.TbConstructionInfiniteConfig.FantasticRankClamp[1])
{
Debug.Log($"<color=red>Fantastic.</color>");
return 2;
}
Debug.Log($"<color=red>Undefined.</color>");
return 0;
}
private int CountCombo(bool doesComboContinue = true)
{
if (!doesComboContinue)
{
PlayerPrefs.SetInt(ComboKey, 0);
Debug.Log($"<color=red>Combo reset.</color>");
return 0;
}
int comboCount = PlayerPrefs.GetInt(ComboKey) + 1;
PlayerPrefs.SetInt(ComboKey, comboCount);
// if (comboCount >= 2)
// Debug.Log($"<color=red>Combo: {comboCount}</color>");
return comboCount;
}
#region Audio
private readonly Dictionary<string, string> _audioAliases = new Dictionary<string, string>()
{
["CraneRise"] = "audio_ui_skyscraper_1",
["CraneDescend"] = "audio_ui_skyscraper_2",
["BlockFall"] = "audio_ui_skyscraper_3",
["BlockHit"] = "audio_ui_skyscraper_4",
["BlockPerfect"] = "audio_ui_skyscraper_5",
["Collapse"] = "audio_ui_skyscraper_6",
["Reset"] = "audio_ui_skyscraper_7",
["BGM"] = "audio_ui_skyscraper_bgm"
};
private readonly Dictionary<string, InfiniteBuildingAudioClip> _audioClips =
new Dictionary<string, InfiniteBuildingAudioClip>();
private struct InfiniteBuildingAudioClip
{
public string Name;
public string Address;
public AudioClip Clip;
public AsyncOperationHandle Op;
public InfiniteBuildingAudioClip(string name, string addr, AudioClip clip, AsyncOperationHandle op)
{
Name = name;
Clip = clip;
Address = addr;
Op = op;
}
}
private async System.Threading.Tasks.Task LoadAudioClips()
{
foreach (var e in _audioAliases)
{
AsyncOperationHandle<AudioClip> op = Addressables.LoadAssetAsync<AudioClip>(e.Value);
_audioClips.Add(e.Key, new InfiniteBuildingAudioClip(e.Key, e.Value, await op.Task, op));
}
}
private async System.Threading.Tasks.Task PlayAudio(string audioName)
{
if (!_audioAliases.ContainsKey(audioName))
{
Debug.LogError($"Audio name {audioName} not found in dictionary.");
return;
}
Sound s = GContext.container.Resolve<ISoundService>()
.GetNewFishingSound(clip: _audioClips[audioName].Clip);
s.soundMainType = SoundMainType.Fishing;
s.audioSource.Play();
await System.Threading.Tasks.Task.Delay((int)(_audioClips[audioName].Clip.length * 1000));
s.ReturnPool();
}
private void PlayBGM()
{
GContext.Publish(new EventBGMSound(_audioAliases["BGM"]));
}
private void OnCollisionSound(string hash)
{
if (_sm.State != EInfiniteBuildingState.BlockFall || _collisionSounds.Contains(hash))
return;
_collisionSounds.Add(hash);
PlayAudio("BlockHit");
}
#endregion
#region FX
private readonly List<string> _fxNames = new List<string>()
{
"fx_infinitebuilding_cloud",
"fx_infinitebuilding_collapse",
"fx_infinitebuilding_reset",
"fx_infinitebuilding_replay",
"fx_infinitebuilding_fall",
"fx_infinitebuilding_fallperfact"
};
[SerializeField] private Dictionary<string, GameObject> _fxDic = new Dictionary<string, GameObject>();
private void GetFX()
{
foreach (string name in _fxNames)
{
_fxDic.Add(name.Split('_')[^1], transform.Find("Building999Main/fx/" + name).gameObject);
}
}
private void PlayFX(string name, Vector3 pos)
{
_fxDic[name].transform.position = pos;
_fxDic[name].SetActive(false);
_fxDic[name].SetActive(true);
}
private void MoveFx(string name, Vector3 pos)
{
_fxDic[name].transform.position = pos;
}
#endregion
#region State Machine Driver
private void Init_Enter()
{
//Debug.Log("Init_Enter!");
//Debug.Log($"<color=red>Init_Enter thread id: {Thread.CurrentThread.ManagedThreadId}</color>");
InitEnterAsync();
//GenerateBlock().ContinueWith(_ => _sm.SetState(EInfiniteBuildingState.PlayerCtrl));
}
private async System.Threading.Tasks.Task InitEnterAsync()
{
//Debug.Log($"<color=red>InitEnterAsync thread id: {Thread.CurrentThread.ManagedThreadId}</color>");
await _blockManager.RebuildBlocks();
_cam.Init(_focus, _cfg, _skyLoop, _data);
_deathWall.transform.position = _focus.position + Vector3.up * _cfg.deathWallOffset;
_crane.ResetPosition();
Block b = await _blockManager.GenerateBlock(_crane.transform.position + _cfg.blockSpawnOffset, true);
_blockManager.CurrentBlock = b;
_data.LastHangingBlock = b.Idx;
UpdateData();
_crane.AttachJoints(b);
if (_focus.position.y > _cfg.fxCloudAppearHeight)
PlayFX("cloud", _focus.position + _cfg.fxCloud);
_sm.SetState(EInfiniteBuildingState.PlayerCtrl);
}
private void Init_Exit()
{
//Debug.Log("Init_Exit!");
}
private void InitLoop_Enter()
{
//Debug.Log("InitLoop_Enter!");
//GenerateBlock().ContinueWith(_ => _sm.SetState(EInfiniteBuildingState.PlayerCtrl));
InitLoopEnterAsync();
}
private async System.Threading.Tasks.Task InitLoopEnterAsync()
{
// Debug.Log($"construction_state: {_EVConstructionState}");
// Debug.Log($"construction_lvl: {_data.Lvl}");
// Debug.Log($"retry_type: {_EVRetryType}");
// Debug.Log($"hook_count: {_playerData.GetEnergyRM()}");
// Debug.Log($"cost_cash: {_EVCost}");
// Debug.Log($"reward_hook: {_EVHookRewardGot}");
// Debug.Log($"reward_cash: {_EVCashRewardGot}");
// Debug.Log($"rating: {_EVRating}");
// Debug.Log($"combo_count: {_EVCombo}");
// Debug.Log($"cash_back: {_EVCashBack}");
#if AGG
using (var e = GEvent.GameEvent("infinite_construction"))
{
e.AddContent("construction_state", _EVConstructionState)
.AddContent("construction_lv", _data.Lvl)
.AddContent("retry_type", _EVRetryType)
.AddContent("hook_count", _playerData.GetEnergyRM())
.AddContent("cost_cash", _EVCost)
.AddContent("reward_hook", _EVHookRewardGot)
.AddContent("reward_cash", _EVCashRewardGot)
.AddContent("rating", _EVRating)
.AddContent("combo_count", _EVCombo)
.AddContent("cash_back", _EVCashBack);
}
#endif
var b = await _blockManager.GenerateBlock(_crane.transform.position + _cfg.blockSpawnOffset);
_blockManager.CurrentBlock = b;
_data.LastHangingBlock = b.Idx;
UpdateData();
_crane.AttachJoints(b);
_sm.SetState(EInfiniteBuildingState.PlayerCtrl);
}
private void InitLoop_Exit()
{
//Debug.Log("InitLoop_Exit!");
}
private void PlayerCtrl_Enter()
{
//Debug.Log("PlayerCtrl_Enter!");
//Debug.Log($"<color=red>Player Ctrl thread id: {Thread.CurrentThread.ManagedThreadId}</color>");
PlayerCtrlEnterAsync();
//Debug.Log(_crane.gameObject);
}
private async System.Threading.Tasks.Task PlayerCtrlEnterAsync()
{
await _crane.Descend();
_crane.Kick();
_mainPanel.ActivateBtns();
}
private void PlayerCtrl_Exit()
{
//Debug.Log("PlayerCtrl_Exit!");
_mainPanel.DeactivateBtns();
}
private void BlockFall_Enter()
{
//Debug.Log("BlockFall_Enter!");
//Debug.Log($"<color=red>Block Fall thread id: {Thread.CurrentThread.ManagedThreadId}</color>");
StartCoroutine(_crane.DropBlockAndRise());
_blockManager.CurrentBlock.Drop();
//_currentBlock.Drop();
//DestroyCountDown();
}
private void BlockFall_Exit()
{
//Debug.Log("BlockFall_Exit!");
_blockManager.ResetDestroyCountDown();
}
private void Success_Enter()
{
//Debug.Log("Success_Enter!");
SuccessEnterAsync();
}
private async System.Threading.Tasks.Task SuccessEnterAsync()
{
int newHeight = (int)_blockManager.CurrentBlock.WorldHeight;
int oldHeight = (int)_focus.position.y;
int deltaLvl = newHeight > oldHeight ? (int)_blockManager.CurrentBlock.Height : 0;
//_blockManager.CurrentBlock.Rb.position =
// new Vector2(_blockManager.CurrentBlock.Rb.position.x, _focus.position.y);
_blockManager.CurrentBlock.PlayFurnitureAnimation();
int combo = CountCombo();
int rating = GetRating();
bool isPerfect = _blockManager.TrySnap();
_EVCombo = combo;
_EVRating = rating;
if (isPerfect)
{
_ = PlayAudio("BlockPerfect");
PlayFX("fallperfact", _blockManager.CurrentBlock.transform.position + _cfg.fxPerfect);
_EVConstructionState = 2;
}
else
{
_EVConstructionState = 1;
}
float refundRatio = 0.0f;
if (combo >= 2)
refundRatio += Mathf.Min(combo - 1, _tables.TbConstructionInfiniteConfig.ComboReturnMaxCount) *
_tables.TbConstructionInfiniteConfig.ComboOnceReturnPoint;
if (rating != 0)
refundRatio += rating == 1
? _tables.TbConstructionInfiniteConfig.GoodReturnPoint
: _tables.TbConstructionInfiniteConfig.FantasticReturnPoint;
if (isPerfect)
refundRatio += _tables.TbConstructionInfiniteConfig.PerfectReturnPoint;
// Debug.Log($"<color=red>RefundRatio: {refundRatio}</color>");
_mainPanel.PlayRatingFx(rating);
_mainPanel.PlayComboFx(combo);
_EVCashBack = 0;
if (refundRatio != 0.0f)
{
int price = GetConstructionPrice();
int amount = (int)(refundRatio * price);
_EVCashBack = (ulong)amount;
_playerData.SetGold(_playerData.gold + (ulong)amount);
await _mainPanel.PlayCashFlyAnimation(amount);
}
_EVRetryType = 0;
_EVHookRewardGot = 0;
_EVCashRewardGot = 0;
_data.Step++;
if (await _mainPanel.UpdateUIWhenSuccess())
{
await _mainPanel.ReceiveReward();
}
if (newHeight > oldHeight)
_focus.position = new Vector3(_focus.position.x, _blockManager.CurrentBlock.WorldHeight, _focus.position.z);
_cam.FollowFocus();
_blockManager.AddCurrentBlock();
_blockManager.LockOrClearBlocks(true);
UpdateData(deltaLvl);
//leyuanniubi!!!
if (deltaLvl > 0)
{
GContext.Publish(new ConditionTypeEvent(ConditionType.ConstructionCount, deltaLvl));
GContext.container.Resolve<LeadboardData>().AwaitSetLvData();
}
_deathWall.transform.position += deltaLvl * Vector3.up;
MoveFx(name: "cloud", pos: _focus.position + _cfg.fxCloud);
_sm.SetState(EInfiniteBuildingState.InitLoop);
}
private void Success_Exit()
{
//Debug.Log("Success_Exit!");
}
private void Failure_Enter()
{
//Debug.Log("Failure_Enter!");
FailureEnterAsync();
}
private async System.Threading.Tasks.Task FailureEnterAsync()
{
_EVCombo = CountCombo(false);
_EVConstructionState = 0;
_EVRating = 0;
_EVCashBack = 0;
PlayAudio("Collapse");
CampSettlementPanel ui = (await UIManager.Instance.ShowUI(UITypes.CampSettlementPanel))
.GetComponent<CampSettlementPanel>();
ui.Init(_eventAggregator);
await _blockManager.RebuildAllBlocks();
_blockManager.LockOrClearBlocks();
}
private void Failure_Exit()
{
//Debug.Log("Failure_Exit!");
}
//private void BlockDestroy_Enter()
//{
// Debug.Log("BlockDestroy_Enter!");
// //UIManager.Instance.ShowUI(UITypes.CampSettlementPanel);
// EnterBlockDestroyAsync();
// //_sm.SetState(EInfiniteBuildingState.InitLoop);
//}
//private void BlockDestroy_Exit()
//{
// Debug.Log("BlockDestroy_Exit!");
//}
#endregion
}
public enum EInfiniteBuildingState
{
Default,
Init,
InitLoop,
PlayerCtrl,
BlockFall,
Success,
Failure
}
public class EventInfiniteBuildingRetry
{
}
public class EventInfiniteBuildingAlign
{
}
public class EventInfiniteBuildingBlockDeath
{
public BlockState stateBeforeDeath { get; set; }
public EventInfiniteBuildingBlockDeath(BlockState stateBeforeDeath)
{
this.stateBeforeDeath = stateBeforeDeath;
}
}
public class EventInfiniteBuildingConstruct
{
public ulong ConstructionCost;
public EventInfiniteBuildingConstruct(ulong cost)
{
ConstructionCost = cost;
}
}
public class EventInfiniteBuildingFail
{
}
public class EventInfiniteBuildingSucceed
{
}
public class EventInfiniteBuildingPlayAudio
{
public string AudioName { get; set; }
public EventInfiniteBuildingPlayAudio(string audioName)
{
AudioName = audioName;
}
}
public class EventInfiniteBuildingCollisionSound
{
public string Hash { get; set; }
public EventInfiniteBuildingCollisionSound(string hash)
{
Hash = hash;
}
}
public class EventInfiniteBuildingFirstCollision
{
public readonly Block block;
public EventInfiniteBuildingFirstCollision(Block b)
{
block = b;
}
}
public class EventInfiniteBuildingGetReward
{
public readonly int DropID;
public EventInfiniteBuildingGetReward(int dropID)
{
DropID = dropID;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1ed1a7b98cf4e12428de88bccd086c60
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using Unity.Mathematics;
using UnityEngine;
[CreateAssetMenu(fileName = "InfiniteBuildingConf",
menuName = "ScriptableObjects/InfiniteBuildingConf", order = 1)]
public class InfiniteBuildingConf : ScriptableObject
{
[Serializable]
public class HeightConfigData
{
public int LvlThresh;
public float craneHeightRise;
public float craneHeightDescend;
public float craneCycleTime;
public float cameraDepth = 20f;
}
[Header("General Debug Settings")]
public bool FreezeCrane = false;
public int NextBlockToSpawn = -1;
[Header("Block Generation Settings")]
public int blockDestroyDelay = 4000;//in miliseconds, 1/1000 second
public Vector2 craneAnchorOffset = new(0.2f, -0.5f);
public float blockAnchorCoefficient = 0.8f;
public Vector3 blockSpawnOffset = new(0, -3f, 0);
public float blockDriftOffset = 2f;
public float blockDestroyThreshAngle = 10f;//in deg
public bool maxDistanceOnly = true;
public bool hasAutoDistance = true;
public float blockRestingOffset = -5f;
public float blockDestroyOffset = -8f;
public float deathWallOffset = -3;
public float snapThresh = 0.5f;
public float blockDepth = 20f;
public float blockFreezeVelocity = 0.1f;
public float blockFreezeAngularVelocity = 0.1f;
public float blockFreezeAcc = 1f;
public float blockFreezeAngularAcc = 1f;
[Header("Crane Settings")]
//public float craneRiseTime = 0.5f;
//public List<HeightConfigData> heightSpecificConfig = new List<HeightConfigData>();
public float craneCycleHalfDistance = 5f;
public float craneLineThickness = 0.1f;
[Header("Camera Settings")]
public float skyLoopTriggerHeight = 1200f;
public float skyLoopOffsetDelta = 0.2f;
[Header("FX Settings")]
public Vector3 fxCollapse = -8f * Vector3.up;
public Vector3 fxCloud = -5f * Vector3.up;
public float fxCloudAppearHeight = 0f;
public Vector3 fxFall = Vector3.zero;
public Vector3 fxPerfect = Vector3.zero;
[Header("Furniture Animation")]
public float3 animationDurationRange = new float3(0.33f, 0.66f, 0.2f);
public Color glassColor = new Color(0.7735f, 0.4370f, 0.2298f, 1);
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 10329b288f550294e831527316fd68c6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,86 @@
using asap.core;
using cfg;
using GameCore;
using System.Collections.Generic;
using UnityEngine;
public class InfiniteBuildingData
{
public int Lvl, Step, StepLvl = 1, LastHangingBlock = -1;
public List<BlockRecord> Record = new List<BlockRecord>();
// private readonly TbConstructionUnits BlocksTable = GContext.container.Resolve<Tables>().TbConstructionUnits;
public int ConstructPrice => (int)
(GContext.container.Resolve<Tables>().TbMapData.DataList[^1].ConstrutionCost
* GContext.container.Resolve<Tables>().TbConstructionInfiniteConfig.CashMagList[Step]);
public struct BlockRecord
{
public readonly int ID;
public Vector2 Pos;
public readonly float Height => GContext.container.Resolve<Tables>().TbConstructionUnits[ID].Height;
public readonly string PrefabID => GContext.container.Resolve<Tables>().TbConstructionUnits[ID].Prefab;
public BlockRecord(int id = 0, Vector2 pos = default)
{
this.ID = id;
this.Pos = pos;
}
public BlockRecord(int id = 0, float x = 0, float y = 0)
{
this.ID = id;
Pos = new Vector2(x, y);
}
public readonly override string ToString() => $"{ID},{Pos.x},{Pos.y}";
}
private string Serialize()
{
var sb = new System.Text.StringBuilder();
sb.Append($"{Lvl},{Step},{StepLvl},{LastHangingBlock},");
foreach (BlockRecord node in Record)
sb.Append($"{node.ToString()},");
return sb.ToString().Trim(',');
}
public void Deserialize(string s)
{
string[] tokens = s.Split(',');
if (tokens == null || tokens.Length < 4 || tokens.Length % 3 != 1)
{
Debug.LogWarning($"string \"{s}\" cannot be deserialized.");
return;
}
Lvl = int.Parse(tokens[0]);
Step = int.Parse(tokens[1]);
StepLvl = int.Parse(tokens[2]);
LastHangingBlock = int.Parse(tokens[3]);
Record = new List<BlockRecord>();
for (int i = 4; i < tokens.Length; i+=3)
{
Record.Add(new BlockRecord(int.Parse(tokens[i]),
float.Parse(tokens[i + 1]), float.Parse(tokens[i + 2])));
//Debug.Log($"{int.Parse(tokens[i])}, {float.Parse(tokens[i + 1])}, {float.Parse(tokens[i + 2])}");
}
}
public void UploadData()
{
string s = Serialize();
//Debug.Log("Upload!!!!!!!!!!!!!!");
//Debug.Log(s);
GContext.container.Resolve<PlayerData>().InfiniteBuildingData = s;
PlayFabMgr.Instance.UpdateUserDataValue("InfiniteBuildingData", s);
}
public void DownloadData(string s)
{
Deserialize(s);
}
#if UNITY_EDITOR
public void PrintSelf()
{
Debug.Log($"Lvl: {Lvl}");
Debug.Log($"Step: {Step}");
Debug.Log($"StepLvl: {StepLvl}");
foreach (BlockRecord node in Record)
{
Debug.Log($"node: {node.PrefabID}, {node.Pos}");
}
}
#endif
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 04013307478c7bd43a953e3a332b768f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3cc5cea7e748f4fe8814954cc54a90d6
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,46 @@
using UnityEngine;
using UnityEditor;
public class ConvertFromArtPrefabToGamePrefab : EditorWindow
{
[MenuItem("Tools/Creat IB Prefabs")]
public static void ConvertPrefabs()
{
Object[] artPrefabs = Selection.objects;
PhysicsMaterial2D pm = AssetDatabase.LoadAssetAtPath<PhysicsMaterial2D>("Assets/ABPackage/InfiniteBuildingPrefabs/PhysicMat_Block.physicsMaterial2D");
string dest = "Assets/ABPackage/InfiniteBuildingPrefabs/";
foreach (Object artGO in artPrefabs)
{
string assetPath = AssetDatabase.GetAssetPath(artGO);
GameObject artPrefab = AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
GameObject artInstance = PrefabUtility.InstantiatePrefab(artPrefab) as GameObject;
Debug.Log(assetPath);
if (artInstance == null)
continue;
string artName = artPrefab.name;
BoxCollider artBc = artInstance.GetComponent<BoxCollider>();
Vector3 colliderSize = artBc.size;
Vector3 colliderCenter = artBc.center;
DestroyImmediate(artBc, true);
GameObject go = new GameObject();
go.name = artName;
go.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);
go.transform.localScale = Vector3.one;
artInstance.transform.parent = go.transform;
artInstance.transform.position = Vector3.zero;
Rigidbody2D rb = go.AddComponent<Rigidbody2D>();
rb.drag = 4;
rb.angularDrag = 1;
BoxCollider2D bc = go.AddComponent<BoxCollider2D>();
bc.sharedMaterial = pm;
bc.isTrigger = false;
bc.offset = new Vector2(-colliderCenter.x, colliderCenter.z);
bc.size = new Vector2(colliderSize.x, colliderSize.z);
go.AddComponent<Block>();
PrefabUtility.SaveAsPrefabAsset(go, dest + go.name + ".prefab");
AssetDatabase.SaveAssets();
Debug.Log($"Converted colliders in prefab: {go.name}");
DestroyImmediate(go, true);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fc6578f9d1b69ad4cb9e685605e185dc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,18 @@
{
"name": "InfiniteBuilding.Editor",
"rootNamespace": "",
"references": [
"GUID:f720a012c494ab7478b1926183db234f"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 6ea8c55f787d445a8bcb69e94dd0cf9b
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,18 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class InfiniteBuildingFSM
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b13f87b4a1981ac4f94999f3c421c760
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,18 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class InfiniteBuildingUI : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5f188429e27e05d4a826fb954bd453b6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: