From 935e207bdf14484c87b52a1d4a790ce2027770bb Mon Sep 17 00:00:00 2001 From: Tirlititi Date: Thu, 14 Sep 2023 19:19:33 +0200 Subject: [PATCH] Event script API and ElseThread is .seq --- .../Scripts/EventEngine/Utils/CalcStack.cs | 22 +- Assembly-CSharp/Global/EBin.cs | 523 ++++++++++-------- Assembly-CSharp/Global/EMinigame.cs | 4 +- .../Event/Engine/EventEngine.DoEventCode.cs | 407 +++++++++----- .../Event/Engine/EventEngine.MoveToward.cs | 18 +- .../Global/Event/Engine/EventEngine.cs | 51 +- Assembly-CSharp/Global/Event/EventState.cs | 21 + .../Global/Field/FieldRainRenderer.cs | 5 +- Assembly-CSharp/Global/Field/FieldSPSConst.cs | 30 +- .../Global/Field/FieldSPSSystem.cs | 122 ++-- .../Global/Honolulu/HonoluluFieldMain.cs | 2 + Assembly-CSharp/Global/PARTY_DATA.cs | 2 +- Assembly-CSharp/Global/PartySettingUI.cs | 25 +- Assembly-CSharp/Global/SFX/SFX.cs | 2 +- Assembly-CSharp/Global/SFXRender/SFXRender.cs | 32 +- Assembly-CSharp/Global/Walk/WalkMesh.cs | 19 + .../Global/World/WorldRainRenderer.cs | 5 +- .../Global/battle/Result/BattleResultUI.cs | 1 - .../Global/ff9/State/FF9StateGlobal.cs | 3 +- Assembly-CSharp/Global/ff9/ff9.cs | 1 + Assembly-CSharp/Global/ff9play.cs | 18 + .../Application/SmoothFrameUpdater_Battle.cs | 3 +- .../Application/SmoothFrameUpdater_Field.cs | 1 + .../Application/SmoothFrameUpdater_World.cs | 1 + .../Battle/Calculator/BattleCalculator.cs | 4 +- .../Memoria/Battle/SFX/BattleActionCode.cs | 1 + .../Memoria/Battle/SFX/BattleActionThread.cs | 8 +- Assembly-CSharp/Memoria/Battle/SFX/SFXData.cs | 87 ++- .../Memoria/Battle/SFX/SFXDataMesh.cs | 18 +- .../Battle/SFX/UnifiedBattleSequencer.cs | 14 +- .../Memoria/Data/Items/ShopItems.cs | 9 +- Assembly-CSharp/NCalc/NCalcUtility.cs | 2 + 32 files changed, 913 insertions(+), 548 deletions(-) diff --git a/Assembly-CSharp/Assets/Sources/Scripts/EventEngine/Utils/CalcStack.cs b/Assembly-CSharp/Assets/Sources/Scripts/EventEngine/Utils/CalcStack.cs index 1955ee0fb..aaa00a788 100644 --- a/Assembly-CSharp/Assets/Sources/Scripts/EventEngine/Utils/CalcStack.cs +++ b/Assembly-CSharp/Assets/Sources/Scripts/EventEngine/Utils/CalcStack.cs @@ -7,10 +7,8 @@ public class CalcStack { public Boolean push(Int32 arg0) { - if (this.topOfStackID >= (Int32)this.stack.Length - 1) - { + if (this.topOfStackID >= this.stack.Length - 1) return false; - } this.stack[this.topOfStackID] = arg0; this.topOfStackID++; return true; @@ -20,7 +18,7 @@ public Boolean pop(out Int32 output) { if (this.topOfStackID == 0) { - Log.Error($"[{nameof(CalcStack)}.{nameof(pop)}]if (this.topOfStackID == 0)"); + Log.Error($"[{nameof(CalcStack)}.{nameof(pop)}] this.topOfStackID == 0"); output = default; return false; } @@ -31,10 +29,8 @@ public Boolean pop(out Int32 output) public Boolean advanceTopOfStack() { - if (this.topOfStackID >= (Int32)this.stack.Length - 1) - { + if (this.topOfStackID >= this.stack.Length - 1) return false; - } this.topOfStackID++; return true; } @@ -42,19 +38,15 @@ public Boolean advanceTopOfStack() public Boolean retreatTopOfStack() { if (this.topOfStackID == 0) - { return false; - } this.topOfStackID--; return true; } public void emptyCalcStack() { - for (Int32 i = 0; i < (Int32)this.stack.Length; i++) - { + for (Int32 i = 0; i < this.stack.Length; i++) this.stack[i] = 0; - } this.topOfStackID = 0; } @@ -68,10 +60,8 @@ public Int32 getValueAtOffset(Int32 offset) return this.stack[this.topOfStackID + offset]; } - private const Int32 stackSize = 16; - - private Int32[] stack = new Int32[16]; - + private const Int32 STACK_SIZE = 16; + private Int32[] stack = new Int32[STACK_SIZE]; private Int32 topOfStackID; } } diff --git a/Assembly-CSharp/Global/EBin.cs b/Assembly-CSharp/Global/EBin.cs index ba50f9960..dabd40cca 100644 --- a/Assembly-CSharp/Global/EBin.cs +++ b/Assembly-CSharp/Global/EBin.cs @@ -1,7 +1,10 @@ using System; -using Assets.Sources.Scripts.EventEngine.Utils; using System.IO; +using System.Linq; +using Assets.Sources.Scripts.EventEngine.Utils; +using FF9; using Memoria; +using Memoria.Data; using Memoria.Assets; using UnityEngine; @@ -357,7 +360,7 @@ public Int32 expr() _exprLoop = true; while (_exprLoop) { - SByte b = (SByte)s1.getByteIP(); + Byte varOperation = s1.getByteIP(); if (s1.sid != 3 || s1.ip != 110) { if (FF9StateSystem.Settings.IsFastTrophyMode) @@ -379,89 +382,165 @@ public Int32 expr() } EMinigame.ChanbaraBonusPoints(s1, this); EMinigame.SetViviSpeed(s1, this); - if (b < 0) + s1.ip++; + if (varOperation >= 0x80) { - s1.ip++; - _v0 = expr_varSpec(b); - _s7.push(_v0); + if (varOperation == 0xD3) + { + expr_customSubCommand(); + } + else + { + _v0 = expr_varSpec(varOperation); + _s7.push(_v0); + } } else { - s1.ip++; - expr_jumpToSubCommand((op_binary) b); + expr_jumpToSubCommand((op_binary)varOperation); } } return 0; } - private Int32 expr_varSpec(Int32 arg0) + private void expr_customSubCommand() { - _v0 = (arg0 & 3); - _v0 <<= 26; - int a1 = (arg0 & 28); - a1 <<= 27; - _v0 |= a1; - a1 = s1.getByteIP(); - arg0 &= 32; + flexible_varfunc commandId = (flexible_varfunc)s1.getUShortIP(); + s1.ip += 2; + Byte argCount = s1.getByteIP(); + s1.ip++; + Int32[] args = new Int32[argCount]; + for (Int32 i = argCount - 1; i >= 0; i--) + args[i] = EvaluateValueExpression(); + _v0 = 0; + switch (commandId) + { + case flexible_varfunc.ITEM_REGULAR_TO_ID: + _v0 = ff9item.GetItemIdFromRegularId((RegularItem)args[0]); + break; + case flexible_varfunc.ITEM_ID_TO_REGULAR: + _v0 = (Int32)ff9item.GetRegularIdFromItemId(args[0]); + break; + case flexible_varfunc.ITEM_KEY_TO_ID: + _v0 = ff9item.GetItemIdFromImportantId(args[0]); + break; + case flexible_varfunc.ITEM_ID_TO_KEY: + _v0 = (Int32)ff9item.GetImportantIdFromItemId(args[0]); + break; + case flexible_varfunc.ITEM_CARD_TO_ID: + _v0 = ff9item.GetItemIdFromCardId((TetraMasterCardId)args[0]); + break; + case flexible_varfunc.ITEM_ID_TO_CARD: + _v0 = (Int32)ff9item.GetCardIdFromItemId(args[0]); + break; + case flexible_varfunc.ABILITY_ACTIVE_TO_ID: + _v0 = ff9abil.GetAbilityIdFromActiveAbility((BattleAbilityId)args[0]); + break; + case flexible_varfunc.ABILITY_ID_TO_ACTIVE: + _v0 = (Int32)ff9abil.GetActiveAbilityFromAbilityId(args[0]); + break; + case flexible_varfunc.ABILITY_SUPPORT_TO_ID: + _v0 = ff9abil.GetAbilityIdFromSupportAbility((SupportAbility)args[0]); + break; + case flexible_varfunc.ABILITY_ID_TO_SUPPORT: + _v0 = (Int32)ff9abil.GetSupportAbilityFromAbilityId(args[0]); + break; + case flexible_varfunc.PARTY_MEMBER: + _v0 = (Int32)ff9play.CharacterIDToOldIndex(FF9StateSystem.Common.FF9.party.GetCharacterId(args[0])); + break; + case flexible_varfunc.ITEM_FULL_COUNT: + _v0 = ff9item.FF9Item_GetAnyCount((RegularItem)args[0]); + break; + case flexible_varfunc.PLAYER_EQUIP: + _v0 = (Int32)(FF9StateSystem.Common.FF9.GetPlayer(ff9play.CharacterOldIndexToID((CharacterOldIndex)args[0]))?.equip[args[1]] ?? RegularItem.NoItem); + break; + case flexible_varfunc.PLAYER_LEVEL: + _v0 = FF9StateSystem.Common.FF9.GetPlayer(ff9play.CharacterOldIndexToID((CharacterOldIndex)args[0]))?.level ?? 0; + break; + case flexible_varfunc.PLAYER_EXP: + _v0 = (Int32)(FF9StateSystem.Common.FF9.GetPlayer(ff9play.CharacterOldIndexToID((CharacterOldIndex)args[0]))?.exp ?? 0); + break; + case flexible_varfunc.PLAYER_EXP_REQ: + if (args[0] <= 0) + _v0 = 0; + else if (args[0] > ff9level.LEVEL_COUNT) + _v0 = (Int32)9999999u; + else + _v0 = (Int32)ff9level.CharacterLevelUps[args[0] - 1].ExperienceToLevel; + break; + case flexible_varfunc.PLAYER_ABILITY_LEARNT: + { + PLAYER player = FF9StateSystem.Common.FF9.GetPlayer(ff9play.CharacterOldIndexToID((CharacterOldIndex)args[0])); + if (player == null || !ff9abil.FF9Abil_HasAp(new Character(player))) + break; + Int32 abilIndex = ff9abil.FF9Abil_GetIndex(player, args[1]); + if (abilIndex < 0) + break; + _v0 = player.pa[abilIndex] >= ff9abil._FF9Abil_PaData[player.PresetId][abilIndex].Ap ? 1 : 0; + if (_v0 == 0 && args[2] != 0) + for (Int32 i = 0; i < 5; i++) + if (player.equip[i] != RegularItem.NoItem && ff9item._FF9Item_Data[player.equip[i]].ability.Any(id => id == args[1])) + _v0 = 1; + break; + } + case flexible_varfunc.PLAYER_SUPPORT_ENABLED: + { + PLAYER player = FF9StateSystem.Common.FF9.GetPlayer(ff9play.CharacterOldIndexToID((CharacterOldIndex)args[0])); + _v0 = player != null && player.saExtended.Contains((SupportAbility)args[1]) ? 1 : 0; + break; + } + case flexible_varfunc.SHOP_ITEM: + _v0 = ff9buy.ShopItems.ContainsKey(args[0]) && ff9buy.ShopItems[args[0]].ItemIds.Contains((RegularItem)args[1]) ? 1 : 0; + break; + case flexible_varfunc.SHOP_SYNTH: + _v0 = ff9mix.SynthesisData.ContainsKey(args[1]) && ff9mix.SynthesisData[args[1]].Shops.Contains(args[0]) ? 1 : 0; + break; + } + expr_Push_v0_Int24(); + } + + private Int32 expr_varSpec(Int32 varOperation) + { + _v0 = (varOperation & 3) << 26 | (varOperation & 0x1C) << 27; + Int32 varArrayIndex = s1.getByteIP(); s1.ip++; - if (arg0 != 0) + if ((varOperation & 0x20) != 0) { - _v0 |= a1; - a1 = s1.getByteIP(); + _v0 |= varArrayIndex; + varArrayIndex = s1.getByteIP(); s1.ip++; - a1 <<= 8; + varArrayIndex <<= 8; } - _v0 |= a1; + _v0 |= varArrayIndex; return _v0; } - public Int32 setVarManually(Int32 var, Int32 value) + public Int32 setVarManually(Int32 varOperation, Int32 value) { - Int32 num = var & 255; - Int32 num2 = num & 3; - num2 <<= 26; - Int32 num3 = num & 28; - num3 <<= 27; - num2 |= num3; - Int32 num4 = (var & 65280) >> 8; - num &= 32; - if (num != 0) - { - num2 |= num4; - num4 = (var & 16711680) >> 16; - num4 <<= 8; - } - num2 |= num4; - _s7.push(num2); + Int32 varCode = (varOperation & 3) << 26 | (varOperation & 0x1C) << 27; + Int32 varArrayIndex = (varOperation >> 8) & 0xFF; + if ((varOperation & 0x20) != 0) + varArrayIndex |= (varOperation >> 8) & 0xFF00; + varCode |= varArrayIndex; + _s7.push(varCode); SetVariableValue(value); - num3 = encodeTypeAndVarClass(7); - num2 |= num3; - _s7.push(num2); + varCode |= encodeTypeAndVarClass(7); + _s7.push(varCode); - return num2; + return varCode; } - public Int32 getVarManually(Int32 var) + public Int32 getVarManually(Int32 varOperation) { CalcStack calcStack = _s7; _s7 = _tempStack; _s7.emptyCalcStack(); - Int32 num = var & 255; - Int32 num2 = num & 3; - num2 <<= 26; - Int32 num3 = num & 28; - num3 <<= 27; - num2 |= num3; - Int32 num4 = (var & 65280) >> 8; - num &= 32; - if (num != 0) - { - num2 |= num4; - num4 = (var & 16711680) >> 16; - num4 <<= 8; - } - num2 |= num4; - _s7.push(num2); + Int32 varCode = (varOperation & 3) << 26 | (varOperation & 0x1C) << 27; + Int32 varArrayIndex = (varOperation & 0xFF00) >> 8; + if ((varOperation & 0x20) != 0) + varArrayIndex |= (varOperation >> 8) & 0xFF00; + varCode |= varArrayIndex; + _s7.push(varCode); Int32 result = EvaluateValueExpression(); _s7 = calcStack; return result; @@ -1024,13 +1103,7 @@ private void expr_jumpToSubCommand(op_binary arg0) case op_binary.B_KEYON: // B_KEYON = 79 { VoicePlayer.scriptRequestedButtonPress = true; - Int32 keyOn = (Int32)ETb.KeyOn(); - _v0 = EvaluateValueExpression(); - _v0 &= keyOn; - if (s1.sid == 5) - { - } - _v0 = ((0 >= Mathf.Abs(_v0)) ? 0 : 1); + _v0 = (Mathf.Abs(EvaluateValueExpression() & ETb.KeyOn()) <= 0) ? 0 : 1; expr_Push_v0_Int24(); break; } @@ -1050,19 +1123,13 @@ private void expr_jumpToSubCommand(op_binary arg0) } case op_binary.B_KEYOFF: { - Int32 keyOff = (Int32)ETb.KeyOff(); - _v0 = EvaluateValueExpression(); - _v0 &= keyOff; - _v0 = ((0 >= Mathf.Abs(_v0)) ? 0 : 1); + _v0 = (Mathf.Abs(EvaluateValueExpression() & ETb.KeyOff()) <= 0) ? 0 : 1; expr_Push_v0_Int24(); break; } case op_binary.B_KEY: { - Int32 padReadE = (Int32)_eTb.PadReadE(); - _v0 = EvaluateValueExpression(); - _v0 &= padReadE; - _v0 = ((0 >= Mathf.Abs(_v0)) ? 0 : 1); + _v0 = (Mathf.Abs(EvaluateValueExpression() & _eTb.PadReadE()) <= 0) ? 0 : 1; expr_Push_v0_Int24(); break; } @@ -1070,19 +1137,11 @@ private void expr_jumpToSubCommand(op_binary arg0) { Int32 t3 = EvaluateValueExpression(); _v0 = EvaluateValueExpression(); - Obj gCur = _eventEngine.gCur; - Actor actor = (Actor)gCur; + Actor actor = (Actor)_eventEngine.gCur; if (actor.fieldMapActorController == null) { } - Single num = actor.pos[0]; - Single num2 = actor.pos[2]; - num = _v0 - num; - num2 = t3 - num2; - Single floatAngle = angleAsm(num, num2); - Int32 num3 = ConvertFloatAngleToFixedPoint(floatAngle); - _v0 = 0; - _v0 = num3; + _v0 = ConvertFloatAngleToFixedPoint(angleAsm(_v0 - actor.pos[0], t3 - actor.pos[2])); _v0 <<= 20; _v0 >>= 24; expr_Push_v0_Int24(); @@ -1092,14 +1151,8 @@ private void expr_jumpToSubCommand(op_binary arg0) { Int32 t3 = EvaluateValueExpression(); _v0 = EvaluateValueExpression(); - Obj gCur = _eventEngine.gCur; - Actor actor = (Actor)gCur; - Single x = actor.pos[0]; - Single z = actor.pos[2]; - x = _v0 - x; - z = t3 - z; - var y = 0; - _v0 = (Int32)distance(x, y, z); + Actor actor = (Actor)_eventEngine.gCur; + _v0 = (Int32)distance(_v0 - actor.pos[0], 0, t3 - actor.pos[2]); expr_Push_v0_Int24(); break; } @@ -1207,7 +1260,7 @@ private void expr_jumpToSubCommand(op_binary arg0) Int32 a0 = s1.getByteIP(); s1.ip++; _v0 = _eventEngine.GetSysvar(a0); - a0 = 0x3FFFFFF; + a0 = 0x3FFFFFF; // 26 bit (unsigned?) a0 = _v0 & a0; int a1 = encodeTypeAndVarClass(7); a0 |= a1; @@ -1227,7 +1280,7 @@ private void expr_jumpToSubCommand(op_binary arg0) { Int32 a0 = s1.getIntIP(); s1.ip += 4; - a0 &= 0x3FFFFFF; // 26 bit + a0 &= 0x3FFFFFF; // 26 bit (unsigned?) int a1 = encodeTypeAndVarClass(7); a0 |= a1; _s7.push(a0); @@ -1396,16 +1449,17 @@ public Int32 commandDefault() public Int32 commandDefault2() { - Int32 ip = s1.ip; _v0 = _eventEngine.DoEventCode(); _s2 = _v0; - Int32 a0 = _eventEngine.gArgUsed; - _nextCodeIndex = s1.ip; - s1.ip = ip; - a0 = ((0 >= a0) ? 0 : 1); - a0 ^= 1; - _nextCodeIndex -= a0; - s1.ip = _nextCodeIndex; + if (_eventEngine.gArgUsed > 0) + { + _nextCodeIndex = s1.ip; + } + else + { + _nextCodeIndex = s1.ip - 1; + s1.ip = _nextCodeIndex; + } return 0; } @@ -1623,57 +1677,72 @@ public Int32 CollisionAngle(PosObj po, PosObj pot, Single myrot) public Int32 EvaluateValueExpression() { _s7.pop(out var t0); - Int32 valType = getTypeAndVarClass(t0); - Int32 cls = getVarClass(t0); - switch ((VariableSource)cls) + VariableType varType = (VariableType)((getTypeAndVarClass(t0) >> 3) & 7); + VariableSource cls = (VariableSource)getVarClass(t0); + switch (cls) { case VariableSource.Global: - { - int ofs = (t0 & 65535); - return GetVariableValueInternal(FF9StateSystem.EventState.gEventGlobal, ofs, valType, 0); - } + return GetVariableValueInternal(FF9StateSystem.EventState.gEventGlobal, t0 & 0xFFFF, varType, 0); case VariableSource.Map: - { - int ofs = (t0 & 65535); - return GetVariableValueInternal(_eventEngine.GetMapVar(), ofs, valType, 0); - } + return GetVariableValueInternal(_eventEngine.GetMapVar(), t0 & 0xFFFF, varType, 0); case VariableSource.Instance: - { - int ofs = (t0 & 65535); - return GetVariableValueInternal(_instance, ofs, valType, _instanceVOfs); - } + return GetVariableValueInternal(_instance, t0 & 0xFFFF, varType, _instanceVOfs); + case VariableSource.Null: + if (varType == VariableType.SBit) + return GetMemoriaCustomVariable((memoria_variable)(t0 & 0xFFFF)); + return 0; case VariableSource.Object: - { - cls = t0 >> 8; - cls &= 255; - Obj objUID = _eventEngine.GetObjUID(cls); - int type = (t0 & 255); - _v0 = getvobj(objUID, type); - return _v0; - } + _v0 = getvobj(_eventEngine.GetObjUID((t0 >> 8) & 0xFF), t0 & 0xFF); + return _v0; case VariableSource.System: - { - cls = (t0 & 255); - _v0 = _eventEngine.GetSysList(cls); + _v0 = _eventEngine.GetSysList(t0 & 0xFF); return _v0; - } case VariableSource.Member: - { - t0 <<= 6; - int type = t0 >> 6; - _v0 = getvobj(_eventEngine.gMemberTarget, type); + _v0 = getvobj(_eventEngine.gMemberTarget, (t0 << 6) >> 6); return _v0; - } case VariableSource.Int26: - { - t0 <<= 6; - _v0 = t0 >> 6; + _v0 = (t0 << 6) >> 6; return _v0; - } } return 0; } + private Int32 GetMemoriaCustomVariable(memoria_variable varCode) + { + switch (varCode) + { + case memoria_variable.TETRA_MASTER_WIN: + return FF9StateSystem.MiniGame.SavedData.sWin; + case memoria_variable.TETRA_MASTER_LOSS: + return FF9StateSystem.MiniGame.SavedData.sLose; + case memoria_variable.TETRA_MASTER_DRAW: + return FF9StateSystem.MiniGame.SavedData.sDraw; + case memoria_variable.TETRA_MASTER_POINTS: + return QuadMistDatabase.MiniGame_GetPlayerPoints(); + case memoria_variable.TETRA_MASTER_RANK: + return QuadMistDatabase.MiniGame_GetCollectorLevel(); + case memoria_variable.TREASURE_HUNTER_POINTS: + return FF9StateSystem.EventState.GetTreasureHunterPoints(); + } + return 0; + } + + private void SetMemoriaCustomVariable(memoria_variable varCode, Int32 val) + { + switch (varCode) + { + case memoria_variable.TETRA_MASTER_WIN: + FF9StateSystem.MiniGame.SavedData.sWin = (Int16)val; + break; + case memoria_variable.TETRA_MASTER_LOSS: + FF9StateSystem.MiniGame.SavedData.sLose = (Int16)val; + break; + case memoria_variable.TETRA_MASTER_DRAW: + FF9StateSystem.MiniGame.SavedData.sDraw = (Int16)val; + break; + } + } + private Int32 getvobj(Obj obj, Int32 type) { Int32 result; @@ -1770,62 +1839,35 @@ private Single distance(Single x, Single y, Single z) return Mathf.Sqrt(x * x + y * y + z * z); } - public Int32 GetVariableValueInternal(Byte[] buffer, Int32 ofs, Int32 type, Int32 bufferOffset = 0) + public Int32 GetVariableValueInternal(Byte[] buffer, Int32 ofs, VariableType type, Int32 bufferOffset = 0) { - _v0 = (type & 56) >> 3; - switch ((VariableType)_v0) + switch (type) { case VariableType.SBit: case VariableType.Bit: { - _v0 = ofs >> 3; // (767 bit >> 3) == (767 bit / 8) == 95 byte - Int32 a0 = (SByte)buffer[_v0 + bufferOffset]; - _v0 = (ofs & 7); // (767 bit & 7) == 7 bit - a0 >>= _v0; // (7 bit >> 7) => 1 bit - _v0 = (a0 & 1); // (1 bit & 1) => result + Byte bitFlags = buffer[(ofs >> 3) + bufferOffset]; // (767 bit >> 3) == (767 bit / 8) == 95 byte + _v0 = (bitFlags >> (ofs & 7)) & 1; // (1 bit & 1) => result return _v0; } case VariableType.Int24: case VariableType.UInt24: - { - _v0 = (SByte)buffer[ofs + 2 + bufferOffset]; - int a1 = buffer[ofs + 1 + bufferOffset]; - _v0 = (_v0 << 8 | a1); - a1 = buffer[ofs + bufferOffset]; - _v0 <<= 8; - _v0 |= a1; + _v0 = buffer[ofs + bufferOffset] | (buffer[ofs + 1 + bufferOffset] << 8) | ((SByte)buffer[ofs + 2 + bufferOffset] << 16); return _v0; - } case VariableType.SByte: - { _v0 = (SByte)buffer[ofs + bufferOffset]; return _v0; - } case VariableType.Byte: - { _v0 = buffer[ofs + bufferOffset]; return _v0; - } case VariableType.Int16: - { - _v0 = (SByte)buffer[ofs + 1 + bufferOffset]; - Int32 a0 = buffer[ofs + bufferOffset]; - _v0 <<= 8; - _v0 |= a0; + _v0 = buffer[ofs + bufferOffset] | ((SByte)buffer[ofs + 1 + bufferOffset] << 8); return _v0; - } case VariableType.UInt16: - { - _v0 = buffer[ofs + 1 + bufferOffset]; - Int32 a0 = buffer[ofs + bufferOffset]; - _v0 <<= 8; - _v0 |= a0; + _v0 = buffer[ofs + bufferOffset] | (buffer[ofs + 1 + bufferOffset] << 8); return _v0; - } default: - { return 0; - } } } @@ -1848,95 +1890,66 @@ public Int32 SetVariableValue(Int32 arg0) { _s7.pop(out var t0); Int32 varValue = arg0; - Int32 varType = t0 >> 26; - switch ((VariableSource)(varType & 7)) + VariableType varType = (VariableType)((getTypeAndVarClass(t0) >> 3) & 7); + VariableSource cls = (VariableSource)getVarClass(t0); + switch (cls) { case VariableSource.Global: - { - int ofs = (t0 & 65535); - SetVariableValueInternal(FF9StateSystem.EventState.gEventGlobal, ofs, varType, varValue, 0); + SetVariableValueInternal(FF9StateSystem.EventState.gEventGlobal, t0 & 0xFFFF, varType, varValue, 0); break; - } case VariableSource.Map: - { - int ofs = (t0 & 65535); - SetVariableValueInternal(_eventEngine.GetMapVar(), ofs, varType, varValue, 0); + SetVariableValueInternal(_eventEngine.GetMapVar(), t0 & 0xFFFF, varType, varValue, 0); break; - } case VariableSource.Instance: - { - int ofs = (t0 & 65535); - SetVariableValueInternal(_instance, ofs, varType, varValue, _instanceVOfs); + SetVariableValueInternal(_instance, t0 & 0xFFFF, varType, varValue, _instanceVOfs); + break; + case VariableSource.Null: + if (varType == VariableType.SBit) + SetMemoriaCustomVariable((memoria_variable)(t0 & 0xFFFF), varValue); break; - } case VariableSource.System: - { - Int32 a0 = (t0 & 255); - int value = varValue; - _eventEngine.SetSysList(a0, value); + _eventEngine.SetSysList(t0 & 0xFF, varValue); break; - } case VariableSource.Member: - { - int type = (t0 & 255); - varType = varValue; - _eventEngine.putvobj(_eventEngine.gMemberTarget, type, varType); + _eventEngine.putvobj(_eventEngine.gMemberTarget, t0 & 0xFF, varValue); break; - } } return 0; } - public Int32 SetVariableValueInternal(Byte[] buffer, Int32 ofs, Int32 type, Int32 value, Int32 bufferOffset = 0) + public Int32 SetVariableValueInternal(Byte[] buffer, Int32 ofs, VariableType type, Int32 value, Int32 bufferOffset = 0) { - _v0 = (type & 56) >> 3; - switch ((VariableType)_v0) + switch (type) { case VariableType.SBit: case VariableType.Bit: - { - _v0 = (ofs & 7); - Int32 num = ofs >> 3; - int a1 = (SByte)buffer[num + bufferOffset]; - Int32 a2 = 1; - a2 <<= _v0; - if (value == 0) - { - a2 ^= 255; - a1 &= a2; - buffer[num + bufferOffset] = (Byte)a1; - } - else - { - a1 |= a2; - buffer[num + bufferOffset] = (Byte)a1; - } - break; - } + { + Int32 byteIndex = (ofs >> 3) + bufferOffset; + if (value == 0) + buffer[byteIndex] &= (Byte)~(1 << (ofs & 7)); + else + buffer[byteIndex] |= (Byte)(1 << (ofs & 7)); + break; + } + case VariableType.Int24: case VariableType.UInt24: - { if (EventHUD.CurrentHUD == MinigameHUD.JumpingRope && Configuration.Hacks.Enabled && (ofs == 43 || ofs == 59)) value = value - 1 + Configuration.Hacks.RopeJumpingIncrement; - - buffer[ofs + bufferOffset] = (Byte)(value & 255); - buffer[ofs + 1 + bufferOffset] = (Byte)((value & 65280) >> 8); - buffer[ofs + 2 + bufferOffset] = (Byte)((value & 16711680) >> 16); + buffer[ofs + bufferOffset] = (Byte)(value & 0xFF); + buffer[ofs + 1 + bufferOffset] = (Byte)((value >> 8) & 0xFF); + buffer[ofs + 2 + bufferOffset] = (Byte)((value >> 16) & 0xFF); break; - } + case VariableType.SByte: case VariableType.Byte: - { buffer[ofs + bufferOffset] = (Byte)value; break; - } case VariableType.Int16: case VariableType.UInt16: - { - buffer[ofs + bufferOffset] = (Byte)(value & 255); - buffer[ofs + 1 + bufferOffset] = (Byte)((value & 65280) >> 8); + buffer[ofs + bufferOffset] = (Byte)(value & 0xFF); + buffer[ofs + 1 + bufferOffset] = (Byte)((value >> 8) & 0xFF); break; - } } return 0; } @@ -2271,7 +2284,52 @@ public enum event_code_binary BAWAITALL, BAWAIT, BARANGE, - BAVISIBLE + BAVISIBLE, + // Custom Memoria codes + PLAYER_EQUIP, + PLAYER_LEVEL, + PLAYER_EXP, + SHOP_ITEM, + SHOP_SYNTH, + MOVE_EX, + TURN_OBJ_EX, + AANIM_EX, + } + + public enum flexible_varfunc : ushort + { + // Custom Memoria codes + ITEM_REGULAR_TO_ID, + ITEM_ID_TO_REGULAR, + ITEM_KEY_TO_ID, + ITEM_ID_TO_KEY, + ITEM_CARD_TO_ID, + ITEM_ID_TO_CARD, + ABILITY_ACTIVE_TO_ID, + ABILITY_ID_TO_ACTIVE, + ABILITY_SUPPORT_TO_ID, + ABILITY_ID_TO_SUPPORT, + PARTY_MEMBER, + ITEM_FULL_COUNT, + PLAYER_EQUIP, + PLAYER_LEVEL, + PLAYER_EXP, + PLAYER_EXP_REQ, + PLAYER_ABILITY_LEARNT, + PLAYER_SUPPORT_ENABLED, + SHOP_ITEM, + SHOP_SYNTH, + } + + public enum memoria_variable : ushort + { + // Custom Memoria codes + TETRA_MASTER_WIN, + TETRA_MASTER_LOSS, + TETRA_MASTER_DRAW, + TETRA_MASTER_POINTS, + TETRA_MASTER_RANK, + TREASURE_HUNTER_POINTS, } public enum op_binary @@ -2398,7 +2456,7 @@ public enum op_binary B_CONST = 125, B_CONST4 = 126, B_EXPR_END = 127, - B_VAR = 192 + B_VAR = 0xC0 } public enum VariableSource @@ -2406,6 +2464,7 @@ public enum VariableSource Global = 0, Map = 1, Instance = 2, + Null = 3, Object = 4, System = 5, Member = 6, diff --git a/Assembly-CSharp/Global/EMinigame.cs b/Assembly-CSharp/Global/EMinigame.cs index 408bfa129..fc46b5b6f 100644 --- a/Assembly-CSharp/Global/EMinigame.cs +++ b/Assembly-CSharp/Global/EMinigame.cs @@ -37,14 +37,12 @@ public static Int32 StiltzkinBuy } } - public static void StiltzkinAchievement(PosObj gCur, Int32 gilDecrease) + public static void StiltzkinAchievement(PosObj gCur, UInt32 gilDecrease) { if (gCur.model == 212) { if (gilDecrease == 333 || gilDecrease == 444 || gilDecrease == 555 || gilDecrease == 666 || gilDecrease == 777 || gilDecrease == 888 || gilDecrease == 2222 || gilDecrease == 5555) - { FF9StateSystem.Achievement.StiltzkinBuy++; - } AchievementManager.ReportAchievement(AcheivementKey.AllStiltzkinItem, FF9StateSystem.Achievement.StiltzkinBuy); } } diff --git a/Assembly-CSharp/Global/Event/Engine/EventEngine.DoEventCode.cs b/Assembly-CSharp/Global/Event/Engine/EventEngine.DoEventCode.cs index 356b8cb85..855fb61f8 100644 --- a/Assembly-CSharp/Global/Event/Engine/EventEngine.DoEventCode.cs +++ b/Assembly-CSharp/Global/Event/Engine/EventEngine.DoEventCode.cs @@ -31,7 +31,14 @@ public Int32 DoEventCode() po = (PosObj)this.gCur; } this._lastIP = this.gExec.ip; - Int32 code = this.geti(); + Int32 codeByte = this.geti(); + Int32 code = 0; + while (codeByte == 0xFF) + { + codeByte = this.geti(); + code += 0x100; + } + code += codeByte; this.gArgFlag = this.geti(); this.gArgUsed = 0; EBin.event_code_binary eventCodeBinary = (EBin.event_code_binary)code; @@ -151,14 +158,14 @@ public Int32 DoEventCode() Queue missingMemberVar = new Queue(); for (Int32 varIndex = 3536; varIndex <= 3542; varIndex++) // "VARL_GenBool_3536" etc. { - if (eBin.GetVariableValueInternal(FF9StateSystem.EventState.gEventGlobal, varIndex, (Int32)EBin.VariableType.Bit << 3, 0) == 0) + if (eBin.GetVariableValueInternal(FF9StateSystem.EventState.gEventGlobal, varIndex, EBin.VariableType.Bit, 0) == 0) oeilvertPartyCount++; else missingMemberVar.Enqueue(varIndex); } while (oeilvertPartyCount < 3 && missingMemberVar.Count > 0) { - eBin.SetVariableValueInternal(FF9StateSystem.EventState.gEventGlobal, missingMemberVar.Dequeue(), (Int32)EBin.VariableType.Bit << 3, 0, 0); + eBin.SetVariableValueInternal(FF9StateSystem.EventState.gEventGlobal, missingMemberVar.Dequeue(), EBin.VariableType.Bit, 0, 0); oeilvertPartyCount++; } } @@ -1847,14 +1854,13 @@ public Int32 DoEventCode() { Int32 num55 = this.getv2(); Int32 num56 = this.getv2(); - if ((Int32)FF9StateSystem.Common.FF9.fldMapNo == 66 && (Int32)po.sid == 14 && (num55 == -145 && num56 == -9135)) + if (FF9StateSystem.Common.FF9.fldMapNo == 66 && po.sid == 14 && (num55 == -145 && num56 == -9135)) { + // Prima Vista/Interior, Marcus attacking King Leo as Cornelia (Garnet) moves to protect him num55 = -160; num56 = -9080; } - Boolean flag3 = this.MoveToward_mixed((Single)num55, 0.0f, (Single)num56, 1, (PosObj)null); - eulerAngles1 = po.go.transform.localRotation.eulerAngles; - if (flag3) + if (this.MoveToward_mixed(num55, 0.0f, num56, 1, null)) this.stay(); return 1; } @@ -2041,13 +2047,13 @@ public Int32 DoEventCode() return 0; } case EBin.event_code_binary.DANIM: - { - Actor actObj = (Actor)this.GetObj1(); - Int32 animId = this.getv2(); - AnimationFactory.AddAnimWithAnimatioName(actObj.go, FF9DBAll.AnimationDB.GetValue(animId)); - this.ExecAnim(actObj, animId); - return 0; - } + { + Actor actObj = (Actor)this.GetObj1(); + Int32 animId = this.getv2(); + AnimationFactory.AddAnimWithAnimatioName(actObj.go, FF9DBAll.AnimationDB.GetValue(animId)); + this.ExecAnim(actObj, animId); + return 0; + } case EBin.event_code_binary.DWAITANIM: { if (((Int32)((Actor)this.GetObj1()).animFlag & EventEngine.afExec) == 0) @@ -2177,14 +2183,14 @@ public Int32 DoEventCode() } case EBin.event_code_binary.GILADD: { - if ((this._ff9.party.gil += (UInt32)this.getv3()) > 9999999U) + if ((this._ff9.party.gil += this.getv3u()) > 9999999U) this._ff9.party.gil = 9999999U; return 0; } case EBin.event_code_binary.GILDELETE: { - Int32 gilDecrease = this.getv3(); - if ((this._ff9.party.gil -= (UInt32)gilDecrease) > 9999999U) + UInt32 gilDecrease = this.getv3u(); + if ((this._ff9.party.gil -= gilDecrease) > 9999999U) this._ff9.party.gil = 0U; if (this.isPosObj(this.gCur)) EMinigame.StiltzkinAchievement((PosObj)this.gCur, gilDecrease); @@ -2466,7 +2472,7 @@ public Int32 DoEventCode() // https://github.com/Albeoris/Memoria/issues/22 if (!player.info.sub_replaced) - { + { PLAYER subPlayer = FF9StateSystem.Common.FF9.GetPlayer(charId + 3); subPlayer.cur.hp = (UInt32)Math.Min(subPlayer.max.hp, newHp); } @@ -2614,140 +2620,251 @@ public Int32 DoEventCode() } return 0; } - case EBin.event_code_binary.EXT: + case EBin.event_code_binary.BSSTART: { - eventCodeBinary = (EBin.event_code_binary)(0x100 | this.gArgFlag); - this.gArgFlag = this.geti(); - switch (eventCodeBinary) + num1 = this.getv1(); + num3 = this.getv1(); + return 0; + } + case EBin.event_code_binary.BSFRAME: + { + num1 = this.getv1(); + num3 = this.getv1(); + return 0; + } + case EBin.event_code_binary.BSACTIVE: + { + this.fieldmap.walkMesh.BGI_simSetActive((UInt32)this.getv1(), (UInt32)this.getv1()); + return 0; + } + case EBin.event_code_binary.BSFLAG: + { + this.fieldmap.walkMesh.BGI_simSetFlags((UInt32)this.getv1(), (UInt32)this.getv1()); + return 0; + } + case EBin.event_code_binary.BSFLOOR: + { + this.fieldmap.walkMesh.BGI_simSetFloor((UInt32)this.getv1(), (UInt32)this.getv1()); + return 0; + } + case EBin.event_code_binary.BSRATE: + { + this.fieldmap.walkMesh.BGI_simSetFrameRate((UInt32)this.getv1(), (Int16)this.getv2()); + return 0; + } + case EBin.event_code_binary.BSALGO: + { + this.fieldmap.walkMesh.BGI_simSetAlgorithm((UInt32)this.getv1(), (UInt32)this.getv1()); + return 0; + } + case EBin.event_code_binary.BSDELTA: + { + this.fieldmap.walkMesh.BGI_simSetDelta((UInt32)this.getv1(), (Int16)this.getv2(), (Int16)this.getv2()); + return 0; + } + case EBin.event_code_binary.BSAXIS: + { + this.fieldmap.walkMesh.BGI_simSetAxis((UInt32)this.getv1(), (UInt32)this.getv1()); + return 0; + } + case EBin.event_code_binary.BAANIME: + { + num1 = this.getv1(); + num3 = this.getv1(); + return 0; + } + case EBin.event_code_binary.BAFRAME: + { + this.fieldmap.walkMesh.BGI_animShowFrame((UInt32)this.getv1(), (UInt32)this.getv1()); + return 0; + } + case EBin.event_code_binary.BAACTIVE: + { + num1 = this.getv1(); + num3 = this.getv1(); + return 0; + } + case EBin.event_code_binary.BAFLAG: + { + num1 = this.getv1(); + num3 = this.getv1(); + return 0; + } + case EBin.event_code_binary.BARATE: + { + num1 = this.getv1(); + num3 = this.getv2(); + return 0; + } + case EBin.event_code_binary.BAWAITALL: + { + num1 = this.getv1(); + num3 = this.getv1(); + return 0; + } + case EBin.event_code_binary.BAWAIT: + { + num1 = this.getv1(); + num2 = this.getv1(); + num3 = this.getv1(); + return 0; + } + case EBin.event_code_binary.BARANGE: + { + num1 = this.getv1(); + num2 = this.getv1(); + num3 = this.getv1(); + return 0; + } + case EBin.event_code_binary.BAVISIBLE: + { + num1 = this.getv1(); + num3 = this.getv1(); + return 0; + } + case EBin.event_code_binary.PLAYER_EQUIP: + { + CharacterId charId = this.chr2slot(this.getv3()); + Int32 equipType = this.getv3(); + RegularItem item = (RegularItem)this.getv3(); + PLAYER player = FF9StateSystem.Common.FF9.GetPlayer(charId); + if (player != null) { - case EBin.event_code_binary.BSSTART: - { - num1 = this.getv1(); - num3 = this.getv1(); - return 0; - } - case EBin.event_code_binary.BSFRAME: - { - num1 = this.getv1(); - num3 = this.getv1(); - return 0; - } - case EBin.event_code_binary.BSACTIVE: - { - this.fieldmap.walkMesh.BGI_simSetActive((UInt32)this.getv1(), (UInt32)this.getv1()); - return 0; - } - case EBin.event_code_binary.BSFLAG: - { - this.fieldmap.walkMesh.BGI_simSetFlags((UInt32)this.getv1(), (UInt32)this.getv1()); - return 0; - } - case EBin.event_code_binary.BSFLOOR: - { - this.fieldmap.walkMesh.BGI_simSetFloor((UInt32)this.getv1(), (UInt32)this.getv1()); - return 0; - } - case EBin.event_code_binary.BSRATE: - { - this.fieldmap.walkMesh.BGI_simSetFrameRate((UInt32)this.getv1(), (Int16)this.getv2()); - return 0; - } - case EBin.event_code_binary.BSALGO: - { - this.fieldmap.walkMesh.BGI_simSetAlgorithm((UInt32)this.getv1(), (UInt32)this.getv1()); - return 0; - } - case EBin.event_code_binary.BSDELTA: - { - this.fieldmap.walkMesh.BGI_simSetDelta((UInt32)this.getv1(), (Int16)this.getv2(), (Int16)this.getv2()); - return 0; - } - case EBin.event_code_binary.BSAXIS: - { - this.fieldmap.walkMesh.BGI_simSetAxis((UInt32)this.getv1(), (UInt32)this.getv1()); - return 0; - } - case EBin.event_code_binary.BAANIME: - { - num1 = this.getv1(); - num3 = this.getv1(); - return 0; - } - case EBin.event_code_binary.BAFRAME: - { - this.fieldmap.walkMesh.BGI_animShowFrame((UInt32)this.getv1(), (UInt32)this.getv1()); - return 0; - } - case EBin.event_code_binary.BAACTIVE: - { - num1 = this.getv1(); - num3 = this.getv1(); - return 0; - } - case EBin.event_code_binary.BAFLAG: - { - num1 = this.getv1(); - num3 = this.getv1(); - return 0; - } - case EBin.event_code_binary.BARATE: - { - num1 = this.getv1(); - num3 = this.getv2(); - return 0; - } - case EBin.event_code_binary.BAWAITALL: - { - num1 = this.getv1(); - num3 = this.getv1(); - return 0; - } - case EBin.event_code_binary.BAWAIT: - { - num1 = this.getv1(); - num2 = this.getv1(); - num3 = this.getv1(); - return 0; - } - case EBin.event_code_binary.BARANGE: - { - num1 = this.getv1(); - num2 = this.getv1(); - num3 = this.getv1(); - return 0; - } - case EBin.event_code_binary.BAVISIBLE: - { - num1 = this.getv1(); - num3 = this.getv1(); - return 0; - } - default: + player.equip.Change(equipType, item); + ff9feqp.FF9FEqp_UpdatePlayer(player); + } + return 0; + } + case EBin.event_code_binary.PLAYER_LEVEL: + { + CharacterId charId = this.chr2slot(this.getv3()); + Int32 lvl = Mathf.Clamp(this.getv3(), 1, ff9level.LEVEL_COUNT); + PLAYER player = FF9StateSystem.Common.FF9.GetPlayer(charId); + if (player != null) + ff9play.FF9Play_Build(player, lvl, false, false); + return 0; + } + case EBin.event_code_binary.PLAYER_EXP: + { + CharacterId charId = this.chr2slot(this.getv3()); + UInt32 exp = Math.Min(this.getv3u(), 9999999u); + PLAYER player = FF9StateSystem.Common.FF9.GetPlayer(charId); + if (player != null) + { + player.exp = exp; + while (player.level < ff9level.LEVEL_COUNT && exp >= ff9level.CharacterLevelUps[player.level].ExperienceToLevel) + ff9play.FF9Play_GrowLevel(player, player.level + 1); + } + return 0; + } + case EBin.event_code_binary.SHOP_ITEM: + { + Int32 shopId = this.getv3(); + RegularItem item = (RegularItem)this.getv3(); + Boolean add = this.getv3() != 0; + if (!ff9buy.ShopItems.ContainsKey(shopId)) + return 0; + ShopItems shop = ff9buy.ShopItems[shopId]; + if (add) + shop.ItemIds.Add(item); + else + shop.ItemIds.Remove(item); + return 0; + } + case EBin.event_code_binary.SHOP_SYNTH: + { + Int32 shopId = this.getv3(); + Int32 synthId = this.getv3(); + Boolean add = this.getv3() != 0; + if (!ff9mix.SynthesisData.ContainsKey(synthId)) + return 0; + FF9MIX_DATA synth = ff9mix.SynthesisData[synthId]; + if (add) + synth.Shops.Add(shopId); + else + synth.Shops.Remove(shopId); + return 0; + } + case EBin.event_code_binary.MOVE_EX: + { + Actor actor = this.GetObj3() as Actor; + Int32 speed = this.getv3(); + Single x = this.getv3(); + Single y = -this.getv3(); + Single z = this.getv3(); + Int32 flags = this.getv3(); + if (actor == null) + return 0; + if (actor.loopCount != Byte.MaxValue) + { + actor.loopCount = Byte.MaxValue; + this.clrdist(actor); + } + if (this.gMode == 1 && (flags & 2) != 0) + { + FieldMapActorController controller = actor.go?.GetComponent(); + controller?.walkMesh.BGI_charSetActive(controller, 0); + ff9shadow.FF9ShadowOffField(actor.uid); + actor.isShadowOff = true; + } + if (this.MoveToward_mixed_ex(actor, speed, x, y, z, flags, null)) + { + this.stay(); + } + else + { + if (this.gMode == 1 && (flags & 2) != 0) { - return 0; + FieldMapActorController controller = actor.go?.GetComponent(); + if (controller != null && controller.walkMesh.BGI_nearestWalkPosInVertical(new Vector3(x, y, z), out Single h) && Math.Abs(h) < 100f) + { + // Enable walkmesh pathing and shadow if the destination is near the ground + controller.walkMesh.BGI_charSetActive(controller, 1); + ff9shadow.FF9ShadowOnField(actor.uid); + } } } + return 1; + } + case EBin.event_code_binary.TURN_OBJ_EX: + { + Actor turner = this.GetObj3() as Actor; + PosObj target = this.GetObj3() as PosObj; + Int32 tspeed = this.getv3(); + if (turner != null && target != null) + { + Single angle = this.eBin.angleAsm(target.pos[0] - turner.pos[0], target.pos[2] - turner.pos[2]); + this.StartTurn(turner, angle, true, tspeed); + } + return 0; + } + case EBin.event_code_binary.AANIM_EX: + { + Actor actor = this.GetObj3() as Actor; + Int32 kind = this.getv3(); + Int32 anim = this.getv3(); + if (kind == 0) actor.idle = (UInt16)anim; + else if (kind == 1) actor.walk = (UInt16)anim; + else if (kind == 2) actor.run = (UInt16)anim; + else if (kind == 3) actor.turnl = (UInt16)anim; + else if (kind == 4) actor.turnr = (UInt16)anim; + else if (kind == 5) actor.sleep = (UInt16)anim; + else if (kind == 6) actor.jump = (UInt16)anim; + AnimationFactory.AddAnimWithAnimatioName(actor.go, FF9DBAll.AnimationDB.GetValue(anim)); + return 0; } default: { switch (this.gMode) { case 1: - { return this.DoEventCodeField(po, code); - } case 2: - { return this.DoEventCodeBattle(po, code); - } case 3: - { return this.DoEventCodeWorld(po, code); - } default: - { return 1; - } } } } @@ -2916,6 +3033,11 @@ private Obj GetObj1() return this.GetObjUID(this.getv1()); } + private Obj GetObj3() + { + return this.GetObjUID(this.getv3()); + } + private void FF9FieldDiscRequest(Byte disc_id, UInt16 map_id) { //this._ff9fieldDisc.disc_id = disc_id; @@ -2935,27 +3057,22 @@ internal void SetActorPosition(PosObj po, Single x, Single y, Single z) po.pos[2] = po.lastz = z; if (this.gMode == 1) { - FieldMapActorController mapActorController = ((Actor)po).fieldMapActorController; - if (!((UnityEngine.Object)mapActorController != (UnityEngine.Object)null)) - return; - mapActorController.SetPosition(new Vector3(po.pos[0], po.pos[1], po.pos[2]), true, true); + ((Actor)po).fieldMapActorController?.SetPosition(new Vector3(po.pos[0], po.pos[1], po.pos[2]), true, true); } - else + else if (this.gMode == 3) { - if (this.gMode != 3) - return; //if ((Int32)po.uid != (Int32)this._context.controlUID) // ; ((Actor)po).wmActor.SetPosition(po.pos[0], po.pos[1], po.pos[2]); - if ((Int32)po.index < 3 || (Int32)po.index > 7) + if (po.index < 3 || po.index > 7) return; Int32 posX = (Int32)po.pos[0]; Int32 posY = (Int32)po.pos[1]; Int32 posZ = (Int32)po.pos[2]; ff9.w_movementChrVerifyValidCastPosition(ref posX, ref posY, ref posZ); - po.pos[0] = (Single)posX; - po.pos[1] = (Single)posY; - po.pos[2] = (Single)posZ; + po.pos[0] = posX; + po.pos[1] = posY; + po.pos[2] = posZ; ((Actor)po).wmActor.SetPosition(po.pos[0], po.pos[1], po.pos[2]); } } diff --git a/Assembly-CSharp/Global/Event/Engine/EventEngine.MoveToward.cs b/Assembly-CSharp/Global/Event/Engine/EventEngine.MoveToward.cs index dc8793bf4..a6d71b19f 100644 --- a/Assembly-CSharp/Global/Event/Engine/EventEngine.MoveToward.cs +++ b/Assembly-CSharp/Global/Event/Engine/EventEngine.MoveToward.cs @@ -4,9 +4,16 @@ public partial class EventEngine { - private bool MoveToward_mixed(Single x, Single y, Single z, Int32 flags, PosObj followPosObj) + private Boolean MoveToward_mixed(Single x, Single y, Single z, Int32 flags, PosObj followPosObj) + { + Actor actor = this.gCur as Actor; + if (actor == null) + return false; + return MoveToward_mixed_ex(actor, actor.speed, x, y, z, flags, followPosObj); + } + + private Boolean MoveToward_mixed_ex(Actor actor, Int32 speed, Single x, Single y, Single z, Int32 flags, PosObj followPosObj) { - Actor actor = (Actor)this.gCur; if (FF9StateSystem.Common.FF9.fldMapNo == 1823 && actor.sid == 13 && x == -365 && z == -373) { // A. Castle/Hallway, Steiner, one of the mid-steps before saying "Princess, we are ready." @@ -19,8 +26,7 @@ private bool MoveToward_mixed(Single x, Single y, Single z, Int32 flags, PosObj x = -1155f; z = -1070f; } - GameObject go = this.gCur.go; - Single sqrSpeed = actor.speed * actor.speed; + Single sqrSpeed = speed * speed; Single moveDistance = 0f; PosObj posObj = null; FieldMapActorController actorController = null; @@ -74,7 +80,7 @@ private bool MoveToward_mixed(Single x, Single y, Single z, Int32 flags, PosObj angleMoveFaceDiff += 360f; if (angleMoveFaceDiff > 180f || EventEngineUtils.nearlyEqual(angleMoveFaceDiff, 180f)) angleMoveFaceDiff -= 360f; - if ((FF9StateSystem.Common.FF9.fldMapNo != 307 || this.gCur.sid != 11) && (FF9StateSystem.Common.FF9.fldMapNo != 610 || this.gCur.sid != 3) && EventEngineUtils.nearlyEqual(angleMoveFaceDiff, 0f)) + if ((FF9StateSystem.Common.FF9.fldMapNo != 307 || actor.sid != 11) && (FF9StateSystem.Common.FF9.fldMapNo != 610 || actor.sid != 3) && EventEngineUtils.nearlyEqual(angleMoveFaceDiff, 0f)) { // Always except (Ice Cavern/Ice Path, Zidane) and (L. Castle/Castle Station, Lindblum_OldAviator) actor.actf |= (UInt16)EventEngine.actLockDir; @@ -130,7 +136,7 @@ private bool MoveToward_mixed(Single x, Single y, Single z, Int32 flags, PosObj deltaY = 0f; } - EventEngine.GetMoveVector(out Vector3 moveVec, movingPitch, movingAngle, actor.speed); + EventEngine.GetMoveVector(out Vector3 moveVec, movingPitch, movingAngle, speed); if (Configuration.Control.PSXMovementMethod && (flags & 2) == 0 && actorController != null) moveVec *= actorController.fieldMap.walkMesh.GetTriangleSlopeFactor(actorController.activeTri); diff --git a/Assembly-CSharp/Global/Event/Engine/EventEngine.cs b/Assembly-CSharp/Global/Event/Engine/EventEngine.cs index 7dc4b531e..c01c5785a 100644 --- a/Assembly-CSharp/Global/Event/Engine/EventEngine.cs +++ b/Assembly-CSharp/Global/Event/Engine/EventEngine.cs @@ -666,7 +666,7 @@ public void StartEvents(Byte[] ebFileData) Int32 memberIndex = 0; ff9play.FF9Play_SetParty(memberIndex++, CharacterId.Zidane); for (Int32 varIndex = 3536; varIndex <= 3542 && memberIndex < 4; varIndex++) // "VARL_GenBool_3536" etc. - if (eBin.GetVariableValueInternal(FF9StateSystem.EventState.gEventGlobal, varIndex, (Int32)EBin.VariableType.Bit << 3, 0) == 0) + if (eBin.GetVariableValueInternal(FF9StateSystem.EventState.gEventGlobal, varIndex, EBin.VariableType.Bit, 0) == 0) ff9play.FF9Play_SetParty(memberIndex++, variableToCharacter[varIndex - 3536]); this.SetupPartyUID(); } @@ -684,7 +684,7 @@ public void StartEvents(Byte[] ebFileData) this.SetupPartyUID(); } // Hotfix: force a normal team for the cutscene at the bottom of Gulug (field "Gulug/Path") - if (FF9StateSystem.Common.FF9.fldMapNo == 2362 && FF9StateSystem.EventState.ScenarioCounter == 9950 && eBin.GetVariableValueInternal(FF9StateSystem.EventState.gEventGlobal, 3262, (Int32)EBin.VariableType.Bit << 3, 0) == 0) + if (FF9StateSystem.Common.FF9.fldMapNo == 2362 && FF9StateSystem.EventState.ScenarioCounter == 9950 && eBin.GetVariableValueInternal(FF9StateSystem.EventState.gEventGlobal, 3262, EBin.VariableType.Bit, 0) == 0) { Boolean shouldHack = !partychk((Int32)CharacterOldIndex.Zidane) || !partychk((Int32)CharacterOldIndex.Vivi); for (Int32 memberIndex = 0; memberIndex < 4; memberIndex++) @@ -1274,47 +1274,70 @@ private Int32 geti() private Int32 getv1() { - Int32 num; + Int32 result; if ((this.gArgFlag & 1) != 0) { this.eBin.CalcExpr(); - num = this.eBin.getv(); + result = this.eBin.getv(); } else - num = this.geti(); + { + result = this.geti(); + } this.gArgFlag >>= 1; this.gArgUsed = 1; - return num; + return result; } private Int32 getv2() { - Int32 num; + Int32 result; if ((this.gArgFlag & 1) != 0) { this.eBin.CalcExpr(); - num = this.eBin.getv(); + result = this.eBin.getv(); } else - num = (this.geti() | this.geti() << 8) << 16 >> 16; + { + result = (this.geti() | this.geti() << 8) << 16 >> 16; + } this.gArgFlag >>= 1; this.gArgUsed = 1; - return num; + return result; + } + + private UInt32 getv3u() + { + UInt32 result; + if ((this.gArgFlag & 1) != 0) + { + this.eBin.CalcExpr(); + result = (UInt32)this.eBin.getv(); + } + else + { + result = (UInt32)(this.geti() | this.geti() << 8 | this.geti() << 16); + } + this.gArgFlag >>= 1; + this.gArgUsed = 1; + return result; } private Int32 getv3() { - Int32 num; + Int32 result; if ((this.gArgFlag & 1) != 0) { this.eBin.CalcExpr(); - num = this.eBin.getv(); + result = this.eBin.getv(); } else - num = this.geti() | this.geti() << 8 | this.geti() << 16; + { + result = (this.geti() | this.geti() << 8 | this.geti() << 16) << 8 >> 8; + } this.gArgFlag >>= 1; this.gArgUsed = 1; - return num; + return result; } private void ExecAnim(Actor p, Int32 anim) diff --git a/Assembly-CSharp/Global/Event/EventState.cs b/Assembly-CSharp/Global/Event/EventState.cs index 85e1eb994..b42d45bec 100644 --- a/Assembly-CSharp/Global/Event/EventState.cs +++ b/Assembly-CSharp/Global/Event/EventState.cs @@ -48,6 +48,27 @@ public void IncreaseAAUsageCounter(BattleAbilityId abilityId) gAbilityUsage[abilityId] = 1; } + public Int32 GetTreasureHunterPoints() + { + // Rank H: 0-199 pts + // Rank G: 200-219 pts + // Rank F: 220-239 pts + // Rank E: 240-259 pts + // Rank D: 260-279 pts + // Rank C: 280-299 pts + // Rank B: 300-319 pts + // Rank A: 320-339 pts + // Rank S: 340+ pts + Int32 pts = 0; + for (Int32 index = 896; index <= 960; index++) + pts += FF9.Comn.countBits(gEventGlobal[index]); + for (Int32 index = 966; index <= 975; index++) + pts += FF9.Comn.countBits(gEventGlobal[index]); + for (Int32 index = 182; index <= 186; index++) + pts += 2 * FF9.Comn.countBits(gEventGlobal[index]); + return pts; + } + public List FindVariableInFieldScriptUsage(List variableIndex, List asBool = null) { List fieldList = new List(); diff --git a/Assembly-CSharp/Global/Field/FieldRainRenderer.cs b/Assembly-CSharp/Global/Field/FieldRainRenderer.cs index 8a4e3e726..52f11da76 100644 --- a/Assembly-CSharp/Global/Field/FieldRainRenderer.cs +++ b/Assembly-CSharp/Global/Field/FieldRainRenderer.cs @@ -40,13 +40,10 @@ public void InitRain() private void OnPostRender() { if (PersistenSingleton.Instance.IsFading) - { return; - } + SFXData.RenderEventSFX(); if (this.numRain == 0) - { return; - } GL.PushMatrix(); this.mat.SetPass(0); GL.LoadOrtho(); diff --git a/Assembly-CSharp/Global/Field/FieldSPSConst.cs b/Assembly-CSharp/Global/Field/FieldSPSConst.cs index 8a8ededf5..1b20ab89a 100644 --- a/Assembly-CSharp/Global/Field/FieldSPSConst.cs +++ b/Assembly-CSharp/Global/Field/FieldSPSConst.cs @@ -7,66 +7,38 @@ public class FieldSPSConst public const Int32 FF9FIELDSPSOBJ_ATTR_VISIBLE = 1; public const Int32 FF9FIELDSPS_MAX_REFCOUNT = 16; - public const Int32 FF9FIELDSPS_MAX_OBJCOUNT = 16; public const Int32 FF9FIELDSPS_PARM_REF_DELETE = -1; - public const Int32 FF9FIELDSPS_PARM_SCALE_ONE = 4096; - public const Int32 FF9FIELDSPS_PARM_FRAMERATE_ONE = 16; - public const Int32 FF9FIELDSPS_PARM_ARATE_50P50 = 0; - public const Int32 FF9FIELDSPS_PARM_ARATE_100P100 = 1; - public const Int32 FF9FIELDSPS_PARM_ARATE_100M100 = 2; - public const Int32 FF9FIELDSPS_PARM_ARATE_100P25 = 3; - public const Int32 FF9FIELDSPS_PARM_ARATE_OFF = 15; + public const Int32 FF9FIELDSPS_PARMTYPE_FIELD = 129; public const Int32 FF9FIELDSPS_PARMTYPE_REF = 130; - public const Int32 FF9FIELDSPS_PARMTYPE_ATTR = 131; - public const Int32 FF9FIELDSPS_PARMTYPE_POS = 135; - public const Int32 FF9FIELDSPS_PARMTYPE_POS_X = 136; - public const Int32 FF9FIELDSPS_PARMTYPE_POS_Y = 137; - public const Int32 FF9FIELDSPS_PARMTYPE_POS_Z = 138; - public const Int32 FF9FIELDSPS_PARMTYPE_ROT = 140; - public const Int32 FF9FIELDSPS_PARMTYPE_ROT_X = 141; - public const Int32 FF9FIELDSPS_PARMTYPE_ROT_Y = 142; - public const Int32 FF9FIELDSPS_PARMTYPE_ROT_Z = 143; - public const Int32 FF9FIELDSPS_PARMTYPE_SCALE = 145; - public const Int32 FF9FIELDSPS_PARMTYPE_CHAR = 150; - public const Int32 FF9FIELDSPS_PARMTYPE_BONE = 151; - public const Int32 FF9FIELDSPS_PARMTYPE_FADE = 155; - public const Int32 FF9FIELDSPS_PARMTYPE_ARATE = 156; - public const Int32 FF9FIELDSPS_PARMTYPE_FRAMERATE = 160; - public const Int32 FF9FIELDSPS_PARMTYPE_FRAME = 161; - public const Int32 FF9FIELDSPS_PARMTYPE_POSOFFSET = 165; - public const Int32 FF9FIELDSPS_PARMTYPE_POSOFFSET_X = 166; - public const Int32 FF9FIELDSPS_PARMTYPE_POSOFFSET_Y = 167; - public const Int32 FF9FIELDSPS_PARMTYPE_POSOFFSET_Z = 168; - public const Int32 FF9FIELDSPS_PARMTYPE_DEPTHOFFSET = 170; } diff --git a/Assembly-CSharp/Global/Field/FieldSPSSystem.cs b/Assembly-CSharp/Global/Field/FieldSPSSystem.cs index 94a39ee2c..a4cff799d 100644 --- a/Assembly-CSharp/Global/Field/FieldSPSSystem.cs +++ b/Assembly-CSharp/Global/Field/FieldSPSSystem.cs @@ -24,9 +24,9 @@ public void Init(FieldMap fieldMap) this._spsList = new List(); this._spsBinDict = new Dictionary>(); this._fieldMap = fieldMap; - for (Int32 i = 0; i < 16; i++) + for (Int32 i = 0; i < FieldSPSConst.FF9FIELDSPS_MAX_OBJCOUNT; i++) { - GameObject gameObject = new GameObject("SPS_" + i.ToString("D4")); + GameObject gameObject = new GameObject($"SPS_{i:D4}"); gameObject.transform.parent = base.transform; gameObject.transform.localScale = Vector3.one; gameObject.transform.localPosition = Vector3.zero; @@ -49,6 +49,21 @@ public void Init(FieldMap fieldMap) this._isReady = this._loadSPSTexture(); } + public void ChangeFieldOrigin(Int32 fieldId) + { + foreach (FieldSPS fieldSPS in this._spsList) + { + fieldSPS.spsBin = null; + fieldSPS.meshRenderer.enabled = false; + fieldSPS.charTran = null; + fieldSPS.boneTran = null; + } + this._spsBinDict.Clear(); + this.MapName = EventEngineUtils.eventIDToFBGID[fieldId]; + FieldMapInfo.fieldmapSPSExtraOffset.SetSPSOffset(this.MapName, this._spsList); + this._isReady = this._loadSPSTexture(); + } + public void Service() { if (!this._isReady) @@ -74,21 +89,17 @@ public void Service() public void GenerateSPS() { if (!this._isReady) - { return; - } for (Int32 i = 0; i < this._spsList.Count; i++) { FieldSPS fieldSPS = this._spsList[i]; if (fieldSPS.spsBin != null && (fieldSPS.attr & 1) != 0) { - if (fieldSPS.charTran != (UnityEngine.Object)null && fieldSPS.boneTran != (UnityEngine.Object)null) + if (fieldSPS.charTran != null && fieldSPS.boneTran != null) { FieldMapActor component = fieldSPS.charTran.GetComponent(); - if (component != (UnityEngine.Object)null) - { + if (component != null) component.UpdateGeoAttach(); - } fieldSPS.pos = fieldSPS.boneTran.position + fieldSPS.posOffset; } fieldSPS.GenerateSPS(); @@ -105,36 +116,34 @@ private Boolean _loadSPSTexture() { using (BinaryReader binaryReader = new BinaryReader(new MemoryStream(binAsset))) { - UInt32 num = binaryReader.ReadUInt32(); - UInt32 num2 = binaryReader.ReadUInt32(); - Int32 num3 = binaryReader.ReadInt32(); - binaryReader.BaseStream.Seek((Int64)((UInt64)num), SeekOrigin.Begin); - UInt32 num4 = binaryReader.ReadUInt32(); - Int32 num5 = binaryReader.ReadInt32(); - for (Int32 i = 0; i < num3; i++) + UInt32 secondBatchOffset = binaryReader.ReadUInt32(); + UInt32 firstBatchOffset = binaryReader.ReadUInt32(); + Int32 firstBatchCount = binaryReader.ReadInt32(); + for (Int32 i = 0; i < firstBatchCount; i++) { - binaryReader.BaseStream.Seek((Int64)((UInt64)num2), SeekOrigin.Begin); - Int32 x = (Int32)binaryReader.ReadInt16(); - Int32 y = (Int32)binaryReader.ReadInt16(); - Int32 num6 = (Int32)binaryReader.ReadInt16(); - Int32 num7 = (Int32)binaryReader.ReadInt16(); - PSXTextureMgr.LoadImageBin(x, y, num6, num7, binaryReader); - UInt32 num8 = (UInt32)(num6 * num7 * 2); - num2 += num8 + 8u; + binaryReader.BaseStream.Seek(firstBatchOffset, SeekOrigin.Begin); + Int32 x = binaryReader.ReadInt16(); + Int32 y = binaryReader.ReadInt16(); + Int32 w = binaryReader.ReadInt16(); + Int32 h = binaryReader.ReadInt16(); + PSXTextureMgr.LoadImageBin(x, y, w, h, binaryReader); + firstBatchOffset += (UInt32)(w * h * 2 + 8); } - num += 8u; - for (Int32 j = 0; j < num5; j++) + binaryReader.BaseStream.Seek(secondBatchOffset, SeekOrigin.Begin); + UInt32 secondBatchImgOffset = binaryReader.ReadUInt32(); + Int32 secondBatchCount = binaryReader.ReadInt32(); + secondBatchOffset += 8u; + for (Int32 i = 0; i < secondBatchCount; i++) { - binaryReader.BaseStream.Seek((Int64)((UInt64)num), SeekOrigin.Begin); - Int32 x2 = (Int32)binaryReader.ReadInt16(); - Int32 y2 = (Int32)binaryReader.ReadInt16(); - Int32 num9 = (Int32)binaryReader.ReadInt16(); - Int32 num10 = (Int32)binaryReader.ReadInt16(); - binaryReader.BaseStream.Seek((Int64)((UInt64)num4), SeekOrigin.Begin); - PSXTextureMgr.LoadImageBin(x2, y2, num9, num10, binaryReader); - UInt32 num8 = (UInt32)(num9 * num10 * 2); - num4 += num8; - num += 8u; + binaryReader.BaseStream.Seek(secondBatchOffset, SeekOrigin.Begin); + Int32 x = binaryReader.ReadInt16(); + Int32 y = binaryReader.ReadInt16(); + Int32 w = binaryReader.ReadInt16(); + Int32 h = binaryReader.ReadInt16(); + binaryReader.BaseStream.Seek(secondBatchImgOffset, SeekOrigin.Begin); + PSXTextureMgr.LoadImageBin(x, y, w, h, binaryReader); + secondBatchImgOffset += (UInt32)(w * h * 2); + secondBatchOffset += 8u; } } PSXTextureMgr.ClearObject(); @@ -145,7 +154,7 @@ private Boolean _loadSPSTexture() private Int32 _GetSpsFrameCount(Byte[] spsBin) { - return (Int32)(BitConverter.ToUInt16(spsBin, 0) & 32767) << 4; + return (BitConverter.ToUInt16(spsBin, 0) & 0x7FFF) << 4; } private Boolean _loadSPSBin(Int32 spsNo) @@ -155,13 +164,18 @@ private Boolean _loadSPSBin(Int32 spsNo) Byte[] binAsset = AssetManager.LoadBytes($"FieldMaps/{this.MapName}/{spsNo}.sps"); if (binAsset == null) return false; - Int32 key = this._GetSpsFrameCount(binAsset); - this._spsBinDict.Add(spsNo, new KeyValuePair(key, binAsset)); + this._spsBinDict.Add(spsNo, new KeyValuePair(this._GetSpsFrameCount(binAsset), binAsset)); return true; } public void FF9FieldSPSSetObjParm(Int32 ObjNo, Int32 ParmType, Int32 Arg0, Int32 Arg1, Int32 Arg2) { + if (ParmType == FieldSPSConst.FF9FIELDSPS_PARMTYPE_FIELD) + { + // TODO: Somehow find a way to have SPS from multiple fields simultaneously, which requires something better than PSXTextureMgr + this.ChangeFieldOrigin(Arg0); + return; + } FieldSPS fieldSPS = this._spsList[ObjNo]; if (ParmType == FieldSPSConst.FF9FIELDSPS_PARMTYPE_REF) { @@ -177,6 +191,7 @@ public void FF9FieldSPSSetObjParm(Int32 ObjNo, Int32 ParmType, Int32 Arg0, Int32 fieldSPS.refNo = Arg0; if (FF9StateSystem.Common.FF9.fldMapNo == 2553 && (fieldSPS.refNo == 464 || fieldSPS.refNo == 467 || fieldSPS.refNo == 506 || fieldSPS.refNo == 510)) { + // Wind Shrine/Interior fieldSPS.spsBin = null; } } @@ -184,6 +199,7 @@ public void FF9FieldSPSSetObjParm(Int32 ObjNo, Int32 ParmType, Int32 Arg0, Int32 { if ((FF9StateSystem.Common.FF9.fldMapNo == 911 || FF9StateSystem.Common.FF9.fldMapNo == 1911) && (fieldSPS.refNo == 33 || fieldSPS.refNo == 34)) { + // Treno/Queen's House fieldSPS.pos = Vector3.zero; fieldSPS.scale = 4096; fieldSPS.rot = Vector3.zero; @@ -191,20 +207,16 @@ public void FF9FieldSPSSetObjParm(Int32 ObjNo, Int32 ParmType, Int32 Arg0, Int32 } fieldSPS.spsBin = null; fieldSPS.meshRenderer.enabled = false; - fieldSPS.charTran = (Transform)null; - fieldSPS.boneTran = (Transform)null; + fieldSPS.charTran = null; + fieldSPS.boneTran = null; } } else if (ParmType == FieldSPSConst.FF9FIELDSPS_PARMTYPE_ATTR) { if (Arg1 == 0) - { - fieldSPS.attr = (Byte) (fieldSPS.attr & (Byte) (~(Byte) Arg0)); - } + fieldSPS.attr &= (Byte)~Arg0; else - { - fieldSPS.attr = (Byte) (fieldSPS.attr | (Byte) Arg0); - } + fieldSPS.attr |= (Byte)Arg0; if ((fieldSPS.attr & 1) == 0) { @@ -212,10 +224,10 @@ public void FF9FieldSPSSetObjParm(Int32 ObjNo, Int32 ParmType, Int32 Arg0, Int32 } else if (FF9StateSystem.Common.FF9.fldMapNo == 2928 || FF9StateSystem.Common.FF9.fldMapNo == 1206 || FF9StateSystem.Common.FF9.fldMapNo == 1223) { + // Hill of Despair + // A. Castle/Queen's Chamber if (fieldSPS.spsBin != null) - { fieldSPS.meshRenderer.enabled = true; - } } else { @@ -226,19 +238,18 @@ public void FF9FieldSPSSetObjParm(Int32 ObjNo, Int32 ParmType, Int32 Arg0, Int32 { if (FF9StateSystem.Common.FF9.fldMapNo == 911 || FF9StateSystem.Common.FF9.fldMapNo == 1911) { + // Treno/Queen's House if (fieldSPS.spsBin != null) - { - fieldSPS.pos = new Vector3((Single)Arg0, (Single)(Arg1 * -1), (Single)Arg2); - } + fieldSPS.pos = new Vector3(Arg0, -Arg1, Arg2); } else { - fieldSPS.pos = new Vector3((Single)Arg0, (Single)(Arg1 * -1), (Single)Arg2); + fieldSPS.pos = new Vector3(Arg0, -Arg1, Arg2); } } else if (ParmType == FieldSPSConst.FF9FIELDSPS_PARMTYPE_ROT) { - fieldSPS.rot = new Vector3((Single)Arg0 / 4096f * 360f, (Single)Arg1 / 4096f * 360f, (Single)Arg2 / 4096f * 360f); + fieldSPS.rot = new Vector3(Arg0 / 4096f * 360f, Arg1 / 4096f * 360f, Arg2 / 4096f * 360f); } else if (ParmType == FieldSPSConst.FF9FIELDSPS_PARMTYPE_SCALE) { @@ -270,7 +281,7 @@ public void FF9FieldSPSSetObjParm(Int32 ObjNo, Int32 ParmType, Int32 Arg0, Int32 } else if (ParmType == FieldSPSConst.FF9FIELDSPS_PARMTYPE_POSOFFSET) { - fieldSPS.posOffset = new Vector3((Single)Arg0, (Single)(-(Single)Arg1), (Single)Arg2); + fieldSPS.posOffset = new Vector3(Arg0, -Arg1, Arg2); } else if (ParmType == FieldSPSConst.FF9FIELDSPS_PARMTYPE_DEPTHOFFSET) { @@ -281,11 +292,8 @@ public void FF9FieldSPSSetObjParm(Int32 ObjNo, Int32 ParmType, Int32 Arg0, Int32 public String MapName; private Boolean _isReady; - private FieldMap _fieldMap; - private List _spsList; - private Dictionary> _spsBinDict; public Vector3 rot; diff --git a/Assembly-CSharp/Global/Honolulu/HonoluluFieldMain.cs b/Assembly-CSharp/Global/Honolulu/HonoluluFieldMain.cs index 718602cec..d468c36e7 100644 --- a/Assembly-CSharp/Global/Honolulu/HonoluluFieldMain.cs +++ b/Assembly-CSharp/Global/Honolulu/HonoluluFieldMain.cs @@ -122,6 +122,7 @@ private void ff9InitStateFieldMap(Int32 MapNo) Int32 sndEffectResSoundID = allSoundDispatchPlayer.GetSndEffectResSoundID(0); Int32 sndEffectResSoundID2 = allSoundDispatchPlayer.GetSndEffectResSoundID(1); FF9Snd.BGMFieldSongCounter = 0; + SFXData.Reinit(); this.ee.StartEvents(map.evtPtr); FF9StateSystem.Field.SetTwistAD(this.ee.GetTwistA(), this.ee.GetTwistD()); PersistenSingleton.Instance.eTb.InitMessage(); @@ -197,6 +198,7 @@ private void FF9FieldMapMain() { Int32 num = this.ee.ServiceEvents(); HonoluluFieldMain.eventEngineRunningCount++; + SFXData.AdvanceEventSFXFrame(); this.updatePlayerObj(); switch (num) { diff --git a/Assembly-CSharp/Global/PARTY_DATA.cs b/Assembly-CSharp/Global/PARTY_DATA.cs index 9195e4ef5..eb65aa1b5 100644 --- a/Assembly-CSharp/Global/PARTY_DATA.cs +++ b/Assembly-CSharp/Global/PARTY_DATA.cs @@ -17,5 +17,5 @@ public PARTY_DATA() public Int32 battle_no; public Character GetCharacter(Int32 index) => new Character(member[index]); - public CharacterId GetCharacterId(Int32 index) => member[index] == null ? CharacterId.NONE : member[index].info.slot_no; + public CharacterId GetCharacterId(Int32 index) => index < 0 || index >= member.Length || member[index] == null ? CharacterId.NONE : member[index].info.slot_no; } diff --git a/Assembly-CSharp/Global/PartySettingUI.cs b/Assembly-CSharp/Global/PartySettingUI.cs index 409456bb7..644fdd388 100644 --- a/Assembly-CSharp/Global/PartySettingUI.cs +++ b/Assembly-CSharp/Global/PartySettingUI.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Collections.Generic; using Assets.Scripts.Common; using Assets.Sources.Scripts.UI.Common; @@ -88,7 +89,19 @@ public PartySelect(Mode _group, Int32 _index) [NonSerialized] private Int32 currentFloor; - private Int32 FloorMax => this.info == null || this.info.select == null || this.info.select.Length <= 8 ? 0 : (this.info.select.Length - 5) / 4; + private Int32 TotalCharCount + { + get + { + if (this.info == null) + return 0; + Int32 count = this.info.menu.Sum(cId => cId != CharacterId.NONE ? 1 : 0); + if (this.info.select != null) + count += this.info.select.Sum(cId => cId != CharacterId.NONE ? 1 : 0); + return count; + } + } + private Int32 FloorMax => Math.Max(0, (TotalCharCount - 6) / 4); public FF9PARTY_INFO Info { @@ -462,16 +475,16 @@ private void ExtendSelectSlots() Int32 oldCount; if (this.info.select == null) { - oldCount = 0; - this.info.select = new CharacterId[8]; + oldCount = 8; + this.info.select = new CharacterId[oldCount]; + for (Int32 i = 0; i < oldCount; i++) + this.info.select[i] = CharacterId.NONE; } else { oldCount = this.info.select.Length; } - Int32 count = Math.Max(8, oldCount); - if ((count % 4) != 0) - count += 4 - (count % 4); + Int32 count = 8 + FloorMax * 4; if (count != oldCount) { Array.Resize(ref this.info.select, count); diff --git a/Assembly-CSharp/Global/SFX/SFX.cs b/Assembly-CSharp/Global/SFX/SFX.cs index e705750c6..ca73d4586 100644 --- a/Assembly-CSharp/Global/SFX/SFX.cs +++ b/Assembly-CSharp/Global/SFX/SFX.cs @@ -1620,7 +1620,7 @@ public static void StartBattle() { SFX.StartCommon(false); SFX.StartPlungeCamera(); - SFXData.InitBattle(); + SFXData.Reinit(); SFXDataCamera.currentCameraEngine = SFXDataCamera.CameraEngine.SFX_PLUGIN; if (Configuration.Battle.SFXRework) SFXChannel.LoadAll(); diff --git a/Assembly-CSharp/Global/SFXRender/SFXRender.cs b/Assembly-CSharp/Global/SFXRender/SFXRender.cs index 03f6a7b79..a94ca9286 100644 --- a/Assembly-CSharp/Global/SFXRender/SFXRender.cs +++ b/Assembly-CSharp/Global/SFXRender/SFXRender.cs @@ -10,23 +10,30 @@ public static void Init() { SFXKey.currentTexPage = 0u; SFXKey.currentTexABR = 0u; - SFXRender.meshOrigin = new SFXMesh[SFXRender.MESH_MAX]; - for (Int32 i = 0; i < (Int32)SFXRender.meshOrigin.Length; i++) - SFXRender.meshOrigin[i] = new SFXMesh(); - SFXRender.commandBuffer = new List(); - SFXRender.exportSFXDataMesh = new Dictionary(); + if (SFXRender.meshOrigin == null) + SFXRender.meshOrigin = new SFXMesh[SFXRender.MESH_MAX]; + for (Int32 i = 0; i < SFXRender.meshOrigin.Length; i++) + if (SFXRender.meshOrigin[i] == null) + SFXRender.meshOrigin[i] = new SFXMesh(); + if (SFXRender.commandBuffer == null) + SFXRender.commandBuffer = new List(); + if (SFXRender.exportSFXDataMesh == null) + SFXRender.exportSFXDataMesh = new Dictionary(); } public static void Release() { - for (Int32 i = 0; i < (Int32)SFXRender.meshOrigin.Length; i++) - { - SFXRender.meshOrigin[i].ClearObject(); - SFXRender.meshOrigin[i] = (SFXMesh)null; - } - SFXRender.meshOrigin = null; + // Don't release these objects to allow their use in any module + //for (Int32 i = 0; i < SFXRender.meshOrigin.Length; i++) + //{ + // SFXRender.meshOrigin[i].ClearObject(); + // SFXRender.meshOrigin[i] = null; + //} + //SFXRender.meshOrigin = null; + //SFXRender.commandBuffer = null; + //SFXRender.exportSFXDataMesh = null; + SFXRender.commandBuffer.Clear(); SFXRender.meshEmpty = null; - SFXRender.commandBuffer = null; SFXRender.meshOpa = null; SFXRender.meshAdd = null; SFXRender.meshSub = null; @@ -38,7 +45,6 @@ public static void Release() SFXRender.meshLineAdd = null; SFXRender.meshLineSub = null; SFXRender.exportSFXDataMesh.Clear(); - SFXRender.exportSFXDataMesh = null; } public unsafe static void Update() diff --git a/Assembly-CSharp/Global/Walk/WalkMesh.cs b/Assembly-CSharp/Global/Walk/WalkMesh.cs index fe08754c6..49bf5ffc0 100644 --- a/Assembly-CSharp/Global/Walk/WalkMesh.cs +++ b/Assembly-CSharp/Global/Walk/WalkMesh.cs @@ -2476,6 +2476,25 @@ public Boolean BGI_pointAbovePoly(BGI_TRI_DEF tri, Vector3 pos) return Math3D.PointInsideTriangleTest2D(pos, walkMeshTriangle.originalVertices[0], walkMeshTriangle.originalVertices[1], walkMeshTriangle.originalVertices[2], planarFactor); } + public Boolean BGI_nearestWalkPosInVertical(Vector3 pos, out Single height) + { + BGI_DEF bgi = this.fieldMap.bgi; + height = Single.PositiveInfinity; + for (Int32 i = 0; i < bgi.triCount; i++) + { + BGI_TRI_DEF tri = bgi.triList[i]; + if (this.BGI_pointAbovePoly(tri, pos)) + { + WalkMeshTriangle wTri = this.tris[tri.triIdx]; + Vector3 barCoord = Math3D.CalculateBarycentricRatio(pos, wTri.originalVertices[0], wTri.originalVertices[1], wTri.originalVertices[2]); + Single triangleY = wTri.originalVertices[0].y * barCoord.x + wTri.originalVertices[1].y * barCoord.y + wTri.originalVertices[2].y * barCoord.z; + if (Math.Abs(pos.y - triangleY) < Math.Abs(height)) + height = pos.y - triangleY; + } + } + return height != Single.PositiveInfinity; + } + public Boolean BGI_pointInPoly(BGI_TRI_DEF tri, Vector3 pos) { WalkMeshTriangle walkMeshTriangle = this.tris[tri.triIdx]; diff --git a/Assembly-CSharp/Global/World/WorldRainRenderer.cs b/Assembly-CSharp/Global/World/WorldRainRenderer.cs index 0b7b32acd..2cf697052 100644 --- a/Assembly-CSharp/Global/World/WorldRainRenderer.cs +++ b/Assembly-CSharp/Global/World/WorldRainRenderer.cs @@ -13,13 +13,10 @@ private void Awake() private void OnPostRender() { if (PersistenSingleton.Instance.IsFading) - { return; - } + SFXData.RenderEventSFX(); if (this.numRain == 0) - { return; - } GL.PushMatrix(); this.mat.SetPass(0); GL.Begin(7); diff --git a/Assembly-CSharp/Global/battle/Result/BattleResultUI.cs b/Assembly-CSharp/Global/battle/Result/BattleResultUI.cs index 780db5792..7aa556de5 100644 --- a/Assembly-CSharp/Global/battle/Result/BattleResultUI.cs +++ b/Assembly-CSharp/Global/battle/Result/BattleResultUI.cs @@ -268,7 +268,6 @@ private void DisplayCharacterInfo() private void DisplayLevelup(Int32 index) { PLAYER player = FF9StateSystem.Common.FF9.party.member[index]; - BattleAchievement.GetReachLv99Achievement(player.level + 1); ff9play.FF9Play_GrowLevel(player, player.level + 1); this.totalLevelUp[index]++; this.ShowLevelUpAnimation(index); diff --git a/Assembly-CSharp/Global/ff9/State/FF9StateGlobal.cs b/Assembly-CSharp/Global/ff9/State/FF9StateGlobal.cs index 3c4250d57..9c0387c6b 100644 --- a/Assembly-CSharp/Global/ff9/State/FF9StateGlobal.cs +++ b/Assembly-CSharp/Global/ff9/State/FF9StateGlobal.cs @@ -848,8 +848,7 @@ public FF9Char FF9GetCharPtr(Int32 uid) public PLAYER GetPlayer(CharacterId id) { - PLAYER p; - if (player.TryGetValue(id, out p)) + if (player.TryGetValue(id, out PLAYER p)) return p; return null; } diff --git a/Assembly-CSharp/Global/ff9/ff9.cs b/Assembly-CSharp/Global/ff9/ff9.cs index 9924eb0c2..c2564d3d9 100644 --- a/Assembly-CSharp/Global/ff9/ff9.cs +++ b/Assembly-CSharp/Global/ff9/ff9.cs @@ -9667,6 +9667,7 @@ public static void ff9InitStateWorldMap(Int32 MapNo) map.nextMapNo = (ff.wldMapNo = (Int16)MapNo); if (!FF9StateSystem.World.IsBeeScene) { + SFXData.Reinit(); EventEngine eventEngine = PersistenSingleton.Instance; String ebFileName = FF9DBAll.EventDB[MapNo]; map.evtPtr = EventEngineUtils.loadEventData(ebFileName, EventEngineUtils.ebSubFolderWorld); diff --git a/Assembly-CSharp/Global/ff9play.cs b/Assembly-CSharp/Global/ff9play.cs index 5a43e695b..f518fe41a 100644 --- a/Assembly-CSharp/Global/ff9play.cs +++ b/Assembly-CSharp/Global/ff9play.cs @@ -375,6 +375,23 @@ public static CharacterId CharacterOldIndexToID(CharacterOldIndex characterIndex return (CharacterId)characterIndex; } + public static CharacterOldIndex CharacterIDToOldIndex(CharacterId charId) + { + if (charId <= CharacterId.Amarant) + return (CharacterOldIndex)charId; + if (charId == CharacterId.Beatrix) + return CharacterOldIndex.Beatrix; + if (charId == CharacterId.Cinna) + return CharacterOldIndex.Cinna; + if (charId == CharacterId.Marcus) + return CharacterOldIndex.Marcus; + if (charId == CharacterId.Blank) + return CharacterOldIndex.Blank; + if (charId == CharacterId.NONE) + return CharacterOldIndex.NONE; + return (CharacterOldIndex)charId; + } + public static Int32 CharacterIDToEventId(CharacterId characterId) { if (characterId <= CharacterId.Amarant) @@ -432,6 +449,7 @@ public static void FF9Play_SetDefEquips(CharacterEquipment target, EquipmentSetI public static void FF9Play_GrowLevel(PLAYER player, Int32 lv) { + BattleAchievement.GetReachLv99Achievement(lv); FF9Play_Build(player, lv, false, true); } diff --git a/Assembly-CSharp/Memoria/Application/SmoothFrameUpdater_Battle.cs b/Assembly-CSharp/Memoria/Application/SmoothFrameUpdater_Battle.cs index 581ef14ab..601ed3dd0 100644 --- a/Assembly-CSharp/Memoria/Application/SmoothFrameUpdater_Battle.cs +++ b/Assembly-CSharp/Memoria/Application/SmoothFrameUpdater_Battle.cs @@ -88,8 +88,7 @@ public static void Apply(Single smoothFactor) { if (_skipCount > 0) return; - if (Configuration.Battle.SFXRework) - SFXData.LoadLoop(); + SFXData.LoadLoop(); Single unclampedFactor = 1f + smoothFactor; for (BTL_DATA next = FF9StateSystem.Battle.FF9Battle.btl_list.next; next != null; next = next.next) { diff --git a/Assembly-CSharp/Memoria/Application/SmoothFrameUpdater_Field.cs b/Assembly-CSharp/Memoria/Application/SmoothFrameUpdater_Field.cs index f40cdbc4c..09cf7409e 100644 --- a/Assembly-CSharp/Memoria/Application/SmoothFrameUpdater_Field.cs +++ b/Assembly-CSharp/Memoria/Application/SmoothFrameUpdater_Field.cs @@ -104,6 +104,7 @@ public static void Apply(Single smoothFactor) { if (_skipCount > 0) return; + SFXData.LoadLoop(); FieldMap fieldmap = PersistenSingleton.Instance.fieldmap; EventEngine eEngine = PersistenSingleton.Instance; Single unclampedFactor = 1f + smoothFactor; diff --git a/Assembly-CSharp/Memoria/Application/SmoothFrameUpdater_World.cs b/Assembly-CSharp/Memoria/Application/SmoothFrameUpdater_World.cs index 69c1163d1..9518b02bb 100644 --- a/Assembly-CSharp/Memoria/Application/SmoothFrameUpdater_World.cs +++ b/Assembly-CSharp/Memoria/Application/SmoothFrameUpdater_World.cs @@ -80,6 +80,7 @@ public static void Apply(Single smoothFactor) { if (_skipCount > 0) return; + SFXData.LoadLoop(); Single unclampedFactor = 1f + smoothFactor; for (ObjList objList = ff9.GetActiveObjList(); objList != null; objList = objList.next) { diff --git a/Assembly-CSharp/Memoria/Battle/Calculator/BattleCalculator.cs b/Assembly-CSharp/Memoria/Battle/Calculator/BattleCalculator.cs index e182afb4a..f205dde18 100644 --- a/Assembly-CSharp/Memoria/Battle/Calculator/BattleCalculator.cs +++ b/Assembly-CSharp/Memoria/Battle/Calculator/BattleCalculator.cs @@ -42,6 +42,8 @@ public static class GameState public static Int16 TetraMasterDraw => FF9StateSystem.MiniGame.SavedData.sDraw; public static Int32 TetraMasterCardCount => QuadMistDatabase.MiniGame_GetAllCardCount(); public static Int32 TetraMasterPlayerPoints => QuadMistDatabase.MiniGame_GetPlayerPoints(); + public static Int32 TetraMasterPlayerRank => QuadMistDatabase.MiniGame_GetCollectorLevel(); + public static Int32 TreasureHunterPoints => FF9StateSystem.EventState.GetTreasureHunterPoints(); public static Int32 GameTime => Convert.ToInt32(FF9StateSystem.Settings.time); public static Int32 AbilityUsage(BattleAbilityId index) => FF9StateSystem.EventState.GetAAUsageCounter(index); public static Int32 ItemCount(RegularItem id) => ff9item.FF9Item_GetCount(id); @@ -71,7 +73,7 @@ public static class BattleState public static Boolean IsSpecialStart => FF9StateSystem.Battle.FF9Battle.btl_scene.Info.SpecialStart; public static Boolean IsBattleStateEnabled => UIManager.Battle.FF9BMenu_IsEnable(); public static Boolean IsATBEnabled => UIManager.Battle.FF9BMenu_IsEnable() && UIManager.Battle.FF9BMenu_IsEnableAtb(); - public static Int32 ATBTickCount => HonoluluBattleMain.counterATB; // Number of times the ATB advanced this tick (there are >1 only in turn-based and fast speed modes) + public static Int32 ATBTickCount => HonoluluBattleMain.counterATB; // Number of times the ATB advanced this tick (there are 2 or more only in turn-based and fast speed modes) public static Int32 SharedATBSpeedCoef => btl_para.GetATBCoef(); // Default increment for each ATB advancement public static Boolean IsRandomBattle => FF9StateSystem.Battle.isRandomEncounter && !IsFriendlyBattle; public static Boolean IsFriendlyBattle => ff9.w_friendlyBattles.Contains((UInt16)FF9StateSystem.Battle.battleMapIndex); diff --git a/Assembly-CSharp/Memoria/Battle/SFX/BattleActionCode.cs b/Assembly-CSharp/Memoria/Battle/SFX/BattleActionCode.cs index 430ee8f9d..8878b3a33 100644 --- a/Assembly-CSharp/Memoria/Battle/SFX/BattleActionCode.cs +++ b/Assembly-CSharp/Memoria/Battle/SFX/BattleActionCode.cs @@ -82,6 +82,7 @@ public BattleActionCode(String op, String key1 = "", String arg1 = "", String ke { "SetupReflect", new String[]{ "Delay" } }, { "ActivateReflect", null }, { "StartThread", new String[]{ "Condition", "LoopCount", "Target", "TargetLoop", "Chain", "Sync" } }, + { "ElseThread", new String[]{ "Condition", "LoopCount", "Target", "TargetLoop", "Chain", "Sync" } }, { "MOVE_WATER", new String[]{ "Char", "Type", "Time" } } }; diff --git a/Assembly-CSharp/Memoria/Battle/SFX/BattleActionThread.cs b/Assembly-CSharp/Memoria/Battle/SFX/BattleActionThread.cs index 0bdf22363..149a6b85f 100644 --- a/Assembly-CSharp/Memoria/Battle/SFX/BattleActionThread.cs +++ b/Assembly-CSharp/Memoria/Battle/SFX/BattleActionThread.cs @@ -15,6 +15,7 @@ public class BattleActionThread public Boolean isReflectThread; public Int32 defaultSFXIndex; // -1 until LoadSFX/LoadMonsterSFX is used, then point to the last one (inherit through RunThread) public SFXData parentSFX; // null except for threads started with PlaySFX/PlayMonsterSFX (inherit through RunThread) + public Boolean skipNextElseThread; public Int32 waitFrame; public UInt16 waitAnimId; @@ -34,6 +35,7 @@ public BattleActionThread() isReflectThread = false; defaultSFXIndex = -1; parentSFX = null; + skipNextElseThread = false; waitFrame = 0; waitAnimId = 0; waitMoveId = 0; @@ -51,6 +53,7 @@ public BattleActionThread(BattleActionThread thread, Boolean asReflectThread = f isReflectThread = asReflectThread; defaultSFXIndex = -1; parentSFX = thread.parentSFX; + skipNextElseThread = false; waitFrame = 0; waitAnimId = 0; waitMoveId = 0; @@ -144,7 +147,7 @@ public static List LoadFromTextSequence(String textCode) Int32 argIndex = nonCommentedline.IndexOf(":"); String opCode = argIndex < 0 ? nonCommentedline : nonCommentedline.Substring(0, argIndex); opCode = opCode.Trim(); - if (opCode == "EndThread" && threadStack.Count > 1) + if ((opCode == "EndThread" || opCode == "ElseThread") && threadStack.Count > 1) { threadStack.Pop(); current = threadStack.Peek(); @@ -177,11 +180,12 @@ public static List LoadFromTextSequence(String textCode) action.argument[argKey] = argValue; } } - if (opCode == "StartThread") + if (opCode == "StartThread" || opCode == "ElseThread") { BattleActionThread newThread = new BattleActionThread(); action.operation = "RunThread"; action.argument["Thread"] = result.Count.ToString(); + action.argument["AsElseThread"] = (opCode == "ElseThread").ToString(); result[current].code.AddLast(action); current = result.Count; threadStack.Push(current); diff --git a/Assembly-CSharp/Memoria/Battle/SFX/SFXData.cs b/Assembly-CSharp/Memoria/Battle/SFX/SFXData.cs index 4a02fa4de..369802db3 100644 --- a/Assembly-CSharp/Memoria/Battle/SFX/SFXData.cs +++ b/Assembly-CSharp/Memoria/Battle/SFX/SFXData.cs @@ -19,6 +19,7 @@ public class SFXData public Boolean useCamera; public Int32 firstMeshFrame; public Boolean loadHasEnded; + public Boolean isEventSFX; public List sfxthread; public List camera; @@ -30,15 +31,17 @@ public class SFXData public static SFXData LoadCur; public static Boolean lockLoading; + public static Dictionary EventSFX = new Dictionary(); // TODO: Event SFX would be SFX tied to event scripts (battle scripts but also field/wm scripts). Loading these SFX and rendering them in fields is not possible yet. Note that PSXTextureMgr is already used for FieldSPS so it would conflict. private static Queue loadingQueue = new Queue(); private static HashSet sfxLoadedNotPlayed = new HashSet(); public const Int32 LoadingTimeAllocatedPerFrame = 25; - public static void InitBattle() + public static void Reinit() { SFXData.LoadCur = null; SFXData.lockLoading = false; + SFXData.EventSFX.Clear(); SFXData.loadingQueue.Clear(); SFXData.sfxLoadedNotPlayed.Clear(); SFXDataMesh.Raw.RenderingCount = 0; @@ -48,6 +51,8 @@ public static void InitBattle() public static void LoadLoop() { + if (LoadCur == null && loadingQueue.Count == 0) + return; Stopwatch watch = new Stopwatch(); watch.Start(); Int32 maxLoadingTime = (Int32)Mathf.Floor(1000f / Configuration.Graphics.BattleFPS); @@ -88,6 +93,46 @@ public static void LoadLoop() } } + public static void AdvanceEventSFXFrame() + { + try + { + foreach (SFXData sfx in SFXData.EventSFX.Values) + foreach (SFXData.RunningInstance run in sfx.runningSFX) + run.frame++; + SFXData.LoadLoop(); + } + catch (Exception err) + { + Log.Error(err); + } + } + + public static void RenderEventSFX() + { + try + { + foreach (SFXData sfx in SFXData.EventSFX.Values) + { + for (Int32 i = 0; i < sfx.runningSFX.Count; i++) + { + SFXData.RunningInstance run = sfx.runningSFX[i]; + if (sfx.mesh.Render(run.frame, run)) + { + sfx.runningSFX.RemoveAt(i); + if (sfx.runningSFX.Count == 0) + sfx.mesh.End(); + i--; + } + } + } + } + catch (Exception err) + { + Log.Error(err); + } + } + public void PlaySFX(Int32 frameStart, List preventMeshByKey = null, List preventMeshByIndex = null, Dictionary colorsByKey = null, Dictionary colorsByIndex = null) { SFXData.sfxLoadedNotPlayed.Remove(this); @@ -116,6 +161,7 @@ public void LoadSFX(SpecialEffect effNum, CMD_DATA cmd, BTL_VFX_REQ request, Boo useCamera = applyCamera; firstMeshFrame = -1; loadHasEnded = false; + isEventSFX = false; cancel = false; sfxthread = new List(); camera = new List(); @@ -134,6 +180,43 @@ public void LoadSFX(SpecialEffect effNum, CMD_DATA cmd, BTL_VFX_REQ request, Boo loadingQueue.Enqueue(this); } + public void LoadEventSFX(Int32 eventId, SpecialEffect effNum, BTL_VFX_REQ request) + { + if (SFXData.EventSFX.TryGetValue(eventId, out SFXData oldSFX)) + { + oldSFX.Cancel(); + if (oldSFX.runningSFX.Count > 0) + { + oldSFX.runningSFX.Clear(); + oldSFX.mesh.End(); + } + } + id = effNum; + cmdRef = null; + sfxRequest = request; + useCamera = false; + firstMeshFrame = -1; + loadHasEnded = false; + isEventSFX = true; + cancel = false; + sfxthread = new List(); + camera = new List(); + mesh = null; + runningSFX = new List(); + String defaultFolder = DataResources.PureDataDirectory + $"SpecialEffects/ef{(Int32)effNum:D3}/"; + String sfxInfo = AssetManager.LoadString(defaultFolder + UnifiedBattleSequencer.INFORMATION_FILE, true); + if (sfxInfo != null) + LoadSFXFromInfo(sfxInfo, defaultFolder); + LoadSequenceFromFile(defaultFolder + UnifiedBattleSequencer.SEQUENCE_FILE); + if (mesh != null) + { + loadHasEnded = true; + return; + } + SFXData.loadingQueue.Enqueue(this); + SFXData.EventSFX[eventId] = this; + } + public void Cancel() { cancel = true; @@ -349,7 +432,7 @@ public Boolean LoadSFXRawLoop() public void LoadSFXRawEnd() { - if (SFXData.BattleCallbackReaderExportSequence) + if (SFXData.BattleCallbackReaderExportSequence && cmdRef != null) { List reworkedThreads = new List(); Single BbgIntensityFactor = 1f; diff --git a/Assembly-CSharp/Memoria/Battle/SFX/SFXDataMesh.cs b/Assembly-CSharp/Memoria/Battle/SFX/SFXDataMesh.cs index 47f930e65..fc05d291b 100644 --- a/Assembly-CSharp/Memoria/Battle/SFX/SFXDataMesh.cs +++ b/Assembly-CSharp/Memoria/Battle/SFX/SFXDataMesh.cs @@ -91,6 +91,20 @@ public static EffectMaterial LoadMaterial(JSONClass matClass, String defaultFold public void StoreInUnityMaterial(Int32 frame, Material mat) { + if (Assets.Scripts.Common.SceneDirector.IsFieldScene()) + { + Dictionary shaderReplacer = new Dictionary + { + { "SFX_OPA_GT", "Unlit/Transparent Cutout" }, + { "SFX_ADD_GT", "Unlit/Transparent Cutout" }, + { "SFX_SUB_GT", "Unlit/Transparent Cutout" }, + { "SFX_OPA_G", "Unlit/Transparent Cutout" }, + { "SFX_ADD_G", "Unlit/Transparent Cutout" }, + { "SFX_SUB_G", "Unlit/Transparent Cutout" }, + }; + if (shaderReplacer.TryGetValue(shaderName, out String rep)) + shaderName = rep; + } mat.shader = ShadersLoader.Find(shaderName); if (SFXDataMesh.SFXColor.HasValue) mat.SetColor(SFXMesh.Color, colorIntensity * SFXDataMesh.SFXColor.Value); @@ -290,7 +304,9 @@ public override void Begin() } public override Boolean Render(int frame, SFXData.RunningInstance run = null) { - Camera camera = Camera.main ? Camera.main : GameObject.Find("Battle Camera").GetComponent().GetComponent(); + Camera camera = Camera.main ? Camera.main : GameObject.Find("Battle Camera")?.GetComponent()?.GetComponent(); + if (camera == null) + camera = GameObject.Find("FieldMap Camera")?.GetComponent(); Matrix4x4 worldToCameraMatrix = camera.worldToCameraMatrix; RenderTexture activeRender = RenderTexture.active; Boolean renderSomething = false; diff --git a/Assembly-CSharp/Memoria/Battle/SFX/UnifiedBattleSequencer.cs b/Assembly-CSharp/Memoria/Battle/SFX/UnifiedBattleSequencer.cs index f20df2ee8..2d0d51071 100644 --- a/Assembly-CSharp/Memoria/Battle/SFX/UnifiedBattleSequencer.cs +++ b/Assembly-CSharp/Memoria/Battle/SFX/UnifiedBattleSequencer.cs @@ -41,8 +41,8 @@ public static void Loop() i--; } } + SFXData.AdvanceEventSFXFrame(); SequenceBBGIntensity.Apply(true); - SFXData.LoadLoop(); } catch (Exception err) { @@ -55,6 +55,7 @@ public static void LoopRender() SFXChannel.Render(); for (Int32 i = 0; i < runningActions.Count; i++) runningActions[i].Render(); + SFXData.RenderEventSFX(); } private static void ReleaseRunningAction(Int32 index) @@ -182,11 +183,15 @@ public void ExecuteSingleCode(Int32 runningThreadId) BattleActionCode code = runningThread.code.First.Value; runningThread.code.RemoveFirst(); Boolean isSFXThread = runningThread.parentSFX != null; + Boolean skipNextElse = false; if (runningThread.isReflectThread && !isSFXThread && code.operation != "RunThread") // SFX thread code is always used for reflect even if not flagged "Reflect" { Boolean executeReflect; if (!code.TryGetArgBoolean("Reflect", out executeReflect) || !executeReflect) + { + runningThread.skipNextElseThread = skipNextElse; return; + } } Single tmpSingle; Boolean tmpBool; @@ -989,6 +994,11 @@ public void ExecuteSingleCode(Int32 runningThreadId) ActivateReflect(); break; case "RunThread": + if (code.TryGetArgBoolean("AsElseThread", out tmpBool) && tmpBool && runningThread.skipNextElseThread) + { + skipNextElse = true; + break; + } if (code.TryGetArgInt32("Thread", out tmpInt) && tmpInt >= 0) { Boolean dontCopyThread; @@ -1047,6 +1057,7 @@ public void ExecuteSingleCode(Int32 runningThreadId) if (!NCalcUtility.EvaluateNCalcCondition(c.Evaluate())) break; } + skipNextElse = true; Boolean loopTarget, chain, sync; Int32 loopCount; if (!code.TryGetArgInt32("LoopCount", out loopCount)) @@ -1087,6 +1098,7 @@ public void ExecuteSingleCode(Int32 runningThreadId) } break; } + runningThread.skipNextElseThread = skipNextElse; } public Boolean ExecuteLoop() diff --git a/Assembly-CSharp/Memoria/Data/Items/ShopItems.cs b/Assembly-CSharp/Memoria/Data/Items/ShopItems.cs index 6bdfb3b38..ee777a9e5 100644 --- a/Assembly-CSharp/Memoria/Data/Items/ShopItems.cs +++ b/Assembly-CSharp/Memoria/Data/Items/ShopItems.cs @@ -10,17 +10,17 @@ public sealed class ShopItems : ICsvEntry public String Comment; public Int32 Id; - public RegularItem[] ItemIds; + public List ItemIds = new List(); public RegularItem this[Int32 index] => ItemIds[index]; - public Int32 Length => ItemIds.Length; + public Int32 Length => ItemIds.Count; public void ParseEntry(String[] raw, CsvMetaData metadata) { Comment = CsvParser.String(raw[0]); Id = CsvParser.Int32(raw[1]); - List itemIds = new List(); + ItemIds.Clear(); for (Int32 i = 2; i < raw.Length; i++) { String value = raw[i]; @@ -37,12 +37,11 @@ public void ParseEntry(String[] raw, CsvMetaData metadata) stop = true; break; } - itemIds.Add(itemId); + ItemIds.Add(itemId); } if (stop) break; } - ItemIds = itemIds.ToArray(); } public void WriteEntry(CsvWriter sw, CsvMetaData metadata) diff --git a/Assembly-CSharp/NCalc/NCalcUtility.cs b/Assembly-CSharp/NCalc/NCalcUtility.cs index fba5c3fa7..7e2b2c7fe 100644 --- a/Assembly-CSharp/NCalc/NCalcUtility.cs +++ b/Assembly-CSharp/NCalc/NCalcUtility.cs @@ -206,6 +206,8 @@ public static String EvaluateNCalcString(Object obj, String defaultResult = "") else if (name == "TetraMasterDrawCount") args.Result = (Int32)GameState.TetraMasterDraw; else if (name == "TetraMasterCardCount") args.Result = (Int32)GameState.TetraMasterCardCount; else if (name == "TetraMasterPlayerPoints") args.Result = (Int32)GameState.TetraMasterPlayerPoints; + else if (name == "TetraMasterPlayerRank") args.Result = (Int32)GameState.TetraMasterPlayerRank; + else if (name == "TreasureHunterPoints") args.Result = (Int32)GameState.TreasureHunterPoints; else if (name == "GameTime") args.Result = (Int32)GameState.GameTime; else if (name == "BattleId") args.Result = (Int32)FF9StateSystem.Battle.battleMapIndex; else if (name == "FieldId") args.Result = (Int32)FF9StateSystem.Common.FF9.fldMapNo;