EDuke32 Scripting "CON coding help"
#1711 Posted 06 October 2015 - 05:07 AM
If you decide to go the route of using statnums instead you need to do something like changespritestat within each actor AFTER they have loaded and set all of their proper parameters, and make sure it is a completely unused statnum. At that point they will become non-actors, and you'll require an external loop to cycle through all of the elements.
#1712 Posted 06 October 2015 - 07:16 AM
#1713 Posted 06 October 2015 - 07:34 AM
Mblackwell, on 06 October 2015 - 05:07 AM, said:
Previously you mentioned ...
Mblackwell, on 05 October 2015 - 12:12 PM, said:
... which, rightly or wrongly, I interpreted as meaning all sprite ID's could change after something spawned during the game ?
Mblackwell, on 06 October 2015 - 05:07 AM, said:
Well, it seems my idea of using statnum=1025+original hitag is a non-starter as you cant write values above 1025 to cstat. Rats. Interestingly, setting a sprite's statnum to, say, 130 sees it persist into the game (rem: I'm talking inanimate actors like wall sprites, that kinda thing) and it's EVENT_GAME is still called. (Just to be clear, I've no intention of requiring a user to modify a statnum via mapster to achieve anything, this was just a test to see if a statnum got destroyed anywhere during initialisation).
I've gone round the design loop so many times I'm getting a bit dispondant. Can you confirm that a sprite ID won't ever change under any circumstances _after_ initialisation i.e. if I'm in EVENT_GAME and it is called with THISACTOR of say 20, then that sprite will for ever more be sprite 20 irrespective of any spawning or conversely destruction might occur in the game? Sorry to labour this point but this need to group things is pretty fundamental to some of the things I'm trying to achieve.
If the sprite ID's after initialisation do stay put then I'll return to my list method to define a group but instead of then having a list that links between groups I'll use statnum to mark, say, the primary sprite in a group, a different statnum to mark other game sprites of mine, etc so that way I can easily iterate through the relevant groups (which I guess is kinda what statnum is intended for). Does this sound reasonable?
TTFN,
Jon
#1714 Posted 06 October 2015 - 07:34 AM
December Man, on 06 October 2015 - 07:16 AM, said:
We're not going to give this one to you. You need to learn how to script for yourself. It's possible to understand the entire process by reading the existing code. It's essential if you want to script anything of significance.
#1715 Posted 06 October 2015 - 10:32 AM
#1716 Posted 06 October 2015 - 10:48 AM
The Mechanic, on 06 October 2015 - 07:34 AM, said:
I've gone round the design loop so many times I'm getting a bit dispondant. Can you confirm that a sprite ID won't ever change under any circumstances _after_ initialisation i.e. if I'm in EVENT_GAME and it is called with THISACTOR of say 20, then that sprite will for ever more be sprite 20 irrespective of any spawning or conversely destruction might occur in the game? Sorry to labour this point but this need to group things is pretty fundamental to some of the things I'm trying to achieve.
If the sprite ID's after initialisation do stay put then I'll return to my list method to define a group but instead of then having a list that links between groups I'll use statnum to mark, say, the primary sprite in a group, a different statnum to mark other game sprites of mine, etc so that way I can easily iterate through the relevant groups (which I guess is kinda what statnum is intended for). Does this sound reasonable?
TTFN,
Jon
Correct, after initilization any sprites that exist will have their ids set in stone and anything spawned in-game with espawn will give the correct id via RETURN.
Edit:
I'd probably just do a thing like this
gamearray MYLOCATORS 930 // Max Groups * Max Points + Max Points/Position gamevar INIT 0 2 gamevar TEMP 0 0 gamevar L_GROUP 0 2 gamevar L_POSITION 0 2 define MAXPOINTS 30 define MYLOCATOR 3585 eventloadactor MYLOCATOR getactor[THISACTOR].hitag L_GROUP getactor[THISACTOR].lotag L_POSITION setactor[THISACTOR].hitag 0 setactor[THISACTOR].lotag 0 enda useractor notenemy MYLOCATOR ifvare INIT 0 { cstat 32768 setvarvar TEMP L_GROUP mulvar TEMP MAXPOINTS addvarvar TEMP L_POSITION setarray MYLOCATORS[TEMP] THISACTOR setvar INIT 1 } enda eventloadactor someenemyorsomething getactor[THISACTOR].hitag L_GROUP setactor[THISACTOR].hitag 0 enda useractor someenemyorsomething loop through L_GROUP * MAXPOINTS + until you hit a 0/unfilled ID, doing comparison to find the nearest point and use that as your start position and then iterate through it and do some facing code and other nonsense to move it in the appropriate direction. You could also use this same type of code to build groups of effects actors or whatever else. enda
#1717 Posted 06 October 2015 - 01:46 PM
Perro Seco, on 06 October 2015 - 10:32 AM, said:
Use a var! I'm guessing you're checking ifonwater, right? If you use a var you can say something like
gamevar ON_WATER 0 1 actor APLAYER ifonwater { ifvare ON_WATER 0 { soundonce SPLASHSOUND setvar ON_WATER 1 } } else setvar ON_WATER 0 enda
#1718 Posted 07 October 2015 - 10:11 AM
Mblackwell, on 06 October 2015 - 01:46 PM, said:
gamevar ON_WATER 0 1 actor APLAYER ifonwater { ifvare ON_WATER 0 { soundonce SPLASHSOUND setvar ON_WATER 1 } } else setvar ON_WATER 0 enda
#1720 Posted 08 October 2015 - 01:05 PM
When originally planning I did a test, simply moving a decorative sprite during EVENT_GAME. I did:
movesprite THISACTOR 64 0 -128 65537 tempy
Behold, a sprite slowly and smoothly moving.
Now time to use it in anger and its not working as advertised; during EVENT_GAME I need to initialise the position a decorative sprite and I use 'movesprite' to achieve it, completely ignoring the sprite in later EVENT_GAME's i.e. this is a one-off move. Result ? Eduke32 bizarely can't make its mind up, sometimes it draws the sprite in its initial position, sometimes in various positions in the general direction of (but not the correct) position, rapidly flickering between the various psotions. If I use DNDEBUG and look at the resulting map, the sprite has moved HALF WAY towards where it should be.
So, for test purposes, I revert to the original test movesprite to initialise the decorative sprite's position (which is a very small movement) but I still see the sprite shimering.
I have some per-actor variables, but when the sprite is moved every one of the standard sprite struct variables is as they'd normally be.
TTFN,
Jon
[Edit] If I manually add the required deltax, deltay and deltaz to the sprite's position then I get an improvement; instead of flickering between original position and half way towards the final position, it now flickers between the old and new position (and a few positions inbetwwen).
This post has been edited by The Mechanic: 08 October 2015 - 01:13 PM
#1721 Posted 08 October 2015 - 01:41 PM
The Mechanic, on 08 October 2015 - 01:05 PM, said:
That's intended. As the name indicates, it simply moves the sprite. You have to set it every tic you want the sprite to move.
The Mechanic, on 08 October 2015 - 01:05 PM, said:
That sounds like an interpolation problem. By default sprites have two values for the coordinates, which is used to smoothen the movements up to 120 frames per second compared to the in-game time of 30 frames (tics) per second. Add this before you use movesprite:
setactor[THISACTOR].htbposx sprite[THISACTOR].x setactor[THISACTOR].htbposy sprite[THISACTOR].y setactor[THISACTOR].htbposz sprite[THISACTOR].z
The Mechanic, on 08 October 2015 - 01:05 PM, said:
I don't remember if that's the case for movesprites, but in some circumstances the sprite velocity equals half or a quarter of the expected (i.e. build units per tic). So just multiply the value to match your desired velocity.
#1722 Posted 08 October 2015 - 02:17 PM
Fox, on 08 October 2015 - 01:41 PM, said:
Hmmm ... me thinks the wiki needs modifying, it is to easy to assume 'movesprite' did _exactly_ that, not realising that Eduke might be trying to smoothly move it.
Fox, on 08 October 2015 - 01:41 PM, said:
setactor[THISACTOR].htbposx sprite[THISACTOR].x setactor[THISACTOR].htbposy sprite[THISACTOR].y setactor[THISACTOR].htbposz sprite[THISACTOR].z
Bingo ! ... ish. That has sorted the multi-position flickering Only for some reason it only moves half the distance it should.
However it totally fails again if the sprite does not have a hitag However the following seems to work without requiring teh sprite to have a hitag and moves to the correct position, not simply half way (temp1,temp2,temp3 being deltax,deltay,deltaz respectively):
getactor[jactor].x temp5 addvarvar temp5 temp1 setactor[jactor].htbposx temp5 setactor[jactor].x temp5 getactor[jactor].y temp5 addvarvar temp5 temp2 setactor[jactor].htbposy temp5 setactor[jactor].y temp5 getactor[jactor].z temp5 addvarvar temp5 temp3 setactor[jactor].htbposz temp5 setactor[jactor].z temp5 // TODO : Will need to manually update sector number if crossing sectors
Fox, on 08 October 2015 - 01:41 PM, said:
Ah-ha ! That makes sense now as I thought I could see the sprite being displayed in four different positions. Guess I need a bit of a think - EVENT_GAME is 30fps-per-actor which is where I intend to be moving a sprite but looks like it'll be a lot smoother if I can use this interpolation. Perhaps use brute force position calcs for instant move, then during move between points (locators) switch to using movesprite.
Fox, on 08 October 2015 - 01:41 PM, said:
I didn't want to just double the value, not knowing the cause. However it seems that you cant use movesprite to move sprites that aren't destructable
Anyhow, 'htbpo*' is the key to getting this working right, cheers Fox.
TTFN,
Jon
#1723 Posted 08 October 2015 - 02:42 PM
For a simple movement/offet of X,Y,Z build units assuming you don't need to see it move just setting the correct x,y,z is enough rather than bothering with movesprite.
In all cases (setting x,y,z or using movesprite) it's a good idea to call updatesectorz and set the sprite's current sector to the correct one.
#1724 Posted 08 October 2015 - 03:41 PM
Mblackwell, on 08 October 2015 - 02:42 PM, said:
For a simple movement/offet of X,Y,Z build units assuming you don't need to see it move just setting the correct x,y,z is enough rather than bothering with movesprite.
In all cases (setting x,y,z or using movesprite) it's a good idea to call updatesectorz and set the sprite's current sector to the correct one.
I'm currently using a clipmask of 65537 but I'll probably use 0. When I tried 65537 in my initial tests it was cool to see the sprite reach a wall and move no further in that direction ... although it seems ceilings dont count as blockable as my test sprite went right through it.
Anyhow, the group of sprites I'm moving are following a path defined by "locators" and it is up to the map designer to ensure that the path between the two is valid. As I mentioned in my previous post, I know I need to update the sprites sector too - I shall simply determin sector, if there is no sector (a void) then the afflicted sprite just stays where it is whilst the map designer gets their act together (suitable message in eduke log). I've not reached the point of looking at player or enemy interactions - I'm assuming I'll need to move any actor or enemy currently stood on the sprites manually too?
TTFN,
Jon
#1725 Posted 08 October 2015 - 05:08 PM
#1726 Posted 09 October 2015 - 12:33 AM
Mblackwell, on 08 October 2015 - 05:08 PM, said:
That sounds a bit ominous. More fun ahead
Mblackwell, on 08 October 2015 - 05:08 PM, said:
Yes, a point worth raising, currently I'm at the stage of working in a single sector. I'm anticipating some issues as when moving between sectors there will be a point where a sprite is crossing a sector boundary; the rendering in the original Duke3d would probably rule out crossing sectors with sprites then potentially not getting rendered but Eduke32 seems a lot better in that respect. We shall see. I beleive movesprite also updates the sector and if I'm lucky (unlikely based on issues so far!) during the game I can return to using this - initialising the position clearly can't use movesprite though.
That lot was supposed to be the easy bit; rotating a group of sprites without accumulating rounding errors is going to be .. um ... "interesting".
TTFN,
Jon
#1727 Posted 09 October 2015 - 04:40 AM
The Mechanic, on 09 October 2015 - 12:33 AM, said:
Eduke32 doesn't render sprites from sectors out of reach. That's an optimization issue, there's no reason for the game to render a sprite that you cannot see in first place. Movesprites do update the sector automatically, but you can also use setsprite as a shortcut for modifying the coordinates directly.
The Mechanic, on 09 October 2015 - 12:33 AM, said:
I am thinking of re-calculating the position in relation to the pivot and subtracting it.
#1728 Posted 09 October 2015 - 08:28 AM
Fox, on 09 October 2015 - 04:40 AM, said:
The issue is when a sprite should be visible by the player but the sector containing the sprite in not in the players field of view, this can make it prone to not being rendered - see attached. However it doesn't always become in an issue in Eduke32 - I guess it must be a bit more clever than the original Duke3D but it does still happen.
Fox, on 09 October 2015 - 04:40 AM, said:
Lets say it takes 5 seconds to move/rotate-90 between two locators. At 30 calcs per second that is rotating a tiny 90/150 degrees at a time. When rotating a sprite about pivot point this could lead to accumulation of rounding errors over time. I suspect at initialisation I may have to to store the delta-x and delta-y between a sprite's center and the rotational center and always calculate the rotation-induced position shift relative to those stored values. Sorry, not very good at explaining things, did that make sense ?
TTFN,
Jon
#1729 Posted 09 October 2015 - 09:27 AM
The Mechanic, on 09 October 2015 - 08:28 AM, said:
The thing is that sprites should never be outside of their visible sectors. Whenever that happens, it's because of a glitch or an improper code. For example, it's also possible to use CON to connect nonadjacent sectors, which the player would die if he tries to cross a wall. Similarly, sprites outside of their sectors is not something expected by the engine.
The Mechanic, on 09 October 2015 - 08:28 AM, said:
Lets say it takes 5 seconds to move/rotate-90 between two locators. At 30 calcs per second that is rotating a tiny 90/150 degrees at a time. When rotating a sprite about pivot point this could lead to accumulation of rounding errors over time. I suspect at initialisation I may have to to store the delta-x and delta-y between a sprite's center and the rotational center and always calculate the rotation-induced position shift relative to those stored values. Sorry, not very good at explaining things, did that make sense ?
Eehhh, I suspect my solution wouldn't work. You would have to try yous.
This post has been edited by Fox: 09 October 2015 - 09:30 AM
#1730 Posted 09 October 2015 - 09:53 AM
Fox, on 09 October 2015 - 09:27 AM, said:
In my example image, the sprite is in its correct sector, its just that it is bigger than it's sector.
When moving sprites slowly between sectors, there will always be the situation at some point where the center of the sprite is in one sector (and has the correct sectnum value) but part of the sprite is in another sector. It's a case of suck it and see to find out how real a problem it is in practice. If it ends up sucking then I still have vertical movement - multi-floor TROR elevator for example.
It is possible to fudge this; when a sprite crosses two sectors, come up with a plan for adjusting x,y (setting sectnum exactly as per x,y) and then use xoffset and yoffset to nudge it back into the correct position. Compare the attached image with previous one - I've placed the sprite in the player's sector, then manipulated xoffset and yoffset to put it back exactly where it was in the first image. The sprite no longer dissapears. It's a solution - but probably more complicated than it is worth.
TTFN,
Jon
#1731 Posted 09 October 2015 - 10:14 AM
Hendricks266, on 06 October 2015 - 07:34 AM, said:
Ok, thanks for the motivation. I figured it out, but I don't know whether this is the optimal way to do it. Currently, the shrunken enemy dies before Duke actually steps on him.
gamevar TEMP6 -1 1 state genericshrunkcode ifcount 32 { ifactor ENEMY { ifpdistl SQUISHABLEDISTANCE { ifvarvarg player[THISACTOR].actorsqu TEMP6 { addkills 1 sound SOUND debris SCRAP3 40 debris SCRAP3 40 debris SCRAP3 40 debris SCRAP3 40 killit } getplayer[THISACTOR].actorsqu TEMP6 } } else ifactor ENEMY2 { ifpdistl SQUISHABLEDISTANCE { ifvarvarg player[THISACTOR].actorsqu TEMP6 { addkills 1 sound SOUND debris SCRAP3 40 debris SCRAP3 40 debris SCRAP3 40 debris SCRAP3 40 killit } getplayer[THISACTOR].actorsqu TEMP6 } } ifpdistl SQUISHABLEDISTANCE pstomp } else { sizeto MINXSTRETCH MINYSTRETCH spawn FRAMEEFFECT1 } ends
This post has been edited by December Man: 09 October 2015 - 11:09 AM
#1733 Posted 09 October 2015 - 03:15 PM
The Mechanic, on 09 October 2015 - 09:53 AM, said:
When moving sprites slowly between sectors, there will always be the situation at some point where the center of the sprite is in one sector (and has the correct sectnum value) but part of the sprite is in another sector.
That's fine. It's just recommended to always have sprites on their correct sectors, since otherwise it's undefined behavior and you should expect glitches. For example, you have a sprite in a door sector. If the door closes, the engine will detect that there's no line of sight between the player eyes and that sector, and the sector along with its walls and sprites won't be rendered. If you have a sprite outside of the door sector, but with its current sector ID being that of the door, it will become invisible when the door closes.
#1734 Posted 10 October 2015 - 02:47 AM
#1735 Posted 10 October 2015 - 06:15 AM
Mark., on 10 October 2015 - 02:47 AM, said:
Question is why is the sprite not getting rendered ?
If you have disappearing sprites due to them being in a sector but the sprites were bigger than that sector, you may be able to fix that with two identical sprites, one in the original sector then place the second in the other sector and use xoffset and yoffset to make it render where the first one is. That way if one of them isn't rendered then the other one is.
TTFN,
Jon
#1736 Posted 10 October 2015 - 07:46 AM
This post has been edited by Mark.: 10 October 2015 - 08:17 AM
#1737 Posted 10 October 2015 - 09:59 AM
#1738 Posted 10 October 2015 - 10:42 AM
Mark., on 10 October 2015 - 07:46 AM, said:
I have an idea, though how practical it is in reality I don't know.
Attached image shows red overhead wires, one of which vanishes because it is in a sector (round the corner) not visible to the player. The following code illustrates the idea behind the fix, where the wire that goes missing is hitagged 666 :-
onevent EVENT_GAME getactor[THISACTOR].hitag temp3 ifvare temp3 666 { ifcansee nullop else { getactor[THISACTOR].sectnum temp3 ifvare temp3 0 { setactor[THISACTOR].x 29568 setactor[THISACTOR].xoffset 0 setactor[THISACTOR].sectnum 1 } else { setactor[THISACTOR].x 30080 setactor[THISACTOR].xoffset 8 setactor[THISACTOR].sectnum 0 } } } endevent
OK, I hackcoded it here, but you get the idea. How feasible it'd be to automate this in a more general case I don't know.
Also in the attached map I made a second version - follow the red arrow - no CON code needed, simply duplicated the missing sprite, moved it to another sector and adjusted it's xoffset to put it exactly where the original one was. Visually overlapping which, depending on where you are and where you are looking, one may vanish but the other remains visible. Now I appreciate this may be somewhat awkward with more complex structures.
Thing is, adding a pucka eduke flag isn't so easy. OK, adding the flag is , but how do you define "always render", bearing in mind sorting is needed for who-is-in-front-of-who during rendering, that kinda thing. The situation could be improved if in addition to the rendering process using the center of a sprite for a render/no-render decision, it included say both ends of the sprite. But in particularly complex scenarious even that might fail This would require multiple player-can-see operations as well as calculating sector numbers in which those ends appear. Probably a lot of (computational) effort. Maybe someone with more detailed knowledge of the inner workings of the rendering process could better comment, but my gut feel is it would be difficult.
If I've misunderstood your issue, perhaps start a new thread with a small test map and lets see what we can do.
TTFN,
Jon
[EDit] OK, now I have me specs on, it isn't quite doing what I thought, bear with me whilst I work it out.
Attached File(s)
-
missing-sprite.zip (1.35K)
Number of downloads: 527
This post has been edited by The Mechanic: 10 October 2015 - 11:51 AM
#1739 Posted 10 October 2015 - 11:34 AM
#1740 Posted 10 October 2015 - 12:13 PM
I chose bad example sprites, hidding my error.
It seems xoffset may be ignored if altered during game (or I need to call something I'm not aware of). The version where I just overlapped two sprites worked but the "CON" version doesn't seem to change the xoffset and also wont reset the position to original position when required.
Fox, on 10 October 2015 - 11:34 AM, said:
I think you are absolutely right, the way to do this is to spawn dupicates (triplicates, whatever), moving sprites at runtime just aint gonna work.
The "spawn" command in CON only spawns what a respawn sprite can spawn. How do I spawn/create a regular decorative sprite at runtime?
TTFN,
Jon