Name | Author | Game Mode | Rating | |||||
---|---|---|---|---|---|---|---|---|
True Fur | Violet CLM | Mutator | 9.5 |
#pragma name "True Fur"
#pragma description "Draw players with full 16-bit color palettes instead of the sprite colors of the current level palette"
class Fur {
int MappingID = -1;
jjSTREAM Packet;
Fur(){}
}
array<Fur> Furs(32);
void onLevelBegin() {
if (!jjIsServer)
jjSendPacket(jjSTREAM()); //hey, I'm here, send me stuff
for (int localPlayerID = 0; localPlayerID < jjLocalPlayerCount; ++localPlayerID) {
const int playerID = jjLocalPlayers[localPlayerID].playerID;
Fur@ fur = Furs[playerID];
fur.Packet.push(uint8(playerID));
jjSTREAM furFile("Fur" + (localPlayerID + 1) + ".asdat");
if (furFile.getSize() == 254) { //correct length
uint8 version;
furFile.pop(version);
if (version == 0) { //only supported version
furFile.discard(10); //selectedIndex values for the html file
const int mappingID = jjSpriteModeFirstFreeMapping();
if (mappingID >= 0) { //mappings available
fur.MappingID = mappingID;
fur.Packet.write(furFile);
mapPacket(mappingID, furFile);
}
}
}
if (!jjIsServer)
jjSendPacket(fur.Packet); //even if the file wasn't loaded, a packet with only the player ID is still valid (and counted as meaning no custom fur for this player)
}
}
void mapPacket(int mappingID, jjSTREAM@ packet) {
jjPAL mapping = jjPalette; //SOME palette, shouldn't really matter
uint index = 15;
uint8 r, g, b;
for (int i = 0; i < 243; i += 3, ++index) {
packet.pop(r);
packet.pop(g);
packet.pop(b);
mapping.color[index] = jjPALCOLOR(r,g,b);
}
jjSpriteModeSetMapping(mappingID, array<uint8>(), mapping);
}
void onReceive(jjSTREAM &in packet, int fromClientID) {
if (packet.isEmpty()) { //initial ping
if (jjIsServer)
for (int otherPlayerID = 0; otherPlayerID < 32; ++otherPlayerID) {
const jjPLAYER@ player = jjPlayers[otherPlayerID];
if (player.isActive && player.clientID != fromClientID)
jjSendPacket(Furs[otherPlayerID].Packet, fromClientID); //send the other players' fur to the new player
}
return;
}
uint8 playerID;
packet.pop(playerID);
if (!jjIsServer || jjPlayers[playerID].clientID == fromClientID) {
Fur@ fur = Furs[playerID];
fur.Packet.clear();
fur.Packet.push(playerID);
if (packet.getSize() == 243) {
if (fur.MappingID < 0) //this player ID hasn't had a mapping before
fur.MappingID = jjSpriteModeFirstFreeMapping();
if (fur.MappingID >= 0) {
fur.Packet.write(packet);
mapPacket(fur.MappingID, packet);
}
}
if (jjIsServer) {
for (int otherPlayerID = jjLocalPlayerCount; otherPlayerID < 32; ++otherPlayerID) {
const jjPLAYER@ player = jjPlayers[otherPlayerID];
if (player.isActive && player.clientID != fromClientID)
jjSendPacket(fur.Packet, player.clientID); //send the new player's fur (or lack of fur) to the other players
}
}
}
}
void onPlayerDraw(jjPLAYERDRAW& draw) {
if (jjColorDepth <= 8) //don't bother
return;
if (!draw.sprite || (draw.spriteMode != SPRITE::PLAYER && draw.spriteMode != SPRITE::TRANSLUCENTPLAYER))
return;
if (draw.player.isZombie)
return;
const Fur@ fur = Furs[draw.player.playerID];
if (fur.Packet.getSize() > 1) {
draw.spriteMode = draw.spriteMode == SPRITE::PLAYER ? SPRITE::MAPPING : SPRITE::TRANSLUCENTMAPPING;
draw.spriteParam = fur.MappingID;
}
}
bool onDrawLives(jjPLAYER@ player, jjCANVAS@ canvas) {
if (jjColorDepth <= 8)
return false;
const Fur@ fur = Furs[player.playerID];
if (fur.Packet.getSize() <= 1)
return false;
int faceAnimID;
switch (player.charCurr) {
case CHAR::BIRD2:
faceAnimID = 0;
break;
case CHAR::BIRD:
faceAnimID = 1;
break;
case CHAR::FROG:
faceAnimID = 2;
break;
case CHAR::JAZZ:
faceAnimID = 3;
break;
case CHAR::LORI:
if (jjIsTSF) {
faceAnimID = 4;
break;
}
default:
faceAnimID = jjIsTSF ? 5 : 4;
break;
}
const jjANIMATION@ anim = jjAnimations[jjAnimSets[ANIM::FACES] + faceAnimID];
canvas.drawSpriteFromCurFrame(sprite: anim.firstFrame + ((jjGameTicks / 6) % anim.frameCount), xPixel: 0, yPixel: jjSubscreenHeight, mode: SPRITE::MAPPING, param: fur.MappingID);
if (jjGameCustom == GAME::LRS || jjGameCustom == GAME::TLRS || jjGameCustom == GAME::XLRS)
canvas.drawString(32, jjSubscreenHeight - (jjSubscreenWidth <= 400 ? 9 : 14), "x" + player.lrsLives, jjSubscreenWidth <= 400 ? STRING::SMALL : STRING::MEDIUM);
return true;
}
void onMain() {
if (jjColorDepth <= 8)
return;
if (jjGameTicks & 15 == 15) {
for (int objectID = jjObjectCount; --objectID != 0;) {
jjOBJ@ obj = jjObjects[objectID];
if (obj.behavior == BEHAVIOR::CORPSE && obj.counterEnd == SPRITE::PLAYER) {
const Fur@ fur = Furs[obj.doesHurt]; //sprite param = player ID
if (fur.Packet.getSize() > 1) {
obj.doesHurt = fur.MappingID;
obj.counterEnd = uint8(SPRITE::MAPPING);
}
}
}
}
}
bool onDrawAmmo(jjPLAYER@ player, jjCANVAS@ canvas) {
if (player.currWeapon != WEAPON::BLASTER)
return false;
if (jjObjectPresets[OBJECT::BLASTERBULLET].behavior != BEHAVIOR::BULLET || jjObjectPresets[OBJECT::BLASTERBULLETPU].behavior != BEHAVIOR::BULLET)
return false;
if (jjColorDepth <= 8)
return false;
if (player.isZombie)
return false;
const Fur@ fur = Furs[player.playerID];
if (fur.Packet.getSize() <= 1)
return false;
if (!player.noFire && player.charCurr != CHAR::FROG && player.charCurr != CHAR::BIRD) {
const bool powerup = player.powerup[WEAPON::CURRENT];
const CHAR::Char charCurr = player.charCurr != CHAR::BIRD2 ? player.charCurr : player.charOrig;
const ::jjANIMATION@ anim = jjAnimations[
charCurr == CHAR::SPAZ ? (powerup ? (::jjAnimSets[ANIM::AMMO] + 19) : (::jjAnimSets[ANIM::PICKUPS] + 30)) :
(::jjIsTSF && charCurr == CHAR::LORI) ? (powerup ? (::jjAnimSets[ANIM::PLUS_AMMO] + 6) : (::jjAnimSets[ANIM::PLUS_AMMO] + 5)) :
(powerup ? (::jjAnimSets[ANIM::AMMO] + 18) : (::jjAnimSets[ANIM::PICKUPS] + 29))
];
int x, y;
STRING::Size font;
::string text;
if (::jjSubscreenWidth > 400) {
x = ::jjSubscreenWidth - 88;
y = ::jjSubscreenHeight - 14;
font = STRING::MEDIUM;
} else {
x = ::jjSubscreenWidth - 48;
y = ::jjSubscreenHeight - 9;
font = STRING::SMALL;
}
canvas.drawSpriteFromCurFrame(x, y, anim + (::jjGameTicks >> 2) % anim.frameCount, mode: SPRITE::MAPPING, param: fur.MappingID);
const ::jjWEAPON@ weapon = ::jjWeapons[WEAPON::BLASTER];
if (weapon.infinite || weapon.replacedByShield && player.shieldTime > 0) {
text = "x^";
} else {
const int ammo = player.ammo[WEAPON::BLASTER];
text = "x" + (ammo > 0 ? ammo : 0);
}
canvas.drawString(x + 8, y, text, font);
}
return true;
}
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.