/// <summary> /// Init this enemy AI. /// </summary> override public void Init(Enemy enemy) { base.Init(enemy); // Listen to damage events and if we get them hide enemy.Damaged += EnemyDamaged; enemy.Collided += EnemyDamaged; // If we need it try and find a charge movement if (useChargeState) { EnemyMovement_Distributor distributor = enemy.GetComponentInChildren <EnemyMovement_Distributor>(); if (distributor != null) { foreach (EnemyStateToMovement estm in distributor.statesToMovements) { if (estm.state == EnemyState.CHARGING) { chargeMovement = estm.movement; break; } } } else { chargeMovement = enemy.GetComponentInChildren <EnemyMovement_Charge>(); } } // Try to find a cahracter hurt box so we can collect coins and damage other enemies characterHitBox = GetComponentInChildren <CharacterHitBox>(); if (characterHitBox != null) { // Don't hit ourselves EnemyHurtBox myHurtBox = enemy.GetComponentInChildren <EnemyHurtBox>(); if (myHurtBox != null) { Physics2D.IgnoreCollision(characterHitBox.GetComponent <Collider2D>(), myHurtBox.GetComponent <Collider2D>()); } // Init hit box characterHitBox.Init(new DamageInfo(1, DamageType.PHYSICAL, Vector2.zero)); } }
/// <summary> /// Draws the inspector for a basic attack. /// </summary> /// <param name="attack">Attack.</param> virtual protected void DrawBasicAttackEditor(BasicAttackData attack) { if (!(target is ComboAttacks)) { string name = EditorGUILayout.TextField(new GUIContent("Name", "Human readable name (optional)."), attack.name); if (name != attack.name) { attack.name = name; } } if (((BasicAttacks)target).CanUserSetAttackType) { AttackType type = (AttackType)EditorGUILayout.EnumPopup(new GUIContent("Attack Type", "Attack which this combo triggers from. Empty or null means trigger from ANY other attack."), attack.attackType); if (type != attack.attackType) { attack.attackType = type; } } AnimationState state = (AnimationState)EditorGUILayout.EnumPopup(new GUIContent("Animation", "The animation state to set for this attack."), attack.animation); if (state != attack.animation) { attack.animation = state; } AttackLocation location = (AttackLocation)EditorGUILayout.EnumPopup(new GUIContent("Location", "Where does the character need to be to trigger this attack."), attack.attackLocation); if (location != attack.attackLocation) { attack.attackLocation = location; } GUILayout.Label("Controls", EditorStyles.boldLabel); int buttonIndex = EditorGUILayout.IntField(new GUIContent("Action Button", "The index of the action button that needs to be pressed."), attack.actionButtonIndex); if (buttonIndex != attack.actionButtonIndex && buttonIndex >= 0f) { attack.actionButtonIndex = buttonIndex; } bool fireWhenHeld = EditorGUILayout.Toggle(new GUIContent("Allow Button Held", "If true fire when button held not just when its pressed."), attack.fireWhenHeld); if (fireWhenHeld != attack.fireWhenHeld) { attack.fireWhenHeld = fireWhenHeld; } GUILayout.Label("Timing", EditorStyles.boldLabel); float length = EditorGUILayout.FloatField(new GUIContent("Attack Length", "The animation length in seconds."), attack.attackTime); if (length != attack.attackTime && length > 0.0f) { attack.attackTime = length; } float coolDown = EditorGUILayout.FloatField(new GUIContent("Attack Cool Down", "The time after the attack where it cannot be triggered again."), attack.coolDown); if (coolDown != attack.coolDown) { if (coolDown < 0) { coolDown = 0; } attack.coolDown = coolDown; } if (attack.attackType != AttackType.PROJECTILE) { float min = attack.attackHitBoxStart; float max = attack.attackHitBoxEnd; EditorGUILayout.MinMaxSlider(new GUIContent("Hit Window", "Enable and disable point for the characters hit box."), ref min, ref max, 0, 1); if (max <= min + 0.1f) { max += 0.1f; } if (min != attack.attackHitBoxStart || max != attack.attackHitBoxEnd) { attack.attackHitBoxStart = min; attack.attackHitBoxEnd = max; } } GUILayout.Label("Damage", EditorStyles.boldLabel); // Damage Info DamageType damageType = (DamageType)EditorGUILayout.EnumPopup(new GUIContent("Damage Type", "The type of damage this attack deals"), attack.damageType); if (damageType != attack.damageType) { attack.damageType = damageType; } int damageAmount = EditorGUILayout.IntField(new GUIContent("Damage Amount", "Amount of damage caused by this attack."), attack.damageAmount); if (damageAmount > 0 && damageAmount != attack.damageAmount) { attack.damageAmount = damageAmount; } if (attack.attackType != AttackType.PROJECTILE) { // Hit Box CharacterHitBox hitBox = (CharacterHitBox)EditorGUILayout.ObjectField(new GUIContent("Hit Box", "The character hit box that will be enabled when this attack starts"), attack.hitBox, typeof(CharacterHitBox), true); if (hitBox != attack.hitBox) { attack.hitBox = hitBox; } } else { // Projectile prefab GameObject prefab = (GameObject)EditorGUILayout.ObjectField(new GUIContent("Projectile Prefab", "Prefab to use for the projectile. Created on fire."), attack.projectilePrefab, typeof(GameObject), false); if (prefab != attack.projectilePrefab) { attack.projectilePrefab = prefab; } // Ammo item string ammoType = EditorGUILayout.TextField(new GUIContent("Ammo Type", "Item type to use for ammo. Empty means infinite ammo."), attack.ammoType); if (ammoType != attack.ammoType) { attack.ammoType = ammoType; } // Projectile delay float projectileDelay = EditorGUILayout.FloatField(new GUIContent("Projectile Delay", "Delay in seconds (from attack start) before the projectile is instantiated."), attack.projectileDelay); if (projectileDelay > attack.attackTime) { projectileDelay = attack.attackTime; } if (projectileDelay != attack.projectileDelay) { attack.projectileDelay = projectileDelay; } } GUILayout.Label("Other", EditorStyles.boldLabel); if (!((BasicAttacks)target).attackSystemWantsMovementControl) { showBlockingDetails = EditorGUILayout.Foldout(showBlockingDetails, "Movement Blocking"); if (showBlockingDetails) { // Block Jump bool blockJump = EditorGUILayout.Toggle(new GUIContent("Block Jump", "If true the attack system will not allow jumping whilst this attack is playing."), attack.blockJump); if (blockJump != attack.blockJump) { attack.blockJump = blockJump; } // Block Wall bool blockWall = EditorGUILayout.Toggle(new GUIContent("Block Wall Cling", "If true the attack system will not allow wall cling or slide whilst this attack is playing."), attack.blockWall); if (blockWall != attack.blockWall) { attack.blockWall = blockWall; } // Block Climb bool blockClimb = EditorGUILayout.Toggle(new GUIContent("Block Climb", "If true the attack system will not allow ladder or rope climbing whilst this attack is playing."), attack.blockClimb); if (blockClimb != attack.blockClimb) { attack.blockClimb = blockClimb; } // Block Special bool blockSpecial = EditorGUILayout.Toggle(new GUIContent("Block Special", "If true the attack system will not allow special movements whilst this attack is playing."), attack.blockSpecial); if (blockClimb != attack.blockSpecial) { attack.blockSpecial = blockSpecial; } } } else { // Apply gravity bool applyGravity = EditorGUILayout.Toggle(new GUIContent("Apply Gravity", "Should we apply gravity while this attack plays?"), attack.applyGravity); if (applyGravity != attack.applyGravity) { attack.applyGravity = applyGravity; } } // Set X to Zero bool resetVelocityX = EditorGUILayout.Toggle(new GUIContent("Reset X Velocity", "If true the attack system will set X velocity to zero."), attack.resetVelocityX); if (resetVelocityX != attack.resetVelocityX) { attack.resetVelocityX = resetVelocityX; } // Set Y to Zero bool resetVelocityY = EditorGUILayout.Toggle(new GUIContent("Reset Y Velocity", "If true the attack system will set Y velocity to zero."), attack.resetVelocityY); if (resetVelocityY != attack.resetVelocityY) { attack.resetVelocityY = resetVelocityY; } // Remove button if (((BasicAttacks)target).CanHaveMultipleAttacks) { EditorGUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); if (GUILayout.Button("Remove", GUILayout.MinWidth(100))) { if (target is ComboAttacks) { ((ComboAttacks)target).comboAttacks.Remove((ComboAttackData)attack); } else { ((BasicAttacks)target).attacks.Remove(attack); } } EditorGUILayout.EndHorizontal(); } // Draw a line GUILayout.Box("", GUILayout.Height(1), GUILayout.ExpandWidth(true)); }
/// <summary> /// Draw the inspector GUI. /// </summary> public override void OnInspectorGUI() { EditorGUILayout.HelpBox("Note that some of the attack settings such as the Attack Length and HitBox window are ignored for this attack.", MessageType.Info); // Unity says we don't need to do this, but if we don't do this then the automatic serialised object updates get the same name as the last object recorded Undo.FlushUndoRecordObjects(); Undo.RecordObject(target, "Power Bomb Update"); // Always maintain control with a power bomb bool maintainControl = true; if (maintainControl != ((BasicAttacks)target).attackSystemWantsMovementControl) { ((BasicAttacks)target).attackSystemWantsMovementControl = maintainControl; } // Draw one attack if (((BasicAttacks)target).attacks == null) { ((BasicAttacks)target).attacks = new List <BasicAttackData> (); ((BasicAttacks)target).attacks.Add(new BasicAttackData()); ((BasicAttacks)target).attacks[0].name = "PowerBomb"; } DrawBasicAttackEditor(((BasicAttacks)target).attacks[0]); float pauseTime = EditorGUILayout.FloatField(new GUIContent("Pause Time", "How long to pause for."), ((PowerBombAttack)target).pauseTime); if (pauseTime != ((PowerBombAttack)target).pauseTime && pauseTime > 0.0f) { ((PowerBombAttack)target).pauseTime = pauseTime; } float dropGravity = EditorGUILayout.FloatField(new GUIContent("Drop Gravity", "How much gravity to apply during the drop."), ((PowerBombAttack)target).dropGravity); if (dropGravity != ((PowerBombAttack)target).dropGravity && dropGravity < 0.0f) { ((PowerBombAttack)target).dropGravity = dropGravity; } float landingTime = EditorGUILayout.FloatField(new GUIContent("Landing Time", "How long do we stay in the landing state."), ((PowerBombAttack)target).landingTime); if (dropGravity != ((PowerBombAttack)target).landingTime && landingTime > 0.0f) { ((PowerBombAttack)target).landingTime = landingTime; } float minVelocity = EditorGUILayout.FloatField(new GUIContent("Minimum Velocity", "You must be going faster than this to trigger the attack. Use this to stop power bomb when falling."), ((PowerBombAttack)target).minVelocity); if (minVelocity != ((PowerBombAttack)target).minVelocity) { ((PowerBombAttack)target).minVelocity = minVelocity; } float maxVelocity = EditorGUILayout.FloatField(new GUIContent("Maximum Velocity", "You must be going slower than this to trigger the attack. Use this to ensure you are near the peak of your jump when power bombing."), ((PowerBombAttack)target).maxVelocity); if (maxVelocity != ((PowerBombAttack)target).maxVelocity) { ((PowerBombAttack)target).maxVelocity = maxVelocity; } bool requireDownKey = EditorGUILayout.Toggle(new GUIContent("Require Down Key", "Require user to press the down key as well as the action key to trigger power bomb."), ((PowerBombAttack)target).requireDownKey); if (requireDownKey != ((PowerBombAttack)target).requireDownKey) { ((PowerBombAttack)target).requireDownKey = requireDownKey; } CharacterHitBox hitBox = (CharacterHitBox)EditorGUILayout.ObjectField(new GUIContent("Landing Hit Box", "This hit box is enabled after landing. Use it to cause damage to nearby enemies when you land"), ((PowerBombAttack)target).landingDamageHitHox, typeof(CharacterHitBox), true); if (hitBox != ((PowerBombAttack)target).landingDamageHitHox) { ((PowerBombAttack)target).landingDamageHitHox = hitBox; } }