Jan 10, 2014, 11:11 AM | |
jjDrawSprite , for better or worse, doesn't take the initiative to load sprites from anims.j2a if they haven't already been loaded for that level. To remedy this, either place a corresponding object or ambient sound event somewhere in JCS, or else call jjOBJ::determineCurAnim , which does try to load missing sprites.(Please hold any concerns about that a) not making sense or b) not being documented, because you're right. There wasn't time/understanding to put in place a more elaborate/appropriate API for such things, but there needed to be some way of loading sprites in the meantime, so determineCurAnim got to be an interim solution)
|
Jan 10, 2014, 12:04 PM | |
You have been very helpful! Thank you!
_______ I don't know how to use all the algebra operations. I only know how to use the % in something like "obj.xPos%32" to module the value in a range of 32. Where can I find the whole list of algebra operations in scripting? And how do I repeat an event many times in a game tick? For example, I would like to spawn 64 particles of pixel type on Jazz to simulate bleeding, but I can only add 1 particle per tick. Last edited by DennisKainz; Jan 10, 2014 at 02:52 PM. |
Jan 10, 2014, 03:42 PM | |
At this point you're just asking about how the scripting language works, so I'd suggest reading the docs, particularly the first three sections. Or at least skim and look for words like "operator" and "loop."
|
Jan 10, 2014, 11:17 PM | |
That is exactly the advice I needed. Thank you again.
There's one thing I can't find in the manual, though. How do I remove the decimal parts from a number? For example, I want to check the enemy's x speed, but instead of checking it as "1.25" or "4.0625" or "3.785" I want it to be checked respectively as "1", "4" or "3". Shortly, to check the numbers as natural, non decimal numbers. And there's a new problem: I can't set a walking enemy's x speed to its current value minus something. I ask the game to calculate "necro.xSpeed = necro.xSpeed - 0.0625", but it converts it into "necro.xSpeed = necro.xSpeed" when I do, automatically discarding the subtraction part. And I think it also converts xSpeed from "0" to "1" automatically when a walking enemy is on walking state. And I can't find a behavior that respects everything. The pickup behavior respects the x and y speed, but always blocks on collision. The spark one doesn't block on collision and respects x and y speed, but ignores you in a range outside 240 or something, which isn't ok if you play in 640x480. Can the AngelScript experts create a behavior which respects everything you input to it, and you decide whether it respects collisions or not? Also, when I kill an object and play a sound to it, the sound stops along with the object's death, and I don't want to add expressions apart to make the sound continue. I'm sorry about bothering you so much. I swear I try to figure stuff out myself, but my logic skills aren't as high as yours. Last edited by DennisKainz; Jan 13, 2014 at 06:38 AM. |
Jan 18, 2014, 11:46 AM | ||||
Editing your post didn't bump the thread, so it took me a while to see this:
Quote:
int(number) or (int)(number) should work.Quote:
Quote:
In the "Requests" department: lwe9.j2l. |
Feb 15, 2014, 04:15 PM | |
Hey, so this is probably going to make me seem like an idiot, but how do I check whether or not a player has destroyed a tile of destructible scenery? (If it's of any help, I want it to activate a trigger scenery event as a result, and all of this is supposed to be in singleplayer mode)
|
Feb 15, 2014, 04:18 PM | |
jjTileGet would probably be simplest.
|
Feb 15, 2014, 04:46 PM | |
Okay, it's good to know that I'm doing that part right, but it also means that I've almost definitely got the syntax wrong...
Code:
void onMain { if jjTileGet(4,11,29) == 10 { jjSwitchTrigger(1) } } |
Feb 15, 2014, 07:31 PM | |
This isn't Python, so you'll need to wrap some parentheses around the condition.
if (jjTileGet(4,11,29) == 10) { .
|
Feb 15, 2014, 08:21 PM | |
I did try that at one point(And I just double-checked now) -- still not working.
|
Feb 15, 2014, 09:45 PM | |
Oh, right... you also need
() after onMain .Remember to turn on AngelscriptDebug in plus.ini if you're writing code. It gives you line numbers and things for syntax errors.
|
Feb 16, 2014, 06:46 AM | |
Thanks, it works... Sort of.
New problem: If I have the destruct scenery change the tile into an animated tile(Using WebJCS), the script doesn't work(Although, if I use a non-animated tile, it works perfectly). Here's what the code looks like now: Code:
void onMain() { if ((jjTileGet(4,10,28) == 0) && (jjTriggers[1] == false) == true) { jjSwitchTrigger(1); } } |
Feb 16, 2014, 07:43 AM | |
Code:
(jjTriggers[1] == false) == true Code:
void onMain() { if (jjTileGet(4, 10, 28) == 0 && !jjTriggers[1]) { jjTriggers[1] = true; } }
__________________
Mystic Legends http://www.mysticlegends.org/ The Price of Admission - Hoarfrost Hollow - Sacrosanct - other - stuff |
Feb 16, 2014, 09:03 AM | ||
It checks two things, and if both of them return true, then it triggers.
Quote:
Now that I think about it, it was a really stupid mistake(Although, that's generally how I learn these things). Anyway, thanks for the help. |
Mar 7, 2014, 10:35 PM | ||
Code to morph Spaz to Jazz by Nick of epictest.j2l
Quote:
|
Mar 11, 2014, 07:19 AM | |
Is there any way of giving objects shields(namely enemies so that they can shoot with them and pickups so that they hurt the player upon contact until shieldTime runs out)?
I have disabled the functions of the fire shield so far: void onLevelLoad() { jjObjectPresets[OBJECT::FIRESHIELD].behavior = Incendie; } void Incendie(jjOBJ@ boule) { boule.behave(BEHAVIOR::MONITOR, false); if (boule.state == STATE::KILL) boule.state = STATE::ACTION; } void onPlayer(jjPLAYER@ play) { if (play.shieldType == 1) play.shieldTime = 0; } Pointing out the position of the specific object afterwards does not seem to work. Besides, I have gone through about 80 animations in the ''Pickups'' section and still have not found one of an active shield. I suppose the parameters shieldType and shieldTime should also somehow be added to the jjOBJ class(?). Thank you in advance! |
Mar 11, 2014, 01:18 PM | |
Nope.
|
Mar 12, 2014, 10:08 AM | |
When I start my level in multiplayer mode, the result of following code is always 20, but in single player there are random values.. do you know what's the reason behind that??
Code:
void onLevelLoad() { for(int i = 0; i <= 20; i++) jjAddObject(OBJECT::APPLE, jjRandom()%3000, jjRandom()%3000); } int count() { int x = 0; for (int i = 1; i < jjObjectCount-1; i++) if(jjObjects[i].isActive) x++; return x; } void onMain() { if(jjGameTicks%210 == 0) jjAlert(""+count()); } Last edited by Stavros; Mar 12, 2014 at 11:34 AM. |
Mar 12, 2014, 10:26 AM | |
Single player mode saves memory and improves performance by deactivating most objects when they are too far away from the player. See jjOBJ::deactivates.
Additionally you probably do not want to use jjObjectCount-1 in your code because that means the object will not be registered if it's the final object.
__________________
I am an official JJ2+ programmer and this has been an official JJ2+ statement. |
Mar 15, 2014, 01:37 AM | |
Let me create a post with bunch of large questions regarding the possibilities of Angel Script (some of them I've already asked in SWAG thread, but I don't want to make more offtopings). I'm sorry if some of that was already explained, I just want to put all my ambiguities together. I will really appreciate if someone will take his time and patience and will give me exhaustive answers for all of these points:
|
Mar 15, 2014, 03:16 AM | |||||||||||
Quote:
Quote:
Quote:
Quote:
Quote:
Quote:
Quote:
Quote:
Quote:
Quote:
__________________
I am an official JJ2+ programmer and this has been an official JJ2+ statement. |
Mar 16, 2014, 09:42 AM | |||||
Quote:
I know I may be asking for too much, but can any one show me how can I build the easiest enemy that comes to my mind: that spiky ball from Technoir, which just moves from one wall to another. Let's just say that I have a one tile ball in my tileset and I just want to add to that ball the exactly same behavior as the mentioned enemy from Technoir: that is, moving horizontally from one wall to another. It hurts you when you touch it, you can kill it. Pretty plzzz? Quote:
Quote:
Quote:
|
Mar 16, 2014, 10:33 AM | ||
Code:
void onLevelLoad() { jjObjectPresets[OBJECT::TUFBOSS].behavior = BEHAVIOR::WALKINGENEMY; } Quote:
Code:
void onLevelLoad() { jjObjectPresets[OBJECT::THING].behavior = Spikeball; } void Spikeball(jjOBJ@ obj) { jjOBJ@ exp; switch (obj.state) { case STATE::START: obj.direction = obj.xSpeed = -2; obj.determineCurAnim(ANIM::DESTSCEN, 4); //32x32 square sprite obj.determineCurFrame(); obj.bulletHandling = HANDLING::HURTBYBULLET; obj.playerHandling = HANDLING::ENEMY; obj.state = STATE::FLY; case STATE::FLY: obj.xPos = obj.xPos + obj.xSpeed; if (jjMaskedVLine(obj.xSpeed > 0 ? obj.xPos + 16 : obj.xPos - 16, obj.yPos, 1)) { obj.direction = obj.xSpeed = -obj.xSpeed; } jjDrawTile(obj.xPos - 16, obj.yPos - 16, 4); break; case STATE::KILL: @exp = jjObjects[jjAddObject(OBJECT::EXPLOSION, obj.xPos, obj.yPos, obj.objectID, CREATOR::OBJECT)]; exp.determineCurAnim(ANIM::AMMO, 5); jjSample(obj.xPos, obj.yPos, SOUND::COMMON_EXPL_TNT); obj.delete(); break; } }
__________________
Mystic Legends http://www.mysticlegends.org/ The Price of Admission - Hoarfrost Hollow - Sacrosanct - other - stuff |
Apr 12, 2014, 07:40 AM | |
Is there a simple way to create a flicker light once a trigger is activated, with the light appearing on top of the tile that the trigger activated?
|
Apr 12, 2014, 04:42 PM | |
Simplest would probably be to loop through the object list, find OBJECT::TRIGGERSCENERY objects (with whatever other filters you need, like only ones in a certain area or whatever), and
obj.lightType = (obj.curFrame == 0) ? LIGHT::NONE : LIGHT::FLICKER; After first setting the intensity, something like jjObjectPresets[OBJECT::TRIGGERSCENERY].light = jjObjectPresets[OBJECT::FLICKERLIGHT].light;
|
May 30, 2014, 05:37 PM | |
So I was tweaking around with changing the sprite and energy of some enemies in Castle1 using jjObjectPresets but the script doesn't work. I don't know what the problem is but hope you guys will be able to find a possible solution.
Code:
void onLevelLoad() { jjObjectPresets[OBJECT::NORMTURTLE].determineCurAnim(ANIM::LORI, 13); jjObjectPresets[OBJECT::BAT].determineCurAnim(ANIM::JAZZ, 14); jjObjectPresets[OBJECT::DRAGON].determineCurAnim(ANIM::SPAZ, 5); }
__________________
Uhm? |
May 31, 2014, 02:13 AM | |
A large number of objects, including those you mentioned, contain animation changes within their behavior. Those tend to reference the animation globally rather than relative to the preset one, resulting in the desired animation being displayed either occasionally or never. To reliably and permanently change sprites of such objects, the best way is to modify their behavior. It's technically possible to write a common behavior function for that and I would consider it cleaner but it will be easier to understand if there are separate ones:
Code:
void myTurtle(jjOBJ@ obj) { obj.behave(BEHAVIOR::NORMTURTLE, false); obj.determineCurAnim(ANIM::LORI, 13); obj.draw(); } void myBat(jjOBJ@ obj) { obj.behave(BEHAVIOR::BAT, false); obj.determineCurAnim(ANIM::JAZZ, 14); obj.draw(); } void myDragon(jjOBJ@ obj) { obj.behave(BEHAVIOR::DRAGON, false); obj.determineCurAnim(ANIM::SPAZ, 5); obj.draw(); } Code:
jjObjectPresets[OBJECT::NORMTURTLE].behavior = myTurtle; jjObjectPresets[OBJECT::BAT].behavior = myBat; jjObjectPresets[OBJECT::DRAGON].behavior = myDragon;
__________________
I am an official JJ2+ programmer and this has been an official JJ2+ statement. |
Jun 18, 2014, 08:08 AM | |
I would like to ask, if is it possible to:
a) Make rfs affect only the player who shoots them - rf climbs don't throw others arround. b) Uses that spawnpoint, which has a free route. (for ex. in a testlayer number 1,3,4 are occupied, so it chooses 2, later 5,6... numbered player) If one of them is possible, could someone help me out with that? |
Jun 18, 2014, 01:26 PM | |
a) would be something like this:
Code:
void onMain() { for (int i = 1; i < jjObjectMax: ++i) { jjOBJ@ obj = jjObjects[i]; if (obj.behavior == BEHAVIOR::RFBULLET && obj.state == STATE::EXPLODE && !jjPlayers[obj.creatorID].isLocal) //RF missiles, like most/all bullets, switch to STATE::EXPLODE in one gametick and actually run their explosion code in the next, so you have a chance to find them. obj.delete(); //Or whatever. Changing its behavior to EXPLOSION or EXPLOSION2 might be good for showing its .killAnim animation, but the point is you don't want it to run its own death code and create a shockwave } } |
Jun 21, 2014, 11:55 AM | |
Thank you for a).
I meant Start Position(Jazz/Spaz level start event). Like if they were numbered, the same as players are when they join a game. So When the player joins, it is placed to the same numbered event, as he/she has(actually order doesn't matter to me). |
Jun 21, 2014, 12:12 PM | |
Got it. What I'd probably do would be use warp targets instead of start positions, each of a different ID 0-31. (Or 200-231 or whatever, if you wanted to include an offset so that you didn't accidentally use the same ID somewhere in the level.) Then given a jjPLAYER@ play,
play.warpToID(play.playerID) .You certainly could use start positions, and do a loop through the level using jjEventGet in search of each one, then break; when you find the playerID th such event. Warp targets would just be easier. Up to you.
|
Jul 3, 2014, 12:16 PM | |
What ways of sending information from the server to clients are there with AngelScript? I need to synchronize team ownership and capture progress of control points for a custom gamemode, and I'm currently using the /trigger command to transfer booleans to all clients, but switching those creates unavoidable "Trigger X has been ENABLED" messages, and I cannot send integer values that way.
I looked through all examples and several levels that use AngelScript, but most multiplayer scripts seem to have primarily local effects. Are there any other values that JJ2+ currently synchronizes (preferrably without side effects) that I'm missing here? |
Jul 3, 2014, 01:18 PM | |
You can get a lot of mileage out of jjPLAYER::fireBullet.
(Obviously this is a domain that'll be much better next update.) |
Jul 16, 2014, 05:01 PM | |
Hey, guys, I have some questions, all of which fall under one category, namely: I can't quite understand the way AS refers to objects. If I change an object behavior, would it change just for one instance of the object, for every instance created after the change, or for all instances? Here are some of the things I'm trying to achieve, bear in mind that I have very basic programming skills (some C++, some BASIC, some Python and a lil' bit of WarCraft 3 JASS):
1. How can I palshift the colors of all instances of an object, namely snow? I'm using a modified (through AS) version of Blade's FoFS tileset, and the dirt uses the same gradient as the "dirt", as seen below. I want to shift it to the "grass" (144-159) range. 2. A more complex question: how can I create a basic walking enemy that uses Jazz' stoned sprites, but with changed colors? 3. Is it possible to rotate the texture of the textured background by 90 degrees? 4. Just an additional question to Violet, is it feasible to use different J2A file through AS? I know it's not a CURRENTLY AVAILABLE option, I'm asking if it's a possible one. Of course, the palette should match the original Jazz palette. |
Jul 16, 2014, 07:33 PM | ||||||
Quote:
jjAddObject or by some bit of native code), the contents of the corresponding jjObjectPresets entry are memcpy'd into a slot in jjObjects . So if you make a change to an object in jjObjects , it'll affect only that one object; if you make a change to an object in jjObjectPresets , it'll affect every object created from that preset after that point, but not any objects that were already created. (The same applies to nearly any other object property, except for the few that get set as part of adding an object like xOrg or creatorType.)Code:
jjOBJ@ donutPreset = jjObjectPresets[OBJECT::DONUT]; jjOBJ@ donut1 = jjObjects[jjAddObject(OBJECT::DONUT, 0, 0)]; //donutPreset.behavior == donut1.behavior == BEHAVIOR::PICKUP donutPreset.behavior = BEHAVIOR::MONITOR; //now donutPreset's behavior is MONITOR, but donut1's behavior is still PICKUP jjOBJ@ donut2 = jjObjects[jjAddObject(OBJECT::DONUT, 0, 0)]; //donut2 is copied from donutPreset, so donut2's behavior is also MONITOR donut1.behavior = BEHAVIOR::CRATE; //only donut1's behavior is changed by this, and subsequently added donuts will continue to use MONITOR, not CRATE, unless... jjOBJ@ donut3 = jjObjects[jjAddObject(OBJECT::DONUT, 0, 0, 0, CREATOR::OBJECT, BEHAVIOR::PADDLE)]; //donut3's behavior is PADDLE, not MONITOR, because that was explicitly provided in the jjAddObject call. This option is provided because jjAddObject calls the object's behavior function before you get a chance to initialize any of its other properties, and sometimes you might want to circumvent that. objectID , for obvious reasons, and another two bytes which are only used while loading the level but never again.) If jjObjects[1] is a lizard, and you change its eventID and behavior and curAnim and so on, once you've changed enough properties, there will be no respect in which it is still a lizard.After that I have some bad news for you... Quote:
Quote:
Quote:
Quote:
Last edited by Violet CLM; Jul 16, 2014 at 07:45 PM. |
Jul 17, 2014, 04:59 AM | ||||
Thanks for the answer.
A quick note: I meant that the snow uses the same palette entries as dirt, not dirt. I want to change the behaviour of some enemies (though it seems that with the option for using palshifted jazz sprites gone, this one is off the list), and, more importantly, bullets & ammo pickups. Fastfire gives blaster ammo + fastfire, bouncers gives ammo + increased range, ice gives ammo + increased duration of freeze, and so on. A minor change that I want to achieve is pal-shift some of the enemies, but if I understand correctly, you can palshift the whole image, and not some of the palette entries it uses. Quote:
Quote:
Quote:
Those questions aside, it's good that LGR made this review, cause it made me come back to JJ2 (and finish stuff I was already working on). Which then made me realise that I have a ton of BG Warp suitable textures that might be useful for a next release. And I do mean "a ton". |
Jul 17, 2014, 06:31 AM | ||
Violet's answers are perfectly correct in a way but I wanted to elaborate on the first point.
Quote:
Code:
void newBehavior(jjOBJ@ obj) { obj.behave(BEHAVIOR::oldBehavior, false); jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, value); } Now, getting to the "namely snow" part; this doesn't solve your problem because you seem to have gotten it wrong. Snow instances are not objects. Or, to be unambiguous, they are not jjOBJ instances. They are particles, i.e. jjPARTICLE instances. As such, their options are much more limited. The main problem, as you can imagine, is that you cannot change their behavior. This is a major obstacle but can be overcome by creating snow that is either stored in jjOBJ instances or, preferably, instances of a custom class created for it. In either case you would need to know the default behavior of snow instances, which I believe I'm allowed to provide, and base the new one on that, and that would essentially do the trick, but you would have to prepare to face another problem - this time of much more prosaic nature. You said "144-159". You should be informed that the default snow sprite uses entries 128-136 and entry 201. I suspect that last one could, depending on the exact palette, force a change in your plans. Anyway, the point is, although it requires an inadequate amount of effort, applying PALSHIFT to snowflakes is essentially possible.
__________________
I am an official JJ2+ programmer and this has been an official JJ2+ statement. |
Jul 17, 2014, 11:07 AM | |
Here's the kind of code I meant:
Code:
interface Iparticle { void draw(jjCANVAS@) const; bool process(); } class Tsnowflake : Iparticle { private float x, y, xSpeed, ySpeed; private uint8 frame; private int deathCounter, noClipCounter, speedModifier; Tsnowflake(float xPos, float yPos) { x = xPos; y = yPos; uint random = jjRandom(); xSpeed = -0.5f - (random & 4095) / 16384.f; ySpeed = ((random >>= 12) & 8191) / 4096.f; frame = (random >>= 13) & 7; deathCounter = 0; noClipCounter = 35; speedModifier = ((random >> 3) & 15) << 6; } void draw(jjCANVAS@ canvas) const override { canvas.drawSprite(int(x), int(y), ANIM::SNOW, 0, frame, 0, SPRITE::PALSHIFT, 16); } bool process() override { if (deathCounter == 0) { uint random = jjRandom(); x += xSpeed += (int(random & 1023) - 511) / 65536.f + jjSin(jjGameTicks + speedModifier) / 128.f; y += ySpeed += ((random >> 16) & 1023) / 65536.f; if (noClipCounter > 0) noClipCounter--; else if (jjMaskedPixel(int(x), int(y))) deathCounter = 1; } else { if (++deathCounter & 7 == 0 && frame < 7) frame++; if (deathCounter > 70) return false; } for (int i = 0; i < jjLocalPlayerCount; i++) { const jjPLAYER@ player = jjLocalPlayers[i]; if (x + 32 < player.cameraX || y + 32 < player.cameraY || x - 32 >= player.cameraX + jjSubscreenWidth || y - 32 >= player.cameraY + jjSubscreenHeight) continue; return true; } return false; } } array<Iparticle@> particles; void addSnow() { for (int i = 0; i < jjLocalPlayerCount; i++) { const jjPLAYER@ player = jjLocalPlayers[i]; uint random = jjRandom(); float x = player.cameraX - 32 + player.xSpeed + ((random & 0xFFFF) * (jjResolutionWidth + 64) >> 16); float y = player.cameraY - 32 + (((random >> 16) & 0xFFFF) * jjResolutionHeight >> 16); particles.insertLast(Tsnowflake(x, y)); } } void drawParticleSet(const array<Iparticle@> &in particleSet, jjCANVAS@ canvas) { for (uint i = 0; i < particleSet.length(); i++) { particleSet[i].draw(canvas); } } void processParticleSet(array<Iparticle@>& particleSet) { for (uint i = 0; i < particleSet.length();) { if (particleSet[i].process()) i++; else particleSet.removeAt(i); } } void onDrawLayer4(jjPLAYER@, jjCANVAS@ canvas) { drawParticleSet(particles, canvas); } void onLevelLoad() { jjObjects[0].determineCurAnim(ANIM::SNOW, 0, false); } void onMain() { addSnow(); processParticleSet(particles); }
__________________
I am an official JJ2+ programmer and this has been an official JJ2+ statement. |
Jul 17, 2014, 02:39 PM | |||
SE makes an excellent point re: drawing snow through direct drawSprite calls.
Quote:
jjObjectPresets[OBJECT::FASTFIRE].scriptedCollisions = true; and again for other pickups that you also want to modify in this way.Quote:
We're staying largely mum about what 5.0 will or won't be able to do, so that people will take the time to do cool stuff with 4.3 instead of waiting around patiently for another set of functions to become available, and then another after that, and then another after that... this is planned to change in August, though, as the hype machine warms up again and we look for a release date. |
Tags |
angelscript, code, jcs, request |
«
Previous Thread
|
Next Thread
»
Thread Tools | |
|
|
All times are GMT -8. The time now is 03:23 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.