
EDuke32 Scripting "CON coding help"
#1699 Posted 03 October 2015 - 02:50 AM
#1700 Posted 03 October 2015 - 04:57 AM
Fox, on 03 October 2015 - 02:14 AM, said:
setvar temp 0 whilevarvarn temp MULTIMODE { getplayer[temp].max_actors_killed temp2 addvar temp2 1 setplayer[temp].max_actors_killed temp2 addvar temp 1 }
Ah-ha, so the mysterious MULTIMODE is in fact the number of players. (Does a bit more delving) should that be numplayers as that doesn't include bot players? (for the original purposes of kill count I doubt it makes any difference, but I'm thinking more generally).
Fox, on 03 October 2015 - 02:14 AM, said:
Do you mean unsynchronised between multiple players ? Or something worse ?
The reason I'm using my "ifsoundvar" is only to enable playing one sound effect after another finishes (I've given up doing this with door sectors as duke's door-generated sounds are bloody unpredictable at best), or loop a sound (save building elevator help sectors - that really was a neat trick). I'm not using the end of a sound to do anything more than that so should I get away with it ?
If my object spawns a sound - 71, say - and whilst that is playing some other game event also starts a sound 71 then yes my object will be waiting for the second one to finish, but that is a minor limitation of my system. In practice the sounds spawned by my object are likely to not crop up at the same time elsewhere.
Jblade, on 03 October 2015 - 02:50 AM, said:
By accident yes. (Indeed, 75% of errors I make are 'cos I forget the additioanl 'var' on the end of funcs).
There is 'sound' for playing a fixed sound, 'soundvar' for sounds based on a variable, 'ifsound' to check for a fixed sound and .... (drum roll) ... no fricken 'ifsoundvar'

TTFN,
Jon
This post has been edited by The Mechanic: 03 October 2015 - 05:03 AM
#1701 Posted 03 October 2015 - 05:26 AM
This post has been edited by Mark.: 03 October 2015 - 05:57 AM
#1702 Posted 03 October 2015 - 07:29 AM
Mark., on 03 October 2015 - 05:26 AM, said:
Because I'm creating a re-usable library - think extended/improved version of sector effectors and such. The sound system is also a lot more than only stitching sounds together.
I agree if I were only working on a specific map then, yes, simply whip out CoolEdit Pro or Audacity and stitch the necessary sounds together, job done.
TTFN,
Jon
#1703 Posted 03 October 2015 - 07:44 AM

#1704 Posted 03 October 2015 - 02:17 PM
The Mechanic, on 03 October 2015 - 04:57 AM, said:
Yeah. It's okay to use ifsound to check if a sound should be played. But, for example, sounds are never played if you have sounds off in the menu, so anything that affects the game would break the sync in multiplayer.
#1705 Posted 05 October 2015 - 10:40 AM
I desperately need an explanation of what is going on with sprite indexes as seen in a CON file and actual sprite numbers I see in mapster and how they might change.
Example: using headspritesect + nextspritesect, during a particular EVENT_LOADACTOR, I'm iterating round some sprites in a sector. In my test map I get three sprites (223,220,208). Fine. I have this:
gamevar myvar -1 2 // Per actor
I use myvar to keep a reference to the next sprite - a linked list. So, 223 has myvar=220, 220 has myvar=208 and 208 has myvar=-1 cos its the last one.
When the game is running, my CON file access sprite 223 only to find it's myvar is now -1 !?!? Wtf !?!? . So, just for a test, I also wrote the myvar values into each sprite's xvel,yvel and zvel (just to be thorough) and used DNDEBUG to dump a map and see what the hell is going on. Well, the three sprites in the sector all have xvel,yvel and zvel as I'd expected - only the the sprite numbers are different - according to mapster, they are sprites 219, 216 and 204. In effect, they've been moved down by 4. I've noticed these sprites get set an "owner", e.g. sprite 219 has an owner of 223 and so forth.
Purely for test purposes I subtracted 4 from the myvar values. As expected I now accessed the correct sprite number - 219 instead or 223 - and (....drum roll...) the sodding value of myvar was still -1

I've clearly missed something fundamental - but what ? How _should_ I be keeping a reference to specific sprites ? Could something happen during the game that could cause sprite numbers to re-arrange yet again ? Or can I assume that prior to the first EVENT_GAME sprite data moves around but once the first EVENT_GAME occurs the sprite data finally stays put ?
TTFN,
Jon
#1706 Posted 05 October 2015 - 12:12 PM
Why are you doing the iteration in LOADACTOR?
What's your goal?
Did you remember to use s/getactorvar[actorid].myvar ?
If the sprites are being spawned at any point (beyond initial load) the IDs can definitely change. Nothing to do with CON, it's the engine itself.
#1707 Posted 05 October 2015 - 12:48 PM
Mblackwell, on 05 October 2015 - 12:12 PM, said:
Why are you doing the iteration in LOADACTOR?
What's your goal?
Did you remember to use s/getactorvar[actorid].myvar ?
If the sprites are being spawned at any point (beyond initial load) the IDs can definitely change. Nothing to do with CON, it's the engine itself.
I'm grouping sprites together during initialisation so I can subsequently manipulate them as group of sprites.
As an example, I've a custom "locator" sprite which get grouped together (via hitag) in a user defined order (lotag) in order to define a path, imagine the overhead of sorting that little lot on every game tic. Then there is grouping regular sprites - such as a platform made of regular sprites - which are linked together in a group and follow a path defined by those locators. Pretty much impossible if the sprite indexes keep moving around.
If I can't reliably identify the exact same sprite on different game tics then that pretty much destroys a lot of what I'm wanting to achieve

TTFN,
Jon
#1708 Posted 05 October 2015 - 04:23 PM
#1709 Posted 05 October 2015 - 07:08 PM
A couple of better bets might be:
1) Use custom statnums and headspritestat. (This is great for random stuff)
2) A better method still for LOCATOR type things would probably be to create arrays with offsets. To do it of course you'll need to figure out the max/how many points you want in each path. The hitag would be ordered rather than a random unique number. Each mylocator would simply have to insert its sprite id at position mylotag*MAXPOINTS+myhitag in the array. So for 30 separate paths with 30 different points you'd need an array size of 930 (actually you'd get 31 paths I think due to path 0 but I'm not going to do the math atm). Then individual actors just need to traverse their assigned set of mylocators.
#1710 Posted 06 October 2015 - 01:21 AM
Fox, on 05 October 2015 - 04:23 PM, said:
No. The hitag is used as the "channel" that marks an actor as part of that group. The idea was during initialisation this would be used to set up linked list pointers (implemented as per-actor gamevars). Where sorting was needed that was done via lotag. Advantages:
1) After initialisation, lotag and hitag are redundant
2) When I fire an activation (a jonz version at this point in time) I just scoot across the first sprites in the group and flag that they've been activated and need to do something when it is their turn.
3) When moving a group of sprites they absolutely have to move at exactly the same time and not wait for their respective EVENT_GAME calls else they will flicker. A linked list of exactly the ones to move is quick and simple.
All in all a brilliant plan - right up to the point where ID's change

