Name | Author | Game Mode | Rating | |||||
---|---|---|---|---|---|---|---|---|
Copper web | Rysice | Capture the flag | N/A | |||||
Custom MLLE Naps WeaponPack | Naps | Other | N/A |
#pragma require "WebGun.asc" //Scripted by Naps
#include "MLLE-Weapons.asc"
#pragma require "WebGun.j2a" //Spritework by Lynx
#pragma offer "WebGunFire.wav"
#pragma offer "WebGunWait.wav"
#pragma offer "WebGunBouncePlayer.wav"
namespace NapsWeapons {
class WebGun : MLLEWeapons::WeaponInterface {
array<array<jjOBJ@>> Webs(32);
bool clientRequestedWebs = false;
bool BouncyPU = true; //Powerup version bounces players and bullets back
uint8 EnhancedAirJump = 0; //Copter characters get raised up and double jump resets their double jump on contact
bool SelfEntrap = true; //Countsdown to 3 seconds and after that the webs affect the user too
int MaxWeb = 0; //Max amount of webs you can place
uint currentMaxWeb = 0;
uint WebCounterEnd = 30; //seconds
uint WebPUCounterEnd = 60; //seconds
bool top5Cop = false;
WebGun() {
super(
regularObjectTemplate: MLLEWeapons::ObjectTemplate(
xSpeed: 5,
xAcc: 0,
animSpeed: 2,
killAnim: 6,
curAnim: 0,
lightType: LIGHT::POINT2,
counterEnd: 30,
scriptedCollisions: true,
playerHandling: HANDLING::SPECIAL,
bulletHandling: HANDLING::DETECTBULLET
),
powerupObjectTemplate: MLLEWeapons::ObjectTemplate(
xSpeed: 5,
xAcc: 0,
animSpeed: 3,
killAnim: 7,
curAnim: 4,
lightType: LIGHT::POINT2,
counterEnd: 60,
scriptedCollisions: true,
playerHandling: HANDLING::SPECIAL,
bulletHandling: HANDLING::DETECTBULLET
),
style: WEAPON::MISSILE,
animSetFilename: "WebGun.j2a",
sampleFilenames: array<string> = {"WebGunFire.wav","WebGunWait.wav","WebGunBouncePlayer.wav"},
pickupAnimation: 1,
poweredUpPickupAnimation: 6,
ammoCrateAnimation: 2,
powerupAnimation: 3,
traits: se::weapon_is_effective_against_players | se::weapon_is_effective_against_sp_enemies | se::weapon_supports_mouse_aim | se::weapon_works_in_all_modes | se::weapon_works_in_mp | se::weapon_works_in_sp | se::weapon_works_in_coop | se::weapon_works_online | se::weapon_has_all_pickups | se::weapon_fails_underwater,
behavior: MLLEWeapons::behaviorFunction(DetermineBehavior),
onMain: se::MainCallback(MainSetup),
onDrawAmmo: se::DrawingCallback(DrawLimit),
onReceive: se::PacketCallback(webPacket),
apply: MLLEWeapons::applyFunction(ApplyCustomParameters)
);
}
uint thisSetID = SetID;
array<SOUND::Sample> thisSamples(3);
WebGun@ selfReference = this;
int lastTimeSinceSoundPlayed = 0;
void DetermineBehavior(jjOBJ@ obj, bool powerup) const {
if (obj.creatorType == CREATOR::PLAYER && jjPlayers[obj.creatorID].isLocal)
jjSample(obj.xPos, obj.yPos, Samples[0],64, powerup? 20000 : 28000);
jjOBJ@ o = obj;
obj.behavior = Web(o,selfReference);
if (!powerup) {
obj.counterEnd = WebCounterEnd;
} else {
obj.counterEnd = WebPUCounterEnd;
}
}
bool DrawLimit(jjPLAYER@ player, jjCANVAS@ canvas, const jjANIMATION@ anim) const {
if (player !is null && !player.noFire && player.charCurr != CHAR::FROG && player.charCurr != CHAR::BIRD && MaxWeb != 0) {
int x, y;
bool tinyText = false;
if (::jjSubscreenWidth > 400) {
x = ::jjSubscreenWidth - 28;
y = ::jjSubscreenHeight - 54;
} else {
x = ::jjSubscreenWidth - 8;
y = ::jjSubscreenHeight - 34;
tinyText = true;
}
string text = Webs[player.playerID].length() + "/" + currentMaxWeb;
if (Webs[player.playerID].length() > currentMaxWeb) {
text = currentMaxWeb + "/" + currentMaxWeb;
}
int textSize = jjGetStringWidth(text,tinyText? STRING::SMALL : STRING::MEDIUM,STRING::NORMAL);
canvas.drawString(x - textSize, y,text,tinyText? STRING::SMALL : STRING::MEDIUM);
}
return false;
}
void MainSetup(int) {
if (MaxWeb < 0) {
uint count = playersInGame();
if (count < 1) count = 1;
currentMaxWeb = uint(abs(MaxWeb) / count);
} else currentMaxWeb = MaxWeb;
if (!clientRequestedWebs && !jjIsServer) {
jjSTREAM packet = ConstructPacket();
jjSendPacket(packet);
clientRequestedWebs = true;
}
}
uint8 playersInGame() {
uint8 playerCount = 0;
for (int i = 0;i < 32;i++) {
jjPLAYER@ play = jjPlayers[i];
if (play.isInGame) playerCount++;
}
return playerCount;
}
void webPacket(jjSTREAM& packet, int clientID) {
if (jjIsServer) {
for (int i = 0;i < 32;i++ ) {
jjPLAYER@ play = jjPlayers[i];
if (Webs[i].length == 0) continue;
for (uint j = 0;j < Webs[i].length;j++) {
jjSTREAM replyPacket = ConstructPacket();
replyPacket.push(i);
jjOBJ@ o = Webs[i][j];
replyPacket.push(o.xPos);
replyPacket.push(o.yPos);
bool placed = o.state == STATE::FLY? false : true;
replyPacket.push(o.var[2]);
replyPacket.push(o.var[6]);
replyPacket.push(o.justHit);
if (!placed) {
replyPacket.push(false);
replyPacket.push(o.frameID);
replyPacket.push(o.counter);
} else {
replyPacket.push(true);
replyPacket.push(o.counter);
}
jjSendPacket(replyPacket,clientID);
}
}
} else {
int playerID = 0;
packet.pop(playerID);
float x,y;
bool placed = false;
packet.pop(x);
packet.pop(y);
jjOBJ@ o = jjObjects[jjAddObject(OBJECT::BULLET, x,y, playerID, CREATOR::PLAYER, BEHAVIOR::INACTIVE)];
o.behavior = Web(o,selfReference);
o.playerHandling = HANDLING::SPECIAL;
o.bulletHandling = HANDLING::DETECTBULLET;
o.scriptedCollisions = true;
packet.pop(o.var[2]);
packet.pop(o.var[6]);
packet.pop(o.justHit);
if (!MLLEWeapons::HelpfulBulletFunctions::IsPowerup(o)) {
o.counterEnd = WebCounterEnd;
} else {
o.counterEnd = WebPUCounterEnd;
}
packet.pop(placed);
o.xSpeed = 5;
if (!placed) {
o.state = STATE::FLY;
o.determineCurAnim(SetID,!MLLEWeapons::HelpfulBulletFunctions::IsPowerup(o)? 0 : 4);
packet.pop(o.frameID);
packet.pop(o.counter);
} else {
o.state = STATE::WAIT;
o.determineCurAnim(SetID,!MLLEWeapons::HelpfulBulletFunctions::IsPowerup(o)? 1 : 6);
packet.pop(o.counter);
}
o.var[0] = int(Webs[o.creatorID].length());
if (jjGameState == GAME::STOPPED) {
o.var[5] = 1;
}
if (jjGameState == GAME::OVERTIME) {
o.var[5] = 2;
}
o.var[8] = determineTeam(o,jjPlayers[playerID]);
Webs[o.creatorID].insertLast(@o);
}
}
bool ApplyCustomParameters(uint, se::WeaponHook@, jjSTREAM@ parameter) {
if (parameter !is null && parameter.getSize() >= 1) {
parameter.pop(BouncyPU);
parameter.pop(EnhancedAirJump);
parameter.pop(SelfEntrap);
parameter.pop(MaxWeb);
parameter.pop(WebCounterEnd);
parameter.pop(WebPUCounterEnd);
}
return true;
}
SOUND::Sample determineSample(int ID) {
return Samples[ID];
}
uint determineSetID() {
return SetID;
}
void resortList(int playerID, uint startID) {
for (uint i = startID + 1;i < Webs[playerID].length();i++) {
Webs[playerID][i].var[0] = Webs[playerID][i].var[0] - 1;
}
}
int determineTeam(jjOBJ@ obj,jjPLAYER@ play) {
if (obj.creatorType != CREATOR::PLAYER) return -1;
if (play.isJailed) return 5;
if (jjGameMode == GAME::CTF) {
return play.team + 1;
}
if (jjGameCustom == GAME::RT) {
if (play is jjBottomFeeder) return 6;
if (play is jjTokenOwner) return 7;
}
if (play.isZombie) return 8;
return 0;
}
}
class Web : jjBEHAVIORINTERFACE {
jjOBJ@ obj;
WebGun@ weapon;
bool objectIsExploded = false;
Web(jjOBJ@ originalOBJ,WebGun@ w) {@obj = @originalOBJ; @weapon = @w;}
bool isPowerup(jjOBJ@ obj) {
return (obj.var[6] & 8) == 8;
}
void onBehave(jjOBJ@) {
jjPLAYER@ creator = jjPlayers[obj.creatorID];
if (obj.state == STATE::START) {
obj.state = STATE::FLY;
if (jjGameState == GAME::STOPPED) {
obj.var[5] = 1;
}
if (jjGameState == GAME::OVERTIME) {
obj.var[5] = 2;
}
if (obj.creatorID <= 32 && obj.creatorType == CREATOR::PLAYER) {
obj.var[0] = int(weapon.Webs[obj.creatorID].length());
obj.var[8] = weapon.determineTeam(obj,creator);
weapon.Webs[obj.creatorID].insertLast(@obj);
} else {
obj.var[1] = 1;
}
} else if (obj.state == STATE::FLY) {
obj.xPos += obj.xSpeed;
obj.yPos += obj.ySpeed;
obj.counter++;
uint teamColor = determineTeamColor(obj,creator);
MLLEWeapons::HelpfulBulletFunctions::DrawAngled(obj,1,1,teamColor == 0? SPRITE::NORMAL : SPRITE::SINGLEHUE,teamColor);
if (isPowerup(obj)) {
uint teamColor2 = determineTeamColor2(obj,creator);
jjDrawRotatedSprite(obj.xPos, obj.yPos, weapon.determineSetID(),5,obj.frameID, MLLEWeapons::HelpfulBulletFunctions::GetAngle(obj), MLLEWeapons::HelpfulBulletFunctions::GetDirection(obj) * 1, 1, teamColor2 == 0? SPRITE::NORMAL : SPRITE::SINGLEHUE,teamColor2);
}
if (obj.counter % 5 == 0) {
obj.frameID++;
}
if (MLLEWeapons::HelpfulBulletFunctions::MaskedPixel(obj)) {
obj.frameID = 5;
}
for (uint i = 0; i < 32; ++i) {
const jjPLAYER@ target = jjPlayers[i];
if (!target.isInGame)
continue;
if (!MLLEWeapons::HelpfulBulletFunctions::PlayerIsEnemy(obj,target))
continue;
if (target.blink != 0)
continue;
if (obj.doesCollide(target)) {
obj.frameID = 5;
}
}
if (jjGameMode <= GAME::COOP && obj.creatorType == CREATOR::PLAYER) {
for (int i = 0; i < jjObjectCount; i++) {
jjOBJ@ target = jjObjects[i];
if (!target.isActive)
continue;
if (!target.isTarget)
continue;
if (obj.doesCollide(target)) {
obj.frameID = 5;
}
}
}
if (obj.frameID == 5) {
jjSample(obj.xPos, obj.yPos, weapon.determineSample(1),64,0);
obj.counter = 0;
obj.frameID = 0;
obj.state = STATE::WAIT;
obj.determineCurAnim(weapon.determineSetID(),!isPowerup(obj)? 1 : 6);
}
} else if (obj.state == STATE::WAIT) {
obj.isBlastable = false;
if (jjGameState != GAME::PAUSED) obj.counter++;
if (obj.var[2] < 70*5 && jjGameState != GAME::PAUSED) obj.var[2] = obj.var[2] + 1;
obj.lightType = LIGHT::NONE;
obj.causesRicochet = false;
if (jjGameMode <= GAME::COOP && obj.creatorType == CREATOR::PLAYER) {
for (int i = 0; i < jjObjectCount; i++) {
jjOBJ@ target = jjObjects[i];
if (!target.isActive)
continue;
if (target.playerHandling == HANDLING::ENEMYBULLET) {
if (obj.doesCollide(target)) {
if (obj.justHit == 0) {
obj.counter += (70*5);
obj.justHit = 40;
}
if (isPowerup(obj) && weapon.BouncyPU) {
int lastRicochet = target.var[10];
if (jjGameTicks - target.var[10] > 70*10) {
target.ricochet();
jjDrawString(target.xPos,target.yPos,"test" + target.var[10]);
target.var[10] = jjGameTicks;
}
}
}
break;
}
if (!target.isTarget || !target.isFreezable)
continue;
if (obj.doesCollide(target)) {
if (target.state != STATE::FREEZE) {
if (obj.justHit == 0) {
obj.counter += (70*target.energy);
obj.justHit = 40;
target.freeze = 10;
target.oldState = target.state;
target.state = STATE::FREEZE;
}
} else {
if (target.freeze < 2) {
target.freeze = 0;
target.state = target.oldState;
}
}
}
}
}
if (obj.justHit == 0) {
uint teamColor = determineTeamColor(obj,creator);
int brightness = 0;
if (teamColor == 0) {
if (weapon.SelfEntrap && obj.var[2] < 70*3) {
brightness = 87 + int(jjCos((obj.var[2]*20) % 1023)*87);
} else {
if (obj.counter % 10 == 0) {
obj.frameID++;
}
if (obj.frameID >= 4) {
obj.frameID = 0;
}
brightness = 175;
}
jjDrawSpriteFromCurFrame(obj.xPos,obj.yPos,obj.curFrame,obj.direction,SPRITE::BRIGHTNESS,brightness,3);
} else {
if (weapon.SelfEntrap && obj.var[2] < 70*3) {
brightness = 2 + int(jjSin((obj.var[2]*40) % 1023)*2);
} else {
if (obj.counter % 10 == 0) {
obj.frameID++;
}
if (obj.frameID >= 4) {
obj.frameID = 0;
}
brightness = 0;
}
jjDrawSpriteFromCurFrame(obj.xPos,obj.yPos,obj.curFrame,obj.direction,SPRITE::SINGLEHUE,teamColor + brightness,3);
if (isPowerup(obj)) {
int teamColor2 = determineTeamColor2(obj,creator);
jjDrawSprite(obj.xPos, obj.yPos, weapon.determineSetID(),7,obj.frameID,obj.direction,SPRITE::SINGLEHUE,teamColor2 + brightness,3);
}
}
} else {
if (isPowerup(obj) && weapon.BouncyPU) obj.causesRicochet = true;
jjDrawSpriteFromCurFrame(obj.xPos + jjCos((obj.justHit*400) % 1023)*3,obj.yPos,obj.curFrame,obj.direction,SPRITE::BRIGHTNESS,255,3);
if (jjGameState != GAME::PAUSED) obj.justHit--;
}
} else if (obj.state == STATE::EXPLODE) {
if (obj.var[1] == 0) {
weapon.resortList(obj.creatorID,obj.var[0]);
weapon.Webs[obj.creatorID].removeAt(obj.var[0]);
obj.var[1] = 1;
}
obj.counter = 0;
obj.lightType = 0;
obj.frameID = 0;
obj.lightType = 0;
obj.justHit = 0;
obj.determineCurAnim(weapon.determineSetID(),!isPowerup(obj)? 8 : 9);
uint teamColor = determineTeamColor(obj,creator);
if (teamColor != 0) {
jjDrawSpriteFromCurFrame(obj.xPos,obj.yPos,obj.curFrame,obj.direction,SPRITE::SINGLEHUE,teamColor);
if (isPowerup(obj)) {
int teamColor2 = determineTeamColor2(obj,creator);
jjDrawSprite(obj.xPos, obj.yPos, weapon.determineSetID(),7,obj.frameID,obj.direction,SPRITE::SINGLEHUE,teamColor2,3);
}
} else {
jjDrawSpriteFromCurFrame(obj.xPos,obj.yPos,obj.curFrame,obj.direction,SPRITE::BRIGHTNESS,175,3);
}
obj.state = STATE::DONE;
//obj.behavior = BEHAVIOR::EXPLOSION2;
} else if (obj.state == STATE::DONE) {
if (obj.var[1] == 0) {
weapon.resortList(obj.creatorID,obj.var[0]);
weapon.Webs[obj.creatorID].removeAt(obj.var[0]);
obj.var[1] = 1;
}
uint teamColor = determineTeamColor(obj,creator);
if (teamColor != 0) {
jjDrawSpriteFromCurFrame(obj.xPos,obj.yPos,obj.curFrame,obj.direction,SPRITE::SINGLEHUE,teamColor);
if (isPowerup(obj)) {
int teamColor2 = determineTeamColor2(obj,creator);
jjDrawSprite(obj.xPos, obj.yPos, weapon.determineSetID(),10,obj.frameID,obj.direction,SPRITE::SINGLEHUE,teamColor2,3);
}
} else {
jjDrawSpriteFromCurFrame(obj.xPos,obj.yPos,obj.curFrame,obj.direction,SPRITE::BRIGHTNESS,175,3);
}
obj.counter++;
if (obj.counter % 5 == 0) {
obj.frameID++;
}
if (obj.frameID >= 4) {
obj.state = STATE::DEACTIVATE;
}
}
if (obj.state == STATE::DEACTIVATE) {
if (obj.var[1] == 0) {
weapon.resortList(obj.creatorID,obj.var[0]);
weapon.Webs[obj.creatorID].removeAt(obj.var[0]);
obj.var[1] = 1;
}
obj.delete();
}
obj.curFrame = jjAnimations[obj.curAnim].firstFrame + obj.frameID;
if ((obj.state != STATE::EXPLODE && obj.state != STATE::DEACTIVATE && obj.state != STATE::DONE) &&
(
obj.counter >= int(obj.counterEnd*70) ||
obj.yPos > jjWaterLevel ||
!creator.isInGame ||
(obj.var[5] != 0 && jjGameState == GAME::STARTED) ||
(obj.var[5] != 2 && jjGameState == GAME::OVERTIME) ||
obj.var[8] != weapon.determineTeam(obj,creator) ||
limitDestroy()
)) {
obj.state = STATE::EXPLODE;
}
}
bool limitDestroy() {
if (weapon.Webs[obj.creatorID].length() > weapon.currentMaxWeb && weapon.MaxWeb != 0) {
if (obj.var[0] < int(weapon.Webs[obj.creatorID].length() - weapon.currentMaxWeb)) {
return true;
}
}
return false;
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ playerBullet, jjPLAYER@ play, int force) {
jjPLAYER@ creator = jjPlayers[obj.creatorID];
if (play !is null) {
if (obj.doesCollide(play)) {
if (obj.state == STATE::FLY) {
if ((MLLEWeapons::HelpfulBulletFunctions::PlayerIsEnemy(obj,play) || obj.creatorType != CREATOR::PLAYER) && play.blink == 0) {
obj.frameID = 4;
}
}
if (obj.state == STATE::WAIT && jjGameState != GAME::PREGAME) {
if (((creator.blink == 0) || obj.creatorType != CREATOR::PLAYER)) {
if (determineTargets(obj,play) && play.blink == 0) {
if (weapon.EnhancedAirJump & 2 == 2) {
if (play.helicopter > 0) {
play.ySpeed = -1;
}
play.helicopterElapsed = 0;
if (play.ySpeed > 0) {
play.doubleJumpCount = 0;
}
}
play.buttstomp = 121;
if (isPowerup(obj) && (abs(play.xSpeed) > 10) && weapon.BouncyPU) {
int targetDirection = play.xSpeed < 0? 1 : -1;
play.spring(10 * targetDirection,0,true,false);
if (jjGameTicks - weapon.lastTimeSinceSoundPlayed > 10) {
jjSample(obj.xPos, obj.yPos, weapon.determineSample(2),64,40000 + (jjRandom() % 8000));
weapon.lastTimeSinceSoundPlayed = jjGameTicks;
}
} else {
if (play.xSpeed != 0) {
play.xSpeed *= 0.5;
}
if (play.ySpeed != 0) {
play.ySpeed *= 0.5;
}
}
} else {
if (weapon.EnhancedAirJump & 1 == 1) {
if (play.helicopter > 0) {
play.ySpeed = -1;
}
play.helicopterElapsed = 0;
if (play.ySpeed > 0) {
play.doubleJumpCount = 0;
}
}
}
}
}
}
}
if (obj.state == STATE::WAIT) {
if (playerBullet !is null) {
if (obj.justHit == 0) {
if (jjGameState != GAME::PAUSED) {
jjPLAYER@ targetCreator = jjPlayers[playerBullet.creatorID];
if (playerBullet.creatorType != CREATOR::PLAYER || determineTargets(obj,targetCreator)) {
if (targetCreator.blink == 0 || playerBullet.creatorType != CREATOR::PLAYER) {
int damage = isPowerup(playerBullet)? 10 : 5;
obj.counter += (70*damage);
obj.justHit = 40;
/*if (jjGameTicks - weapon.lastTimeSinceSoundPlayed > 10) {
jjSample(obj.xPos, obj.yPos, weapon.determineSample(3 + (jjRandom() % 2)),64,41000 + (jjRandom() % 8000));//41000
weapon.lastTimeSinceSoundPlayed = jjGameTicks;
}*/
}
if ((playerBullet.creatorType != CREATOR::PLAYER || creator.blink == 0) && isPowerup(obj) && weapon.BouncyPU) {
int lastRicochet = playerBullet.var[10];
playerBullet.var[10] = 9;
playerBullet.ricochet();
playerBullet.var[10] = lastRicochet;
}
}
}
}
}
}
return true;
}
bool determineTargets(const jjOBJ@ obj, const jjPLAYER@ other) {
if (obj.creatorType != CREATOR::PLAYER) return true;
else if (weapon.SelfEntrap && obj.var[2] > 70*3 && jjPlayers[obj.creatorID] is other) return true;
else return jjPlayers[obj.creatorID].isEnemy(other);
}
uint determineTeamColor(jjOBJ@ obj,jjPLAYER@ play) {
if (obj.creatorType != CREATOR::PLAYER) return 0;
array<uint> colors = {32,24,16,40,72,48,80};
if (play.isJailed) return colors[4];
if (jjGameMode == GAME::CTF) {
if (play.team < 4) return colors[play.team];
else return colors[4];
}
if (jjGameCustom == GAME::RT) {
if (play is jjBottomFeeder) return colors[5];
else
if (play is jjTokenOwner) return colors[2];
else
return 72;
}
if (play.isZombie) return colors[6];
if (weapon.top5Cop) return 72;
return 0;
}
uint determineTeamColor2(jjOBJ@ obj,jjPLAYER@ play) {
if (obj.creatorType != CREATOR::PLAYER) return 0;
array<uint> colors = {88,56,88,32,64,24};
if (play.isJailed) return colors[4];
if (jjGameMode == GAME::CTF) {
if (play.team < 4) return colors[play.team];
else return colors[4];
}
if (jjGameCustom == GAME::RT) {
if (play is jjBottomFeeder) return colors[3];
else
if (play is jjTokenOwner) {
uint result = 16;
const int time = 10;
if (obj.counter > time) {
uint color = uint(obj.counter / time) % 8;
result = 16 + (8*color);
}
return result;
}
else {
return copColorShift(40);
}
}
if (play.isZombie) return colors[5];
if (weapon.top5Cop) return copColorShift(10);
return 0;
}
uint copColorShift(int timer) {
uint result = 24;
int frameChange = timer;
bool change = (obj.counter / frameChange) % 2 == 1? false : true;
if (change) {
result = 32;
}
return result;
}
}
}
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.