Downloads containing DD-Order.asc

Downloads
Name Author Game Mode Rating
TSF with JJ2+ Only: Diamondus UltimateFeatured Download DoubleGJ Tileset conversion 10 Download file

File preview

/* ===Demon Dash dialogue script v1.4===
Written by Violet CLM, minor adjustments by Gnegon Galek
Font in animation file is Kangaroo Court Rotalic

Version history:
v1.1: added scripted events support, use the following format in the same manner as top/bottom line:
		finish: function() { jjPrint("hello world"); }
v1.2: sound effects added
v1.3: Mastah Yoman added to character pool, needs color palette entries 248-254 allocated for him, which are unused in every Nick Stadler tileset
v1.4: fixed a null pointer exception occuring when CurrentPopup is initiated by anything other than onFunction# (thx Speaktrap!)

---PUT IN LEVEL SCRIPT, MERGE WITH SAME FUNCTIONS IF NEEDED:---

void onLevelLoad() {
	OrderTextAppearance.pipe = STRING::DISPLAYSIGN;
	OrderTextAppearance.spacing -= 3;
	uint8 i;
	for (i = 0; i < 256; ++i)
		if (jjAnimSets[ANIM::CUSTOM[i]] == 0) {
			@OrderFontAnim = jjAnimations[jjAnimSets[ANIM::CUSTOM[i++]].load(0, "DD-Anims.j2a")];
			break;
		}
	for (; i < 256; ++i)
		if (jjAnimSets[ANIM::CUSTOM[i]] == 0) {
			jjAnimSets[OrderPortraitSet = ANIM::CUSTOM[i]].load(1, "DD-Anims.j2a");
			break;
		}
}

bool onDrawScore(jjPLAYER@ play, jjCANVAS@ canvas) {
	if (CurrentPopup !is null) {
		CurrentPopup.Draw(canvas);
		return !CurrentPopup.DrawHUD();
	}
	return false;
}
bool onDrawAmmo(jjPLAYER@ play, jjCANVAS@ canvas) { return CurrentPopup !is null && !CurrentPopup.DrawHUD(); }
bool onDrawHealth(jjPLAYER@ play, jjCANVAS@ canvas) { return CurrentPopup !is null && !CurrentPopup.DrawHUD(); }
bool onDrawLives(jjPLAYER@ play, jjCANVAS@ canvas) { return CurrentPopup !is null && !CurrentPopup.DrawHUD(); }
bool onDrawPlayerTimer(jjPLAYER@ play, jjCANVAS@ canvas) { return CurrentPopup !is null && !CurrentPopup.DrawHUD(); }

void onPlayer(jjPLAYER@ play) {
	const bool inCutscene = CurrentPopup !is null;
	jjCharacters[play.charCurr].canRun = !inCutscene; //block revving
	if (inCutscene) {
		play.timerPause();
		play.invincibility = -15;
		if (!CurrentPopup.Do())
			@CurrentPopup = null;
		PressingKeyToMakeCutsceneGoAway = true;
		play.keyLeft = play.keyRight = play.keyDown = play.keyUp = play.keyRun = play.keyFire = play.keyJump = play.keySelect = false;
		play.idle = 0;
	} else {
		if (play.keyFire || play.keySelect) {
			if (PressingKeyToMakeCutsceneGoAway)
				play.keySelect = play.keyFire = false;
		} else
			PressingKeyToMakeCutsceneGoAway = false;
			play.timerResume();
	}
}

---ADD TO ONLEVELLOAD IF LEVEL INCLUDES MASTAH YOMAN:---

jjPalette.color[248] = jjPALCOLOR(113, 255, 255);
jjPalette.color[249] = jjPALCOLOR(83, 237, 224);
jjPalette.color[250] = jjPALCOLOR(78, 219, 201);
jjPalette.color[251] = jjPALCOLOR(56, 176, 181);
jjPalette.color[252] = jjPALCOLOR(30, 133, 144);
jjPalette.color[253] = jjPALCOLOR(21, 99, 111);
jjPalette.color[254] = jjPALCOLOR(11, 67, 80);

---APPLY TO DESIRED DIALOGUE EVENT:---


		@CurrentPopup = Conversation(array<Screen@> = {
			Screen(top: Line("this is an example of the ORDERLOG system! press FIRE or SELECT to continue to the next screen.", left: Jazz, direction: -1)),
			Screen(
				top: Line("you can display multiple characters onscreen at once. any one of them can be given a speech box.", right: Lori, direction: 1, color: 88),
				bottom: Line(left: Addie)
			),
			Screen(
				top: Line("character corners are completely arbitrary, so are text box colors.", left: Eva, right: Jazz, direction: -1, color: 64),
				bottom: Line(left: Devan, right: Eva)
			),
			Screen(bottom: Line("text can also appear at the bottom of the screen. text box tails can point to empty corners for characters who are just out of sight.", direction: 1)),
			Screen(
				top: Line("if textboxes appear on both the top and bottom of the screen, they fill up with letters simultaneously.", color: 24),
				bottom: Line("wow TWO spazes! just like in multiplayer!", left: Spaz, right: Spaz, direction: -1, color: 48)
			),
			Screen(
				top: Line("we sure are glad you came and played through this example level!", left: Jazz, right: Spaz, direction: -1),
				bottom: Line("I'M not.", left: Eva, right: Devan, direction: 1, color: 80)
			)
		});
*/

