public void Lock(PlayerChangeType type) { if (valueLocks.ContainsKey(type)) { valueLocks[type] = true; } }
public bool IsLocked(PlayerChangeType type) { Debugger.WriteLine( LogLevel.Info, $"Attempted to change value {EnumHelper.GetName(type)}. Locked: {valueLocks[type]}"); return valueLocks[type]; }
public bool IsLocked(PlayerChangeType type) { Debugger.WriteLine( LogLevel.Info, $"Attempted to change value {EnumHelper.GetName(type)}. Locked: {valueLocks[type]}"); return(valueLocks[type]); }
private async Task OnPlayerChanged(PlayerChangeType type, string connectionId, string playerId) { if (PlayerChanged != null) { await PlayerChanged(this, new PlayerChangedEventArgs(type, connectionId, playerId)); } }
public void Unlock(PlayerChangeType type) { if (valueLocks.ContainsKey(type)) { valueLocks[type] = false; } }
private void UpdateTableValue(PlayerChangeType type) { object value; switch (type) { case PlayerChangeType.Days: value = Player.status.days; break; case PlayerChangeType.PhaseDays: value = Player.status.phase_days; break; case PlayerChangeType.SalonBeautiful: value = Player.status.salon_beautiful; break; case PlayerChangeType.SalonClean: value = Player.status.salon_clean; break; case PlayerChangeType.SalonEvaluation: value = Player.status.salon_evaluation; break; case PlayerChangeType.Money: value = Player.status.money; break; case PlayerChangeType.SalonLoan: value = Player.status.salon_loan; break; case PlayerChangeType.ShopUseMoney: value = Player.status.shop_use_money; break; case PlayerChangeType.BestSalonGrade: value = Player.status.best_salon_grade; break; case PlayerChangeType.SalonGrade: value = Player.status.current_salon_grade; break; case PlayerChangeType.InitSalonLoan: value = Player.status.init_salon_loan; break; default: value = "ERROR"; break; } Debugger.Assert( () => { gui.PlayerParameters[type].Cells[PARAMS_COLUMN_VALUE].Value = value; }, $"Failed to update player parameter {EnumHelper.GetName(type)}!"); }
private void AddRow(PlayerChangeType type, DataGridView table, IDictionary<int, PlayerChangeType> dic, bool addLock = true) { string key = EnumHelper.GetName(type); int index = addLock ? table.Rows.Add(key, 0, false) : table.Rows.Add(key, 0); dic.Add(index, type); Translation.AddTranslationAction(key, s => table.Rows[index].Cells[0].Value = s); PlayerParameters.Add(type, table.Rows[index]); }
public void SetValue(PlayerChangeType type, object value) { Action <int> setValInt; Action <long> setValLong; Action <string> setValString; if (setMethodInt.TryGetValue(type, out setValInt)) { int val; string s = value as string; #pragma warning disable 642 if (s != null && int.TryParse(s, out val)) { ; } #pragma warning restore 642 else if (value is int) { val = (int)value; } else { return; } setValInt(val); } else if (setMethodLong.TryGetValue(type, out setValLong)) { long val; string s = value as string; #pragma warning disable 642 if (s != null && !long.TryParse(s, out val)) { ; } #pragma warning restore 642 else if (value is int || value is long) { val = (long)value; } else { return; } setValLong(val); } else if (value is string && setMethodString.TryGetValue(type, out setValString)) { setValString((string)value); } }
private void AddRow(PlayerChangeType type, DataGridView table, IDictionary <int, PlayerChangeType> dic, bool addLock = true) { string key = EnumHelper.GetName(type); int index = addLock ? table.Rows.Add(key, 0, false) : table.Rows.Add(key, 0); dic.Add(index, type); Translation.AddTranslationAction(key, s => table.Rows[index].Cells[0].Value = s); PlayerParameters.Add(type, table.Rows[index]); }
public void UpdateField(PlayerChangeType type) { Debugger.WriteLine(LogLevel.Info, $"Updating value {type}!"); Action <PlayerChangeType> updateVal; if (!updateMethods.TryGetValue(type, out updateVal)) { return; } gui.valueUpdatePlayer[type] = true; updateVal(type); gui.valueUpdatePlayer[type] = false; }
private void InitField(Label label, Control control, PlayerChangeType type) { if (label != null) { Translation.AddTranslatableControl(label); } if (control is CheckBox) { Translation.AddTranslatableControl(control); } uiControlsPlayer.Add(control, type); InitControl(control); }
private void UpdateGameValue(Control c, object value) { if (uiControls.ContainsKey(c)) { MaidInfo maid = SelectedMaid; if (maid == null) { return; } Debugger.Assert( () => { MaidChangeType type = uiControls[c]; if (type == MaidChangeType.YotogiClassType) { value = EnumHelper.EnabledYotogiClasses[(int)value]; } Debugger.WriteLine( LogLevel.Info, $"Attempting to update value {type} to {value}. Allowed: {!valueUpdate[type]}."); if (!valueUpdate[type]) { maid.SetValue(type, value); } valueUpdate[type] = false; }, $"Failed to set maid value for {maid.Maid.Param.status.first_name} {maid.Maid.Param.status.last_name}"); } else if (uiControlsPlayer.ContainsKey(c)) { if (Player == null) { return; } Debugger.Assert( () => { PlayerChangeType type = uiControlsPlayer[c]; Debugger.WriteLine( LogLevel.Info, $"Attempting to update player value {type} to {value}. Allowed: {!valueUpdatePlayer[type]}."); if (!valueUpdatePlayer[type]) { Player.SetValue(type, value); } valueUpdatePlayer[type] = false; }, "Failed to set player value"); } }
private void InitFunctions() { setMethodInt = new Dictionary <PlayerChangeType, Action <int> > { { PlayerChangeType.Days, SetDays }, { PlayerChangeType.PhaseDays, SetPhaseDays }, { PlayerChangeType.SalonBeautiful, SetSalonBeautiful }, { PlayerChangeType.SalonClean, SetSalonClean }, { PlayerChangeType.SalonEvaluation, SetSalonEvaluation }, { PlayerChangeType.BestSalonGrade, SetBestSalonGrade }, { PlayerChangeType.SalonGrade, SetSalonGrade }, { PlayerChangeType.ScenarioPhase, SetScenarioPhase }, { PlayerChangeType.BaseMaidPoints, SetBaseMaidPoints } }; setMethodLong = new Dictionary <PlayerChangeType, Action <long> > { { PlayerChangeType.Money, SetMoney }, { PlayerChangeType.SalonLoan, SetSalonLoan }, { PlayerChangeType.ShopUseMoney, SetShopUseMoney }, { PlayerChangeType.InitSalonLoan, SetInitSalonLoan } }; setMethodString = new Dictionary <PlayerChangeType, Action <string> > { { PlayerChangeType.Name, SetName } }; updateMethods = new Dictionary <PlayerChangeType, Action <PlayerChangeType> > { { PlayerChangeType.ScenarioPhase, UpdateScenatioPhase }, { PlayerChangeType.Name, UpdateName } }; for (PlayerChangeType e = PlayerChangeType.Days; e < PlayerChangeType.InitSalonLoan; e++) { if (e == PlayerChangeType.ScenarioPhase) { continue; } updateMethods.Add(e, UpdateTableValue); } }
private void OnGameTabCellContentClick(object sender, DataGridViewCellEventArgs e) { if (clearingTables || e.ColumnIndex != PARAMS_COLUMN_LOCK) { return; } DataGridView table = (DataGridView)sender; PlayerChangeType type = gameValuesDic[e.RowIndex]; bool val = !((bool)table[e.ColumnIndex, e.RowIndex].Value); if (val) { Player.Lock(type); } else { Player.Unlock(type); } }
private void OnGameTabCellValueChanged(object sender, DataGridViewCellEventArgs e) { if (clearingTables || e.ColumnIndex == PARAMS_COLUMN_LOCK) { return; } DataGridView table = (DataGridView)sender; PlayerChangeType type = gameValuesDic[e.RowIndex]; if (valueUpdatePlayer[type]) { valueUpdatePlayer[type] = false; return; } object val = table[e.ColumnIndex, e.RowIndex].Value; if (!(val is int) && !(val is long)) { Player.UpdateField(type); return; } bool wasLocked = Player.IsLocked(type); if (wasLocked) { Debugger.WriteLine(LogLevel.Info, $"Value {EnumHelper.GetName(type)} is locked! Unlocking..."); Player.Unlock(type); } Player.SetValue(type, val); if (wasLocked) { Debugger.WriteLine(LogLevel.Info, $"Returning lock to {EnumHelper.GetName(type)}..."); Player.Lock(type); } }
private void InitField(Label label, Control control, PlayerChangeType type) { if (label != null) Translation.AddTranslatableControl(label); if (control is CheckBox) Translation.AddTranslatableControl(control); uiControlsPlayer.Add(control, type); InitControl(control); }
public void SetValue(PlayerChangeType type, object value) { Action<int> setValInt; Action<long> setValLong; Action<string> setValString; if (setMethodInt.TryGetValue(type, out setValInt)) { int val; string s = value as string; #pragma warning disable 642 if (s != null && int.TryParse(s, out val)) ; #pragma warning restore 642 else if (value is int) val = (int) value; else return; setValInt(val); } else if (setMethodLong.TryGetValue(type, out setValLong)) { long val; string s = value as string; if (s == null || !long.TryParse(s, out val)) return; setValLong(val); } else if (value is string && setMethodString.TryGetValue(type, out setValString)) setValString((string) value); gui.valueUpdatePlayer[type] = true; UpdateField(type); }
private void UpdateScenatioPhase(PlayerChangeType _) { gui.comboBox_scenario_phase.SelectedIndex = Player.status.scenario_phase; }
public static void Patch(AssemblyDefinition assembly) { AssemblyDefinition hookAssembly = AssemblyLoader.LoadAssembly( Path.Combine( Path.GetDirectoryName(Assembly.GetAssembly(typeof(MaidFiddlerPatcher)).Location), @"..\Plugins\Managed\CM3D2.MaidFiddler.Hook.dll")); TypeDefinition gameMainType = assembly.MainModule.GetType("GameMain"); TypeDefinition maidParam = assembly.MainModule.GetType("MaidParam"); TypeDefinition maidType = assembly.MainModule.GetType("Maid"); TypeDefinition scheduleAPI = assembly.MainModule.GetType("Schedule.ScheduleAPI"); TypeDefinition daytimeTaskCtrl = assembly.MainModule.GetType("DaytimeTaskCtrl"); TypeDefinition nightTaskCtrl = assembly.MainModule.GetType("NightTaskCtrl"); TypeDefinition playerParam = assembly.MainModule.GetType("PlayerParam"); TypeDefinition yotogiPlayMgr = assembly.MainModule.GetType("YotogiPlayManager"); TypeDefinition wf = assembly.MainModule.GetType("wf"); TypeDefinition status = assembly.MainModule.GetType("param.Status"); TypeDefinition skillData = assembly.MainModule.GetType("Yotogi").NestedTypes.FirstOrDefault(t => t.Name == "SkillData"); TypeDefinition freeModeItemEveryday = assembly.MainModule.GetType("FreeModeItemEveryday"); TypeDefinition freeModeItemVip = assembly.MainModule.GetType("FreeModeItemVip"); TypeDefinition hookType = hookAssembly.MainModule.GetType("CM3D2.MaidFiddler.Hook.FiddlerHooks"); TypeDefinition maidHooks = hookAssembly.MainModule.GetType("CM3D2.MaidFiddler.Hook.MaidStatusChangeHooks"); TypeDefinition playerHooks = hookAssembly.MainModule.GetType("CM3D2.MaidFiddler.Hook.PlayerStatusChangeHooks"); TypeDefinition valueLimitHooks = hookAssembly.MainModule.GetType("CM3D2.MaidFiddler.Hook.ValueLimitHooks"); gameMainType.GetMethod("Deserialize") .GetInjector(hookType, "OnSaveDeserialize", InjectFlags.PassParametersVal) .Inject(-1); // Maid hooks MethodDefinition statusChangeHook = maidHooks.GetMethod(nameof(MaidStatusChangeHooks.OnStatusChanged)); MethodDefinition statusChangeCallbackHook = maidHooks.GetMethod(nameof(MaidStatusChangeHooks.OnStatusChangedCallback)); MethodDefinition propertyGetHook = maidHooks.GetMethod(nameof(MaidStatusChangeHooks.OnNewPropertyGet)); MethodDefinition statusChangeIDHook1 = maidHooks.GetMethod( nameof(MaidStatusChangeHooks.OnStatusChangedID), "System.Int32", "Maid&", "System.Int32"); MethodDefinition statusChangeIDHook2 = maidHooks.GetMethod( nameof(MaidStatusChangeHooks.OnStatusChangedID), "System.Int32", "Maid&", "System.Int32", "System.Int32"); MethodDefinition propertyRemovedHook = maidHooks.GetMethod(nameof(MaidStatusChangeHooks.OnPropertyRemoved)); MethodDefinition statusUpdateHook = maidHooks.GetMethod(nameof(MaidStatusChangeHooks.OnStatusUpdate)); MethodDefinition maidYotogiUpdateHook = maidHooks.GetMethod(nameof(MaidStatusChangeHooks.OnMaidClassAndYotogiUpdate)); MethodDefinition classUpdateHook = maidHooks.GetMethod(nameof(MaidStatusChangeHooks.OnClassTypeUpdate)); MethodDefinition thumbnailChangedHook = maidHooks.GetMethod( nameof(MaidStatusChangeHooks.OnThumbnailChanged)); MethodDefinition noonWorkEnableCheckHook = maidHooks.GetMethod(nameof(MaidStatusChangeHooks.OnNoonWorkEnableCheck)); MethodDefinition nightWorkEnableCheckHook = maidHooks.GetMethod(nameof(MaidStatusChangeHooks.OnNightWorkEnableCheck)); MethodDefinition reloadNoonWorkDataHook = maidHooks.GetMethod(nameof(MaidStatusChangeHooks.ReloadNoonWorkData)); MethodDefinition reloadNightWorkDataHook = maidHooks.GetMethod(nameof(MaidStatusChangeHooks.ReloadNightWorkData)); MethodDefinition featurePropensityUpdatedHook = maidHooks.GetMethod(nameof(MaidStatusChangeHooks.OnFeaturePropensityUpdated)); MethodDefinition nightWorkVisCheckHook = maidHooks.GetMethod(nameof(MaidStatusChangeHooks.CheckNightWorkVisibility)); MethodDefinition yotogiSkillVisCheckHook = maidHooks.GetMethod(nameof(MaidStatusChangeHooks.OnYotogiSkillVisibilityCheck)); MethodDefinition postProcessFreeModeSceneHook = maidHooks.GetMethod(nameof(MaidStatusChangeHooks.PostProcessFreeModeScene)); MethodDefinition onValueRoundInt1 = valueLimitHooks.GetMethod( nameof(ValueLimitHooks.OnValueRound), typeof(int).MakeByRefType(), typeof(int)); MethodDefinition onValueRoundLong1 = valueLimitHooks.GetMethod( nameof(ValueLimitHooks.OnValueRound), typeof(long).MakeByRefType(), typeof(long)); MethodDefinition onValueRoundInt3 = valueLimitHooks.GetMethod( nameof(ValueLimitHooks.OnValueRound), typeof(int).MakeByRefType(), typeof(int), typeof(int), typeof(int)); MethodDefinition onValueRoundLong3 = valueLimitHooks.GetMethod( nameof(ValueLimitHooks.OnValueRound), typeof(long).MakeByRefType(), typeof(long), typeof(long), typeof(long)); // Player hooks MethodDefinition playerStatChangeHook = playerHooks.GetMethod(nameof(PlayerStatusChangeHooks.OnPlayerStatChanged)); const InjectFlags features1 = InjectFlags.PassTag | InjectFlags.PassFields | InjectFlags.ModifyReturn; const InjectFlags features2 = features1 | InjectFlags.PassParametersVal; const InjectFlags features3 = InjectFlags.PassFields | InjectFlags.PassTag; string[] typeNames = Enum.GetNames(typeof(MaidChangeType)); for (int i = (int)MaidChangeType.Care; i <= (int)MaidChangeType.TotalEvaluation; i++) { maidParam.GetMethod($"Add{typeNames[i]}") .InjectWith(statusChangeHook, 0, i, features1, typeFields: new[] { maidParam.GetField("maid_") }); maidParam.GetMethod($"Set{typeNames[i]}") .InjectWith(statusChangeHook, 0, i, features1, typeFields: new[] { maidParam.GetField("maid_") }); } maidParam.GetMethod("SetSexual")? .InjectWith( statusChangeHook, -1, (int)MaidChangeType.Sexual, features1, typeFields: new[] { maidParam.GetField("maid_") }); for (int i = (int)MaidChangeType.FirstName; i <= (int)MaidChangeType.Seikeiken; i++) { maidParam.GetMethod($"Set{typeNames[i]}")? .InjectWith(statusChangeHook, 0, i, features1, typeFields: new[] { maidParam.GetField("maid_") }); } for (int i = (int)MaidChangeType.MaidClassExp; i <= (int)MaidChangeType.YotogiClassExp; i++) { maidParam.GetMethod($"Add{typeNames[i]}", typeof(int)) .InjectWith(statusChangeHook, 0, i, features1, typeFields: new[] { maidParam.GetField("maid_") }); } for (int i = (int)MaidChangeType.SkillPlayCount; i <= (int)MaidChangeType.WorkPlayCount; i++) { maidParam.GetMethod($"Add{typeNames[i]}") .InjectWith( statusChangeIDHook1, 0, i, features2, typeFields: new[] { maidParam.GetField("maid_") }); } maidParam.GetMethod("UpdateProfileComment") .InjectWith( statusChangeHook, 0, (int)MaidChangeType.Profile, features1, typeFields: new[] { maidParam.GetField("maid_") }); maidParam.GetMethod($"Add{typeNames[(int) MaidChangeType.SkillExp]}") .InjectWith( statusChangeIDHook2, 0, (int)MaidChangeType.SkillExp, InjectFlags.PassFields | InjectFlags.PassTag | InjectFlags.PassParametersVal, typeFields: new[] { maidParam.GetField("maid_") }); maidParam.GetMethod($"Set{typeNames[(int) MaidChangeType.WorkLevel]}") .InjectWith( statusChangeIDHook2, 0, (int)MaidChangeType.WorkLevel, features2, typeFields: new[] { maidParam.GetField("maid_") }); PatchFuncEnumBool(MaidChangeType.Propensity, maidParam.GetMethod("SetPropensity"), statusUpdateHook); PatchFuncEnumBool(MaidChangeType.Feature, maidParam.GetMethod("SetFeature"), statusUpdateHook); for (int i = (int)MaidChangeType.NewGetSkill; i <= (int)MaidChangeType.NewGetWork; i++) { maidParam.GetMethod($"Set{typeNames[i]}") .InjectWith( propertyGetHook, 0, i, features3 | InjectFlags.PassParametersVal, typeFields: new[] { maidParam.GetField("maid_") }); } for (int i = (int)MaidChangeType.Skill; i <= (int)MaidChangeType.Work; i++) { maidParam.GetMethod($"Remove{typeNames[i]}") .InjectWith( propertyRemovedHook, 0, i, features3 | InjectFlags.PassParametersVal, typeFields: new[] { maidParam.GetField("maid_") }); } maidParam.GetMethod("UpdatetAcquisitionMaidClassType") .InjectWith( classUpdateHook, 0, (int)MaidChangeType.MaidClassType, features3, typeFields: new[] { maidParam.GetField("maid_") }); maidParam.GetMethod("UpdatetAcquisitionYotogiClassType") .InjectWith( classUpdateHook, 0, (int)MaidChangeType.YotogiClassType, features3, typeFields: new[] { maidParam.GetField("maid_") }); maidParam.GetMethod("UpdateMaidClassAndYotogiClassStatus") .InjectWith( maidYotogiUpdateHook, 0, 0, InjectFlags.PassFields, typeFields: new[] { maidParam.GetField("maid_") }); PatchFuncEnum( MaidChangeType.MaidClassType, maidParam.GetMethods("AddMaidClassExp").FirstOrDefault(m => m.Parameters.Count == 2), statusChangeIDHook1); PatchFuncEnum( MaidChangeType.YotogiClassType, maidParam.GetMethods("AddYotogiClassExp").FirstOrDefault(m => m.Parameters.Count == 2), statusChangeIDHook1); maidType.GetMethod("ThumShot").InjectWith(thumbnailChangedHook, -1, 0, InjectFlags.PassInvokingInstance); maidType.GetMethod("SetThumIcon")?.InjectWith(thumbnailChangedHook, -1, 0, InjectFlags.PassInvokingInstance); scheduleAPI.GetMethod("EnableNoonWork") .InjectWith( noonWorkEnableCheckHook, 0, 0, InjectFlags.ModifyReturn | InjectFlags.PassParametersVal); scheduleAPI.GetMethod("EnableNightWork") .InjectWith( nightWorkEnableCheckHook, 0, 0, InjectFlags.ModifyReturn | InjectFlags.PassParametersVal); daytimeTaskCtrl.GetMethod("LoadData") .InjectWith( reloadNoonWorkDataHook, 5, flags: InjectFlags.PassFields | InjectFlags.PassParametersVal, typeFields: new[] { daytimeTaskCtrl.GetField("m_scheduleApi") }); nightTaskCtrl.GetMethod("LoadData") .InjectWith( reloadNightWorkDataHook, 5, flags: InjectFlags.PassFields | InjectFlags.PassParametersVal, typeFields: new[] { nightTaskCtrl.GetField("m_scheduleApi") }); scheduleAPI.GetMethod("VisibleNightWork") .InjectWith( nightWorkVisCheckHook, 0, 0, InjectFlags.ModifyReturn | InjectFlags.PassParametersVal); maidParam.GetMethod("UpdateFeatureAndPropensity") .InjectWith( featurePropensityUpdatedHook, -1, 0, InjectFlags.PassFields | InjectFlags.PassParametersVal, typeFields: new[] { maidParam.GetField("maid_") }); maidParam.GetMethod("SetFeature", "System.Collections.Generic.HashSet`1<param.Feature>") .InjectWith( statusChangeCallbackHook, -1, (int)MaidChangeType.FeatureHash, InjectFlags.PassTag | InjectFlags.PassFields, typeFields: new[] { maidParam.GetField("maid_") }); maidParam.GetMethod("SetPropensity", "System.Collections.Generic.HashSet`1<param.Propensity>") .InjectWith( statusChangeCallbackHook, -1, (int)MaidChangeType.PropensityHash, InjectFlags.PassTag | InjectFlags.PassFields, typeFields: new[] { maidParam.GetField("maid_") }); for (PlayerChangeType e = PlayerChangeType.Days; e <= PlayerChangeType.ShopUseMoney; e++) { string addMethod = $"Add{Enum.GetName(typeof (PlayerChangeType), e)}"; string setMethod = $"Set{Enum.GetName(typeof (PlayerChangeType), e)}"; playerParam.GetMethod(addMethod) .InjectWith(playerStatChangeHook, 0, (int)e, InjectFlags.PassTag | InjectFlags.ModifyReturn); playerParam.GetMethod(setMethod) .InjectWith(playerStatChangeHook, 0, (int)e, InjectFlags.PassTag | InjectFlags.ModifyReturn); } for (PlayerChangeType e = PlayerChangeType.BestSalonGrade; e <= PlayerChangeType.Name; e++) { string setMethod = $"Set{Enum.GetName(typeof (PlayerChangeType), e)}"; playerParam.GetMethod(setMethod) .InjectWith(playerStatChangeHook, 0, (int)e, InjectFlags.PassTag | InjectFlags.ModifyReturn); } yotogiPlayMgr.GetMethod("UpdateCommand") .InjectWith( maidHooks.GetMethod(nameof(MaidStatusChangeHooks.OnUpdateCommand)), -1, 0, InjectFlags.PassFields, typeFields: new[] { yotogiPlayMgr.GetField("player_state_"), yotogiPlayMgr.GetField("valid_command_dic_"), yotogiPlayMgr.GetField("command_factory_") }); skillData.GetMethod("IsExecMaid") .InjectWith(yotogiSkillVisCheckHook, 0, 0, InjectFlags.PassTag | InjectFlags.ModifyReturn); skillData.GetMethod("IsExecStage") .InjectWith(yotogiSkillVisCheckHook, 0, 1, InjectFlags.PassTag | InjectFlags.ModifyReturn); wf.GetMethod("NumRound2") .InjectWith(onValueRoundInt1, 0, 0, InjectFlags.ModifyReturn | InjectFlags.PassParametersVal); wf.GetMethod("NumRound3") .InjectWith(onValueRoundInt1, 0, 0, InjectFlags.ModifyReturn | InjectFlags.PassParametersVal); wf.GetMethod("NumRound4", typeof(int)) .InjectWith(onValueRoundInt1, 0, 0, InjectFlags.ModifyReturn | InjectFlags.PassParametersVal); wf.GetMethod("NumRound4", typeof(long)) .InjectWith(onValueRoundLong1, 0, 0, InjectFlags.ModifyReturn | InjectFlags.PassParametersVal); wf.GetMethod("NumRound6") .InjectWith(onValueRoundLong1, 0, 0, InjectFlags.ModifyReturn | InjectFlags.PassParametersVal); wf.GetMethod("RoundMinMax", typeof(int), typeof(int), typeof(int)) .InjectWith(onValueRoundInt3, 0, 0, InjectFlags.ModifyReturn | InjectFlags.PassParametersVal); wf.GetMethod("RoundMinMax", typeof(long), typeof(long), typeof(long)) .InjectWith(onValueRoundLong3, 0, 0, InjectFlags.ModifyReturn | InjectFlags.PassParametersVal); freeModeItemEveryday?.GetMethod(".ctor") .InjectWith( postProcessFreeModeSceneHook, -1, 0, InjectFlags.PassFields, typeFields: new[] { freeModeItemEveryday.GetField("is_enabled_") }); freeModeItemVip?.GetMethod(".ctor") .InjectWith( postProcessFreeModeSceneHook, -1, 0, InjectFlags.PassFields, typeFields: new[] { freeModeItemVip.GetField("is_enabled_") }); maidParam.ChangeAccess("status_"); playerParam.ChangeAccess("status_"); status.ChangeAccess("kInitMaidPoint"); SetCustomPatchedAttribute(assembly); }
public void UpdateField(PlayerChangeType type) { Debugger.WriteLine(LogLevel.Info, $"Updating value {type}!"); Action<PlayerChangeType> updateVal; if (!updateMethods.TryGetValue(type, out updateVal)) return; gui.valueUpdatePlayer[type] = true; updateVal(type); gui.valueUpdatePlayer[type] = false; }
private void UpdateName(PlayerChangeType _) { gui.textBox_player_name.Text = Player.status.player_name; }
public void Lock(PlayerChangeType type) { if (valueLocks.ContainsKey(type)) valueLocks[type] = true; }
public void Unlock(PlayerChangeType type) { if (valueLocks.ContainsKey(type)) valueLocks[type] = false; }
public override void Patch(PatcherArguments args) { TypeDefinition gameMainType = args.Assembly.MainModule.GetType("GameMain"); TypeDefinition maidParam = args.Assembly.MainModule.GetType("MaidParam"); TypeDefinition maidType = args.Assembly.MainModule.GetType("Maid"); TypeDefinition scheduleAPI = args.Assembly.MainModule.GetType("Schedule.ScheduleAPI"); TypeDefinition daytimeTaskCtrl = args.Assembly.MainModule.GetType("DaytimeTaskCtrl"); TypeDefinition nightTaskCtrl = args.Assembly.MainModule.GetType("NightTaskCtrl"); TypeDefinition playerParam = args.Assembly.MainModule.GetType("PlayerParam"); TypeDefinition yotogiPlayMgr = args.Assembly.MainModule.GetType("YotogiPlayManager"); TypeDefinition wf = args.Assembly.MainModule.GetType("wf"); TypeDefinition status = args.Assembly.MainModule.GetType("param.Status"); TypeDefinition skillData = args.Assembly.MainModule.GetType("Yotogi").NestedTypes.FirstOrDefault(t => t.Name == "SkillData"); TypeDefinition freeModeItemEveryday = args.Assembly.MainModule.GetType("FreeModeItemEveryday"); TypeDefinition freeModeItemVip = args.Assembly.MainModule.GetType("FreeModeItemVip"); TypeDefinition hookType = FiddlerAssembly.MainModule.GetType("CM3D2.MaidFiddler.Hook.FiddlerHooks"); TypeDefinition maidHooks = FiddlerAssembly.MainModule.GetType( "CM3D2.MaidFiddler.Hook.MaidStatusChangeHooks"); TypeDefinition playerHooks = FiddlerAssembly.MainModule.GetType("CM3D2.MaidFiddler.Hook.PlayerStatusChangeHooks"); TypeDefinition valueLimitHooks = FiddlerAssembly.MainModule.GetType( "CM3D2.MaidFiddler.Hook.ValueLimitHooks"); gameMainType.GetMethod("Deserialize") .GetInjector(hookType, "OnSaveDeserialize", InjectFlags.PassParametersVal) .Inject(-1); // Maid hooks MethodDefinition statusChangeHook = maidHooks.GetMethod(nameof(MaidStatusChangeHooks.OnStatusChanged)); MethodDefinition statusChangeCallbackHook = maidHooks.GetMethod(nameof(MaidStatusChangeHooks.OnStatusChangedCallback)); MethodDefinition propertyGetHook = maidHooks.GetMethod(nameof(MaidStatusChangeHooks.OnNewPropertyGet)); MethodDefinition statusChangeIDHook1 = maidHooks.GetMethod( nameof(MaidStatusChangeHooks.OnStatusChangedID), typeof(int), typeof(Maid).MakeByRefType(), typeof(int)); MethodDefinition statusChangeIDHook2 = maidHooks.GetMethod( nameof(MaidStatusChangeHooks.OnStatusChangedID), typeof(int), typeof(Maid).MakeByRefType(), typeof(int), typeof(int)); MethodDefinition propertyRemovedHook = maidHooks.GetMethod(nameof(MaidStatusChangeHooks.OnPropertyRemoved)); MethodDefinition statusUpdateHook = maidHooks.GetMethod(nameof(MaidStatusChangeHooks.OnStatusUpdate)); MethodDefinition maidYotogiUpdateHook = maidHooks.GetMethod(nameof(MaidStatusChangeHooks.OnMaidClassAndYotogiUpdate)); MethodDefinition classUpdateHook = maidHooks.GetMethod(nameof(MaidStatusChangeHooks.OnClassTypeUpdate)); MethodDefinition thumbnailChangedHook = maidHooks.GetMethod( nameof(MaidStatusChangeHooks.OnThumbnailChanged)); MethodDefinition noonWorkEnableCheckHook = maidHooks.GetMethod(nameof(MaidStatusChangeHooks.OnNoonWorkEnableCheck)); MethodDefinition nightWorkEnableCheckHook = maidHooks.GetMethod(nameof(MaidStatusChangeHooks.OnNightWorkEnableCheck)); MethodDefinition reloadNoonWorkDataHook = maidHooks.GetMethod(nameof(MaidStatusChangeHooks.ReloadNoonWorkData)); MethodDefinition reloadNightWorkDataHook = maidHooks.GetMethod(nameof(MaidStatusChangeHooks.ReloadNightWorkData)); MethodDefinition featurePropensityUpdatedHook = maidHooks.GetMethod(nameof(MaidStatusChangeHooks.OnFeaturePropensityUpdated)); MethodDefinition nightWorkVisCheckHook = maidHooks.GetMethod(nameof(MaidStatusChangeHooks.CheckNightWorkVisibility)); MethodDefinition yotogiSkillVisCheckHook = maidHooks.GetMethod(nameof(MaidStatusChangeHooks.OnYotogiSkillVisibilityCheck)); MethodDefinition postProcessFreeModeSceneHook = maidHooks.GetMethod(nameof(MaidStatusChangeHooks.PostProcessFreeModeScene)); MethodDefinition onValueRoundInt1 = valueLimitHooks.GetMethod( nameof(ValueLimitHooks.OnValueRound), typeof(int).MakeByRefType(), typeof(int)); MethodDefinition onValueRoundLong1 = valueLimitHooks.GetMethod( nameof(ValueLimitHooks.OnValueRound), typeof(long).MakeByRefType(), typeof(long)); MethodDefinition onValueRoundInt3 = valueLimitHooks.GetMethod( nameof(ValueLimitHooks.OnValueRound), typeof(int).MakeByRefType(), typeof(int), typeof(int), typeof(int)); MethodDefinition onValueRoundLong3 = valueLimitHooks.GetMethod( nameof(ValueLimitHooks.OnValueRound), typeof(long).MakeByRefType(), typeof(long), typeof(long), typeof(long)); // Player hooks MethodDefinition playerStatChangeHook = playerHooks.GetMethod(nameof(PlayerStatusChangeHooks.OnPlayerStatChanged)); const InjectFlags features1 = InjectFlags.PassTag | InjectFlags.PassFields | InjectFlags.ModifyReturn; const InjectFlags features2 = features1 | InjectFlags.PassParametersVal; const InjectFlags features3 = InjectFlags.PassFields | InjectFlags.PassTag; string[] typeNames = Enum.GetNames(typeof(MaidChangeType)); Console.WriteLine("Patching basic Add/Set methods:"); for (int i = (int)MaidChangeType.Care; i <= (int)MaidChangeType.TotalEvaluation; i++) { WritePreviousLine($"Add{typeNames[i]}"); maidParam.GetMethod($"Add{typeNames[i]}") .InjectWith(statusChangeHook, 0, i, features1, typeFields: new[] { maidParam.GetField("maid_") }); WritePreviousLine($"Set{typeNames[i]}"); maidParam.GetMethod($"Set{typeNames[i]}") .InjectWith(statusChangeHook, 0, i, features1, typeFields: new[] { maidParam.GetField("maid_") }); } MethodDefinition setSexual = maidParam.GetMethod("SetSexual"); if (setSexual != null) { WritePreviousLine("SetSexual"); maidParam.GetMethod("SetSexual") .InjectWith( statusChangeHook, -1, (int)MaidChangeType.Sexual, features1, typeFields: new[] { maidParam.GetField("maid_") }); } for (int i = (int)MaidChangeType.FirstName; i <= (int)MaidChangeType.Seikeiken; i++) { WritePreviousLine($"Set{typeNames[i]}"); MethodDefinition setDefinition = maidParam.GetMethod($"Set{typeNames[i]}"); if (setDefinition == null) { Console.WriteLine("Method not found (probably older version of the game). Skipping..."); continue; } setDefinition.InjectWith( statusChangeHook, 0, i, features1, typeFields: new[] { maidParam.GetField("maid_") }); } for (int i = (int)MaidChangeType.MaidClassExp; i <= (int)MaidChangeType.YotogiClassExp; i++) { WritePreviousLine($"Add{typeNames[i]}"); maidParam.GetMethod($"Add{typeNames[i]}", typeof(int)) .InjectWith(statusChangeHook, 0, i, features1, typeFields: new[] { maidParam.GetField("maid_") }); } for (int i = (int)MaidChangeType.SkillPlayCount; i <= (int)MaidChangeType.WorkPlayCount; i++) { WritePreviousLine($"Add{typeNames[i]}"); maidParam.GetMethod($"Add{typeNames[i]}") .InjectWith( statusChangeIDHook1, 0, i, features2, typeFields: new[] { maidParam.GetField("maid_") }); } WritePreviousLine("UpdateProfileComment"); maidParam.GetMethod("UpdateProfileComment") .InjectWith( statusChangeHook, 0, (int)MaidChangeType.Profile, features1, typeFields: new[] { maidParam.GetField("maid_") }); WritePreviousLine($"Add{typeNames[(int) MaidChangeType.SkillExp]}"); maidParam.GetMethod($"Add{typeNames[(int) MaidChangeType.SkillExp]}") .InjectWith( statusChangeIDHook2, 0, (int)MaidChangeType.SkillExp, InjectFlags.PassFields | InjectFlags.PassTag | InjectFlags.PassParametersVal, typeFields: new[] { maidParam.GetField("maid_") }); WritePreviousLine($"Set{typeNames[(int) MaidChangeType.WorkLevel]}"); maidParam.GetMethod($"Set{typeNames[(int) MaidChangeType.WorkLevel]}") .InjectWith( statusChangeIDHook2, 0, (int)MaidChangeType.WorkLevel, features2, typeFields: new[] { maidParam.GetField("maid_") }); WritePreviousLine("SetPropensity"); PatchFuncEnumBool(MaidChangeType.Propensity, maidParam.GetMethod("SetPropensity"), statusUpdateHook); WritePreviousLine("SetFeature"); PatchFuncEnumBool(MaidChangeType.Feature, maidParam.GetMethod("SetFeature"), statusUpdateHook); for (int i = (int)MaidChangeType.NewGetSkill; i <= (int)MaidChangeType.NewGetWork; i++) { WritePreviousLine($"Set{typeNames[i]}"); maidParam.GetMethod($"Set{typeNames[i]}") .InjectWith( propertyGetHook, 0, i, features3 | InjectFlags.PassParametersVal, typeFields: new[] { maidParam.GetField("maid_") }); } for (int i = (int)MaidChangeType.Skill; i <= (int)MaidChangeType.Work; i++) { WritePreviousLine($"Remove{typeNames[i]}"); maidParam.GetMethod($"Remove{typeNames[i]}") .InjectWith( propertyRemovedHook, 0, i, features3 | InjectFlags.PassParametersVal, typeFields: new[] { maidParam.GetField("maid_") }); } WritePreviousLine("UpdatetAcquisitionMaidClassType"); maidParam.GetMethod("UpdatetAcquisitionMaidClassType") .InjectWith( classUpdateHook, 0, (int)MaidChangeType.MaidClassType, features3, typeFields: new[] { maidParam.GetField("maid_") }); WritePreviousLine("UpdatetAcquisitionYotogiClassType"); maidParam.GetMethod("UpdatetAcquisitionYotogiClassType") .InjectWith( classUpdateHook, 0, (int)MaidChangeType.YotogiClassType, features3, typeFields: new[] { maidParam.GetField("maid_") }); WritePreviousLine("UpdateMaidClassAndYotogiClassStatus"); maidParam.GetMethod("UpdateMaidClassAndYotogiClassStatus") .InjectWith( maidYotogiUpdateHook, 0, 0, InjectFlags.PassFields, typeFields: new[] { maidParam.GetField("maid_") }); WritePreviousLine("AddMaidClassExp"); PatchFuncEnum( MaidChangeType.MaidClassType, maidParam.GetMethods("AddMaidClassExp").FirstOrDefault(m => m.Parameters.Count == 2), statusChangeIDHook1); WritePreviousLine("AddYotogiClassExp"); PatchFuncEnum( MaidChangeType.YotogiClassType, maidParam.GetMethods("AddYotogiClassExp").FirstOrDefault(m => m.Parameters.Count == 2), statusChangeIDHook1); WritePreviousLine("ThumShot"); maidType.GetMethod("ThumShot").InjectWith(thumbnailChangedHook, -1, 0, InjectFlags.PassInvokingInstance); MethodDefinition setThumIcon = maidType.GetMethod("SetThumIcon"); if (setThumIcon != null) { WritePreviousLine("SetThumIcon"); setThumIcon.InjectWith(thumbnailChangedHook, -1, 0, InjectFlags.PassInvokingInstance); } WritePreviousLine("EnableNoonWork"); scheduleAPI.GetMethod("EnableNoonWork") .InjectWith( noonWorkEnableCheckHook, 0, 0, InjectFlags.ModifyReturn | InjectFlags.PassParametersVal); WritePreviousLine("EnableNightWork"); scheduleAPI.GetMethod("EnableNightWork") .InjectWith( nightWorkEnableCheckHook, 0, 0, InjectFlags.ModifyReturn | InjectFlags.PassParametersVal); WritePreviousLine("DaytimeTaskCtrl.LoadData"); daytimeTaskCtrl.GetMethod("LoadData") .InjectWith( reloadNoonWorkDataHook, 5, flags: InjectFlags.PassFields | InjectFlags.PassParametersVal, typeFields: new[] { daytimeTaskCtrl.GetField("m_scheduleApi") }); WritePreviousLine("NightTaskCtrl.LoadData"); nightTaskCtrl.GetMethod("LoadData") .InjectWith( reloadNightWorkDataHook, 5, flags: InjectFlags.PassFields | InjectFlags.PassParametersVal, typeFields: new[] { nightTaskCtrl.GetField("m_scheduleApi") }); WritePreviousLine("VisibleNightWork"); scheduleAPI.GetMethod("VisibleNightWork") .InjectWith( nightWorkVisCheckHook, 0, 0, InjectFlags.ModifyReturn | InjectFlags.PassParametersVal); WritePreviousLine("UpdateFeatureAndPropensity"); maidParam.GetMethod("UpdateFeatureAndPropensity") .InjectWith( featurePropensityUpdatedHook, -1, 0, InjectFlags.PassFields | InjectFlags.PassParametersVal, typeFields: new[] { maidParam.GetField("maid_") }); WritePreviousLine("SetFeature(HashSet)"); maidParam.GetMethod("SetFeature", typeof(HashSet <>).MakeGenericType(typeof(Feature))) .InjectWith( statusChangeCallbackHook, -1, (int)MaidChangeType.FeatureHash, InjectFlags.PassTag | InjectFlags.PassFields, typeFields: new[] { maidParam.GetField("maid_") }); WritePreviousLine("SetPropensity(HashSet)"); maidParam.GetMethod("SetPropensity", typeof(HashSet <>).MakeGenericType(typeof(Propensity))) .InjectWith( statusChangeCallbackHook, -1, (int)MaidChangeType.PropensityHash, InjectFlags.PassTag | InjectFlags.PassFields, typeFields: new[] { maidParam.GetField("maid_") }); for (PlayerChangeType e = PlayerChangeType.Days; e <= PlayerChangeType.ShopUseMoney; e++) { string addMethod = $"Add{Enum.GetName(typeof (PlayerChangeType), e)}"; string setMethod = $"Set{Enum.GetName(typeof (PlayerChangeType), e)}"; WritePreviousLine(addMethod); playerParam.GetMethod(addMethod) .InjectWith(playerStatChangeHook, 0, (int)e, InjectFlags.PassTag | InjectFlags.ModifyReturn); WritePreviousLine(setMethod); playerParam.GetMethod(setMethod) .InjectWith(playerStatChangeHook, 0, (int)e, InjectFlags.PassTag | InjectFlags.ModifyReturn); } for (PlayerChangeType e = PlayerChangeType.BestSalonGrade; e <= PlayerChangeType.Name; e++) { string setMethod = $"Set{Enum.GetName(typeof (PlayerChangeType), e)}"; WritePreviousLine(setMethod); playerParam.GetMethod(setMethod) .InjectWith(playerStatChangeHook, 0, (int)e, InjectFlags.PassTag | InjectFlags.ModifyReturn); } WritePreviousLine("UpdateCommand"); yotogiPlayMgr.GetMethod("UpdateCommand") .InjectWith( maidHooks.GetMethod(nameof(MaidStatusChangeHooks.OnUpdateCommand)), -1, 0, InjectFlags.PassFields, typeFields: new[] { yotogiPlayMgr.GetField("player_state_"), yotogiPlayMgr.GetField("valid_command_dic_"), yotogiPlayMgr.GetField("command_factory_") }); WritePreviousLine("IsExecMaid"); skillData.GetMethod("IsExecMaid") .InjectWith(yotogiSkillVisCheckHook, 0, 0, InjectFlags.PassTag | InjectFlags.ModifyReturn); WritePreviousLine("IsExecStage"); skillData.GetMethod("IsExecStage") .InjectWith(yotogiSkillVisCheckHook, 0, 1, InjectFlags.PassTag | InjectFlags.ModifyReturn); WritePreviousLine("NumRound2"); wf.GetMethod("NumRound2") .InjectWith(onValueRoundInt1, 0, 0, InjectFlags.ModifyReturn | InjectFlags.PassParametersVal); WritePreviousLine("NumRound3"); wf.GetMethod("NumRound3") .InjectWith(onValueRoundInt1, 0, 0, InjectFlags.ModifyReturn | InjectFlags.PassParametersVal); WritePreviousLine("NumRound4(int)"); wf.GetMethod("NumRound4", typeof(int)) .InjectWith(onValueRoundInt1, 0, 0, InjectFlags.ModifyReturn | InjectFlags.PassParametersVal); WritePreviousLine("NumRound4(long)"); wf.GetMethod("NumRound4", typeof(long)) .InjectWith(onValueRoundLong1, 0, 0, InjectFlags.ModifyReturn | InjectFlags.PassParametersVal); WritePreviousLine("NumRound6"); wf.GetMethod("NumRound6") .InjectWith(onValueRoundLong1, 0, 0, InjectFlags.ModifyReturn | InjectFlags.PassParametersVal); WritePreviousLine("RoundMinMax(int)"); wf.GetMethod("RoundMinMax", typeof(int), typeof(int), typeof(int)) .InjectWith(onValueRoundInt3, 0, 0, InjectFlags.ModifyReturn | InjectFlags.PassParametersVal); WritePreviousLine("RoundMinMax(long)"); wf.GetMethod("RoundMinMax", typeof(long), typeof(long), typeof(long)) .InjectWith(onValueRoundLong3, 0, 0, InjectFlags.ModifyReturn | InjectFlags.PassParametersVal); if (freeModeItemEveryday != null) { WritePreviousLine("FreeModeItemEveryday.ctor"); freeModeItemEveryday.GetMethod(".ctor") .InjectWith( postProcessFreeModeSceneHook, -1, 0, InjectFlags.PassFields, typeFields: new[] { freeModeItemEveryday.GetField("is_enabled_") }); } if (freeModeItemVip != null) { WritePreviousLine("FreeModeItemVip.ctor"); freeModeItemVip.GetMethod(".ctor") .InjectWith( postProcessFreeModeSceneHook, -1, 0, InjectFlags.PassFields, typeFields: new[] { freeModeItemVip.GetField("is_enabled_") }); } Console.WriteLine("Done. Patching class members:\n"); WritePreviousLine("MaidParam.status_"); maidParam.ChangeAccess("status_"); WritePreviousLine("MaidParam.status_"); playerParam.ChangeAccess("status_"); WritePreviousLine("param.Status.kInitMaidPoint"); status.ChangeAccess("kInitMaidPoint"); SetPatchedAttribute(args.Assembly, TAG); SetCustomPatchedAttribute(args.Assembly); Console.WriteLine("\nPatching complete."); }
private void InitField(Label label, Control control, PlayerChangeType type) { if (label != null) label.Text = Resources.GetFieldText(EnumHelper.GetName(type)); if (control is CheckBox) control.Text = Resources.GetFieldText(EnumHelper.GetName(type)); uiControlsPlayer.Add(control, type); InitControl(control); }
public void UpdateField(PlayerChangeType type) { Action updateVal; if (!updateMethods.TryGetValue(type, out updateVal)) return; gui.valueUpdatePlayer[type] = true; updateVal(); gui.valueUpdatePlayer[type] = false; }
public PlayerChangedEventArgs(PlayerChangeType type, string connectionId, string playerId) { Type = type; ConnectionId = connectionId; PlayerId = playerId; }