Name | Author | Game Mode | Rating | |||||
---|---|---|---|---|---|---|---|---|
Custom HUD | Spaz Electro | Mutator | N/A |
funcdef void TimerVDictionaryFunction(dictionary @);
class TimerV : jjBEHAVIORINTERFACE
{
TimerV(int time, jjVOIDFUNC @callback)
{
@_callback = @callback;
_start(time);
}
TimerV(int time, TimerVDictionaryFunction @callback, dictionary @arguments)
{
@_callbackWithArguments = @callback;
@_arguments = @arguments;
_start(time);
}
bool get_Active() const
{
return cast<jjBEHAVIORINTERFACE @>(_object.behavior) is this;
}
int get_Elapsed() const
{
if (Active)
return _object.age;
return -1;
}
int get_Total() const
{
if (Active)
return _object.counter;
return -1;
}
int get_Remaining() const
{
if (Active)
return _object.counter - _object.age;
return -1;
}
bool Stop()
{
if (Active && _object.age < _object.counter)
{
_object.delete();
return true;
}
return false;
}
bool Paused = false;
private
jjVOIDFUNC @_callback = null;
private
TimerVDictionaryFunction @_callbackWithArguments;
private
dictionary @_arguments;
private
jjOBJ @_object;
private
int _startTime;
private
void _start(int time)
{
if (time > 0)
{
@_object = jjObjects[jjAddObject(OBJECT::BEES, -1000, -1000, 0, CREATOR::OBJECT, BEHAVIOR::BEES)];
_object.behavior = this;
_object.counter = time;
_object.age = 0;
_object.playerHandling = HANDLING::PARTICLE;
_object.deactivates = false;
_startTime = jjGameTicks;
}
else
{
@_object = jjObjects[0]; // avoid null pointer access
_pickCallback();
}
}
private
void onBehave(jjOBJ @obj)
{
if (!Paused && jjGameTicks > _startTime && obj is _object && ++_object.age >= _object.counter)
{
_pickCallback();
_object.delete();
}
}
private
void _pickCallback()
{
if (_callback !is null)
_callback();
else
_callbackWithArguments(_arguments);
}
}
class Key
{
string id;
uint code;
Key(string id, uint code)
{
this.id = id;
this.code = code;
}
}
jjRNG stvutilRNG = jjRNG();
jjTEXTAPPEARANCE normalTextAppearance = jjTEXTAPPEARANCE(STRING::NORMAL);
array<Key @>
KEYS = {
Key("F2", 0x71), // 0
Key("F5", 0x74), // 1
Key("F6", 0x75), // 2
Key("F7", 0x76), // 3
Key("F10", 0x79), // 4
Key("F11", 0x7A), // 5
Key("Insert", 0x2D), // 6
Key("Home", 0x24), // 7
Key("PageUp", 0x21), // 8
Key("Delete", 0x2E), // 9
Key("End", 0x23), // 10
Key("PageDown", 0x22), // 11
Key("Colon", 0xBA), // 12
Key("QuotationMark", 0xDE), // 13
Key("Backspace", 0x08), // 14
Key("Backslash", 0xDC), // 15
Key("Backquote", 0xC0), // 16
Key("BracketLeft", 0xDB), // 17
Key("BracketRight", 0xDD), // 18
Key("Comma", 0xBC), // 19
Key("Minus", 0xBD), // 20
Key("Period", 0xBE), // 21
Key("Slash", 0xBF), // 22
Key("Plus", 0xBB), // 23
Key("Shift", 0x10), // 24
Key("Alt", 0x12), // 25
Key("Control", 0x11), // 26
Key("Tab", 0x09), // 27
Key("Caps Lock", 0x14), // 28
Key("Space", 0x20), // 29
Key("Up", 0x26), // 30
Key("Down", 0x28), // 31
Key("Left", 0x25), // 32
Key("Right", 0x27), // 33
Key("NumpadSlash", 0x6F), // 34
Key("NumpadAsterisk", 0x6A), // 35
Key("NumpadMinus", 0x6D), // 36
Key("NumpadPlus", 0x6B), // 37
Key("Numpad1", 0x61), // 38
Key("Numpad2", 0x62), // 39
Key("Numpad3", 0x63), // 40
Key("Numpad4", 0x64), // 41
Key("Numpad5", 0x65), // 42
Key("Numpad6", 0x66), // 43
Key("Numpad7", 0x67), // 44
Key("Numpad8", 0x68), // 45
Key("Numpad9", 0x69), // 46
Key("Numpad0", 0x60), // 47
Key("NumpadPeriod", 0x6E), // 48
Key("0", 0x30), // 49
Key("1", 0x31), // 50
Key("2", 0x32), // 51
Key("3", 0x33), // 52
Key("4", 0x34), // 53
Key("5", 0x35), // 54
Key("6", 0x36), // 55
Key("7", 0x37), // 56
Key("8", 0x38), // 57
Key("9", 0x39), // 58
Key("A", 0x41), // 59
Key("B", 0x42), // 60
Key("C", 0x43), // 61
Key("D", 0x44), // 62
Key("E", 0x45), // 63
Key("F", 0x46), // 64
Key("G", 0x47), // 65
Key("H", 0x48), // 66
Key("I", 0x49), // 67
Key("J", 0x4A), // 68
Key("K", 0x4B), // 69
Key("L", 0x4C), // 70
Key("M", 0x4D), // 71
Key("N", 0x4E), // 72
Key("O", 0x4F), // 73
Key("P", 0x50), // 74
Key("Q", 0x51), // 75
Key("R", 0x52), // 76
Key("S", 0x53), // 77
Key("T", 0x54), // 78
Key("U", 0x55), // 79
Key("V", 0x56), // 80
Key("W", 0x57), // 81
Key("X", 0x58), // 82
Key("Y", 0x59), // 83
Key("Z", 0x5A), // 84
Key("Enter", 0x0D), // 85
};
class AnimatedSprite
{
int id;
float frame;
int frame_count;
int x;
int y;
double anim_speed;
bool can_reverse;
bool reverse = false;
bool visible = true;
ANIM::Set animSet = ANIM::AMMO;
SPRITE::Mode spriteMode = SPRITE::NORMAL;
int spriteModeParam = 123;
SPRITE::Direction direction = SPRITE::FLIPNONE;
AnimatedSprite(int id, int frame, int x, int y, double anim_speed, bool can_reverse)
{
this.id = id;
this.frame = frame;
this.x = x;
this.y = y;
this.anim_speed = anim_speed;
this.can_reverse = can_reverse;
this.frame_count = jjAnimations[jjAnimSets[animSet].firstAnim + id].frameCount;
}
void setVisible(bool visible)
{
this.visible = visible;
}
void setAnimSet(ANIM::Set animSet)
{
this.animSet = animSet;
this.frame_count = jjAnimations[jjAnimSets[animSet].firstAnim + id].frameCount;
}
void setId(uint id)
{
this.id = id;
this.frame_count = jjAnimations[jjAnimSets[this.animSet].firstAnim + id].frameCount;
}
void update()
{
if (this.reverse == false)
{
this.frame += this.anim_speed;
}
else
{
this.frame -= this.anim_speed;
}
if (this.frame > this.frame_count)
{
if (this.can_reverse == true)
{
this.reverse = not this.reverse;
}
else
{
this.frame = 0;
}
}
if (this.frame <= 0)
{
if (this.can_reverse == true)
{
this.reverse = not this.reverse;
}
else
{
this.frame = 0;
}
}
}
void draw(jjCANVAS @canvas)
{
if (this.visible)
{
canvas.drawSprite(this.x, this.y, this.animSet, this.id, int(this.frame), this.direction, this.spriteMode, this.spriteModeParam);
}
}
}
class Vector2
{
uint x;
uint y;
Vector2(int x, int y)
{
this.x = x;
this.y = y;
}
float magnitude(Vector2 @otherVector)
{
return sqrt((this.x + this.y) - (otherVector.x + otherVector.y));
}
};
class Box
{
uint x;
uint y;
uint width;
uint height;
Box(uint x, uint y, uint width, uint height)
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
void draw(jjCANVAS @canvas)
{
canvas.drawRectangle(this.x, this.y, this.width, this.height, 0, SPRITE::NORMAL, 0);
}
}
// shouldClose: bool
funcdef bool DialogueChoiceCallback(DialogueChoice @, Dialogue @);
class DialogueChoice
{
string text;
int choiceId;
DialogueChoiceCallback @callback;
DialogueChoice(string text, int choiceId, DialogueChoiceCallback @callback)
{
this.text = text;
this.choiceId = choiceId;
@ this.callback = callback;
}
void draw(jjCANVAS @canvas, Box @box, string originalText, bool selected)
{
canvas.drawString(box.x, box.y + 40 + (choiceId * 45) + getStringHeight(originalText), (selected ? "|" : "") + "[" + formatInt(choiceId + 1) + "] " + this.text, STRING::MEDIUM, STRING::NORMAL, 0);
}
}
class Dialogue
{
string text;
string textDisplayed;
uint choice;
int speed = 5;
int x = 0;
int y = 0;
int lastCharTick = 0;
bool visible = false;
bool finished = false;
bool can_skip = true;
bool moreDialog = false;
bool skipped = false;
bool keyCooldown = false;
bool characterLoaded = false;
array<DialogueChoice @> choices;
string character;
int characterCID = 0;
int characterScaleX = 1;
int characterScaleY = 1;
Box @box;
Box @characterBox;
Dialogue(string text, array<DialogueChoice @> choices)
{
this.text = text;
this.x = 0;
this.y = 0;
this.choices = choices;
}
Dialogue(string text, array<DialogueChoice @> choices,
string character, int CID, Box @characterBox)
{
this.text = text;
this.x = 0;
this.y = 0;
this.choices = choices;
this.character = character;
this.characterCID = CID;
@ this.characterBox = characterBox;
}
void initialize()
{
@ this.box = Box(0, 0, jjGetStringWidth(this.text, STRING::MEDIUM, normalTextAppearance), 50 + (this.choices.length * 45));
this.visible = true;
this.finished = false;
this.textDisplayed = "";
this.lastCharTick = jjGameTicks;
// (this.box.x) - uint(
// jjAnimFrames[jjAnimations[jjAnimSets[ANIM::CUSTOM[this.characterCID]]]]
// .width / 2.5
// ),
// jjResolutionHeight / 2,
jjAnimSets[ANIM::CUSTOM[this.characterCID]].load(jjPIXELMAP(this.character),
this.characterBox.width, this.characterBox.height);
this.characterLoaded = true;
uint longestChoice = 1;
for (uint choiceIndex = 0; choiceIndex < this.choices.length; choiceIndex++)
{
DialogueChoice @choice = this.choices[choiceIndex];
if (getStringLength(choice.text) > longestChoice)
longestChoice = getStringLength(choice.text);
}
this.box.width += (longestChoice * 45);
}
void reload()
{
@ this.box = Box(0, 0, jjGetStringWidth(this.text, STRING::MEDIUM, normalTextAppearance), 50 + (this.choices.length * 45));
jjAnimSets[ANIM::CUSTOM[this.characterCID]].load(jjPIXELMAP(this.character),
this.characterBox.width, this.characterBox.height);
this.characterLoaded = true;
uint longestChoice = 1;
for (uint choiceIndex = 0; choiceIndex < this.choices.length; choiceIndex++)
{
DialogueChoice @choice = this.choices[choiceIndex];
if (getStringLength(choice.text) > longestChoice)
longestChoice = getStringLength(choice.text);
}
this.box.width += (longestChoice * 45);
}
void loadNewCharacter(string character, int CID, Box @characterBox)
{
this.character = character;
this.characterCID = CID;
@ this.characterBox = characterBox;
jjAnimSets[ANIM::CUSTOM[CID]].load(jjPIXELMAP(character),
characterBox.width, characterBox.height);
}
void draw(jjCANVAS @canvas)
{
if (this.visible)
{
this.box.x = jjResolutionWidth / 2 - (jjGetStringWidth(this.text, STRING::MEDIUM, normalTextAppearance)) / 2 + this.x;
this.box.y = (jjResolutionHeight - 100 + this.y) - 25 - (this.choices.length * 25);
this.box.draw(canvas);
canvas.drawString(
this.box.x,
this.box.y + 10,
this.textDisplayed, STRING::MEDIUM, STRING::NORMAL, 0);
if (this.finished)
{
for (uint choiceIndex = 0; choiceIndex < this.choices.length; choiceIndex++)
{
DialogueChoice @choice = this.choices[choiceIndex];
choice.draw(
canvas,
@ this.box,
this.text,
this.choice ==
choiceIndex);
}
}
if (this.moreDialog)
{
canvas.drawString(
this.box.x + this.box.width - 25,
this.box.y + 50,
">>", STRING::SMALL, STRING::NORMAL, 0);
// } else {
// canvas.drawString(
// this.box.x + this.box.width - 25,
// this.box.y + 50,
// ">", STRING::SMALL, STRING::NORMAL, 0);
}
if (this.characterLoaded)
{
canvas.drawResizedSprite(
this.characterBox.x, this.characterBox.y,
ANIM::CUSTOM[this.characterCID], 0, 0,
this.characterScaleX, this.characterScaleY);
}
}
}
void update()
{
if (this.visible && this.lastCharTick + this.speed < jjGameTicks)
{
if (uint(jjGetStringWidth(this.text, STRING::MEDIUM, normalTextAppearance)) >= this.box.y)
{
this.textDisplayed = this.text.substr(0, this.textDisplayed.length() + 1) + "@";
}
else
{
this.textDisplayed = this.text.substr(0, this.textDisplayed.length() + 1);
}
if (getStringLength(this.textDisplayed) >= getStringLength(this.text))
{
this.finished = true;
}
lastCharTick = jjGameTicks;
}
}
void input(jjPLAYER @player)
{
if (this.visible)
{
if (jjKey[KEYS[85].code] && this.keyCooldown == false)
{
if (this.finished || this.can_skip)
this.end();
if (!this.finished && this.can_skip)
this.skipped = true;
}
if (this.choice < 0)
this.choice = 0;
if (this.choice > (this.choices.length - 2))
this.choice = this.choices.length - 1;
// up
if (jjKey[KEYS[30].code])
{
// this is because if we get a negative value then the number is over 416k
if (!(this.choice - 1 > this.choices.length + 1))
this.choice -= 1;
}
// down
if (jjKey[KEYS[31].code])
{
this.choice += 1;
}
this.keyCooldown = true;
dictionary dict = {{"dialogue", @ this}};
TimerV(
80, function(this) {
Dialogue @dialog;
this.get("dialogue", @dialog);
dialog.keyCooldown = false;
},
dict);
}
}
void end()
{
if (this.choices.length != 0)
{
if (this.finished)
{
if (
(this.choices[this.choice])
.callback(
@(this.choices[this.choice]), @ this))
{
this.visible = false;
}
return;
}
}
this.visible = false;
this.finished = true;
}
}
// incomplete
enum RabbitState {
IDLE,
WALKING,
RUNNING,
JUMPING,
FALLING,
DYING,
DEAD,
SHOOTING,
PUSHING,
HURT
};
class RabbitFur {
// this isn't RGBA but its instead of using "abcd"
int r, g, b, a;
RabbitFur(int r, int g, int b, int a) {
this.r = r;
this.g = g;
this.b = b;
this.a = a;
}
// use SPRITE::PLAYER and spriteParam as the result
int emulateFur() {
getFreePlayer().furSet(this.r, this.g, this.b, this.a);
return getFreePlayer().clientID;
}
}
class RabbitNPC {
RabbitState state;
string name;
RabbitFur@ fur;
RabbitNPC(string name, RabbitFur fur) {
this.name = name;
@this.fur = fur;
this.state = RabbitState::IDLE;
}
}
jjPLAYER@ getFreePlayer() {
for (int i = 0; i < 32; i++)
{
if (!jjPlayers[i].isActive)
return jjPlayers[i];
}
return jjPlayers[1];
}
uint getStringLength(string str)
{
string str2 = str;
uint i = 0;
while (i < str2.length())
{
if (str2[i] == "|"[0])
{
str2 = str2.substr(0, i) + str2.substr(i + 1);
}
i++;
}
return str2.length();
}
uint getStringHeight(string str)
{
uint height = 0;
for (uint i = 0; i < str.length(); i++)
{
if (str[i] == "@"[0])
{
height += 1;
}
}
return height * 20;
}
bool parseBool(string str)
{
if (str == "true" || str == "1" || str == "yes")
return true;
return false;
}
string formatBool(bool b)
{
if (b)
return "1";
return "0";
}
string formatSize(STRING::Size size)
{
if(size == STRING::SMALL) return "small";
if(size == STRING::MEDIUM) return "medium";
return "large";
}
STRING::Size parseSize(string size)
{
if(size == "small") return STRING::SMALL;
if(size == "medium") return STRING::MEDIUM;
return STRING::LARGE;
}
string formatBoolToStringInteger(bool b)
{
if (b)
return "1";
return "0";
}
CHAR::Char parseCharacter(string str)
{
if (str == "SPAZ")
return CHAR::SPAZ;
if (str == "LORI")
return CHAR::LORI;
if (str == "BIRD")
return CHAR::BIRD;
if (str == "FROG")
return CHAR::FROG;
if (str == "BIRD2")
return CHAR::BIRD2;
return CHAR::JAZZ;
}
string formatCharacter(CHAR::Char charc)
{
if (charc == CHAR::SPAZ)
return "SPAZ";
if (charc == CHAR::LORI)
return "LORI";
if (charc == CHAR::BIRD)
return "BIRD";
if (charc == CHAR::FROG)
return "FROG";
if (charc == CHAR::BIRD2)
return "BIRD2";
return "JAZZ";
}
GEM::Color parseGem(string str)
{
if (str == "GREEN")
return GEM::GREEN;
if (str == "BLUE")
return GEM::BLUE;
if (str == "PURPLE")
return GEM::PURPLE;
return GEM::RED;
}
string formatGem(GEM::Color g)
{
if (g == GEM::GREEN)
return "GREEN";
if (g == GEM::BLUE)
return "BLUE";
if (g == GEM::PURPLE)
return "PURPLE";
return "RED";
}
array<string> cloneStringArray(array<string> arr)
{
array<string> newArray;
for (uint itemIndex = 0; itemIndex < arr.length; itemIndex++)
{
newArray.insertLast(arr[itemIndex]);
}
return newArray;
}
int boolToInt(bool b)
{
if (b)
return 1;
else
return 0;
}
string getPipeColor(int pipeCount)
{
string color = "white";
switch (pipeCount)
{
case 1:
color = "green";
break;
case 2:
color = "red";
break;
case 3:
color = "blue";
break;
case 4:
color = "yellow";
break;
case 5:
color = "pink";
break;
case 6:
color = "white";
break;
case 7:
color = "green";
break;
case 8:
color = "cyan";
break;
}
return color;
}
string restartPipePattern(string str)
{
// fix this
// w|g|r|b|y|p|w|g|c|(restart from g)
// white-green-red-blue-yellow-pink-white(ish)-green-cyan(i think)
int pipeCount = 0;
string color = "white";
for (uint i = 0; i < str.length(); i++)
{
if (str[i] == "|"[0])
{
pipeCount += 1;
if (pipeCount > 8)
{
pipeCount = 1;
}
}
}
color = getPipeColor(pipeCount);
while (color != "white")
{
str = str + "|";
pipeCount += 1;
if (pipeCount > 8)
{
pipeCount = 1;
}
}
return str;
}
Key @isAnyKeyDown()
{
Key @keyThatIsDown;
for (uint i = 0; i < KEYS.length() - 1; i++)
{
Key @key = KEYS[i];
if (jjKey[key.code])
{
@keyThatIsDown = key;
}
}
return keyThatIsDown;
}
bool isKeyDown(Key @key)
{
return jjKey[key.code];
}
Key @getKeyById(string id)
{
Key @foundKey;
for (uint i = 0; i < KEYS.length() - 1; i++)
{
Key @key = KEYS[i];
if (key.id == id)
{
@foundKey = key;
break;
}
}
return foundKey;
}
int getRandomNumber(int min, int max)
{
int num = stvutilRNG();
if (num < 0)
num *= -1;
num = (num % (max - min + 1)) + min;
return num;
}
int getPlayerCount()
{
int count = 0;
for (int i = 0; i < 32; i++)
{
if (jjPlayers[i].isActive)
count++;
}
return count;
}
jjPLAYER @getRandomPlayer()
{
jjPLAYER @user = jjPlayers[getRandomNumber(0, getPlayerCount())];
if (user.isActive and !user.isOut)
return user;
else
return getRandomPlayer();
}
funcdef void KeyPressCallback(uint);
array<bool> prevKeys(256, false);
array<KeyPressCallback@> keyPressCallbacks;
void updateKeys()
{
for (uint keyCode = 0; keyCode < 256; keyCode++)
{
if (jjKey[keyCode] && !prevKeys[keyCode])
{
for (uint i = 0; i < keyPressCallbacks.length; i++)
{
keyPressCallbacks[i](keyCode);
}
}
prevKeys[keyCode] = jjKey[keyCode];
}
}
Jazz2Online © 1999-INFINITY (Site Credits). We have a Privacy Policy. Jazz Jackrabbit, Jazz Jackrabbit 2, Jazz Jackrabbit Advance and all related trademarks and media are ™ and © Epic Games. Lori Jackrabbit is © Dean Dodrill. J2O development powered by Loops of Fury and Chemical Beats.
Eat your lima beans, Johnny.