#pragma require "DD-Anims.j2a"

const jjANIMATION@ OrderFontAnim;
ANIM::Set OrderPortraitSet;
enum Portrait { Devan, Eva, Jazz, Spaz, Addie, Lori, Bubba, Queen, Yoman, _LAST };
Popup@ CurrentPopup = null;
const uint8 FillColor = 15;
const uint8 StrokeColor = 71;
const array<uint8> MultiplyColors = {74, 42, 82, 90, 34, 50, 66};
const int LineSize = 17;
const int StrokeSize = 2;
const int FillSize = LineSize - StrokeSize * 2;
jjTEXTAPPEARANCE OrderTextAppearance(STRING::NORMAL);

abstract class Popup {
	Popup(){}
	bool Do() {
		return true;
	}
	void Draw(jjCANVAS@ canvas) const { }
	bool DrawHUD() const { return false; }
}
class Line {
	string Text;
	Portrait PLeft, PRight;
	uint8 Color;
	int TailDirection;
	array<string> WrappedLines;
	array<int> LinesX;
	int Left, Top, Width, Height;
	Line(const string &in text = "", Portrait left = Portrait::_LAST, Portrait right = Portrait::_LAST, uint8 color = 16, int direction = 0) { Text = text; PLeft = left; PRight = right; Color = color; TailDirection = direction; }
	
	void Wrap(Portrait pLeft, Portrait pRight, bool isTop) {
		const bool tooSmallForPortraits = jjSubscreenWidth < 640 || jjSubscreenHeight < 400;
		Left = (tooSmallForPortraits || (pLeft == Portrait::_LAST && TailDirection >= 0)) ? 8 : 173;
		Width = jjSubscreenWidth - ((tooSmallForPortraits || (pRight == Portrait::_LAST && TailDirection <= 0)) ? 8 : 173) - Left;
		const int maxWidth = Width - 16;
		WrappedLines.resize(0);
		LinesX.resize(0);
		if (Text.length != 0) {
			string line = "";
			const array<string> words = Text.split(" ");
			for (uint wordID = 0; wordID < words.length; ++wordID) {
				if (jjGetStringWidth(line + words[wordID], OrderFontAnim, OrderTextAppearance) >= maxWidth) {
					WrappedLines.insertLast(line);
					LinesX.insertLast(Left + (Width - jjGetStringWidth(line, OrderFontAnim, OrderTextAppearance)) / 2);
					line = words[wordID] + " ";
				} else
					line += words[wordID] + " ";
			}
			WrappedLines.insertLast(line);
			LinesX.insertLast(Left + (Width - jjGetStringWidth(line, OrderFontAnim, OrderTextAppearance)) / 2);
		}
		Height = WrappedLines.length * 20 + 16;
		Top = (isTop ? (tooSmallForPortraits ? 30 : 60) : jjSubscreenHeight - (tooSmallForPortraits ? 30 : 60)) - Height / 2;
		if (isTop) {
			if (Top < 7)
				Top = 7;
		} else {
			if (Top + Height > jjSubscreenHeight - 7)
				Top = jjSubscreenHeight - 7 - Height;
		}
	}
}
class Screen {
	array<Portrait> portraits(4, Portrait::_LAST);
	array<Line@> boxes(2);
	jjVOIDFUNC@ finishCallback;
    Screen(Line@ top = null, Line@ bottom = null, jjVOIDFUNC@ finish = null) {
        @boxes[0] = top;
        @boxes[1] = bottom;
        @finishCallback = finish;
		if (top is null && bottom is null)
			jjAlert("Please define at least one line!");
		if (top !is null) {
			portraits[0] = top.PLeft;
			portraits[2] = top.PRight;
		}
		if (bottom !is null) {
			portraits[1] = bottom.PLeft;
			portraits[3] = bottom.PRight;
		}
	}
}
class Conversation : Popup {
	bool LastSelect = true;
	array<array<int>> PortraitX(4, array<int>(Portrait::_LAST, 180));
	array<Portrait> PortraitPerCorner(4, Portrait::_LAST);
	const array<Screen@>@ Screens;
	uint ScreenID = 0;
	uint CharactersToDraw;
	uint MaxCharactersToDraw;
	int LastSubscreenSize;
//	string OriginalMusic = jjMusicFileName;
	
