• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Winter Veil Reforged

Winter Veil Reforged

This is the cinematic map that was used to record my YouTube video below:

Credits:
Christmas Wreath by Deolrin:
https://www.hiveworkshop.com/threads/christmas-wreath.185688/
Winter Hat by Deolrin:
https://www.hiveworkshop.com/threads/santa-hat.151805/
The music is from here, and a lot of the animation is also heavily borrowed from this video:


Map Creation History:

Similar to my Makrura Rave project, the video recording is unedited from the Warcraft 3 map, including the music, so I thought it might be fun to share this map for posterity. (Make sure you enable Music in the options before playing the map ingame!)

I tagged the map as open source so you can feel free to tinker and look around to see how the music is able to sync with the animation even when inside the Warcraft 3 client, but as opposed to Makrura Rave which was fairly simple, although this map operates on the same basic premise I am dubious that any map developer who opens this map to look at how it is created would be able to take much from it.

The map's light animations were created using external software written specifically to automate the process of creating this map, specifically. Accordingly, without that software, updating the light show on this map would be a complete nightmare.

The software written to create and modify this map produced a grid of 8th notes matched against the beat of the song, where each column was the 8th note beat and each row was one of the lights in the scene. Clicking on a cell in the grid would toggle that light for that beat on or off, or there was an additional option of a "flash" mode that would essentially be a 16th note at that time (using multiple 8th notes "subsequently" would normally only leave the light on for a prolonged period of time, not ever turning off and therefore not appearing to move to the beat).

219500-1ce08b539409ea51dc6dc0440d0f5681.png


The "X" shape is the 16th-note "flash" effect.
Any names created in this UI for a row to represent a light could then be hooked up to a model by linking the model object and the light row names together in code:

Java:
                generator.generate(swordsFile) //
                        .emissiveAnimate("SwordA1", 1, "Textures/Black32.blp", "CS_Props_Statue_Mat_Emissive.tif") //
                        .lightAnimate("SwordA1", 0) //
                        .emissiveAnimate("SwordA2", 2, "Textures/Black32.blp", "CS_Props_Statue_Mat_Emissive.tif") //
                        .lightAnimate("SwordA2", 1) //
                        .emissiveAnimate("SwordA3", 3, "Textures/Black32.blp", "CS_Props_Statue_Mat_Emissive.tif") //
                        .lightAnimate("SwordA3", 2) //
                        .emissiveAnimate("SwordA4", 4, "Textures/Black32.blp", "CS_Props_Statue_Mat_Emissive.tif") //
                        .lightAnimate("SwordA4", 3) //
                        .save(new File(output + "SwordsA.mdx"));

                generator.generate(swordsFile) //
                        .emissiveAnimate("SwordB1", 1, "Textures/Black32.blp", "CS_Props_Statue_Mat_Emissive.tif") //
                        .lightAnimate("SwordB1", 0) //
                        .emissiveAnimate("SwordB2", 2, "Textures/Black32.blp", "CS_Props_Statue_Mat_Emissive.tif") //
                        .lightAnimate("SwordB2", 1) //
                        .emissiveAnimate("SwordB3", 3, "Textures/Black32.blp", "CS_Props_Statue_Mat_Emissive.tif") //
                        .lightAnimate("SwordB3", 2) //
                        .emissiveAnimate("SwordB4", 4, "Textures/Black32.blp", "CS_Props_Statue_Mat_Emissive.tif") //
                        .lightAnimate("SwordB4", 3) //
                        .save(new File(output + "SwordsB.mdx"));

                generator.generate(wreathFile) //
                        .geosetVisibleAnimate("WreathLeftOuter", 3) //
                        .geosetVisibleAnimate("WreathLeftOuter", 4) //
                        .geosetVisibleAnimate("WreathLeftOuter", 5) //
                        .save(new File(output + "WreathLeftOuter.mdx"));

                generator.generate(wreathFile) //
                        .geosetVisibleAnimate("WreathLeftInner", 3) //
                        .geosetVisibleAnimate("WreathLeftInner", 4) //
                        .geosetVisibleAnimate("WreathLeftInner", 5) //
                        .save(new File(output + "WreathLeftInner.mdx"));

                generator.generate(wreathFile) //
                        .geosetVisibleAnimate("WreathRightInner", 3) //
                        .geosetVisibleAnimate("WreathRightInner", 4) //
                        .geosetVisibleAnimate("WreathRightInner", 5) //
                        .save(new File(output + "WreathRightInner.mdx"));

                generator.generate(wreathFile) //
                        .geosetVisibleAnimate("WreathRightOuter", 3) //
                        .geosetVisibleAnimate("WreathRightOuter", 4) //
                        .geosetVisibleAnimate("WreathRightOuter", 5) //
                        .save(new File(output + "WreathRightOuter.mdx"));

                generator.generate(archwayTopperFile) //
                        .geosetVisibleAnimate("RoofRibbonA", 0) //
                        .geosetVisibleAnimate("RoofRibbonB", 1) //
                        .geosetVisibleAnimate("RoofRibbonC", 2) //
                        .lightAnimate("RoofRibbonA", 0) //
                        .lightAnimate("RoofRibbonB", 1) //
                        .lightAnimate("RoofRibbonC", 2) //
                        .save(new File(output + "RoofRibbons.mdx"));

                final GeneratingModel wallLampGen = generator.generate(lampFile);
                for (int i = 0; i < 7; i++) {
                    final int strId = (i + 1);
                    wallLampGen //
                            .emissiveAnimate("WallLamp0" + strId, i, "Textures/Black32.blp",
                                    "Doodads/Cityscape/Props/LanternPost/CS_Props_PostLantern_Emissive.tif") //
                            .lightAnimate("WallLamp0" + strId, i);
                }
                wallLampGen.save(new File(output + "WallLamp.mdx"));

                generator.generate(niceIceFile) //
                        .emissiveAnimate("IceTop_Left", 0, "Textures/Black32.blp",
                                "Doodads/Icecrown/Structures/IC_IceArch45/ICG_Structure_ArchwayIcy_Diffuse.blp") //
                        .lightAnimate("IceTop_Left", 0) //
                        .save(new File(output + "NiceIce.mdx"));

                for (int i = 1; i <= 6; i++) {
                    for (int j = 1; j <= i; j++) {
                        final String ghoulKey = "GhoulRow" + i + "Guy" + j;
                        System.out.println("making ghoul " + ghoulKey);
                        final boolean red = ((((i - 1) % 2) + (j - 1)) % 2) == 0;
                        File ghoulFile;
                        String colorString;
                        if (red) {
                            ghoulFile = lanternGhoulRedFile;
                            colorString = "Red";
                        } else {
                            ghoulFile = lanternGhoulGreenFile;
                            colorString = "Green";
                        }
                        generator.generate(ghoulFile)//
                                .emissiveAnimate(ghoulKey, 4, "Textures/Black32.blp",
                                        "CS_Props_PostLantern_" + colorString + "_Emissive.tif") //
                                .lightAnimate(ghoulKey, 0)//
                                .save(new File(output + ghoulKey + ".mdx"));
                    }
                }

                generator.generate(snowmanFile) //
                        .emissiveAnimate("TerenasStatusStaff", 2, "Textures/Black32.blp",
                                "Doodads/Cityscape/Props/LanternPost/CS_Props_PostLantern_Emissive.tif") //
                        .emissiveAnimate("TerenasStatusStaff", 3, "Textures/Black32.blp",
                                "CS_SH_Props_StatueKingTerenas_Emissive.tif") //
                        .lightAnimate("TerenasStatusStaff", 0) //
                        .save(new File(output + "KingSnowman.mdx"));

                generator.generate(greenLanternArthasFile) //
                        .emissiveAnimate("GreenLanternArthas", 0, "Textures/Black32.blp",
                                "CS_Props_PostLantern_Green_Emissive.tif") //
                        .lightAnimate("GreenLanternArthas", 0) //
                        .save(new File(output + "GreenLanternArthas.mdx"));

                generator.generate(redLanternArthasFile) //
                        .emissiveAnimate("RedLanternArthas", 0, "Textures/Black32.blp",
                                "CS_Props_PostLantern_Red_Emissive.tif") //
                        .lightAnimate("RedLanternArthas", 0) //
                        .save(new File(output + "RedLanternArthas.mdx"));

                generator.generate(beetleFile) //
                        .emissiveAnimate("BlueExtras", 1, "Textures/Black32.blp", "shinybeetle2.tif", true) //
                        .lightLinearColorAnimate("BlueExtras", 0) //
                        .lightAnimate("BlueEnableBit", 0, true) //
                        .save(new File(output + "BlueBeetle.mdx"));

                for (int i = 1; i <= 4; i++) {
                    generator.generate(bansheeFile) //
                            .fresnelLinearAnimate("BansheeA" + i, 0) //
                            .fresnelLinearAnimate("BansheeA" + i, 1) //
                            .lightLinearColorAnimate("BansheeA" + i, 0) //
                            .lightAnimate("GhostEnableBit", 0, true) //
                            .save(new File(output + "BansheeChoirA" + i + ".mdx"));
                }
                for (int i = 1; i <= 4; i++) {
                    generator.generate(bansheeFile) //
                            .fresnelLinearAnimate("BansheeB" + i, 0) //
                            .fresnelLinearAnimate("BansheeB" + i, 1) //
                            .lightLinearColorAnimate("BansheeB" + i, 0) //
                            .lightAnimate("GhostEnableBit", 0, true) //
                            .save(new File(output + "BansheeChoirB" + i + ".mdx"));
                }
