/// <summary> /// /// </summary> /// <param name="evt"></param> /// <param name="chosenDifficulty"></param> /// <param name="client"></param> private void ChooseDifficultyHandler(string evt, byte[] chosenDifficulty, VMEODClient client) { if (GameState.Equals(FreeSOMazeStates.Lobby) && NextState.Equals(FreeSOMazeStates.Invalid)) { FreeSOMazePlayer caller = null; FreeSOMazePlayer partner = null; if (LogicPlayer != null && client.Equals(LogicPlayer.Client)) { caller = LogicPlayer; partner = CharismaPlayer; } else { caller = CharismaPlayer; partner = LogicPlayer; } int difficultyNum = BitConverter.ToInt32(chosenDifficulty, 0); FreeSOMazeDifficulties difficulty = FreeSOMazeDifficulties.Unselected; if (Enum.IsDefined(typeof(FreeSOMazeDifficulties), difficultyNum)) { difficulty = (FreeSOMazeDifficulties)Enum.ToObject(typeof(FreeSOMazeDifficulties), difficultyNum); } ValidateDifficulty(caller, difficulty, partner); } }
/// <summary> /// Pay the player from Maxis the amount specified. /// </summary> /// <param name="player"></param> /// <param name="amount"></param> private void ExecutePlayerPayout(FreeSOMazePlayer player, int amount) { if (player != null && player.Client != null) { var vm = player.Client.vm; // payout from Maxis to the player vm.GlobalLink.PerformTransaction(vm, false, uint.MaxValue, player.Client.Avatar.PersistID, amount, (bool success, int transferAmount, uint uid1, uint budget1, uint uid2, uint budget2) => { }); } }
/// <summary> /// Send to the player the event that will allow their input doing the maze gameplay, and their direction/barrier/hint data. /// </summary> /// <param name="player"></param> /// <param name="rollForHint">If true, execute the random to determine if the hint should be sent, if false just send only if hint already exists</param> private void SendAllowMazeEvent(FreeSOMazePlayer player, bool rollForHint) { if (player?.Cooldown >= GLOBAL_COOLDOWN) { player?.Send("FreeSOMaze_allow_maze", player?.GetLocationData(GetHint(player, rollForHint))); } else { player?.QueueAllowMazeEvent("FreeSOMaze_allow_maze", player?.GetLocationData(GetHint(player, rollForHint))); } }
/// <summary> /// /// </summary> /// <param name="evt"></param> /// <param name="chosenCardinal"></param> /// <param name="client"></param> private void MoveRequestHandler(string evt, byte[] chosenCardinal, VMEODClient client) { if (GameState.Equals(FreeSOMazeStates.NavigatingMaze) && NextState.Equals(FreeSOMazeStates.Invalid)) { FreeSOMazePlayer player = null; FreeSOMazePlayer partner = null; if (LogicPlayer?.Client.Equals(client) ?? false) { player = LogicPlayer; partner = CharismaPlayer; } else if (CharismaPlayer?.Client.Equals(client) ?? false) { player = CharismaPlayer; partner = LogicPlayer; } if (player != null) { if (player.Cooldown >= GLOBAL_COOLDOWN && Enum.IsDefined(typeof(FreeSOMazeCardinals), chosenCardinal[0])) { var location = player.Location; var cardinal = (FreeSOMazeCardinals)Enum.ToObject(typeof(FreeSOMazeCardinals), chosenCardinal[0]); AbstractMazeCell <FreeSOMazeData> target = null; switch (cardinal) { case FreeSOMazeCardinals.North: target = location.North_Neighbor; break; case FreeSOMazeCardinals.East: target = location.East_Neighbor; break; case FreeSOMazeCardinals.West: target = location.West_Neighbor; break; case FreeSOMazeCardinals.South: target = location.South_Neighbor; break; } if (target != null) // it is a legal move { ValidateLegalMove(player, target, cardinal, partner); return; } } SendAllowMazeEvent(player, false); // re-enables input } } }
/// <summary> /// When the user has loaded all of the textures for the first time. If their partner exists, send their object id and their difficulty choice, if applicable. /// </summary> /// <param name="evt">"FreeSOMaze_loaded"</param> /// <param name="nothing"></param> /// <param name="client"></param> private void FirstLoadHandler(string evt, byte[] nothing, VMEODClient client) { FreeSOMazePlayer caller = null; FreeSOMazePlayer partner = null; if (LogicPlayer != null && client.Equals(LogicPlayer.Client)) { caller = LogicPlayer; partner = CharismaPlayer; } else { caller = CharismaPlayer; partner = LogicPlayer; } caller.Loaded(); SendLobbyInfoEvent(caller, partner); SendLobbyInfoEvent(partner, caller); }
/// <summary> /// /// </summary> /// <param name="caller"></param> /// <param name="target"></param> /// <param name="cardinal"></param> /// <param name="partner"></param> private void ValidateLegalMove(FreeSOMazePlayer caller, AbstractMazeCell <FreeSOMazeData> target, FreeSOMazeCardinals cardinal, FreeSOMazePlayer partner) { if (caller != null && partner != null) { lock (MoveLock) { if (GameState.Equals(FreeSOMazeStates.NavigatingMaze) && NextState.Equals(FreeSOMazeStates.Invalid) && caller.Cooldown >= GLOBAL_COOLDOWN) { bool rollForHint = true; caller.MoveTo(target); caller.Cooldown = 0; caller.CurrentFacingCardinal = cardinal; // is the partner at the target, meaning have the two met in any cell if (partner.Location.Equals(target)) { // gameover win! rollForHint = false; EnqueueGotoState(FreeSOMazeStates.Gameover); // payout data var skillPayout = (int)Math.Round((caller.Skill + partner.Skill) * SKILL_PAYOUT_MULTIPLIER, 0); var callerPayoutData = new string[] { BasePayouts[ChosenMazeDifficulty] + "", skillPayout + "", RoundTimes[ChosenMazeDifficulty] - MazeTimeRemaining + "", caller.TotalMoves + "", partner.TotalMoves + "" }; var partnerPayoutData = new string[] { BasePayouts[ChosenMazeDifficulty] + "", skillPayout + "", RoundTimes[ChosenMazeDifficulty] - MazeTimeRemaining + "", partner.TotalMoves + "", caller.TotalMoves + "" }; var totalPayout = skillPayout + BasePayouts[ChosenMazeDifficulty]; // queue gameover for caller caller.QueuePayoutEvent("FreeSOMaze_win", callerPayoutData, totalPayout); // queue gameover for partner partner.QueuePayoutEvent("FreeSOMaze_win", partnerPayoutData, totalPayout); // pay the object owner now, keeping in tradition with 10% of participant(s) payout Controller.SendOBJEvent(new VMEODEvent((short)FreeSOMazeEvents.PayOwner, new short[] { (short)(totalPayout / 10) })); } caller.Send("FreeSOMaze_move_to", caller.GetLocationData(GetHint(caller, rollForHint))); if (rollForHint) // don't send allow maze event on a gameover { SendAllowMazeEvent(caller, false); } } } } }
/// <summary> /// /// </summary> /// <param name="player"></param> /// <returns></returns> private int GetSolutionCardinal(FreeSOMazePlayer player) { var solution = player.PeekSolution(); if (solution != null) { return((int)player.GetTargetCardinal(player.Location, solution)); } // if there are no nodes left in Solution and this player has no bread crumbs, then they're next to the partner's very first breadcrumb. else { FreeSOMazePlayer partner = (player.Equals(LogicPlayer) ? CharismaPlayer : LogicPlayer); solution = partner?.FirstCrumb; if (solution != null) { return((int)partner.GetTargetCardinal(player.Location, solution)); } } return((int)FreeSOMazeCardinals.Invalid); // 10 is no hint, but if this is reached then something went very wrong }
/// <summary> /// Send to the partner the the object id of this player and their difficulty choice, if applicable. /// </summary> /// <param name="sendTo"></param> /// <param name="sendFrom"></param> private void SendLobbyInfoEvent(FreeSOMazePlayer sendTo, FreeSOMazePlayer sendFrom) { if (sendTo != null) { string concat = ""; short objectID = 0; if (sendFrom != null) { if (sendFrom.Client != null) { objectID = sendFrom.Client.Avatar.ObjectID; } if (!sendFrom.Difficulty.Equals(FreeSOMazeDifficulties.Unselected)) { concat = "" + (int)sendFrom.Difficulty; } } sendTo.Send("FreeSOMaze_lobby_info" + concat, BitConverter.GetBytes(objectID)); } }
/// <summary> /// Validates the difficulties of both players, triggering the start of the game only if they both agree. /// </summary> /// <param name="caller"></param> /// <param name="chosenDifficulty"></param> /// <param name="partner"></param> private void ValidateDifficulty(FreeSOMazePlayer caller, FreeSOMazeDifficulties chosenDifficulty, FreeSOMazePlayer partner) { lock (DifficultyLock) { if (GameState.Equals(FreeSOMazeStates.Lobby) && NextState.Equals(FreeSOMazeStates.Invalid)) { caller.Difficulty = chosenDifficulty; if (partner != null) { if (caller.Difficulty.Equals(partner.Difficulty)) { ChosenMazeDifficulty = chosenDifficulty; EnqueueGotoState(FreeSOMazeStates.GeneratingMaze); } else { partner.Send("FreeSOMaze_partner_difficulty", BitConverter.GetBytes((int)chosenDifficulty)); } } } } }
/// <summary> /// /// </summary> /// <param name="player"></param> /// <returns></returns> private int GetHint(FreeSOMazePlayer player, bool rollForHint) { if (player != null) { if (player.Location.CellData.IsDeadEnd) { player.Send("FreeSOMaze_alert", "Server: I sent hint: " + (int)FreeSOMazeDirections.None); return((int)FreeSOMazeDirections.None); } else if (player.Location.CellData.ShowHint) { var hint = GetSolutionCardinal(player); player.Send("FreeSOMaze_alert", "Server: I sent hint: " + hint); return(hint); //return GetSolutionCardinal(player); } else if (rollForHint) { // roll for a hint var roll = ThankU.Next(0, 100); if (roll < CumulativeHintProbability) { CumulativeHintProbability = HintProbabilities[ChosenMazeDifficulty].Item2; player.Location.CellData.ShowHint = true; var hint = GetSolutionCardinal(player); player.Send("FreeSOMaze_alert", "Server: I sent hint: " + hint); return(hint); //return GetSolutionCardinal(player); } else { CumulativeHintProbability += HintProbabilities[ChosenMazeDifficulty].Item3; } } } player.Send("FreeSOMaze_alert", "Server: I sent no hint"); return((int)FreeSOMazeCardinals.Invalid); // no hint }
/// <summary> /// Send a disposing event to the player leaving, alert the partner UIEOD that their partner just left. /// </summary> /// <param name="client">quitter</param> public override void OnDisconnection(VMEODClient client) { // identify the person that left and determine if there's a partner FreeSOMazePlayer disconnecting = null; FreeSOMazePlayer partner = null; if (CharismaPlayer?.Client?.Equals(client) ?? false) { disconnecting = CharismaPlayer; CharismaPlayer = null; partner = LogicPlayer; } else if (LogicPlayer?.Client?.Equals(client) ?? false) { disconnecting = LogicPlayer; LogicPlayer = null; partner = CharismaPlayer; } disconnecting?.Send("FreeSOMaze_dispose", new byte[0]); partner?.Send("FreeSOMaze_partner_disconnected", new byte[0]); EnqueueGotoState(FreeSOMazeStates.Lobby); base.OnDisconnection(client); }
/// <summary> /// /// </summary> /// <param name="client"></param> public override void OnConnection(VMEODClient client) { if (client.Avatar != null) { // get the temps, [0] == 1 is logic, 2 is charisma var args = client.Invoker.Thread.TempRegisters; if (args[0] == 1) { LogicPlayer = new FreeSOMazePlayer(client, client.Avatar.GetPersonData(SimAntics.Model.VMPersonDataVariable.LogicSkill) / 100m, true); client.Send("FreeSOMaze_show_l", BitConverter.GetBytes(client.Avatar.ObjectID)); } else { CharismaPlayer = new FreeSOMazePlayer(client, client.Avatar.GetPersonData(SimAntics.Model.VMPersonDataVariable.CharismaSkill) / 100m, false); client.Send("FreeSOMaze_show_c", BitConverter.GetBytes(client.Avatar.ObjectID)); } EnqueueGotoState(FreeSOMazeStates.Lobby); base.OnConnection(client); } else { Controller = client; } }