	Conversation(const array<Screen@>@ screens) {
		@Screens = screens;
		if (Screens[ScreenID] !is null) StartScreen();
	}
	void StartScreen() {
		const Screen@ screen = Screens[ScreenID];
		for (int cornerID = 0; cornerID < 4; ++cornerID)
			PortraitPerCorner[cornerID] = screen.portraits[cornerID];
		CharactersToDraw = 0;
		if (screen.boxes[0] is null)
			MaxCharactersToDraw = screen.boxes[1].Text.length;
		else if (screen.boxes[1] is null)
			MaxCharactersToDraw = screen.boxes[0].Text.length;
		else {
			MaxCharactersToDraw = screen.boxes[0].Text.length;
			if (screen.boxes[1].Text.length > MaxCharactersToDraw)
				MaxCharactersToDraw = screen.boxes[1].Text.length;
		}
		WrapBoxes();
	}
	void WrapBoxes() {
		LastSubscreenSize = jjSubscreenWidth | (jjSubscreenHeight << 16);
		if (Screens[ScreenID].boxes[0] !is null)
			Screens[ScreenID].boxes[0].Wrap(PortraitPerCorner[0], PortraitPerCorner[2], true);
		if (Screens[ScreenID].boxes[1] !is null)
			Screens[ScreenID].boxes[1].Wrap(PortraitPerCorner[1], PortraitPerCorner[3], false);
	}
	
	bool Do() {
		if (Screens[ScreenID] is null)
				return Finish();
				
		if (LastSubscreenSize != jjSubscreenWidth | (jjSubscreenHeight << 16))
			WrapBoxes();
		for (int cornerID = 0; cornerID < 4; ++cornerID) {
			array<int>@ corner = PortraitX[cornerID];
			for (int portraitID = 0; portraitID < Portrait::_LAST; ++portraitID) {
				if (PortraitPerCorner[cornerID] == portraitID) {
					if (corner[portraitID] > 0)
						corner[portraitID] -= 6;
				} else {
					if (corner[portraitID] < 180)
						corner[portraitID] += 6;
				}
			}
		 if (CharactersToDraw < MaxCharactersToDraw)
            jjSamplePriority(SOUND::MENUSOUNDS_TYPE);
		}
		
		if (jjKey[8]) //backspace
			return Finish();
		const bool pressingSelect = jjLocalPlayers[0].keyFire || jjLocalPlayers[0].keySelect || jjKey[1]; //left mouse button
		if (!LastSelect && pressingSelect) {
            playRandomMenuSample();
			if (MaxCharactersToDraw > CharactersToDraw)
                CharactersToDraw = MaxCharactersToDraw;
				
            else {
                if (Screens[ScreenID].finishCallback !is null)
                    Screens[ScreenID].finishCallback();
                if (++ScreenID >= Screens.length)
                    return Finish();
                else
					
                    if (Screens[ScreenID] !is null) StartScreen();
            }
        }
		LastSelect = pressingSelect;
		CharactersToDraw += 1;
		return true;
	}
	
	bool Finish() const {
//		jjMusicLoad(OriginalMusic);
		return false;
	}
	
