void OnTriggerEnter2D(Collider2D other) { //Check to see if collider belongs to interactive character if (other.tag == "InteractiveChar") { //Player is in range of a interactive character. Set script reference for use. this.NearbyChar = other.GetComponent <CharMgrScript>(); } }
public NPCCombatTurn ChooseCombatAction(CharMgrScript npc, List <CharMgrScript> possibleTargets) { NPCCombatTurn thisTurn = new NPCCombatTurn(); //TODO: Implement logic for NPC combat action selection int actChoiceProb = Random.Range(0, 100); int subSelectionProb = Random.Range(0, 100); //Choose action based on the NPC's internal logic GameConstants.ActionOptionIndices selectedAction = this.ChooseAction(npc, actChoiceProb); //Create list that will hold targets and their priority List <PrioritizedTarget> weightedTargets = new List <PrioritizedTarget>(); List <CharMgrScript> randomTargets = new List <CharMgrScript>(); CharAbility turnAbility = new CharAbility(); /*Generate list of all targets based on a conditional statement based off the chosen action by the NPC*/ switch (selectedAction) { case (GameConstants.ActionOptionIndices.Ability): break; case (GameConstants.ActionOptionIndices.Attack): //Get reference to the npc's attack turnAbility = npc.GetBasicAttack(); //Get list of targets that the attack effects randomTargets = this.GetNPCTargets(turnAbility, CombatMgr._instance.PlayerParty); break; default: Debug.Log("Selected action was" + selectedAction.ToString() + " and NPC Turn Switch Fell through - Performing default action"); break; } //Add priorities to targets from above selection and put them into a list TODO: prioitize via function foreach (CharMgrScript target in randomTargets) { weightedTargets.Add(new PrioritizedTarget(100, target)); } //TODO perform some function to prioritize list of targets and grab the preffered one List <CharMgrScript> turnTargets = new List <CharMgrScript>(); foreach (PrioritizedTarget t in weightedTargets) { turnTargets.Add(t.target); } //Set the fields of the created turn and return it thisTurn.SelectedAbility = turnAbility; thisTurn.SelectedTargets = turnTargets; thisTurn.SelectedAction = selectedAction; //return the created turn data return(thisTurn); }
public IEnumerator TakeNPCTurn(CharMgrScript npc, List <CharMgrScript> pTargets) { Debug.Log("NPC" + CombatMgr._instance.currentTurnChar.stats.name + " is taking their turn!"); /*Select Character's action*/ NPCCombatTurn npcTurnData = NPCChoiceMgr._instance.ChooseCombatAction(npc, pTargets); //this.PerformAttack( npcTurnData.SelectedTargets, npcTurnData.ability ); this.PerformAttack(npcTurnData.SelectedAbility, npcTurnData.SelectedTargets); //this.EndCombatTurn(); yield return(null); }
/// <summary> /// Adds a given character to the party /// </summary> /// <returns><c>true</c>, if character was successfully added, <c>false</c> otherwise.</returns> /// <param name="charScript">Char script.</param> public bool AddCharacterToParty(CharMgrScript charScript) { if (PlayerParty.Count == GameConstants.MAX_PARTY_SIZE) { //party full //TODO: Add 'Party Full' failure use case return(false); } else { //If party size is less then max then we add character to party //TODO:Is checking for duplicates necessary? PlayerParty.Add(charScript.stats.StatsAsData()); return(true); } }
public List <CharMgrScript> GetPossibleTargets(CharMgrScript currChar, CharAbility ability, bool playerParty) { //Pass in ability script, check who is taking their tun and the ability to get the possible targets, then return them as a list List <CharMgrScript> possTargets = new List <CharMgrScript>(); /*Check the target type of the ability and based on the type return the correct targets*/ switch (ability.TType) { case (GameConstants.TargetType.EnemyParty): //Case for hitting whole party break; case (GameConstants.TargetType.SingleEnemy): //Single enemy attack type so get next item in correct list and return it if (playerParty) { //If it's the player's party then the npc party of enemies are possible targets - NOTE: Excluding downed/dead characters possTargets = this.EnemyParty.FindAll(x => x.stats.Status != GameConstants.StatusType.Downed); if (TestScript._instance.TestMode) { Debug.Log("POSSIBLE TARGETS OBTAINED! cOUNT IS:" + possTargets.Count); } } else { } break; case (GameConstants.TargetType.Party): break; case (GameConstants.TargetType.Ally): break; case (GameConstants.TargetType.Self): break; default: break; } return(possTargets); }
/// <summary> /// Starts the turn of the next character. Initializes UI elements, etc. /// </summary> public void StartNextTurn() { //Get reference to the script whose turn is next CharMgrScript currentChar = this.GetCombatantTurn(this.PlayerParty, this.EnemyParty); //Set it to local variable currentTurnChar = currentChar; //Set flag for which team is taking its turn - In a PVE encounter, either payer party or NPC party if (this.PlayerParty.Contains(currentChar)) { /*Debug statement for test*/ if (TestScript._instance.TestMode) { Debug.Log("--StartNextTurn() called and character from *Player Party* found: " + currentChar.stats.CharName); } this._waitForPlayer = true; //Display the action selection menu if it's not already open and highlight current character if (CombatUIManager._instance.MenuLevel == GameConstants.CombatMenuPage.Unopened) { //Create the action menu CombatUIManager._instance.CreateActionMenu(CombatUIManager._instance.ActionMenuPos); //Update menu state CombatUIManager._instance.MenuLevel = GameConstants.CombatMenuPage.Action; } } else if (this.EnemyParty.Contains(currentChar)) { /*Debug statement for test*/ if (TestScript._instance.TestMode) { Debug.Log("--StartNextTurn() called and character from ~~Enemy Party~~ found: " + currentChar.stats.CharName); } this._waitForNPC = true; //Setup npc turn and pass in targets SetupNPCTurn(currentChar, this.PlayerParty); } //Handle w/e character specific highlighting is involved currentChar.UITurnEmphasisStatus(true); }
public RuntimeAnimatorController LoadCharacterAnimator(CharMgrScript charMgr) { //Get unformatted string name string animatorName = charMgr.stats.AnimatorType; //Format string name by lowercasing it and replacing the spaces with underscores string animatorNameFormatted = animatorName.ToLower().Replace(' ', '_'); string path = "Animators/" + animatorNameFormatted; RuntimeAnimatorController loadedAnimator = Resources.Load(path) as RuntimeAnimatorController; //Verify if asset was loaded correctly before returning. If none found then return generic animator if (loadedAnimator == null) { Debug.LogError("Animator for " + animatorNameFormatted + " not found at " + path); Debug.LogWarning("Loading default character animator!"); string defaultPath = "Animators/generic_animator"; loadedAnimator = Resources.Load(path) as RuntimeAnimatorController; } //Return loaded animator return(loadedAnimator); }
public void UpdateMenuFromSelection(GameConstants.ActionOptionIndices selection) { if (TestScript._instance.TestMode) { Debug.Log("UPDATE menu from selection called in Combat UI mgr!!"); } //Set the selected menu state as active CombatUIManager._instance.actMenuScript.SetSelectedState(selection, true); CharMgrScript character = CombatMgr._instance.currentTurnChar; switch (selection) { //Update menu level to reflect game state case (GameConstants.ActionOptionIndices.Attack): if (TestScript._instance.TestMode) { Debug.Log("UpdateMenuFromSelection - Entered switch and refreshed targets!!"); } //Update menu level to the match CombatUIManager._instance.MenuLevel = GameConstants.CombatMenuPage.Attack; //Update lists of targets - First check to see who is attacking, player party or enemy bool playerParty = CombatMgr._instance.PlayerParty.Contains(character); //Get list of all possible targets for moving selection UI possibleTargets = CombatMgr._instance.GetPossibleTargets(character, character.GetBasicAttack(), playerParty); //Get list of the currently higlighted targets for the start currTargets = CombatMgr._instance.GetNextTargets(character, character.GetBasicAttack(), currTargets, possibleTargets, playerParty, 1); //Turn on highlight arrows for current targets foreach (CharMgrScript c in currTargets) { c.HighlightArrowStatus(true); } break; default: break; } }
public void SetupNPCTurn(CharMgrScript npcCharacter, List <CharMgrScript> possibleTargets) { Debug.Log("*&@#$ The NPC: " + this.currentTurnChar.stats.CharName + " TOOK A TURN! *#$&"); //TODO:Handle logic for selecting action and targets etc, then calling the appropriate method for the NPC StartCoroutine(TakeNPCTurn(npcCharacter, possibleTargets)); }
/// <summary> /// Gets the next targets. /// </summary> /// <returns>The next targets.</returns> /// <param name="currChar">Curr char.</param> /// <param name="ability">Ability.</param> /// <param name="currTargets">Curr targets.</param> /// <param name="playerParty">If set to <c>true</c> then attacking character is a member of the player party.</param> /// <param name="dir">Value should be either 1 or -1. This is the direction the selection is moving in the list</param> public List <CharMgrScript> GetNextTargets(CharMgrScript currChar, CharAbility ability, List <CharMgrScript> currTargets, List <CharMgrScript> possTargets, bool playerParty, int dir) { //Pass in ability script, check who is taking their tun and the ability to get the possible targets, then return them as a list List <CharMgrScript> nextTargets = new List <CharMgrScript>(); int numTargets; /*Check the target type of the ability and based on the type return the correct targets*/ switch (ability.TType) { case (GameConstants.TargetType.EnemyParty): numTargets = EnemyParty.Count; //Case for hitting whole party break; case (GameConstants.TargetType.SingleEnemy): //For now, use hard coded value, later can look into building this into the ability class numTargets = 1; //Single enemy attack type so get next item in correct list and return it if (playerParty) { //If it's the player's party then get a script from npc party as the enemy if (currTargets == null || currTargets.Count == 0) { if (TestScript._instance.TestMode) { Debug.Log("GetNextTargets -> retreived first from list because currTargets was null"); } //IF no targets currently just grab the first item from the list //CharMgrScript nTarget = this.EnemyParty[0]; CharMgrScript nTarget = possTargets[0]; nextTargets.Add(nTarget); } else { /* * Otherwise find the greatest index of the curr targets, * use it as starting index, increase count by 'number of targets' */ int startingIndex = -1; //Find the 'largest' index from current targets to use as a starting point foreach (CharMgrScript c in currTargets) { // if (this.EnemyParty.IndexOf(c) > startingIndex) // { // startingIndex = this.EnemyParty.IndexOf(c); // } if (possTargets.IndexOf(c) > startingIndex) { startingIndex = possTargets.IndexOf(c); } } for (int i = 0; i < numTargets; i++) { if (startingIndex + dir >= possTargets.Count) { //Reset starting index to avoid being out of bounds startingIndex = 0; //Remove dir because we've rotated around the list dir = 0; } else if (startingIndex + dir < 0) { //Reset starting index to avoid being out of bounds startingIndex = possTargets.Count - 1; //Remove dir because we've rotated around the list dir = 0; } CharMgrScript nTarget = possTargets[startingIndex + dir]; nextTargets.Add(nTarget); } } } else { //Handle enemy attack selection? } break; case (GameConstants.TargetType.Party): numTargets = PlayerParty.Count; break; case (GameConstants.TargetType.Ally): numTargets = 1; break; case (GameConstants.TargetType.Self): break; default: break; } return(nextTargets); }
/// <summary> /// Finds the combatant whose turn it is. Looks through the list for the fastest charcter /// </summary> /// <returns>The combatant turn.</returns> public CharMgrScript GetCombatantTurn(List <CharMgrScript> playerParty, List <CharMgrScript> enemyParty) { //add the lists of both parties together to get a list of total combatants List <CharMgrScript> currCombatants = new List <CharMgrScript>(); foreach (CharMgrScript c in playerParty) { if (c.stats.Status != GameConstants.StatusType.Downed) { currCombatants.Add(c); } } foreach (CharMgrScript enemyChar in enemyParty) { if (enemyChar.stats.Status != GameConstants.StatusType.Downed) { currCombatants.Add(enemyChar); } } //Get subset of chars that haven't moved yet List <CharMgrScript> unmovedCombatants = currCombatants.FindAll(x => x.ActedThisRound == false); //Test DEBUG OUTPUT if (TestScript._instance.TestMode) { Debug.Log("UNMOVED COMBATANTS COUNT:" + unmovedCombatants.Count); } //Get the first list item as a starting point CharMgrScript currTurnChar = unmovedCombatants[0]; switch (InitiativeType) { case (GameConstants.TurnOrderType.IndividualSpeed): //Iterate through each script and compare speed foreach (CharMgrScript combatant in unmovedCombatants) { //Test DEBUG OUTPUT if (TestScript._instance.TestMode) { Debug.Log("CurrTurnChar has speed of:" + currTurnChar.stats.Speed); Debug.Log("Combatant being compared has speed of:" + currTurnChar.stats.Speed); } //if this character is faster than current script, then this character gets initiative if (combatant.stats.Speed > currTurnChar.stats.Speed) { currTurnChar = combatant; } else if (combatant.stats.Speed == currTurnChar.stats.Speed) //If speed is equal need to determine initiative another way { //TODO:Implement secondary stat check //Until secondary stat check just use random selection between the two int num = Random.Range(0, 100); if (num >= 50) { //If coin flip is over fifty or equal currTurnChar = combatant; } } } break; case (GameConstants.TurnOrderType.FastestTeammate): Debug.LogWarning("Fastest teammate iniative type not implemented!!"); break; default: Debug.LogWarning("No turn order type found! Case fell through"); break; } return(currTurnChar); }
public void StartCombat(Scene pOneWin, Scene pTwoWin) { Vector3 partyPos, enemyPos; this.PartyOneReturnScene = pOneWin; this.PartyTwoReturnScene = pTwoWin; /*Check referenc to tagged starting pos objects*/ if (CombatPartyStartPos == null) { partyPos = new Vector3(GameConstants.CombatPartyStartPosX, GameConstants.CombatPartyStartPosY, 0); } else { partyPos = CombatPartyStartPos.position; } if (CombatEnemyStartPos == null) { enemyPos = new Vector3(GameConstants.CombatPartyStartPosX, GameConstants.CombatPartyStartPosY, 0); } else { enemyPos = CombatEnemyStartPos.position; } Debug.Log("StartCombat() called!"); //Counter to use for positioning int count = 0; //Instantiate an object for each member of the player's party and set their variables accordingly foreach (CharStatsData characterStats in PlayerStateManager.Instance.PlayerParty) { Debug.Log("Party Member" + characterStats.CharName + "Instantiated called!"); //Debug.Log("Creating character" + character.stats.CharName + "for combat scene."); //Create empty object from prefab GameObject partyMemberCopy = GameObject.Instantiate(EmptyCharacter); //Set position for the party member partyMemberCopy.transform.position = partyPos + (DistCharsCombat * (float)count); //Grab the new script CharMgrScript partyMemberCopyScript = partyMemberCopy.GetComponent <CharMgrScript>(); //Init necessary variables partyMemberCopyScript.Init(); /* --- Set the variables of the script --- */ //Dialogue partyMemberCopyScript.dialogMgr = characterStats.DialogMgr; //Stats & Abilities characterStats.StatsAsScript(ref partyMemberCopyScript.stats); //Character sprite partyMemberCopy.GetComponent <SpriteRenderer>().sprite = characterStats.charSprite; //change object name in hierarchy partyMemberCopy.name = characterStats.CharName; /*Create UI objects (highlight arrow, hp counter) and parent them to the canvas, assign them to the characters script and disable via script*/ //Create or recreate menu objects and refresh references //Instantiate the UI object used for emphasis when indicating it's a character's turn GameObject uiTurnEmphasisObj = GameObject.Instantiate(this.UITurnEmphasisObj); //Parent the turn emphasis object to the canvas uiTurnEmphasisObj.transform.SetParent(CombatUIManager._instance.CanvasObject.transform, false); //Assign the prefab as a member of the current charMgr script partyMemberCopyScript.UITurnEmphasisElem = uiTurnEmphasisObj; //Move the emphasis object under the character partyMemberCopyScript.UITurnEmphasisElem.GetComponent <UIAnim>().PositionElementOnSprite(partyMemberCopyScript.gameObject); //Disable the UI element for now partyMemberCopyScript.UITurnEmphasisStatus(false); //Instantiate the HP counter UI text prefab GameObject hpUIText = GameObject.Instantiate(HPUITxtObj); //Parent the ui text to the canvas for positioning purposes hpUIText.transform.SetParent(CombatUIManager._instance.CanvasObject.transform, false); //Assign the prefab as a member of the charMgr script partyMemberCopyScript.HPUITxt = hpUIText; //Move the hp text under the character partyMemberCopyScript.HPUITxt.GetComponent <UIAnim>().PositionElementOnSprite(partyMemberCopyScript.gameObject); //Set HP text's initial values partyMemberCopyScript.HPUITxt.GetComponent <UIAnim>().SetText(partyMemberCopyScript.stats.HP.ToString() + "/" + partyMemberCopyScript.stats.MaxHP.ToString()); //Enable HP Text for now partyMemberCopyScript.HPTextStatus(true); //Instantiate the arrow prefab GameObject highlightArrow = GameObject.Instantiate(HighlightArrowObj); //Parent the highlight arrow to the canvas highlightArrow.transform.SetParent(CombatUIManager._instance.CanvasObject.transform, false); //Assign the sprite component as a member of the charMgr script partyMemberCopyScript.HighlightArrow = highlightArrow; //Move highlight arrow over character's head via setting it = to pos, + half the sprite's height partyMemberCopyScript.HighlightArrow.GetComponent <UIAnim>().PositionElementOnSprite(partyMemberCopyScript.gameObject); //Disable highlight arrow for now partyMemberCopyScript.HighlightArrowStatus(false); /********** Animator asset loading **********/ //Attempt to load character's animator and attach it partyMemberCopy.GetComponent <Animator>().runtimeAnimatorController = this.LoadCharacterAnimator(partyMemberCopyScript); /*Add the character script to the total list of combatants for determining turn order*/ Combatants.Add(partyMemberCopyScript); PlayerParty.Add(partyMemberCopyScript); //Set team direction partyMemberCopyScript.TeamDirection = GameConstants.COMBAT_DIR_LEFT_SIDE; //Increment counter for spacing count++; } //Clear counter count = 0; //Instantiate each enemy party member foreach (CharStatsData characterStats in this.EnemyPartyData) { Debug.Log("Enemy Member" + characterStats.CharName + "Instantiated called!"); //Create empty enemy object from prefab GameObject enemyCharCopy = GameObject.Instantiate(EmptyCharacter); //Set position for the enemy enemyCharCopy.transform.position = CombatEnemyStartPos.position + (DistCharsCombat * (float)count); //Get reference to prefab's script CharMgrScript enemyScript = enemyCharCopy.GetComponent <CharMgrScript>(); //init necessary variables enemyScript.Init(); /* --- Set script variables --*/ //Dialogue enemyScript.dialogMgr = characterStats.DialogMgr; //Stats & Abilities characterStats.StatsAsScript(ref enemyScript.stats); //Character sprite enemyScript.GetComponent <SpriteRenderer>().sprite = characterStats.charSprite; //change object name in hierarchy enemyCharCopy.name = enemyScript.stats.CharName; /*Create UI objects, parent them to the canvas, assign them to the the characters scripts and disable via script*/ //Instantiate the UI object used for emphasis when indicating it's a character's turn GameObject uiTurnEmphasisObj = GameObject.Instantiate(this.UITurnEmphasisObj); //Parent the turn emphasis object to the canvas uiTurnEmphasisObj.transform.SetParent(CombatUIManager._instance.CanvasObject.transform, false); //Assign the prefab as a member of the current charMgr script enemyScript.UITurnEmphasisElem = uiTurnEmphasisObj; //Move the emphasis object under the character enemyScript.UITurnEmphasisElem.GetComponent <UIAnim>().PositionElementOnSprite(enemyScript.gameObject); //Disable the UI element for now enemyScript.UITurnEmphasisStatus(false); //Instantiate the HP counter UI text prefab GameObject hpUIText = GameObject.Instantiate(HPUITxtObj); //Parent the ui text to the canvas for positioning purposes hpUIText.transform.SetParent(CombatUIManager._instance.CanvasObject.transform, false); //Assign the prefab as a member of the charMgr script enemyScript.HPUITxt = hpUIText; //Move the hp text under the character enemyScript.HPUITxt.GetComponent <UIAnim>().PositionElementOnSprite(enemyScript.gameObject); //Set HP text's initial values enemyScript.HPUITxt.GetComponent <UIAnim>().SetText(enemyScript.stats.HP.ToString() + "/" + enemyScript.stats.MaxHP.ToString()); //Ensure HP Text is enabled for now enemyScript.HPTextStatus(true); //Instantiate the highlight arrow prefab GameObject highlightArrow = GameObject.Instantiate(HighlightArrowObj); //Parent the highlight arrow to the canvas highlightArrow.transform.SetParent(CombatUIManager._instance.CanvasObject.transform, false); //Assign the sprite component as a member of the charMgr script enemyScript.HighlightArrow = highlightArrow; //Move highlight arrow over character's head via setting it = to pos, + half the sprite's height enemyScript.HighlightArrow.GetComponent <UIAnim>().PositionElementOnSprite(enemyScript.gameObject); //Disable highlight arrow for now enemyScript.HighlightArrowStatus(false); /********** Animator asset loading **********/ //Attempt to load character's animator and attach it enemyCharCopy.GetComponent <Animator>().runtimeAnimatorController = this.LoadCharacterAnimator(enemyScript); /*Add the character script to the total list of combatants for determining turn order*/ Combatants.Add(enemyScript); EnemyParty.Add(enemyScript); //Set team direction enemyScript.TeamDirection = GameConstants.COMBAT_DIR_RIGHT_SIDE; //Increment counter for spacing count++; } /********Set flag to track game state that manager is done initializing and waiting for player input********/ this._initializing = false; //this._waitForPlayer = true; /****************/ }
public GameConstants.ActionOptionIndices ChooseAction(CharMgrScript npc, int actionProb) { GameConstants.ActionOptionIndices selectedAction = GameConstants.ActionOptionIndices.Default; switch (npc.stats.BehaviorType) { case (GameConstants.EnemyCombatBehaviorType.Standard): /*Standard enemies select between attack and abilities when health is greather than half of the max. When health is under half of the max, may use a healing item or ability * For the time being, 'standard' units just attack to keep things simple */ Debug.Log("Current turn NPC is:" + npc.stats.CharName + " and has " + npc.stats.HP + "out of " + npc.stats.MaxHP + " remaining."); if (npc.stats.HP > (npc.stats.MaxHP / 2)) { //CharAbility abilitySelection = ; if (actionProb < probFavored) //Select favored action { selectedAction = GameConstants.ActionOptionIndices.Attack; //Test DEBUG OUTPUT if (TestScript._instance.TestMode) { Debug.Log("**Random number is:" + actionProb + "**Action selected:" + selectedAction.ToString()); } } else if (actionProb < probFavored + probNeutral) { selectedAction = GameConstants.ActionOptionIndices.Attack; } else if (actionProb < probFavored + probNeutral + probDisliked) { selectedAction = GameConstants.ActionOptionIndices.Attack; } else { //Strongly disliked action selectedAction = GameConstants.ActionOptionIndices.Attack; } } else { //CharAbility abilitySelection = ; if (actionProb < probFavored) { //Select favored action selectedAction = GameConstants.ActionOptionIndices.Attack; } else if (actionProb < probFavored + probNeutral) { selectedAction = GameConstants.ActionOptionIndices.Attack; } else if (actionProb < probFavored + probNeutral + probDisliked) { selectedAction = GameConstants.ActionOptionIndices.Attack; } else { //Strongly disliked action selectedAction = GameConstants.ActionOptionIndices.Attack; } } break; case (GameConstants.EnemyCombatBehaviorType.Offensive): break; case (GameConstants.EnemyCombatBehaviorType.Defensive): break; case (GameConstants.EnemyCombatBehaviorType.Healer): break; default: //No conditions met and case fell through break; } return(selectedAction); }
public PrioritizedTarget(int p, CharMgrScript t) { this.Priority = p; this.target = t; }
public virtual void Action(CharMgrScript attackingChar) { //Action method overridden by menu options that inherit from this class }