Skip to content

Commit

Permalink
Add skills and cinematics for mythic mobs
Browse files Browse the repository at this point in the history
  • Loading branch information
gabber235 committed Jan 12, 2024
1 parent 0885524 commit bfa423a
Show file tree
Hide file tree
Showing 10 changed files with 309 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ import java.time.Duration
* This entry could be used to show a title during a cinematic, such as a title for a cutscene.
*/
class TitleCinematicEntry(
override val id: String,
override val name: String,
override val criteria: List<Criteria>,
override val id: String = "",
override val name: String = "",
override val criteria: List<Criteria> = emptyList(),
@Segments(icon = Icons.PARAGRAPH)
val segments: List<TitleSegment>,
val segments: List<TitleSegment> = emptyList(),
) : CinematicEntry {
override fun create(player: Player): CinematicAction {
return TitleCinematicAction(
Expand All @@ -41,8 +41,8 @@ class TitleCinematicEntry(
}

data class TitleSegment(
override val startFrame: Int,
override val endFrame: Int,
override val startFrame: Int = 0,
override val endFrame: Int = 0,
@Help("The title to show")
val title: String = "",
@Help("The subtitle to show")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,4 @@ object MythicMobsAdapter : TypewriteAdapter() {
return
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package me.ahdg6.typewriter.mythicmobs.entries.action

import io.lumine.mythic.api.mobs.GenericCaster
import io.lumine.mythic.bukkit.BukkitAdapter
import io.lumine.mythic.bukkit.MythicBukkit
import io.lumine.mythic.core.skills.SkillMetadataImpl
import io.lumine.mythic.core.skills.SkillTriggers
import me.gabber235.typewriter.adapters.Colors
import me.gabber235.typewriter.adapters.Entry
import me.gabber235.typewriter.adapters.modifiers.Help
import me.gabber235.typewriter.entry.Criteria
import me.gabber235.typewriter.entry.Modifier
import me.gabber235.typewriter.entry.entries.ActionEntry
import me.gabber235.typewriter.logger
import me.gabber235.typewriter.utils.Icons
import org.bukkit.entity.Player

@Entry("execute_mythicmob_skill", "Executes a MythicMobs skill", Colors.RED, Icons.BOLT_LIGHTNING)
/**
* The `Execute Skill Action` action executes a MythicMobs skill.
*
* ## How could this be used?
* Create fancy particle animations.
* For example, you can create a little animation when a player opens a door.
*/
class ExecuteSkillActionEntry(
override val id: String = "",
override val name: String = "",
override val triggers: List<String> = emptyList(),
override val criteria: List<Criteria> = emptyList(),
override val modifiers: List<Modifier> = emptyList(),
@Help("The name of the skill to execute")
val skillName: String = "",
) : ActionEntry {
override fun execute(player: Player) {
super.execute(player)

val skill = MythicBukkit.inst().skillManager.getSkill(skillName).orElseGet {
throw IllegalArgumentException("Skill $skillName not found")
}
val trigger = BukkitAdapter.adapt(player)
val caster = GenericCaster(trigger)

val skillMeta =
SkillMetadataImpl(SkillTriggers.API, caster, trigger)

if (skill.isUsable(skillMeta)) skill.execute(skillMeta)
else logger.warning("Skill $skillName is not usable at this time (cooldown, etc.)")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package me.ahdg6.typewriter.mythicmobs.entries.cinematic

import com.github.shynixn.mccoroutine.bukkit.minecraftDispatcher
import io.lumine.mythic.api.mobs.GenericCaster
import io.lumine.mythic.bukkit.BukkitAdapter
import io.lumine.mythic.bukkit.MythicBukkit
import io.lumine.mythic.core.mobs.ActiveMob
import io.lumine.mythic.core.skills.SkillMetadataImpl
import io.lumine.mythic.core.skills.SkillTriggers
import kotlinx.coroutines.withContext
import lirand.api.extensions.server.server
import me.gabber235.typewriter.adapters.Colors
import me.gabber235.typewriter.adapters.Entry
import me.gabber235.typewriter.adapters.modifiers.Help
import me.gabber235.typewriter.adapters.modifiers.Segments
import me.gabber235.typewriter.entry.Criteria
import me.gabber235.typewriter.entry.cinematic.SimpleCinematicAction
import me.gabber235.typewriter.entry.entries.CinematicAction
import me.gabber235.typewriter.entry.entries.CinematicEntry
import me.gabber235.typewriter.entry.entries.Segment
import me.gabber235.typewriter.plugin
import me.gabber235.typewriter.utils.Icons
import org.bukkit.Location
import org.bukkit.entity.Player

@Entry("mythicmob_cinematic", "Spawn a MythicMob during a cinematic", Colors.PURPLE, Icons.DRAGON)
/**
* The `Spawn MythicMob Cinematic` cinematic entry spawns a MythicMob during a cinematic.
*
* ## How could this be used?
*
* This can be used to animate a MythicMob spawning during a cinematic.
*/
class MythicMobCinematicEntry(
override val id: String = "",
override val name: String = "",
override val criteria: List<Criteria> = emptyList(),
@Segments(Colors.PURPLE, Icons.DRAGON)
val segments: List<MythicMobSegment> = emptyList(),
) : CinematicEntry {
override fun create(player: Player): CinematicAction {
return MobCinematicAction(player, this)
}
}

data class MythicMobSegment(
override val startFrame: Int = 0,
override val endFrame: Int = 0,
@Help("The name of the mob to spawn")
val mobName: String = "",
@Help("The location to spawn the mob at")
val location: Location = Location(null, 0.0, 0.0, 0.0),
) : Segment

class MobCinematicAction(
private val player: Player,
entry: MythicMobCinematicEntry,
) : SimpleCinematicAction<MythicMobSegment>() {
override val segments: List<MythicMobSegment> = entry.segments

private var mob: ActiveMob? = null

override suspend fun startSegment(segment: MythicMobSegment) {
super.startSegment(segment)

withContext(plugin.minecraftDispatcher) {
val mob = MythicBukkit.inst().mobManager.spawnMob(segment.mobName, segment.location)
this@MobCinematicAction.mob = mob
val hideMechanic = MythicBukkit.inst().skillManager.getMechanic("hide")

val targets =
server.onlinePlayers.filter { it.uniqueId != player.uniqueId }.map { BukkitAdapter.adapt(it) }.toSet()

val skillMeta = SkillMetadataImpl(
SkillTriggers.API,
GenericCaster(mob.entity),
mob.entity,
mob.location,
targets,
null,
1f
)

hideMechanic.execute(skillMeta)
}
}

override suspend fun stopSegment(segment: MythicMobSegment) {
super.stopSegment(segment)

mob?.let {
it.despawn()
mob = null
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package me.ahdg6.typewriter.mythicmobs.entries.cinematic

import io.lumine.mythic.api.mobs.GenericCaster
import io.lumine.mythic.bukkit.BukkitAdapter
import io.lumine.mythic.bukkit.MythicBukkit
import io.lumine.mythic.core.skills.SkillMetadataImpl
import io.lumine.mythic.core.skills.SkillTriggers
import me.gabber235.typewriter.adapters.Colors
import me.gabber235.typewriter.adapters.Entry
import me.gabber235.typewriter.adapters.modifiers.Help
import me.gabber235.typewriter.adapters.modifiers.InnerMax
import me.gabber235.typewriter.adapters.modifiers.Max
import me.gabber235.typewriter.adapters.modifiers.Segments
import me.gabber235.typewriter.entry.Criteria
import me.gabber235.typewriter.entry.cinematic.SimpleCinematicAction
import me.gabber235.typewriter.entry.entries.CinematicAction
import me.gabber235.typewriter.entry.entries.CinematicEntry
import me.gabber235.typewriter.entry.entries.Segment
import me.gabber235.typewriter.logger
import me.gabber235.typewriter.utils.Icons
import org.bukkit.entity.Player

@Entry("mythicskill_cinematic", "Spawn a MythicMob during a cinematic", Colors.PURPLE, Icons.BOLT_LIGHTNING)
/**
* The `Mythic Skill Cinematic` cinematic entry triggers a skill during a cinematic.
*
* :::caution
* A skill itself needs to define the audience to be self using `audience=self`
*
* ### Example:
* ```
* - effect:particlesphere{particle=flame;amount=200;radius=2;audience=self} @self
* ```
* :::
*
* ## How could this be used?
*
* This can be used to animate fancy particle effects during a cinematic.
*/
class MythicSkillCinematicEntry(
override val id: String = "",
override val name: String = "",
override val criteria: List<Criteria> = emptyList(),
@Segments(Colors.PURPLE, Icons.BOLT_LIGHTNING)
@InnerMax(Max(1))
val segments: List<MythicSkillSegment> = emptyList(),
) : CinematicEntry {
override fun create(player: Player): CinematicAction {
return SkillCinematicAction(player, this)
}
}

data class MythicSkillSegment(
override val startFrame: Int = 0,
override val endFrame: Int = 0,
@Help("The name of the skill to trigger")
val skillName: String = "",
) : Segment

class SkillCinematicAction(
private val player: Player,
entry: MythicSkillCinematicEntry,
) : SimpleCinematicAction<MythicSkillSegment>() {
override val segments: List<MythicSkillSegment> = entry.segments

override suspend fun startSegment(segment: MythicSkillSegment) {
super.startSegment(segment)

val skill = MythicBukkit.inst().skillManager.getSkill(segment.skillName).orElseGet {
throw IllegalArgumentException("Skill ${segment.skillName} not found")
}

val trigger = BukkitAdapter.adapt(player)
val caster = GenericCaster(trigger)

val skillMeta =
SkillMetadataImpl(SkillTriggers.API, caster, trigger)

if (skill.isUsable(skillMeta)) skill.execute(skillMeta)
else logger.warning("Skill ${segment.skillName} is not usable at this time (cooldown, etc.)")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,16 @@ This adapter is untested. It may not work as expected. Please report any issues
| Name | Description |
| ---- | ----------- |
| [Despawn Mob Action](MythicMobsAdapter/entries/action/despawn_mythicmobs_mob) | Despawn a mob from MythicMobs |
| [Execute Skill Action](MythicMobsAdapter/entries/action/execute_mythicmob_skill) | Executes a MythicMobs skill |
| [Spawn Mob Action](MythicMobsAdapter/entries/action/spawn_mythicmobs_mob) | Spawn a mob from MythicMobs |

### Cinematics

| Name | Description |
| ---- | ----------- |
| [Mythic Mob Cinematic](MythicMobsAdapter/entries/cinematic/mythicmob_cinematic) | Spawn a MythicMob during a cinematic |
| [Mythic Skill Cinematic](MythicMobsAdapter/entries/cinematic/mythicskill_cinematic) | Spawn a MythicMob during a cinematic |

### Events

| Name | Description |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import * as fields from '@site/src/components/EntryField';
import Admonition from '@theme/Admonition';
import Link from '@docusaurus/Link';

# Execute Skill Action

The `Execute Skill Action` action executes a MythicMobs skill.

## How could this be used?
Create fancy particle animations.
For example, you can create a little animation when a player opens a door.


## Fields

<fields.TriggersField />
<fields.CriteriaField />
<fields.ModifiersField />
<fields.EntryField name='Skill Name' required>
The name of the skill to execute
</fields.EntryField>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
label: Cinematics
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import * as fields from '@site/src/components/EntryField';
import Admonition from '@theme/Admonition';
import Link from '@docusaurus/Link';

# Mythic Mob Cinematic

The `Spawn MythicMob Cinematic` cinematic entry spawns a MythicMob during a cinematic.

## How could this be used?

This can be used to animate a MythicMob spawning during a cinematic.


## Fields

<fields.CriteriaField />
<fields.EntryField name='Segments' required multiple segment>
</fields.EntryField>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import * as fields from '@site/src/components/EntryField';
import Admonition from '@theme/Admonition';
import Link from '@docusaurus/Link';

# Mythic Skill Cinematic

The `Mythic Skill Cinematic` cinematic entry triggers a skill during a cinematic.

:::caution
A skill itself needs to define the audience to be self using `audience=self`

### Example:
```
- effect:particlesphere{particle=flame;amount=200;radius=2;audience=self} @self
```
:::

## How could this be used?

This can be used to animate fancy particle effects during a cinematic.


## Fields

<fields.CriteriaField />
<fields.EntryField name='Segments' required multiple segment>
</fields.EntryField>

0 comments on commit bfa423a

Please sign in to comment.