	void drawH(jjCANVAS@ canvas, int x, int y, int w) {
		canvas.drawRectangle(x, y, w, LineSize, StrokeColor);
		canvas.drawRectangle(x, y + StrokeSize, w, FillSize, FillColor);
	}
	void drawV(jjCANVAS@ canvas, int x, int y, int h) {
		canvas.drawRectangle(x, y, LineSize, h, StrokeColor);
		canvas.drawRectangle(x + StrokeSize, y, FillSize, h, FillColor);
	}
	void Draw(jjCANVAS@ canvas) const override {
		const int width = jjSubscreenWidth;
		const int height = jjSubscreenHeight;
		
		int y = 37;
		drawH(canvas, 0, y, width);
		
		int x = (width - LineSize) / 2;
		drawV(canvas, x, 0, y + StrokeSize);
		
		canvas.drawRectangle(0,0, x,y, MultiplyColors[(ScreenID + 0) % 7],SPRITE::BLEND_MULTIPLY, 255);
		canvas.drawRectangle(x+LineSize,0, width-x-LineSize,y, MultiplyColors[(ScreenID + 1) % 7],SPRITE::BLEND_MULTIPLY, 255);
		
		y = height - 53;
		drawH(canvas, 0, y, width);
		
		x /= 2;
		y += StrokeSize + FillSize;
		drawV(canvas, x, y, height - y);
		
		canvas.drawRectangle(0, y + StrokeSize, x, height - y - StrokeSize, MultiplyColors[(ScreenID + 2) % 7],SPRITE::BLEND_MULTIPLY, 255);
		canvas.drawRectangle(x + LineSize, y + StrokeSize, x * 3 - x - LineSize, height - y - StrokeSize, MultiplyColors[(ScreenID + 3) % 7],SPRITE::BLEND_MULTIPLY, 255);
		
		x *= 3;
		drawV(canvas, x, y, height - y);
		
		canvas.drawRectangle(x + LineSize, y + StrokeSize, width - x - LineSize, height - y - StrokeSize, MultiplyColors[(ScreenID + 4) % 7],SPRITE::BLEND_MULTIPLY, 255);
		
		y = 37 + StrokeSize + FillSize;
		drawV(canvas, 43, y, height - 53 - y + StrokeSize);
		drawV(canvas, width - 43 - LineSize, y, height - 53 - y + StrokeSize);
		
		canvas.drawRectangle(0, y + StrokeSize, 43, height - 53 - y - StrokeSize, MultiplyColors[(ScreenID + 5) % 7],SPRITE::BLEND_MULTIPLY, 255);
		canvas.drawRectangle(width - 43, y + StrokeSize, 43, height - 53 - y - StrokeSize, MultiplyColors[(ScreenID + 6) % 7],SPRITE::BLEND_MULTIPLY, 255);
		
		canvas.drawRectangle(43 + LineSize, 37 + LineSize, width - (43 + LineSize) * 2, height - 37 - 53 - LineSize, 0,SPRITE::SHADOW);
		
		const bool tooSmallForPortraits = width < 640 || height < 400;
		
		if (!tooSmallForPortraits) {
			const array<array<int>> portraitLocations = {{0,100}, {0,height-92}, {width-1,100}, {width-1,height-92}};
			for (int cornerID = 0; cornerID < 4; ++cornerID) {
				const array<int>@ corner = PortraitX[cornerID];
				for (int portraitID = 0; portraitID < Portrait::_LAST; ++portraitID) {
					const int xOffset = corner[portraitID];
					if (xOffset != 180)
						canvas.drawSprite(portraitLocations[cornerID][0] + (cornerID >= 2 ? xOffset : -xOffset), portraitLocations[cornerID][1], OrderPortraitSet, portraitID, cornerID & 1, (cornerID >= 2) ? -1 : 1);
				}
			}
		}
		
		for (uint boxID = 0; boxID < 2; ++boxID) {
			if (Screens[ScreenID] is null)
				continue;
			if (Screens[ScreenID].boxes[boxID] is null)
				continue;
				
			const Line@ box = Screens[ScreenID].boxes[boxID];	
			const array<int>@ xs = box.LinesX;
			const array<string>@ lines = box.WrappedLines;
			if (lines.length != 0) {
				canvas.drawRectangle(box.Left, box.Top, box.Width, box.Height, box.Color + 7);
				canvas.drawRectangle(box.Left + StrokeSize, box.Top + StrokeSize, box.Width - StrokeSize*2, box.Height - StrokeSize*2, box.Color);
				if (box.TailDirection != 0 && !tooSmallForPortraits)
					canvas.drawSprite(box.TailDirection < 0 ? 0 : width-1, boxID == 0 ? 80 : height - 82, OrderPortraitSet, Portrait::_LAST, 0, boxID == 0 ? -box.TailDirection : (-box.TailDirection ^ 0x40), SPRITE::SINGLEHUE, box.Color);
				int charactersRemaining = CharactersToDraw;
				y = box.Top + 16;
				for (uint lineID = 0; lineID < lines.length && charactersRemaining > 0; ++lineID) {
					canvas.drawString(xs[lineID],y, lines[lineID].substr(0, charactersRemaining), OrderFontAnim, OrderTextAppearance,0, SPRITE::ALPHAMAP,0);
					charactersRemaining -= lines[lineID].length;
					y += 20;
				}
			}
		}
	}
}

void playRandomMenuSample() {
	switch(jjRandom()%7) {
	  	case 0: jjSamplePriority(SOUND::MENUSOUNDS_SELECT0); break;
	  	case 1: jjSamplePriority(SOUND::MENUSOUNDS_SELECT1); break;
	  	case 2: jjSamplePriority(SOUND::MENUSOUNDS_SELECT2); break;
	  	case 3: jjSamplePriority(SOUND::MENUSOUNDS_SELECT3); break;
	  	case 4: jjSamplePriority(SOUND::MENUSOUNDS_SELECT4); break;
	  	case 5: jjSamplePriority(SOUND::MENUSOUNDS_SELECT5); break;
	  	case 6: jjSamplePriority(SOUND::MENUSOUNDS_SELECT6); break;
	}
}

bool PressingKeyToMakeCutsceneGoAway = false;
bool IsLevelWhereRunningIsAllowed = jjDifficulty < 2;