Previews
Contents

Winter Veil Reforged (Map)

Reviews
deepstrasz
Lovely cinematic map, a musical even. We haven't had any of these for a long time, not even cinematic maps at all. Approved. If you want more reviews, you should participate in the The Grand Review Exchange! R U L E S Site Rules Map Submission...

deepstrasz

Map Reviewer
Level 69
Joined
Jun 4, 2009
Messages
18,798
Lovely cinematic map, a musical even. We haven't had any of these for a long time, not even cinematic maps at all.

Approved.


If you want more reviews, you should participate in the The Grand Review Exchange!

R U L E S

Site Rules
Map Submission Rules


M A P - D E S C R I P T I O N
BB CODES
BB Codes | HIVE

MELEE MAPS
Description Guide - Melee Maps
Describing Your Melee Map
Melee Map Description Generator v1.3


MAPS IN GENERAL
The importance of a Description
Description Guide - Maps
Map Thread Guide
Map Description Making: Good & Bad
Map Description - Templates
Map Description Generator [1.2]

How to Add a Screenshot to your Map Description


ADDITIONAL NECESSARY INFORMATION
  • A credits list in the map thread description is required where the names of the resource (models, skins, icons, spells, sound etc.) authors are mentioned along with the specific resource. It would be a luxury to have links leading to the used resources. Credits in the Quest Log would be appreciated too.
  • A detailed changelog in the first post would be helpful to reviewers and notify fans about the newest implementations to your map.
  • Map thread tags are important. Please use those that fit and not more or none.


M A P - C R E A T I O N - G U I D E S

If you're not satisfied with the review and wish another opinion, contact the other reviewers or use the staff contact:
Wazzz
Alexen
https://www.hiveworkshop.com/forums/staff-contact.692/
 
Top