Jan 6, 2018, 09:23 AM | ||
Quote:
Code:
void onLevelBegin() { for (int x = 0; x < jjLayerWidth[4]; x++) { for (int y = 0; y < jjLayerHeight[4]; y++) { if (jjEventGet(x,y) == AREA::SLIDE) { jjOBJ@ o = jjObjects[jjAddObject(OBJECT::STEADYLIGHT, (x*32)+16, (y*32)+16)]; //lights go in the middle of tiles o.light = 20; o.lightType = 3; } } } } |
Jan 6, 2018, 10:12 AM | |
That doesn't seem to do the job. Also, doesn't lightType use names?
|
Jan 6, 2018, 10:33 AM | |
I'm guessing yours is a single player level and PJ is writing code for a multiplayer level (or at least testing it in a single screen). Try
o.deactivates = false; ?
|
Jan 6, 2018, 10:41 AM | |
Single Player indeed. I included that line, but it still doesn't seem to work.
|
Jan 6, 2018, 11:38 AM | ||
Quote:
The following script has been tested and works perfectly for me, so if this still doesn't work it means that there may be an error elsewhere in your script. Code:
void onLevelBegin() { for (int x = 0; x < jjLayerWidth[4]; x++) { for (int y = 0; y < jjLayerHeight[4]; y++) { if (jjEventGet(x,y) == AREA::SLIDE) { jjOBJ@ o = jjObjects[jjAddObject(OBJECT::STEADYLIGHT, (x*32)+16, (y*32)+16)]; //add in middle of tiles o.light = 20; o.lightType = 3; o.deactivates = false; } } } } void onLevelReload() { onLevelBegin(); //add lights again after death } |
Jan 7, 2018, 01:46 PM | |
Thanks, that worked!
I'm also trying to make those areas one-way, as well as slide. Is there any way to do this? So far any attempt to achieve this has resulted either in Slide-only, or One-way-only tiles, depending on the ordering of the code. Code:
void onLevelBegin() { for (int x = 0; x < jjLayerWidth[4]; x++) { for (int y = 0; y < jjLayerHeight[4]; y++) { if (jjEventGet(x,y) == AREA::SLIDE) { jjOBJ@ xenonlight = jjObjects[jjAddObject(OBJECT::STEADYLIGHT, (x*32)+16, (y*32)+16)]; //add in middle of tiles xenonlight.light = 20; xenonlight.lightType = 3; xenonlight.deactivates = false; jjEventSet(x, y, AREA::ONEWAY); jjEventSet(x, y, AREA::SLIDE); } } } If you have a 10-frame animation, with frames a[1], a[2], a[3], a[4], a[5] ... a[9], a[10], instead of using speed to control the animation, you are using player's position. As the player moves in a positive direction (x and y get bigger), the frames move in chronological order. As the player moves in a negative direction (x and y get smaller), the animation runs in reverse. When the player stops moving, the animation also stops. This should apply to all layers, so an animation is the only feasible way I can imagine implementing this. I want to try to implement faux reflections in a tileset, that's the whole idea behind my question. |
Jan 22, 2018, 08:11 AM | |
So, I'm trying to code a custom boss that summons a bunch of enemies, including summoning low HP bosses as enemies, but I've run into an issue: I'm having a hard time making things immune to (or at least not 1HKO'd by) Spaz's kick and Jazz's uppercut. Setting things to use playerHandling mode HANDLING::SPECIAL "works"... but also removes non-bullet collision detection for most enemies and the main boss (the latter would actually be a good thing if it was consistent, since I don't want it to be hurt by anything other than time passing anyways, but it's too inconsistent to be useful). It also has an issue where setting the bosses to have that collision mode means they beat the level when killed, when you're only supposed to win the level by letting the main boss run out of HP. Basically, it's supposed to be a survival challenge.
Here's the full script for the level as of now, including an attempt at a work-around for the issue where killing bosses clears the level (the work-around works, but only about half the time for some reason): Code:
#include "MLLE-Include-1.4.asc" const bool MLLESetupSuccessful = MLLE::Setup(); #pragma require "Tube.j2t" #pragma require "Medivo.j2t" #pragma require "hgfCow-MLLE-Data-1.j2l" #pragma require "Carrot1.j2t" #pragma require "hgfCow.j2l" //a special thanks to Sir Ementaler and Violet CLM for their assistance with writing the script! void onLevelLoad() { jjObjectPresets[OBJECT::DEVILDEVAN].behavior = cowBoss; jjObjectPresets[OBJECT::DEVILDEVAN].isFreezable = false; jjObjectPresets[OBJECT::DEVILDEVAN].playerHandling = HANDLING::SPECIAL; jjObjectPresets[OBJECT::DEVILDEVAN].scriptedCollisions = true; jjObjectPresets[OBJECT::DEVILDEVAN].energy = 50; jjObjectPresets[OBJECT::DEVILDEVAN].bulletHandling = HANDLING::DESTROYBULLET; jjObjectPresets[OBJECT::BILSY].bulletHandling = HANDLING::HURTBYBULLET; jjObjectPresets[OBJECT::BILSY].playerHandling = HANDLING::ENEMY; jjObjectPresets[OBJECT::BILSY].energy = 14; jjObjectPresets[OBJECT::BUBBA].bulletHandling = HANDLING::HURTBYBULLET; jjObjectPresets[OBJECT::BUBBA].playerHandling = HANDLING::ENEMY; jjObjectPresets[OBJECT::BUBBA].energy = 5+(jjDifficulty*4); jjObjectPresets[OBJECT::TUFBOSS].bulletHandling = HANDLING::HURTBYBULLET; jjObjectPresets[OBJECT::TUFBOSS].playerHandling = HANDLING::ENEMY; jjObjectPresets[OBJECT::TUFBOSS].energy = 7+(jjDifficulty*4); jjObjectPresets[OBJECT::BOLLY].bulletHandling = HANDLING::HURTBYBULLET; jjObjectPresets[OBJECT::BOLLY].playerHandling = HANDLING::SPECIAL; jjObjectPresets[OBJECT::BOLLY].energy = 10; jjObjectPresets[OBJECT::UTERUS].bulletHandling = HANDLING::HURTBYBULLET; jjObjectPresets[OBJECT::UTERUS].playerHandling = HANDLING::ENEMY; jjObjectPresets[OBJECT::UTERUS].energy = 10; jjObjectPresets[OBJECT::ROBOT].bulletHandling = HANDLING::HURTBYBULLET; jjObjectPresets[OBJECT::ROBOT].playerHandling = HANDLING::ENEMY; jjObjectPresets[OBJECT::ROBOT].energy = 30; //just a thing I borrowed from plusPixelMapEx jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::DEVILDEVAN].curAnim]; anim.frameCount = 1; jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame]; jjPIXELMAP kingCow(459*32, 3*32, 6*32, 7*32, 4); kingCow.save(frame); frame.hotSpotX = -frame.width / 2; frame.hotSpotY = -frame.height / 2; } void onLevelBegin(){ //make sure the main song reloads after encountering the boss jjMusicLoad("Meatball Parade.ogg"); } //int rPart(float x,float y) { // render a part of Devan Force // jjDrawSprite(x, y, ANIM::BIGROCK, 0, 0, 0); //void jjDrawSprite(x, y, uint8 (ANIM::BIGROCK), uint8 (0), uint8 (0), int direction = 0, SPRITE::Mode mode = SPRITE::NORMAL, int param = 0, int8 layerZ = 4, uint8 layerXY = 4, int8 playerID = -1) // return 0; //} void cowBoss(jjOBJ@ obj) { switch (obj.state) { case STATE::START: //don't start boss until player has reached boss activation point obj.state = STATE::DELAYEDSTART; case STATE::DELAYEDSTART: //loop players for (int i = 0; i < jjLocalPlayerCount; ++i) { jjPLAYER@ localPlayer = jjLocalPlayers[i]; if (localPlayer.bossActivated) { localPlayer.boss = obj.objectID; obj.state = STATE::START; } } if (obj.state == STATE::START) { //set object to be handled in a more normal way, since we're using Devil Devan as the "base" obj.playerHandling = HANDLING::SPECIAL; //load song jjMusicLoad("dang.j2b"); //start boss obj.state = STATE::ATTACK; //initialize some important variables obj.age = 60; //boss attack cooldown obj.special = 0; //next attack the boss is going to use obj.var[0] = 0; //move direction obj.var[1] = 0; //reticle height obj.var[2] = 10; //carrot delay break; } return; case STATE::KILL: //start next stage jjNxt(true, false); case STATE::DEACTIVATE: //reset boss jjMusicLoad("Meatball Parade.ogg"); obj.deactivate(); break; case STATE::ATTACK: //draw boss jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::NORMAL, 24); //set cow as boss for (int i = 0; i < jjLocalPlayerCount; ++i) { jjPLAYER@ localPlayer = jjLocalPlayers[i]; if (localPlayer.bossActivated) { localPlayer.boss = obj.objectID; } } //just some old code I didn't completely remove //for (int i = 1; i < jjObjectCount; i++){ // jjOBJ@ o = jjObjects[i]; // if (o.eventID == OBJECT::BOLLY){obj.var[0] == 1;} // if (o.eventID == OBJECT::BUBBA){obj.var[0] == 1;} // if (o.eventID == OBJECT::BILSY){obj.var[0] == 1;} // if (o.eventID == OBJECT::TUFBOSS){obj.var[0] == 1;} //} //if (obj.var[0] == 0){} //constantly cool down attack obj.age -= 1; //prepare summon if (obj.age <= 0) { //just some more old code I didn't completely remove //if (obj.special == 1){jjAddObject(OBJECT::TUFBOSS, obj.xPos, obj.yPos+96);} //if (obj.special == 2){jjAddObject(OBJECT::BUBBA, obj.xPos, obj.yPos);} //if (obj.special == 2){jjAddObject(OBJECT::BOLLY, obj.xPos, obj.yPos);} //if (obj.special == 2){jjAddObject(OBJECT::UTERUS, obj.xPos, obj.yPos);} //if (obj.special == 3){jjAddObject(OBJECT::BILSY, obj.xPos, obj.yPos);} //summon an enemy based on next attack chosen if (obj.special == 0){jjObjects[jjAddObject(OBJECT::LIZARD, obj.xPos, obj.yPos)].playerHandling = HANDLING::SPECIAL;} if (obj.special == 1){jjObjects[jjAddObject(OBJECT::BAT, obj.xPos, obj.yPos+120)].playerHandling = HANDLING::SPECIAL;} if (obj.special == 2){jjObjects[jjAddObject(OBJECT::RAVEN, obj.xPos, obj.yPos+120)].playerHandling = HANDLING::SPECIAL;} if (obj.special == 3){jjObjects[jjAddObject(OBJECT::FENCER, obj.xPos, obj.yPos)].playerHandling = HANDLING::SPECIAL;} if (obj.special == 4){jjObjects[jjAddObject(OBJECT::BEE, obj.xPos, obj.yPos+120)].playerHandling = HANDLING::SPECIAL;} if (obj.special == 5){jjObjects[jjAddObject(OBJECT::TUFBOSS, obj.xPos, obj.yPos+120)].playerHandling = HANDLING::SPECIAL;} //if (obj.special == 6){jjObjects[jjAddObject(OBJECT::BEE, obj.xPos, obj.yPos+120)].playerHandling = HANDLING::SPECIAL; // if(jjDifficulty >= 2){jjObjects[jjAddObject(OBJECT::BEE, obj.xPos+10, obj.yPos+120)].playerHandling = HANDLING::SPECIAL; // jjObjects[jjAddObject(OBJECT::BEE, obj.xPos-10, obj.yPos+120)].playerHandling = HANDLING::SPECIAL;}} if (obj.special == 6){jjObjects[jjAddObject(OBJECT::BEE, obj.xPos, obj.yPos+120)].playerHandling = HANDLING::SPECIAL; if(jjDifficulty >= 2){jjObjects[jjAddObject(OBJECT::BEE, obj.xPos+10, obj.yPos+120)].playerHandling = HANDLING::SPECIAL;}} if (obj.special == 7){jjObjects[jjAddObject(OBJECT::BUBBA, obj.xPos, obj.yPos)].playerHandling = HANDLING::SPECIAL;} if (obj.special == 8){jjObjects[jjAddObject(OBJECT::LIZARD, obj.xPos, obj.yPos)].playerHandling = HANDLING::SPECIAL; if(jjDifficulty >= 2){jjObjects[jjAddObject(OBJECT::LIZARD, obj.xPos+10, obj.yPos)].playerHandling = HANDLING::SPECIAL; jjObjects[jjAddObject(OBJECT::LIZARD, obj.xPos-10, obj.yPos)].playerHandling = HANDLING::SPECIAL;}} if (obj.special == 9 && jjDifficulty >= 2){jjObjects[jjAddObject(OBJECT::BILSY, obj.xPos, obj.yPos)].playerHandling = HANDLING::SPECIAL;} if (obj.special == 9 && jjDifficulty == 1){jjObjects[jjAddObject(OBJECT::BAT, obj.xPos, obj.yPos+120)].playerHandling = HANDLING::SPECIAL;} if (obj.special == 9 && jjDifficulty == 0){jjAddObject(OBJECT::CARROT, obj.xPos, obj.yPos+140);} //if (obj.special == 10){jjObjects[jjAddObject(OBJECT::FENCER, obj.xPos, obj.yPos)]; if(jjDifficulty >= 2){jjObjects[jjAddObject(OBJECT::FENCER, obj.xPos+10, obj.yPos)]; jjObjects[jjAddObject(OBJECT::FENCER, obj.xPos-10, obj.yPos)];}} if (obj.special == 10){jjObjects[jjAddObject(OBJECT::FENCER, obj.xPos, obj.yPos)].playerHandling = HANDLING::SPECIAL; if(jjDifficulty >= 2){jjObjects[jjAddObject(OBJECT::FENCER, obj.xPos+10, obj.yPos)].playerHandling = HANDLING::SPECIAL;}} //reset cooldown obj.age = 180; if (jjDifficulty == 2){obj.age = 150;} if (jjDifficulty >= 3){obj.age = 120;} //select next move obj.special += 1; //progress towards next carrot obj.var[2] = obj.var[2]-1; //hurt boss obj.energy -= 1; } //loop attack pattern if (obj.special >= 11){ obj.special = 5; } if (obj.var[2] <= 0){ if (jjDifficulty <= 2){jjAddObject(OBJECT::CARROT, obj.xPos, obj.yPos+140);} if (jjDifficulty >= 3){jjAddObject(OBJECT::SEEKERAMMO3, obj.xPos, obj.yPos+140);} obj.var[2] = 10; } //end boss if (obj.energy <= 0){obj.bulletHandling = HANDLING::DESTROYBULLET; obj.state = STATE::KILL;} //turn around if (obj.xPos <= 495*32){obj.var[0]=1;} if (obj.xPos >= 506*32){obj.var[0]=0;} //move if (obj.var[0] == 0){obj.xPos -=1;} if (obj.var[0] == 1){obj.xPos +=1;} //set reticle height if (obj.special == 0 || obj.special == 3 || obj.special == 5 || obj.special == 7 || obj.special == 8 && obj.special != 9){obj.var[1]=230;} if (obj.special == 1 || obj.special == 2 || obj.special == 4 || obj.special == 6){obj.var[1]=120;} if (obj.special == 9 && jjDifficulty >= 2){obj.var[1]=230;} if (obj.special == 9 && jjDifficulty == 1){obj.var[1]=120;} if (obj.special == 9 && jjDifficulty == 0){obj.var[1]=9001;} //display reticle if (obj.age < 45 && obj.age % 6 <= 2){jjDrawSprite(obj.xPos, obj.yPos+obj.var[1], ANIM::PLUS_RETICLES, 2, 0, 0);} //attempted work-around for killing bosses, this works about half the time for (int i = 1; i < jjObjectCount; i++){ jjOBJ@ o = jjObjects[i]; if (o.state == STATE::DONE){jjDeleteObject(o.objectID);} } default: //empty } } EDIT: Upon thinking about it further, I'm starting to think the easiest solution would be to disable Jazz's uppercut and Spaz's kick during the boss battle. Any easy way to go about doing that? EDIT 2: I managed to figure it out on my own, never mind.
__________________
Words. More words. Line. Insert text here. Placeholder. Lorem ipsum dolor sit amet. Uh... I guess I should put something proper here one day. ¯\_(?)_/¯ Last edited by happygreenfrog; Jan 22, 2018 at 01:57 PM. |
Jan 31, 2019, 01:24 PM | |
I was going to upload a small mutator that allows players to grab ledges and lift themselves on them (as in Earthworm Jim and Commander Keen). However, there are a few problems...
Here's the script: Code:
array I can't find a way to determine the animation of the player itself, so I had to make the player invisible and draw the sprite in front of him instead. This gives the player the default skin color while he's hanging, which is wrong. I need a way to determine the player's current animation, rather than drawing upon him. Oh, right! There also is this problem with the RABBIT::Anim where I simply can't find the one corresponding to Jazz grabbing the ledge. I had to use the numeral value, which probably differs between 1.23 and 1.24.
__________________
Free will was a mistake. - God Last edited by DennisKainz; Jan 31, 2019 at 02:31 PM. Reason: I found the way to use arrays for splitscreeners. |
Jan 31, 2019, 09:20 PM | |||
That's a neat idea for a mutator!
Quote:
Quote:
|
Feb 7, 2019, 01:10 PM | |
hey, quick question.
is it possible to draw a custom scoreboard HUD in non-coop gametypes like CTF or battle? i've been trying to define "bool onDrawScore()", but that seems to only alter the co-op score. is it possible? thank you in advance. |
Feb 7, 2019, 03:30 PM | |
At present, the score display in game modes other than SP and coop may not be altered, aside from drastic measures such as overwriting font sprites, which certainly wouldn't be limited in scope to said display and would probably quite negatively affect the game. Remaining HUD functions such as
onDrawAmmo may still be used to display other information beside the usual.
__________________
I am an official JJ2+ programmer and this has been an official JJ2+ statement. |
Feb 7, 2019, 05:01 PM | |
oh... that's a bummer.
oh well, i'm gonna hold off on my project until it's possible to draw over CTF score, i guess. thank you again.
__________________
http://teeworlds.com http://ddnet.tw |
Jan 28, 2020, 01:47 AM | |
I'd like to use a regular enemy as a boss. I don't intend to change his behavior. I only change his sprites with tiles or replace them with JJ1Enemies sometimes.
I tried creating a behavior for the enemy and implement the if code below but it doesn't work. if ( boss.energy==0&&++boss.counter>2300) jjEventSet(play.xPos / 32, play.yPos / 32, AREA::EOL); Is there a practical way of putting a health bar and an automatic EOL event when his energy is 0? I am pretty new at scripting btw. Treat me as a noobie |
Jan 28, 2020, 07:25 AM | ||
Quote:
A boss health bar is drawn for players if their bossActivated is true and boss refers to an object by its ID. There's also an accompanying activateBoss method, or you could use the traditional Activate Boss event. See especially the documentation for boss, as it describes how the health bar's size is determined. Most JJ2 boss behaviors work the following way: the boss starts out inactive and its behavior has a loop over all players that checks if any active player's bossActivated is true. If it is, the boss changes its state to something else, indicating that it's now active. Then, whenever the boss is active, it runs a loop that sets all players' boss to itself. This results in the health bar being drawn. When the boss is defeated and its energy is 0, the game doesn't despawn it, and instead (much like you, it seems) uses its behavior as a countdown to end the level. First, when the counter is 0, it might display some message much like showText. Then it waits between 4 and 6.5 seconds before it proceeds to the next level, depending on whether the player is firing bullets, for some weird reason (maybe under the assumption that if they're firing, they're getting impatient? Either way it's currently a speedrun strat to keep shooting after defeating a boss). Your magic number of 2300 seems pretty big as, at 70 ticks per second, that corresponds to over half a minute. Your strategy of spawning an EOL event seems valid, but it's generally a better idea to call jjNxt with default parameters. To sum up the order of events in a typical boss fight:
__________________
I am an official JJ2+ programmer and this has been an official JJ2+ statement. |
Jan 28, 2020, 08:57 AM | |
One possible additional consideration is your
boss.energy==0 condition. Several weapons do more than 1 damage, so it's easy for an enemy to end up with a negative energy number instead of exactly 0. (Some standard enemies/bosses check for this and immediately set energy to 0, others set it to -1, and probably others don't do anything at all.)
|
Jan 29, 2020, 04:41 AM | |||
JJNxt for the end boss
Quote:
Quote:
Code:
#include "Jazz1Enemies v05.asc" #include "Resize v11.asc" #include "TrueColor v13.asc" bool Boss=false; void onLevelLoad() { Jazz1::MakeEnemy(OBJECT::NORMTURTLE, Jazz1::Enemies::Diamondus_TurtleGoon, true); jjObjectPresets[OBJECT::NORMTURTLE].behavior = NORMTURTBOSS; jjObjectPresets[OBJECT::NORMTURTLE].energy = 100; jjObjectPresets[OBJECT::NORMTURTLE].points = 200; } void onFunction0(jjPLAYER@ play) { Boss=true; play.boss=jjAddObject(OBJECT::NORMTURTLE, 37*32, 54*32); } void NORMTURTBOSS(jjOBJ@ boss) { jjPLAYER@ play = jjLocalPlayers[0]; if (boss.energy==0&&++boss.counter>2300) jjNxt(bool warp = false, bool fast = false); } |
Jan 29, 2020, 05:42 PM | |
The main problem you're experiencing is this line:
jjNxt(bool warp = false, bool fast = false); Those bits inside the parentheses are supposed to indicate the default values for those arguments, meaning that if you just type jjNxt(); it'll be interpreted the same as if you had typed jjNxt(false, false); . Typing out the parameter names (and types) doesn't help.The next thing that's going to bite you is when you write jjObjectPresets[OBJECT::NORMTURTLE].behavior = NORMTURTBOSS; you are getting rid of the previous behavior, which included code for moving the object, drawing the object, and handling player collision and bullet collision.
|
Jan 30, 2020, 05:21 AM | |
OK. Solved the problem. But sadly it doesn't work with JJ1 Enemies function. Because when I remove the JJ1Enemies function it works fine. It's main code probably considers it as a normal enemy and the counter does not start. So the level does not end. I tried removing the counter problem by trying to end the level when his energy=1 but it didn't work either.
|
Feb 11, 2020, 12:18 AM | |
Very delayed response, but I don't think I can tell exactly what you're doing from your description. Troubleshooting is generally easiest in response to actual code, like in your previous post, preferably the minimum amount of code that demonstrates the problem in question. What does "works fine" look like in code? What does not removing the JJ1Enemies function look like in code?
|
Mar 6, 2020, 07:33 AM | |
Turtle Boss
And another delayed response from me
It's been a while and I didn't keep the code. However I've tried using Normal Turtle animations and a new behavior in order to make it work and it helped. Here's the thing: Code:
bool boss=false; void onLevelLoad() { jjObjectPresets[OBJECT::PURPLEGEM].points = 2000; jjObjectPresets[OBJECT::NORMTURTLE].behavior = TURTBOSS; jjObjectPresets[OBJECT::NORMTURTLE].points = 5000; jjObjectPresets[OBJECT::NORMTURTLE].energy = 50; jjObjectPresets[OBJECT::NORMTURTLE].bulletHandling = HANDLING::HURTBYBULLET; jjObjectPresets[OBJECT::NORMTURTLE].state = STATE::WALK; } void onFunction0(jjPLAYER@ play) { play.activateBoss(); boss=true; {play.boss=jjAddObject(OBJECT::NORMTURTLE, 38*32, 55*32);} jjMusicLoad("boss.s3m"); play.activateBoss(true); } void TURTBOSS(jjOBJ@ boss) { jjPLAYER@ play = jjLocalPlayers[0]; if ( boss.energy==0) { boss.counter==0; boss.counter += 0; boss.determineCurAnim(ANIM::TURTLE, 7); boss.determineCurFrame(); boss.frameID = boss.counter/56; jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::NORMAL); ++boss.counter; if ( boss.energy==0&&++boss.counter>20) jjEventSet(play.xPos / 32, play.yPos / 32, AREA::EOL); } if ((boss.xPos > play.xPos+3 || boss.xPos < play.xPos-3)&& boss.state != STATE::KILL) {boss.direction = (play.xPos < boss.xPos) ? +1 : +1;} else { boss.direction==1;} if (boss.yPos < 54*32) {boss.yPos = boss.yPos;} if (boss.xPos > 24*32) {boss.xPos = boss.xPos;} switch (boss.state) { case STATE::WALK: boss.behave(BEHAVIOR::WALKINGENEMY); { if (boss.counter >= 180) {boss.counter = 0; } boss.counter++; if (u==0||u==1) {if (++boss.counter < 180){ boss.xSpeed= (1+1)*boss.direction; boss.determineCurAnim(ANIM::TURTLE, 7); if (boss.counter == 10){ jjSample(boss.xPos, boss.yPos, SOUND::INTRO_GREN3);} if (boss.justHit == 0) {jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::NORMAL);} boss.determineCurFrame(); //boss.frameID = boss.counter/10; } break; } } case STATE::FREEZE: if (boss.freeze > 0) { boss.draw(); boss.freeze -= 4; } if (boss.freeze < 4) { boss.unfreeze(0); boss.state = boss.oldState; } break; case STATE::KILL: case STATE::DEACTIVATE: boss.deactivate(); break; } //if (boss.justHit == 0) //jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::NORMAL); //else jjDrawSpriteFromCurFrame(boss.xPos, boss.yPos, boss.curFrame, boss.direction, SPRITE::SINGLECOLOR,15); } |
Mar 9, 2020, 11:55 PM | |||
Quote:
if (u==0||u==1) line which I assume refers to a variable you didn't include in that snippet. You are running into an issue where killing it using a physical attack fails to cause the level to end, but jObjectPresets[OBJECT::NORMTURTLE].playerHandling = HANDLING::ENEMY; should fix that. Also you probably don't want STATE::KILL to call boss.deactivate() .Quote:
|
Mar 10, 2020, 08:09 AM | |||
Walking Enemy
Quote:
Quote:
And I have a one last question. I am trying to create a walking enemy from Frog animations. It works but the animation plays under the ground sprite. Here's the code: Code:
void onLevelLoad() { jjObjectPresets[OBJECT::LIZARD].behavior = Frog; jjObjectPresets[OBJECT::LIZARD].bulletHandling = HANDLING::HURTBYBULLET; jjObjectPresets[OBJECT::LIZARD].playerHandling = HANDLING::ENEMY; } void Frog(jjOBJ@ obj) { obj.behave(BEHAVIOR::WALKINGENEMY, false); obj.determineCurAnim(ANIM::FROG, 12); obj.determineCurFrame(); obj.putOnGround(true); jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::NORMAL, 0); } |
Mar 12, 2020, 05:55 PM | |
First off, you could simplify all that like this:
Code:
void onLevelLoad() { jjObjectPresets[OBJECT::LIZARD].determineCurAnim(ANIM::FROG, jjIsTSF ? 12 : 11); } BEHAVIOR::WALKINGENEMY is one of the only parts of the game that cares about jjANIMFRAME::coldSpotY, but the frog sprites are one of the only land-based animations that don't have that property defined. Walking enemies try to align their hotSpotY point to the surface of the ground they're on, but that number defaults to 0, which is the top of the sprite. Just move it upwards until it looks better:Code:
jjANIMATION@ frogWalkAnim = jjAnimations[jjObjectPresets[OBJECT::LIZARD].curAnim]; for (uint i = 0; i < frogWalkAnim.frameCount; ++i) jjAnimFrames[frogWalkAnim.firstFrame + i].coldSpotY = -25; |
Mar 13, 2020, 12:04 AM | ||
Solved
Quote:
|
Mar 21, 2020, 09:40 AM | |
There are a couple things you might be running into. One is that JJ2 is of course always changing the player's
xSpeed on its own, so if you make a single short-term change, in response to something like one of the onFunction# hooks, then that change is not going to last very long before JJ2's normal speed handling takes over. But onPlayer works constantly instead of as a one-time thing, so naturally it's going to have more visible impact. The other is that p is deprecated and may not (should not) work in all situations, and you should use the actual jjPLAYER@ argument available to onObjectHit and onFunction# instead.
|
Mar 22, 2020, 11:11 PM | |
So even if I try with jjPLAYER I can’t make a constant speed change.
I could change the speed like this though, again with onPlayer. if(play.xPos>27 && play.yPos>43) if(play.keyRight) { play.xSpeed = 10; } if(play.keyLeft) { play.xSpeed = -10; } play.keyRun = true; } But that’s not the exact effect I want. I’d like to make a constant speed up (at least for ten seconds or so) regardless of the player pos |
Mar 23, 2020, 07:41 AM | |
Ah, okay, I see what you mean. Try something like this:
Code:
int SpeedUpUntil = 0; void onPlayer(jjPLAYER@ play) { if (SpeedUpUntil > jjGameTicks) { //adjust player's xspeed and such in here } } SpeedUpUntil = jjGameTicks + 10 * 70; where 10 is the number of seconds you want the effect to last.(if you want to support cooperative, SpeedUpUntil should be an array<int> instead of a int .)
|
Apr 18, 2024, 01:02 PM |
DennisKainz |
This message has been deleted by DennisKainz.
Reason: Just found out a better method
|
Tags |
angelscript, code, jcs, request |
«
Previous Thread
|
Next Thread
»
Thread Tools | |
|
|
All times are GMT -8. The time now is 03:31 PM.
Jazz2Online © 1999-INFINITY (Site Credits). 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. Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Original site design by Ovi Demetrian. DrJones is the puppet master. Eat your lima beans, Johnny.