//Constructor of move. ONLY TO BE USED AT START OF GAME ON AWAKE OR UPON LEARNING MOVE. melee hitbox should be first child of PKMNEntity gameObject public Pound(Animator animator, PKMNEntity baseStats) { this.animator = animator; this.basis = baseStats; this.hitbox = basis.transform.GetChild(0); this.enemyTag = (animator.tag == "Player") ? "Enemy" : "Player"; offCD = true; cTimer = 0.0f; hit = new HashSet <Collider2D>(); }
//Applies effects to enemy hit public void enactEffects(Collider2D tgt) { PKMNEntity enemy = tgt.GetComponent <PKMNEntity>(); int damage = Battle.damageCalc(basis.level, INITIAL_PWR, basis.accessStat(BaseStat.SPECIAL_ATTACK), basis.accessStat(BaseStat.SPECIAL_DEFENSE)); enemy.StartCoroutine(enemy.receiveDamage(damage, basis)); //Add debuff StatEffect debuff = new StatEffect(DEBUFF_DURATION, DEBUFF_FACTOR, DEBUFF_TYPE); debuff.applyEffect(enemy.GetComponent <PKMNEntity>()); }
//Upon collision on enemy, enact effects public void enactEffects(Collider2D enemy) { Vector2 knockbackVector = Battle.dirKnockbackCalc(basis.transform.position, enemy.transform.position, KNOCKBACK_VAL); enemy.GetComponent <Rigidbody2D>().AddForce(knockbackVector); //Calculates damage PKMNEntity enemyFighter = enemy.GetComponent <PKMNEntity>(); int damage = Battle.damageCalc(basis.level, PWR, basis.accessStat(BaseStat.ATTACK), enemyFighter.accessStat(BaseStat.DEFENSE)); enemyFighter.StartCoroutine(enemyFighter.receiveDamage(damage, basis)); }
// Update is called once per frame void FixedUpdate() { if (canMove && target != null) { //Enemy movement Vector2 movement = new Vector2(target.position.x - transform.position.x, target.position.y - transform.position.y); movement.Normalize(); Battle.updateBasicOrientation(movement, transform); anim.SetFloat("speed", enemyFighter.getMoveSpeed()); transform.Translate(movement * enemyFighter.getMoveSpeed() * 0.5f); //Behavior upon stun: If enemy stunned, charge dash. If dash couldn't be run, use a water pulse PKMNEntity tgtFighter = target.GetComponent <PlayerMovement>().getCurFighter(); if (!stunMoveExecuted && tgtFighter.isStunned()) { stunMoveExecuted = enemyFighter.executeSecMove(MAIN_TACKLE, target); if (stunMoveExecuted) { aTimer = 0f; } else { stunMoveExecuted = enemyFighter.executeSecMove(BUBBLE_SHIELD, target); } } //Timers float delta = Time.deltaTime; aTimer += delta; //Resetter for attack timer if (aTimer >= MAX_ATTACK_INTERVAL) { enemyFighter.executeSecMove(MAIN_TACKLE, target); stunMoveExecuted = false; aTimer = 0f; } //Resetter for melee timer if (!canMelee) { meleeTimer += delta; if (meleeTimer >= MELEE_ATTACK_INTERVAL) { canMelee = true; meleeTimer = 0.0f; } } } }
//Constructor public QuickAttack(Animator anim, PKMNEntity basis) { //Set reference variables and any other variables concerning entity this.anim = anim; this.basis = basis; this.dashBox = basis.GetComponent <DashChargeHitBox>(); this.enemyTag = (basis.tag == "Player") ? "Enemy" : "Player"; //Establish any other variables numCharges = MAX_CHARGES; offCD = true; cTimer = 0f; }
//Constructor public ShellDash(Animator anim, PKMNEntity basis, ProgressBar progress) { //Set reference variables and any other variables concerning entity this.anim = anim; this.basis = basis; this.dashBox = basis.GetComponent <DashChargeHitBox>(); this.enemyTag = (basis.tag == "Player") ? "Enemy" : "Player"; this.progress = progress; //Establish any other variables cTimer = 0.0f; offCD = true; }
//Adds fighters to the menu display // ONLY used in the beginning when loading information // ALL BUTTONS MUST BE DISABLED BEFORE THIS RUNS public void addFighter(PKMNEntity fighter) { if (fighters == null) { fighters = new List <PKMNEntity>(); } fighters.Add(fighter); Button curButton = fighterButtons[fighters.Count - 1]; curButton.gameObject.SetActive(true); curButton.GetComponentInChildren <Text>().text = fighter.fighterName; }
// Update is called once per frame void FixedUpdate() { if (target != null && canMove) { enemyMovement(); //Behavior upon player stun PKMNEntity tgtFighter = target.GetComponent <PlayerMovement>().getCurFighter(); if (!stunMoveExecuted && tgtFighter.isStunned()) { stunMoveExecuted = enemyFighter.executeSecMove(MAIN_SHOOTER, target); aTimer = (stunMoveExecuted) ? 0f : aTimer; } //Updating timers foir shooting intervals float delta = Time.deltaTime; aTimer += delta; if (aTimer >= MAX_ATTACK_INTERVAL) { enemyFighter.executeSecMove(MAIN_SHOOTER, target); stunMoveExecuted = false; aTimer = 0f; } //Updating timers for melee attacks if (!canMelee) { meleeTimer += delta; if (meleeTimer >= MELEE_ATTACK_INTERVAL) { canMelee = true; meleeTimer = 0f; } } //Updating dash timers if (!canDash) { dashTimer += delta; if (dashTimer >= DASH_INTERVAL) { dashTimer = 0f; canDash = true; } } } }
//Upgrades stat upon button press public void upgradeStat() { numStatBoosts += 1; PKMNEntity linkedFighter = fighterInfo.getFighter(); linkedFighter.useStatBoost(baseStat, potentialStat); //Upgrades stat //Updates display statBar.fillAmount = linkedFighter.accessBaseStat(baseStat) / MAX_STAT; statBoostDisplay.text = linkedFighter.getStatBoostsUsed(baseStat) + "/" + MAX_UPGRADES; //Indicate to main menu that an upgrade has happened fighterInfo.uponUpgrade(this); }
//Constructor public GattlerBlast(Animator anim, PKMNEntity basis) { //Set reference variables and any other variables concerning entity this.anim = anim; this.basis = basis; this.dashBox = basis.GetComponent <DashChargeHitBox>(); this.enemyTag = (basis.tag == "Player") ? "Enemy" : "Player"; this.mainHitbox = Resources.Load <Transform>("MoveHitboxes/TriangleHitbox"); //Set other variables canAttack = true; offCD = true; numCharges = MAX_CHARGES; }
//If someone exits the zone void OnTriggerExit2D(Collider2D collider) { PKMNEntity enemy = collider.GetComponent <PKMNEntity>(); if (hit.Contains(enemy)) { hit.Remove(enemy); if (enemyTag == "Player" && enemy.isAlive()) { enemy.getController().SendMessage("setIsolation", false); } } }
public HashSet <Collider2D> hit; //A hashset that contains all entities hit //Initial setup. Made when character starts loading up moves private void initialSetup(int priority, IMove curMove, float knockback) { PKMNEntity basis = curMove.getBasis(); this.priority = priority; this.currentMove = curMove; string entityTag = basis.tag; bool isPlayer = entityTag == "Player" || entityTag == "PlayerRecovery"; this.enemyTag = (isPlayer) ? "Enemy" : "Player"; this.enemyAttackTag = (isPlayer) ? "EnemyAttack" : "PlayerAttack"; tag = (isPlayer) ? "PlayerAttack" : "EnemyAttack"; knockbackVal = knockback; }
//Move Creator Inventory // Pre: String must be found within move inventory. sourceTag is either "Player" or "Enemy". None of the parameters are null // Post: Returns a new IMove for a character public static IMove moveInv(string moveName, Animator anim, PKMNEntity source, ProgressBar progress) { if (moveName == null || anim == null || source == null) { throw new System.ArgumentException("Error: Null Parameter found for moveInv"); } switch (moveName) { case "Pound": return(new Pound(anim, source)); case "BulletSeed": return(new BulletSeed(anim, source)); case "Agility": return(new Agility(anim, source, progress)); case "QuickAttack": return(new QuickAttack(anim, source)); case "WaterPulse": return(new WaterPulse(anim, source)); case "ShellDash": return(new ShellDash(anim, source, progress)); case "GattlerBlast": return(new GattlerBlast(anim, source)); case "StormZone": return(new ZoneControl(anim, source, BaseStat.SPEED, 0.4f)); case "AnchorSlash": return(new AnchorSlash(anim, source)); case "DredgeLine": return(new DredgeLine(anim, source)); case "GunkShot": return(new GunkShot(anim, source)); case "null": return(null); default: throw new System.ArgumentException("Error: " + moveName + " not found in moveInv"); } }
//General Constructor public Agility(Animator anim, PKMNEntity unit, ProgressBar progress) { this.anim = anim; this.unit = unit; this.progress = progress; //Charge Management variables chargeProgress = 0.0f; charging = false; dTimer = 0.0f; //Cooldown Management Variables offCD = true; cTimer = 0.0f; }
//If someone enters, add them to data structure void OnTriggerEnter2D(Collider2D collider) { PKMNEntity enemy = collider.GetComponent <PKMNEntity>(); if (collider.tag == enemyTag || (collider.tag == enemyAttackTag && enemy != null)) { int damage = Battle.damageCalc(source.level, POISON_PWR, offenseStat, enemy.accessStat(BaseStat.SPECIAL_DEFENSE)); enemy.StartCoroutine(enemy.receiveDoT(damage, source)); hit.Add(enemy); if (enemyTag == "Player") { enemy.getController().SendMessage("setIsolation", true); } } }
//Reverse the effect of this StatEffect // Pre: PKMNEntity effected is not null and is active in the game // Post: Reverses all of the effects using the reciprocal of the factor public void reverseEffect(PKMNEntity effected) { for (int i = 0; i < statsEffected.Length; i++) { int curStat = statsEffected[i]; if (curStat < BaseStat.BASE_STATS_LENGTH) { effected.changeStat(1 / statFactor[i], statsEffected[i]); } else { effected.poisonUnit(-1 * statFactor[i]); } } }
//Sets up ability UI for a fighter public void setUp(PKMNEntity newFighter) { iconMapping.Clear(); fighter = newFighter; List <IMove> fighterMoves = fighter.getMoves(); //Setting fighter icon if (fighterIcon != null) { fighterIcon.sprite = Resources.Load <Sprite>("Portraits/" + fighter.fighterName); } int curIconIndex = 0; int numSecMoves = newFighter.getNumSecMoves(); //Enabling ability icons while (curIconIndex < numSecMoves) { ISecMove curMove = (ISecMove)fighterMoves[curIconIndex]; Image curIcon = abilityIcons[curIconIndex]; curIcon.gameObject.SetActive(true); iconMapping[curMove] = curIcon; cooldownUpdate(curMove); curIconIndex++; } //Disabling redundant ability icons while (curIconIndex < MAX_SEC_ABILITIES) { abilityIcons[curIconIndex].gameObject.SetActive(false); curIconIndex++; } //Settings for exp bar if (fighter.getNumStatBoosts() > 0) { levelUp.SetActive(true); expBar.fillAmount = 1f; } else { expBar.fillAmount = fighter.getPercentToLvL(); levelUp.SetActive(false); } }
//Constructor public WaterPulse(Animator anim, PKMNEntity basis) { this.anim = anim; this.basis = basis; this.enemyTag = (anim.tag == "Player") ? "Enemy" : "Player"; //Set variables for hitbox this.hitbox = Resources.Load <Transform>("MoveHitboxes/BubbleHitbox"); BubbleBehavior projProperties = hitbox.GetComponent <BubbleBehavior>(); projProperties.knockbackVal = KNOCKBACK_VAL; projProperties.priority = PROJ_PRIORITY; //set cooldown variables cTimer = 0.0f; offCD = true; }
//Sends damage if enemy is within hitbox of transform // Does damage to an area in front public void enactEffects(Collider2D enemy) { if (!hit.Contains(enemy)) { hit.Add(enemy); //Add enemy to hashset to avoid double dipping //Calculates knockback Vector2 knockback = Battle.sourceKnockbackCalc(animator, KNOCKBACK_VAL); //Calculates damage PKMNEntity enemyFighter = enemy.GetComponent <PKMNEntity>(); int damage = Battle.damageCalc(basis.level, PWR, basis.accessStat(BaseStat.ATTACK), enemyFighter.accessStat(BaseStat.DEFENSE)); enemy.GetComponent <Rigidbody2D>().AddForce(knockback); //Applies knockback enemyFighter.StartCoroutine(enemyFighter.receiveDamage(damage, basis)); } }
//Responsible for grab knockback IEnumerator grabKnockback(Transform enemy) { //Sets up knockback variable and needed reference variables Vector2 kVect = Battle.dirKnockbackCalc(enemy.position, basis.transform.position, KNOCKBACK_VAL); Rigidbody2D rb = enemy.GetComponent <Rigidbody2D>(); Rigidbody2D basisRB = basis.GetComponent <Rigidbody2D>(); PKMNEntity enemyFighter = enemy.GetComponent <PKMNEntity>(); Controller control = enemyFighter.getController(); //Disable movement until grab movement done if (!enemyFighter.getAssist()) { control.canMove = false; } yield return(new WaitForSeconds(STUN_DELAY)); //Overrides default knockback canceller (receiveDamage) rb.AddForce(kVect); float kbTimer = 0; while (kbTimer < KNOCKBACK_DURATION) { yield return(new WaitForFixedUpdate()); kbTimer += Time.deltaTime; } rb.velocity = Vector2.zero; basisRB.velocity = Vector2.zero; if (basis.tag == "Player" || basis.tag == "PlayerAttack" || basis.tag == "PlayerRecovery") { PlayerMovement mainControl = (PlayerMovement)(basis.getController()); mainControl.selectedFighter.GetComponent <Rigidbody2D>().velocity = Vector2.zero; } if (!enemyFighter.isStunned() && !enemy.GetComponent <DashChargeHitBox>().isDashing() && !enemy.GetComponent <Animator>().GetBool("Dashing")) { control.canMove = true; } //Add debuff StatEffect debuff = new StatEffect(DEBUFF_DURATION, DEBUFF_FACTOR, STAT_TYPE); debuff.applyEffect(enemy.GetComponent <PKMNEntity>()); }
//Swaps UI Bars between 2 characters // both fighters MUST be active in the game and have health and armor > 0 void swapUIBars(PKMNEntity fighter1, PKMNEntity fighter2) { //Create temp variables Image tempHP = fighter1.healthBar; Image tempArmor = fighter1.armorBar; //Set fighter1 UI bars to fighter2's fighter1.healthBar = fighter2.healthBar; fighter1.armorBar = fighter2.armorBar; //Set fighter2 to temp fighter2.healthBar = tempHP; fighter2.armorBar = tempArmor; //Update both fighter1.updateUIBars(); fighter2.updateUIBars(); }
//Applies stat effect to effected entity // Pre: PKMNEntity Effected is not null // Post: PKMNEntity stats are changed in accordance with statsEffected public void applyEffect(PKMNEntity effected) { effected.addStatQ(this); for (int i = 0; i < statsEffected.Length; i++) { int curStat = statsEffected[i]; if (curStat < BaseStat.BASE_STATS_LENGTH) { effected.changeStat(statFactor[i], statsEffected[i]); } else { effected.poisonUnit(statFactor[i]); } } }
// Start is called before the first frame update void Start() { //Set reference variables player = selectedFighter.GetComponent <Transform>(); animator = selectedFighter.GetComponent <Animator>(); //Set canMove to true canMove = true; assistMoveExecuted = false; //Secondary move index secMoveIndex = 0; //Teamwork variables partyIndex = 0; selectedFighter = transform.GetChild(partyIndex).GetComponent <PKMNEntity>(); numPartners = transform.childCount - 1; //Set UI Elements if (numPartners >= 2) { abilityIconSets[1].gameObject.SetActive(true); } if (numPartners >= 3) { abilityIconSets[2].gameObject.SetActive(true); } abilityUIMap = new Dictionary <PKMNEntity, AbilityUI>(); for (int i = 0; i < numPartners; i++) { PKMNEntity curFighter = transform.GetChild(i).GetComponent <PKMNEntity>(); SwitchState curSwitchState = curFighter.gameObject.AddComponent <SwitchState>(); abilityUIMap[curFighter] = abilityIconSets[i]; //Abilities abilityIconSets[i].setUp(curFighter); curSwitchState.setUpState(abilityIconSets[i]); curFighter.healthBar = healthBars[i]; //Stat bars curFighter.armorBar = armorBars[i]; statMenu.addFighter(curFighter); } }
//Displays ALL fighter information and sets menu up public void displayFighterInfo(int newIndex) { //Get Fighter int prevIndex = fighterIndex; fighterIndex = newIndex; PKMNEntity fighter = fighters[fighterIndex]; //Update ALL Info health.fillAmount = fighter.healthBar.fillAmount; float curHealth = fighter.accessStat(BaseStat.HEALTH); curHealth = (curHealth <= 0) ? 0 : (curHealth < 1) ? 1 : curHealth; healthText.text = (int)curHealth + "/" + fighter.accessBaseStat(BaseStat.HEALTH); armor.fillAmount = fighter.armorBar.fillAmount; armorText.text = fighter.armorToString(); levelDisplay.text = "Level: " + fighter.level; exp.fillAmount = fighter.getPercentToLvL(); availableUpgrades = fighter.getNumStatBoosts(); openBoostsText.text = "" + availableUpgrades; numOpenBoosts.color = (availableUpgrades > 0) ? upgradeReady : noUpgrade; //Update base stats foreach (SingleBaseStat baseStat in baseStatDisplays) { baseStat.displayFighterInfo(fighter); if (availableUpgrades > 0) { baseStat.displayPotentialUpgrade(); } else { baseStat.disablePotentialUpgrade(); } } //Update buttons fighterButtons[fighterIndex].interactable = false; fighterButtons[prevIndex].interactable = true; }
public IEnumerator receiveDoT(int damage, PKMNEntity lastHitFighter) { curStats[BaseStat.HEALTH] -= damage; hTimer = 0.0f; aTimer = 0.0f; //Method that checks armor float minReq = baseArmor * MIN_ARMOR_RESERVED; if (curStats[BaseStat.HEALTH] <= CRIPPLE_PERCENT * baseStats[BaseStat.HEALTH] && !shieldStunned && armor > minReq) { //Cripples movement moveSpeed *= MOVE_REDUCTION; yield return(new WaitForSeconds(KNOCKBACK_DURATION)); GetComponent <Rigidbody2D>().velocity = Vector2.zero; moveSpeed = baseMoveSpeed; //Do armor damage, but DO NOT SHIELD STUN once armor damage is too much float curArmor = armor; armor -= baseArmor * DOT_ARMOR_PERCENT; if (armor <= minReq) { armor = minReq; } } updateUIBars(); if (curStats[BaseStat.HEALTH] <= 0 && !dead) { if (lastHitFighter != null) { yield return(StartCoroutine(death(lastHitFighter))); } else { curStats[BaseStat.HEALTH] = 1f; } } }
//Send damage for event driven programming. Usually sent by a hitbox public IEnumerator receiveDamage(int damage, PKMNEntity lastHitFighter) { bool shieldStunAttack = false; //Boolean lock variable to turn on when receiving attack destroys shield if (!invincibilityFrame) { invincibilityFrame = true; //Activate invincibility frame //Decrements health and armor curStats[BaseStat.HEALTH] -= damage; armor -= damage * fullSDFactor; updateUIBars(); //Resets timers hTimer = 0.0f; aTimer = 0.0f; if (curStats[BaseStat.HEALTH] <= 0) { yield return(StartCoroutine(death(lastHitFighter))); } else if (armor <= 0 && !shieldStunned) { yield return(StartCoroutine(shieldStun())); shieldStunAttack = true; } } //Cancel knockback in all cases unless it's the attack that shieldStuns unit if (!shieldStunAttack && !GetComponent <DashChargeHitBox>().isDashing() && !GetComponent <Animator>().GetBool("Dashing")) { //Disables knockback after a period of time moveSpeed *= MOVE_REDUCTION; yield return(new WaitForSeconds(KNOCKBACK_DURATION)); GetComponent <Rigidbody2D>().velocity = Vector2.zero; moveSpeed = baseMoveSpeed; } }
//Private helper method that switches characters if a main character is dead but partners (within rotation) are alive private IEnumerator mainMemberDeathFreePartners() { PKMNEntity prevFighter = selectedFighter; partyIndex %= numPartners; //Change partyIndex selectedFighter.transform.parent = null; //Detaches parent //Enable new partner the GameObject. If a GameObject shares a parent with other GameObjects and are on the same level (i.e. they share the same direct parent), these GameObjects are known as siblings. The sibling index shows where each GameObject sits in this sibling hierarchy. selectedFighter = transform.GetChild(partyIndex).GetComponent <PKMNEntity>(); animator = selectedFighter.GetComponent <Animator>(); player = selectedFighter.GetComponent <Transform>(); player.position = transform.position; canMove = false; yield return(new WaitForSeconds(DEATH_WAIT)); canMove = true; selectedFighter.GetComponent <SpriteRenderer>().enabled = true; selectedFighter.GetComponent <Collider2D>().enabled = true; //Switch UI elements secMoveIndex = 0; mainSwapper.switchAbilities(secMoveIndex); swapUIBars(selectedFighter, prevFighter); abilityUIMap[selectedFighter].swapIcons(abilityUIMap[prevFighter]); //Switches fighter mappings AbilityUI temp = abilityUIMap[selectedFighter]; abilityUIMap[selectedFighter] = abilityUIMap[prevFighter]; abilityUIMap[prevFighter] = temp; abilityUIMap[prevFighter].updateStatus(); setIsolation(false); yield return(StartCoroutine(recoveryFrames())); }
//Private helper method that swaps the main character (selectedFighter) with a partner character // Pre: new partyIndex does not correspond with current selectedFighter in child array // Post: The UI for main character and a partner character is swapped private void swapMainCharUI(bool assist) { //Disables current SelectedFighter and stores prev fighter (if assist is false) if (!assist) { selectedFighter.GetComponent <SpriteRenderer>().enabled = false; selectedFighter.GetComponent <Collider2D>().enabled = false; } PKMNEntity prevFighter = selectedFighter; //Enables new fighter selectedFighter = transform.GetChild(partyIndex).GetComponent <PKMNEntity>(); selectedFighter.GetComponent <SpriteRenderer>().enabled = true; selectedFighter.GetComponent <Collider2D>().enabled = true; //Switch UI elements secMoveIndex = 0; mainSwapper.switchAbilities(secMoveIndex); swapUIBars(selectedFighter, prevFighter); abilityUIMap[selectedFighter].swapIcons(abilityUIMap[prevFighter]); //Switches fighter mappings AbilityUI temp = abilityUIMap[selectedFighter]; abilityUIMap[selectedFighter] = abilityUIMap[prevFighter]; abilityUIMap[prevFighter] = temp; selectedFighter.GetComponent <SwitchState>().setUpState(abilityUIMap[selectedFighter]); prevFighter.GetComponent <SwitchState>().setUpState(abilityUIMap[prevFighter]); //Set Main Character variables to fighter animator = selectedFighter.GetComponent <Animator>(); player = selectedFighter.GetComponent <Transform>(); player.position = transform.position; }
//BulletSeed constructor // Pre: anim MUST have hDirection, vDirection, and special attacking vars. sourceTag is either Player or Enemy public BulletSeed(Animator anim, PKMNEntity basis) { //Establish variables concerning source this.anim = anim; this.basis = basis; this.enemyTag = (anim.tag == "Player") ? "Enemy" : "Player"; //Set variables for hitbox this.hitbox = Resources.Load <Transform>("MoveHitboxes/BulletSeedObj"); ProjectileBehavior projProperties = hitbox.GetComponent <ProjectileBehavior>(); projProperties.speed = PROJ_SPEED; projProperties.knockbackVal = 0; projProperties.priority = PROJ_PRIORITY; //Regen variables curAmmo = MAX_AMMO; rTimer = 0.0f; //Set cooldown variables cTimer = 0.0f; curCooldown = MAX_COOLDOWN; offCD = true; }
//Set reference variable to entity at the start of the game void Awake() { entity = GetComponent <PKMNEntity>(); }