Skip to content

Commit 316733a

Browse files
authored
Add cutscene helper (#644)
* Fix inventory updates * Add cutscene helper * Convert cutscenes * Fix demon slayer energy barrier * Fix npc queue crash and ignoring hide/wandering changes * Update autosave message * Fix dynamic zone clearing causing spam reloading problems * Make delrith instance a bit more robust * Remove unused imports
1 parent 8067d58 commit 316733a

File tree

13 files changed

+351
-291
lines changed

13 files changed

+351
-291
lines changed

data/quest/free/demon_slayer/demon_slayer.objs.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,6 @@ examine = "An evil presence seems to rest in the stone table."
3333
[demon_slayer_stone_table_shattered]
3434
id = 17438
3535
examine = "The stone table has been shattered."
36-
demon_slayer_energy_barrier = 14874
36+
37+
[demon_slayer_energy_barrier]
38+
id = 14874

data/quest/free/restless_ghost/restless_ghost.items.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
id = 552
33
tradeable = false
44
weight = 0.01
5+
aka = ["amulet_of_ghost_speak", "amulet_of_ghostspeak"]
56
slot = "Amulet"
67
examine = "It's an amulet of ghostspeak. It makes vague spooky noises."
78
kept = "Wilderness"

engine/src/main/kotlin/world/gregs/voidps/engine/entity/character/npc/NPCs.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import world.gregs.voidps.engine.entity.MAX_NPCS
99
import world.gregs.voidps.engine.entity.Spawn
1010
import world.gregs.voidps.engine.entity.character.CharacterSearch
1111
import world.gregs.voidps.engine.entity.character.CharacterMap
12+
import world.gregs.voidps.engine.entity.character.mode.EmptyMode
1213
import world.gregs.voidps.engine.entity.character.mode.Wander
1314
import world.gregs.voidps.engine.entity.character.mode.move.AreaEntered
1415
import world.gregs.voidps.engine.entity.character.player.skill.Skill
@@ -39,12 +40,12 @@ data class NPCs(
3940
override fun run() {
4041
for (i in 0 until removeIndex) {
4142
val index = removeQueue[i]
42-
val npc = indexArray[index]!!
43+
removeQueue[i] = -1
44+
size--
45+
val npc = indexArray[index] ?: continue
4346
indexArray[index] = null
4447
map.remove(npc.tile.regionLevel, npc)
4548
npc.index = -1
46-
removeQueue[i] = -1
47-
size--
4849
}
4950
removeIndex = 0
5051
for (i in 0 until spawnIndex) {
@@ -148,11 +149,10 @@ data class NPCs(
148149
npc.levels.clear(Skill.Ranged)
149150
npc.levels.clear(Skill.Magic)
150151
npc["spawn_tile"] = npc.tile
151-
if (Wander.wanders(npc)) {
152+
if (npc.mode == EmptyMode && Wander.wanders(npc)) {
152153
npc.mode = Wander(npc, npc.tile)
153154
}
154155
npc.collision = collision.get(npc)
155-
npc.hide = false
156156
map.add(npc.tile.regionLevel, npc)
157157
val respawnDelay = npc.def.getOrNull<Int>("respawn_delay")
158158
if (respawnDelay != null && respawnDelay > 0) {

engine/src/main/kotlin/world/gregs/voidps/engine/inv/InventoryUpdate.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ data class InventoryUpdate(
99
val inventory: String,
1010
val updates: List<InventorySlotChanged>
1111
) : Event {
12+
13+
override val notification = true
14+
1215
override val size = 2
1316

1417
override fun parameter(dispatcher: EventDispatcher, index: Int) = when(index) {
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package world.gregs.voidps.engine.map.zone
2+
3+
import world.gregs.voidps.engine.event.Event
4+
import world.gregs.voidps.engine.event.EventDispatcher
5+
import world.gregs.voidps.type.Region
6+
7+
data class ClearRegion(val region: Region) : Event {
8+
override val size = 1
9+
10+
override fun parameter(dispatcher: EventDispatcher, index: Int) = if (index == 0) "clear_region" else null
11+
}

engine/src/main/kotlin/world/gregs/voidps/engine/map/zone/DynamicZones.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,13 @@ class DynamicZones(
5757
*/
5858
fun clear(region: Region) {
5959
for (zone in region.toCuboid().toZones()) {
60-
clear(zone)
60+
objects.clear(zone)
61+
collisions.clear(zone)
62+
extract.loadZone(zone, zone, 0)
63+
zones.remove(zone.id)
6164
}
65+
regions.remove(region.id)
66+
World.emit(ClearRegion(region))
6267
}
6368

6469
private fun update(from: Zone, to: Zone, rotation: Int, set: Boolean) {

game/src/main/kotlin/content/area/misthalin/barbarian_village/Gudrun.kts

Lines changed: 48 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
package content.area.misthalin.barbarian_village
22

3+
import content.entity.player.dialogue.*
4+
import content.entity.player.dialogue.type.*
5+
import content.entity.sound.jingle
6+
import content.quest.Cutscene
7+
import content.quest.quest
8+
import content.quest.questComplete
9+
import content.quest.startCutscene
310
import world.gregs.voidps.engine.client.clearCamera
411
import world.gregs.voidps.engine.client.message
512
import world.gregs.voidps.engine.client.moveCamera
613
import world.gregs.voidps.engine.client.turnCamera
714
import world.gregs.voidps.engine.client.ui.open
8-
import world.gregs.voidps.engine.event.Context
915
import world.gregs.voidps.engine.entity.character.mode.interact.Interact
1016
import world.gregs.voidps.engine.entity.character.move.tele
1117
import world.gregs.voidps.engine.entity.character.npc.NPCOption
@@ -15,25 +21,17 @@ import world.gregs.voidps.engine.entity.character.player.Player
1521
import world.gregs.voidps.engine.entity.character.player.skill.Skill
1622
import world.gregs.voidps.engine.entity.obj.GameObjects
1723
import world.gregs.voidps.engine.entity.obj.ObjectShape
24+
import world.gregs.voidps.engine.event.Context
1825
import world.gregs.voidps.engine.inject
1926
import world.gregs.voidps.engine.inv.add
2027
import world.gregs.voidps.engine.inv.holdsItem
2128
import world.gregs.voidps.engine.inv.inventory
2229
import world.gregs.voidps.engine.inv.remove
23-
import world.gregs.voidps.engine.queue.LogoutBehaviour
24-
import world.gregs.voidps.engine.queue.queue
2530
import world.gregs.voidps.engine.queue.softQueue
2631
import world.gregs.voidps.engine.suspend.SuspendableContext
2732
import world.gregs.voidps.type.Direction
2833
import world.gregs.voidps.type.Region
2934
import world.gregs.voidps.type.Tile
30-
import content.quest.quest
31-
import content.quest.questComplete
32-
import content.quest.startCutscene
33-
import content.quest.stopCutscene
34-
import content.entity.player.dialogue.*
35-
import content.entity.player.dialogue.type.*
36-
import content.entity.sound.jingle
3735

3836
val objects: GameObjects by inject()
3937

@@ -71,109 +69,113 @@ val region = Region(12341)
7169

7270
suspend fun SuspendableContext<Player>.cutscene() {
7371
player.open("fade_out")
74-
val instance = startCutscene(region)
75-
val offset = instance.offset(region)
76-
setCutsceneEnd(instance)
72+
val cutscene = startCutscene("gudrun", region)
73+
cutscene.onEnd {
74+
player.open("fade_out")
75+
delay(3)
76+
player.tele(3081, 3416)
77+
player.clearCamera()
78+
player.clearAnim()
79+
}
7780
delay(4)
78-
player.tele(Tile(3078, 3435).add(offset), clearInterfaces = false)
79-
val dororan = npcs.add("dororan_cutscene", Tile(3079, 3435).add(offset), Direction.SOUTH)
81+
player.tele(cutscene.tile(3078, 3435), clearInterfaces = false)
82+
val dororan = npcs.add("dororan_cutscene", cutscene.tile(3079, 3435), Direction.SOUTH)
8083
dororan.anim("dororan_lean_on_door")
8184
player.anim("player_lean_on_door")
8285
dororan.face(Direction.NORTH)
8386
player.face(Direction.NORTH)
84-
player.moveCamera(Tile(3079, 3430).add(offset), 280)
85-
player.turnCamera(Tile(3079, 3436).add(offset), 230)
87+
player.moveCamera(cutscene.tile(3079, 3430), 280)
88+
player.turnCamera(cutscene.tile(3079, 3436), 230)
8689
delay(2)
8790
player.open("fade_in")
8891
npc<Talk>("dororan_cutscene", "How long have they been in there?")
8992
player.anim("player_calm_doroan")
9093
choice {
9194
option<Neutral>("They're just starting.") {
92-
cutsceneMenu(instance)
95+
cutsceneMenu(cutscene)
9396
}
9497
option<Neutral>("You're late.") {
95-
cutsceneMenu(instance)
98+
cutsceneMenu(cutscene)
9699
}
97100
}
98101
}
99102

100-
suspend fun SuspendableContext<Player>.cutsceneMenu(instance: Region) {
103+
suspend fun SuspendableContext<Player>.cutsceneMenu(cutscene: Cutscene) {
101104
npc<Sad>("dororan_cutscene", "This isn't going to work.")
102105
choice {
103106
option<Neutral>("Why's that?") {
104107
player.anim("player_calm_doroan")
105-
cutsceneMenu2(instance)
108+
cutsceneMenu2(cutscene)
106109
}
107110
option<Neutral>("You're so pessimistic.") {
108111
player.anim("player_calm_doroan")
109-
cutsceneMenu2(instance)
112+
cutsceneMenu2(cutscene)
110113
}
111114
}
112115
}
113116

114-
suspend fun SuspendableContext<Player>.cutsceneMenu2(instance: Region) {
117+
suspend fun SuspendableContext<Player>.cutsceneMenu2(cutscene: Cutscene) {
115118
npc<Cry>("dororan_cutscene", "What was I thinking? You should go in there and stop them before Gudrun makes a fool of herself.")
116119
choice {
117120
option<Neutral>("Okay, I will.") {
118121
player.anim("player_calm_doroan")
119122
npc<Sad>("dororan_cutscene", "No! Wait, stay here, it's too late now. We'll just have to see how it turns out.")
120-
cutsceneMenu3(instance)
123+
cutsceneMenu3(cutscene)
121124
}
122125
option<Neutral>("Don't be silly.") {
123126
player.anim("player_calm_doroan")
124127
npc<Sad>("dororan_cutscene", "You're right, it's too late now. We'll just have to see how it turns out.")
125-
cutsceneMenu3(instance)
128+
cutsceneMenu3(cutscene)
126129
}
127130
}
128131
}
129132

130-
suspend fun SuspendableContext<Player>.cutsceneMenu3(instance: Region) {
133+
suspend fun SuspendableContext<Player>.cutsceneMenu3(cutscene: Cutscene) {
131134
npc<Sad>("dororan_cutscene", "I can't hear what's happening. Can you hear what's happening?")
132135
player.anim("player_calm_doroan")
133136
player<Talk>("Gunthor is laughing at something.")
134137
npc<Upset>("dororan_cutscene", "He's probably considering the various tortures he has planned for me.")
135138
player.anim("player_calm_doroan")
136139
choice {
137140
option<Neutral>("Why would he do that?") {
138-
cutsceneMenu4(instance)
141+
cutsceneMenu4(cutscene)
139142
}
140143
option<Neutral>("Now you're just being ridiculous.") {
141-
cutsceneMenu4(instance)
144+
cutsceneMenu4(cutscene)
142145
}
143146
}
144147
}
145148

146-
suspend fun SuspendableContext<Player>.cutsceneMenu4(instance: Region) {
149+
suspend fun SuspendableContext<Player>.cutsceneMenu4(cutscene: Cutscene) {
147150
npc<Talk>("dororan_cutscene", "The poem says you can honour your ancestors by settling peacefully on the land they conquered.")
148151
npc<Sad>("dororan_cutscene", "He'll probably just find it insulting.")
149152
player.anim("player_calm_doroan")
150153
choice {
151154
option<Neutral>("Now's your chance to find out.") {
152-
cutscenePart2(instance)
155+
cutscenePart2(cutscene)
153156
}
154157
option<Neutral>("You're doomed.") {
155-
cutscenePart2(instance)
158+
cutscenePart2(cutscene)
156159
}
157160
}
158161
}
159162

160-
suspend fun SuspendableContext<Player>.cutscenePart2(instance: Region) {
163+
suspend fun SuspendableContext<Player>.cutscenePart2(cutscene: Cutscene) {
161164
player.open("fade_out")
162165
delay(3)
163-
npcs.clear(instance.toLevel(0))
166+
npcs.clear(cutscene.instance.toLevel(0))
164167
player.clearAnim()
165168
delay(1)
166-
val offset = instance.offset(region)
167-
player.tele(Tile(3083, 3426).add(offset), clearInterfaces = false)
169+
player.tele(cutscene.tile(3083, 3426), clearInterfaces = false)
168170
player.face(Direction.WEST)
169-
val dororan = npcs.add("dororan_cutscene", Tile(3082, 3428).add(offset), Direction.SOUTH)
170-
val gudrun = npcs.add("gudrun_cutscene", Tile(3080, 3426).add(offset), Direction.SOUTH)
171-
val kjell = npcs.add("kjell_cutscene", Tile(3077, 3426).add(offset), Direction.SOUTH)
172-
val gunthor = npcs.add("chieftain_gunthor_cutscene", Tile(3079, 3425).add(offset), Direction.SOUTH)
173-
val haakon = npcs.add("haakon_the_champion_cutscene", Tile(3078, 3425).add(offset), Direction.SOUTH)
171+
val dororan = npcs.add("dororan_cutscene", cutscene.tile(3082, 3428), Direction.SOUTH)
172+
val gudrun = npcs.add("gudrun_cutscene", cutscene.tile(3080, 3426), Direction.SOUTH)
173+
val kjell = npcs.add("kjell_cutscene", cutscene.tile(3077, 3426), Direction.SOUTH)
174+
val gunthor = npcs.add("chieftain_gunthor_cutscene", cutscene.tile(3079, 3425), Direction.SOUTH)
175+
val haakon = npcs.add("haakon_the_champion_cutscene", cutscene.tile(3078, 3425), Direction.SOUTH)
174176
dororan.face(gudrun)
175-
player.moveCamera(Tile(3079, 3419).add(offset), 400)
176-
player.turnCamera(Tile(3079, 3426).add(offset), 150)
177+
player.moveCamera(cutscene.tile(3079, 3419), 400)
178+
player.turnCamera(cutscene.tile(3079, 3426), 150)
177179
delay(2)
178180
player.open("fade_in")
179181
npc<Upset>("dororan_cutscene", "I hope they at least give me a decent burial.")
@@ -195,9 +197,9 @@ suspend fun SuspendableContext<Player>.cutscenePart2(instance: Region) {
195197
for (remove in npc) {
196198
npcs.remove(remove)
197199
}
198-
player.moveCamera(Tile(3084, 3421).add(offset), 350)
199-
player.turnCamera(Tile(3082, 3426).add(offset), 250)
200-
val gudrunHugging = objects.add("gudrun_and_dororan", Tile(3082, 3426).add(offset), shape = ObjectShape.CENTRE_PIECE_STRAIGHT, rotation = 1)
200+
player.moveCamera(cutscene.tile(3084, 3421), 350)
201+
player.turnCamera(cutscene.tile(3082, 3426), 250)
202+
val gudrunHugging = objects.add("gudrun_and_dororan", cutscene.tile(3082, 3426), shape = ObjectShape.CENTRE_PIECE_STRAIGHT, rotation = 1)
201203
player.open("fade_in")
202204
npc<Happy>("gudrun_cutscene", "That was brilliant! I must know who wrote that poem.")
203205
npc<Sad>("dororan_cutscene", "Um, that would be me. Hello")
@@ -210,7 +212,7 @@ suspend fun SuspendableContext<Player>.cutscenePart2(instance: Region) {
210212
gudrunHugging.anim("gudrun_hugging")
211213
delay(4)
212214
player.queue.clear("gunnars_ground_cutscene_end")
213-
endCutscene(instance)
215+
cutscene.end(this)
214216
player["gunnars_ground"] = "gunnars_ground"
215217
player["kjell"] = "guitar"
216218
player["dororan"] = "hidden"
@@ -247,21 +249,6 @@ suspend fun SuspendableContext<Player>.gunnarsGround() {
247249
}
248250
}
249251

250-
fun Context<Player>.setCutsceneEnd(instance: Region) {
251-
player.queue("gunnars_ground_cutscene_end", 1, LogoutBehaviour.Accelerate) {
252-
endCutscene(instance)
253-
}
254-
}
255-
256-
suspend fun SuspendableContext<Player>.endCutscene(instance: Region) {
257-
player.open("fade_out")
258-
delay(3)
259-
player.tele(3081, 3416)
260-
stopCutscene(instance)
261-
player.clearCamera()
262-
player.clearAnim()
263-
}
264-
265252
suspend fun SuspendableContext<Player>.poem() {
266253
if (player.holdsItem("gunnars_ground")) {
267254
npc<Quiz>("What have you got there?")

0 commit comments

Comments
 (0)