The effects are totally configured via standard mapster, so primarily they need configuring via lotag/hitag, 'extra' if I need a bit more, and so on (I've a csutom mapster with a menu system which will simplify this setup, but the effects will always be configurable via standard mapster). Part of initialisation is to stash these values and if necessary reset them. With very few exceptions, I leave standard sprite array data well alone after initialisation.
Mblackwell, on 05 October 2015 - 07:08 PM, said:
Indeed. Other than borrowing a few flags in cstat (which has some debugging advantages) I'm avoiding reusing standard sprite variables.
Mblackwell, on 05 October 2015 - 07:08 PM, said:
1) Use custom statnums and headspritestat. (This is great for random stuff)
I didn't think I could use statnum (wiki page) as I infered it might change in, or influence, the game operation.
"Unassigned status numbers are reserved for future EDuke32 features. Please ask the developers to allocate an official user statnum range for CON-side features, should this be desired." You start the petition to allocate statnum > 1024 for user defined use whilst I print the campaign t-shirts and mugs

Mblackwell, on 05 October 2015 - 07:08 PM, said:
Do you mean that, using my previous example sprites {223,220,208}, their ID's may move but their relative ID's will always be the same e.g. {222,219,207}, or {23,20,08} etc ? Otherwise I don't see how an array will help.
Mblackwell, on 05 October 2015 - 07:08 PM, said:
But the ID changes and its been suggested this isn't just on completion of initialisation but also if during the game something is spawned.
Mblackwell, on 05 October 2015 - 07:08 PM, said:
Again, how do they find their associated locators as the ID's of these locators may change?
AH! (lightbulb finally flickers into life), maybe I've just seen where you were going. Assign each group a unique statnum value and use this as the linking mechanism e.g. sprites with statnum 1025 follow the path of locators statnum 1234. I'll take a peek in the code for the size of statnum - if I'm _real_ lucky I could simply use statnum = 1024 + original hitag value. No need for any extra tables at all. Mblackwell, I owe you one.

Right, off to re-write half me darn code

TTFN,
Jon
[Edit] Sprites that are blocking, hitable and have hitag (=>destructable) have their statnums set to 17 so above method for grouping needs to be to iterate all sprites with matching statnums AND all sprites with satnum 17 and matching hitag. Given I'm not interacting with enemies,players,weapons,projectiles and so forth- only inanimate objects - additional checking for statnum 17's is the only extra effort I need. I hope.
This post has been edited by The Mechanic: 06 October 2015 - 02:30 AM
#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

However it totally fails again if the sprite does not have a hitag

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

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