diff --git a/buildtools/ant_modules/dist.xml b/buildtools/ant_modules/dist.xml
index 5e65c516b29..e8ded02dd6a 100644
--- a/buildtools/ant_modules/dist.xml
+++ b/buildtools/ant_modules/dist.xml
@@ -132,6 +132,9 @@
+
+
+
diff --git a/data/maps/effect/lightning.png b/data/maps/effect/lightning.png
new file mode 100644
index 00000000000..510f0117462
Binary files /dev/null and b/data/maps/effect/lightning.png differ
diff --git a/doc/contributors.md b/doc/contributors.md
index 46bc79976bf..8d26c926297 100644
--- a/doc/contributors.md
+++ b/doc/contributors.md
@@ -998,6 +998,7 @@ The following people released their work to the public with a suitable license f
* [Inchadney](http://inchadney.com/sounds.html)
* [Gniffelbaf](https://freesound.org/people/Gniffelbaf/)
* [Kevin Luce (kevp888)](https://freesound.org/people/kevp888/)
+* [Gordon Dylan Johnson (GDJ)](https://openclipart.org/artist/GDJ)
diff --git a/doc/contributors/contributors.json b/doc/contributors/contributors.json
index 3c14d8f4bc7..dcdff94ebd0 100644
--- a/doc/contributors/contributors.json
+++ b/doc/contributors/contributors.json
@@ -4772,6 +4772,11 @@
"name": "kevp888",
"fullname": "Kevin Luce",
"link": "https://freesound.org/people/kevp888/"
+ },
+ {
+ "name": "GDJ",
+ "fullname": "Gordon Dylan Johnson",
+ "link": "https://openclipart.org/artist/GDJ"
}
]
}
diff --git a/doc/sources/graphics-misc.txt b/doc/sources/graphics-misc.txt
index 61a8c6789cc..a542471d44d 100644
--- a/doc/sources/graphics-misc.txt
+++ b/doc/sources/graphics-misc.txt
@@ -63,6 +63,10 @@ rotate* rg1024; CC0; https://openclipart.org/detail/20247
settings* ben; CC0; https://openclipart.org/detail/192629
sound* mightyman; CC0; https://openclipart.org/detail/165992
+data/maps/effect/
+
+lightning Gordon Dylan Johnson (GDJ); CC0; https://openclipart.org/detail/268835
+
data/sprites/
baby_dragon.png Kimmo Rundelin (kiheru); CC BY-SA 3.0; Stendhal
diff --git a/src/js/stendhal/data/Paths.ts b/src/js/stendhal/data/Paths.ts
index 15931181eb9..946c63b11e5 100644
--- a/src/js/stendhal/data/Paths.ts
+++ b/src/js/stendhal/data/Paths.ts
@@ -22,7 +22,8 @@ export class Paths {
public static readonly sprites = Paths.data + "/sprites";
public static readonly weather = Paths.sprites + "/weather";
public static readonly achievements = Paths.sprites + "/achievements";
- public static readonly tileset = Paths.data + "/maps/tileset";
+ public static readonly maps = Paths.data + "/maps";
+ public static readonly tileset = Paths.maps + "/tileset";
public static readonly ws = Paths.extractPath("data-ws");
/**
diff --git a/src/js/stendhal/event/generic/KikaPunishmentEvent.ts b/src/js/stendhal/event/generic/KikaPunishmentEvent.ts
index 9cf5648f527..49dcf5dd2e8 100644
--- a/src/js/stendhal/event/generic/KikaPunishmentEvent.ts
+++ b/src/js/stendhal/event/generic/KikaPunishmentEvent.ts
@@ -12,21 +12,65 @@
import { RPEvent } from "../RPEvent";
+import { Paths } from "../../data/Paths";
+import { store } from "../../data/SpriteStore";
+
import { SoundLayer } from "../../data/enum/SoundLayer";
+import { SoundID } from "../../data/sound/SoundID";
+
import { SoundManager } from "../../ui/SoundManager";
+import { ViewPort } from "../../ui/ViewPort";
+import { Color } from "../../util/Color";
+
+/**
+ * Creates effects for Kika punishment.
+ *
+ * TODO:
+ * - maybe make thunderclap louder
+ * - add some type of beforehand notice, maybe in travel log, about potential punishment
+ */
export class KikaPunishmentEvent extends RPEvent {
- override execute(entity: any) {
- // DEBUG:
- console.log("Kika punishment!");
+ private startTime = 0;
+ private image = store.get(Paths.maps + "/effect/lightning.png");
- SoundManager.get().playGlobalizedEffect("event/thunderclap", SoundLayer.SFX.value);
- // TODO:
- // - lightning flash
- // - maybe make thunderclap louder
+ override execute(entity: any) {
+ this.startTime = Date.now();
+ // thunder sound
+ SoundManager.get().playGlobalizedEffect(SoundID["thunderclap"], SoundLayer.SFX.value);
+ // lightning visual effect
+ const viewport = ViewPort.get();
+ viewport.onDrawComplete = (ctx: CanvasRenderingContext2D, offsetX: number, offsetY: number) => {
+ this.drawLightning(ctx, offsetX, offsetY);
+ }
+ window.setTimeout(function() { viewport.onDrawComplete = undefined; }, 300);
+ }
+
+ /**
+ * Draws a lighning effect on the viewport.
+ *
+ * @param ctx {CanvasRenderingContext2D}
+ * Canvas drawing context.
+ * @param offsetX {number}
+ * Canvas horizontal offset.
+ * @param offsetY {number}
+ * Canvas vertical offset.
+ */
+ private drawLightning(ctx: CanvasRenderingContext2D, offsetX: number, offsetY: number) {
+ const timeDiff = Date.now() - this.startTime;
+ ctx.save();
+ if (timeDiff <= 100 || timeDiff > 200) {
+ ctx.globalAlpha = 0.75;
+ }
+ ctx.fillStyle = Color.WHITE;
+ ctx.fillRect(offsetX, offsetY, 640, 480);
+ if (this.image.height) {
+ ctx.drawImage(this.image, offsetX, offsetY);
+ }
+ ctx.restore();
}
}
diff --git a/src/js/stendhal/ui/ViewPort.ts b/src/js/stendhal/ui/ViewPort.ts
index ed23cfd7d03..e2d764384e8 100644
--- a/src/js/stendhal/ui/ViewPort.ts
+++ b/src/js/stendhal/ui/ViewPort.ts
@@ -74,6 +74,14 @@ export class ViewPort {
/** Styles to be applied when chat panel is not floating. */
private readonly initialStyle: {[prop: string]: string};
+ /**
+ * Callback for instructions to execute when a drawing cycle on the viewport is complete.
+ *
+ * The function is called with the parameters `ctx` (CanvasRenderingContext2D), `offsetX`,
+ * and `offsetY`.
+ */
+ public onDrawComplete?: Function;
+
/** Singleton instance. */
private static instance: ViewPort;
@@ -153,6 +161,10 @@ export class ViewPort {
// redraw inventory sprites
stendhal.ui.equip.update();
(ui.get(UIComponentEnum.PlayerEquipment) as PlayerEquipmentComponent).update();
+
+ if (this.onDrawComplete) {
+ this.onDrawComplete(this.ctx, this.offsetX, this.offsetY);
+ }
}
}
window.setTimeout(function() {