EDuke32 Scripting "CON coding help"
#1786 Posted 30 November 2015 - 08:08 AM
#1787 Posted 30 November 2015 - 09:06 AM
Trooper Dan, on 30 November 2015 - 08:08 AM, said:
Hmm ... ok, more detail.
I have a custom locator.
"Extra" is a number used to group them together, so I could have multiple groups (paths) defined
"Lotag" is their relative position within the group
"Hitag" is an activation channel (consistent with rest of library)
"Angle" specifies if initially enabled / disabled.
"Palette" has a special meaning, 0 = defineing a group of locators, 21 = grouping all sprites in a sector.
During EVENT_LOADACTOR extra, lotag and hitag are safely stored in some per-actor gamevars and then reset to zero so nothing funny happens. If locator had lotag of 0 and pal 0 it is head of a group and given statnum 'A', otherwise it is given statnum 'B'
Each locator has a number of gamevars, in particular psprite and nsprite which get set up to point to previous and next locators within the same group.
At some point, the groups need to be built. So, for path locators :
For each sprite with statnum B
Search sprites with statnum A with a matching "extra" so as to find the head of the group
Insert sprite into head sprite's linked list of locators in the appropriate relative position (based on "lotag").
This creates groups of paths that code-wise are easy and efficient to navigate both forwards and backwards, whilst the use of statnums keep the initialisation process efficient by avoiding iterating over every sprite in the map multiple times.
Special case is locator with palette 21. This says "group _every_ sprite in this sector together (linked list again) and associate it with a locator path (via 'extra'). The locator subsequently follows the path group, dragging with it all those sprites that had originally been in the same sector. Thus you create flying objects out of sprites.
For the mapper, they simply need to (1) define a locator path, lotag 0,1,2,3.... all with same 'extra' (2) in another sector draw whatever object they like out of sprites (3) stick a locator (pal21) in that sector and presto they have a flying object. Simple to set up - easier than setting up a subway!. Wouldn't dream of having a mapper type in sprite ID's !!!
Path locators can also used for elevators, making multi-floor elevators trivial for the mapper.
I can only link between locators using ID, ergo ID mustn't change. I *know* it doesn't change once you start getting EVENT_GAME so my prototype version did a special check in EVENT_GAME to see it this was the first such event and if so built the groups at that point.
Consider what would happen if in EVENT_LOADACTOR I tried to initialise a group - some sprites might not be initialised so (if my theory is correct) their ID's may subsequently change => disaster and it is in fact exactly what happened to me. Debugging CON code is not the easiest of things and it took some time for the penny to drop.
I'm now re-writing it all as a puka library so time to do it properly. Now that I've played around with what events fire when and yes, learnt a lot more about how the Eduke environment works, I *think* EVENT_ENTERLEVEL is where I should build the groups. But ever since the PITA I suffered when I first came across sprite ID's changing I've been paranoid about sprite ID's, hence questioning EVENT_ENTERLEVEL.
TTFN,
Jon
#1788 Posted 30 November 2015 - 10:52 AM
The Mechanic, on 30 November 2015 - 09:06 AM, said:
Search sprites with statnum A with a matching "extra" so as to find the head of the group
Insert sprite into head sprite's linked list of locators in the appropriate relative position (based on "lotag").
What statnums are you using? Some of them have hardcoding that could cause trouble. If you can do it safely, it is efficient. A somewhat less efficient but still manageable solution would be to use gamearrays to hold the IDs of the sprite constructs. Then you would only need to loop through (filled elements of) the arrays, not all the sprites in the map.
The Mechanic, on 30 November 2015 - 09:06 AM, said:
You lost me here. Why can you only link them using ID?
#1789 Posted 30 November 2015 - 01:33 PM
Trooper Dan, on 30 November 2015 - 10:52 AM, said:
This is still the area I'm mulling over. At the moment I had thought of using ang as something easy for the mapper to set initial enabled/disabled state, but it might better be used to specify an angle that the collection of sprites should rotate to, gradually rotating as it progresses locator-to-locator. The necessary angle could also be infered from the positions of the locators in the path, in fact that'll probably have to be the way it works since the locators can be moved so paths can dynamically change.
Whatever, a group of sprites are pulled along by a special locator (pal21) and hence the plan is they would rotate around that special locator.
Trooper Dan, on 30 November 2015 - 10:52 AM, said:
To date I've tried to minimise statnum usage.The only statnum I' relying on in-game is 333, which I use to mark activator targets. I'm using 334 as head locator statnum, 335 as general locator statnum but these are only required during initialisation, whereupon they change to 333 if they have "activation"-type functionality or 0.
I dont want to use gamearrays as that would limit the number of paths and/or locators in path - or be a very big array
In the prototype, I didn't use statnums but instead a sort of double linked list - it worked but was _way_ overcomplicated. The statnum method of initialisation is a good compromise of processing efficiency and ease of coding.
Trooper Dan, on 30 November 2015 - 10:52 AM, said:
Consider 4 locators in this order : 3, 10, 6, 20. They need to be given the following "psprite" and "nsprite" values
Sprite psprite nsprite
3 -1 10
6 10 20
10 3 6
20 6 -1
How else can, for example, sprite 10 record that it's preceeding locator is sprite 3 ?
TTFN,
Jon
#1790 Posted 30 November 2015 - 01:45 PM
The Mechanic, on 30 November 2015 - 01:33 PM, said:
3 -1 10
6 10 20
10 3 6
20 6 -1
How else can, for example, sprite 10 record that it's preceeding locator is sprite 3 ?
Sorry, I wasn't being clear. I was thinking about the original problem of having sprite ID change from what it says in the map file to what they are in-game. I don't see why that matters. You still have the correct order of the locators due to their tags. Then, assuming that "psprite" and "nsprite" are your own vars, you just use those IDs and put them in the vars. Also, I know you said you weren't using arrays, but that would be another possible solution here. If a locator corresponds to element i in the locator array (which is an array of sprite IDs), then i-1 would be the ID of the one before i, and i+1 would be the one after i.
#1791 Posted 30 November 2015 - 03:23 PM
Trooper Dan, on 30 November 2015 - 01:45 PM, said:
All depends when you initialise this table. Lets say in EVENT_LOADACTOR you detect a locator with lotag 0, palette 0 i.e. the head locator of a path. At this point you could then iterate through every sprite in the game looking for associated locators - issue is that (if my theory is correct) the ID's of the locators may change before the game starts, I suspect depending upon whether their own EVENT_LOADACTOR has occured or not.
Anyhow, I'm 90% sure that the situation is this:
* A sprite's ID becomes fixed immmediately prior to it's associated EVENT_LOADACTOR ...
* ... in which case the later EVENT_ENTERLEVEL all sprites have been initialised, their ID's will now be fixed so I can quit worrying, waffling on and safely build my linked lists.
TTFN,
Jon
#1792 Posted 30 November 2015 - 03:44 PM
#1793 Posted 30 November 2015 - 05:13 PM
Mblackwell, on 30 November 2015 - 03:44 PM, said:
The issue was with sprite ID's and when they become stable.
I agree a 2D array could be used, with dimensions (max num paths) * (max num locators in each path), it's a totally valid way to do it, if you know max number of paths and locators in advance.
I have groups of sprites. I have groups of locators. I have groups of other types of effects too. Instead of creating individual fixed size arrays for each of them and choose some arbitary fixed sizes, I've chosen to use linked lists; only two per-actor gamevars required, they get used by whatever I'm trying to group, nice and consistent, and things that aren't related to groups can get to re-use those gamevars for whatever it is they are doing. Flexible too; take the list of locators, the lotags dont have to be 0, 1, 2, 3 etc, more likely I'd use 0, 10, 20, 30 as then if I feel I need to insert an "inbetween" locator to tweak the trajectory I insert a locator I can do it without having to renumber the ones that follow.
No, on the whole I'm happy with the linked list approach, my problem was worrying over sprite ID's which would be a problem regardless of whether I use arrays or linked lists.
If I had a specific map, or set of maps, that I were targetting then I might reconsider arrays as I'd then know exactly what size they'd need to be and it could well be more efficient than lumbering every sprite in a map with two additional vars. But for a general purpose lib, far better to have no arbitary limits.
Anyhow, as nobody has said that initialising my groups in EVENT_ENTERLEVEL is wrong, which was the original question, I'm gonna assume it _is_ the right place.
TTFN,
Jon
#1794 Posted 30 November 2015 - 08:27 PM
The Mechanic, on 30 November 2015 - 05:13 PM, said:
Let us know how that turns out. I honestly don't know the answer. Prior to this thread, I would have said that using EVENT_LOADACTOR is completely safe for this kind of thing. I use it for tons of stuff, myself. For example, in WGR2 I have various torches and other sprites spawn dynamic lights of the appropriate color which are made to flicker, and those lights have the sprite IDs of the sprites which spawned them. Never had a problem with it. However, when I looked at my waypoint initialization code just now, I noticed I have it happening after map load, in the player actor when player_par == 1. Since I generally don't like doing things like that in the player actor, that strongly suggests that there was a problem when I tried it at map load. Sorry to say, my memory is poor enough and I coded it long enough ago that I just don't remember.
#1795 Posted 21 December 2015 - 01:55 PM
Is this possible at all?
I've tried getplayer[THISACTOR].extra adding to that and then setting it, but even that wouldn't let me go over 100 health.
This post has been edited by Drek: 21 December 2015 - 01:57 PM
#1796 Posted 21 December 2015 - 02:29 PM
getplayer[THISACTOR].i temp setactor[temp].extra 200
Works for me.
Also, you can disable a sprite's hardcoded Polymer lights with SFLAG_NOLIGHT.
#1797 Posted 21 December 2015 - 02:59 PM
Drek, on 21 December 2015 - 01:55 PM, said:
You sure you wasn't using God Mode?
#1798 Posted 21 December 2015 - 03:19 PM
Hendricks266, on 21 December 2015 - 02:29 PM, said:
getplayer[THISACTOR].i temp setactor[temp].extra 200
Works for me.
Also, you can disable a sprite's hardcoded Polymer lights with SFLAG_NOLIGHT.
Thanks, I guess dealing with the setplayer command instead of the actor directly was the issue.
Fox, on 21 December 2015 - 02:59 PM, said:
Yeah, I did this...
getplayer[THISACTOR].extra temp addvar temp 2 setplayer[THISACTOR].extra temp
I knew the code would run because the pickup would disappear and the sound would play, but no health would be added over 100.
This post has been edited by Drek: 21 December 2015 - 03:19 PM
#1800 Posted 31 December 2015 - 03:23 AM
Setting the sprite's statnum to 1024 certainly does the trick - only it automatically destroys EVERY sprite in the same sector in one go and if one of those other sprites happens to be an enemy then it hangs Eduke !!
OK, in this instance setting the decorative sprite's cstat to 32768 is a viable alternative, but what is it about writing to statnum directly and if I did want to destroy an enemy how would I do that (assuming the enemy I want rid of is not THISACTOR so can't use killit) ?
TTFN,
Jon
#1801 Posted 31 December 2015 - 05:18 AM
#1802 Posted 31 December 2015 - 07:16 AM
edit; foxs answer was on the next page I didn't get to read... opps
This post has been edited by Drek: 31 December 2015 - 07:17 AM
#1803 Posted 31 December 2015 - 09:19 AM
Fox, on 31 December 2015 - 05:18 AM, said:
This doesn't really delete sprites, for example the Box (spritenum 951) vanishes but if an RPG subsequently lands nearby it still catches fire.
Works fine for enemies though, provided you manually adjust the kill count with addkills 1.
TTFN,
Jon
#1804 Posted 31 December 2015 - 10:08 AM
#1805 Posted 31 December 2015 - 11:39 AM
Trooper Dan, on 31 December 2015 - 10:08 AM, said:
Ah-ha ... I have a number of per-sprite vars which are actually only used by a few non-decorative sprites, so I could changespritestat 1, set one of these now spare vars to flag as "delete me" which I can then detect in EVENT_GAME. Cheers.
TTFN,
Jon
#1806 Posted 03 January 2016 - 11:16 AM
#1807 Posted 03 January 2016 - 12:17 PM
Trooper Dan, on 03 January 2016 - 11:16 AM, said:
'Course, we 'ad it 'ard, we used to live in't shoe box in middle of t'road. Kids these days don't know they're born.
One debug thing I'd really like to see is being able to output text in addlogvar; I'm using temp1, temp2, temp3 ... etc shared between loads of functions, would be nice if I could have:
addlogvar temp1 spriteId
with text "spriteId" written to logfile instead of text "temp1". When trying to debug something with 3 or 4 "temp" vars dumped out it can get a trifle confusing.
TTFN,
Jon
#1808 Posted 03 January 2016 - 12:34 PM
The first is within actual CON functions as it'd be nice to detect if user could be alerted if they are using an incompatible version. For example:
Quote
r5492 | hendricks266 | 2015-12-26 07:41:59 -0800 (Sat, 26 Dec 2015) | 3 lines
Add new spriteflag SFLAG_GREENSLIMEFOOD = 8388608, which controls whether GREENSLIME will eat a given actor.
The flag is automatically set on LIZTROOP, LIZMAN, PIGCOP, and NEWBEAST, .....
Excellent ! Now NEWBEASTHANGING can be made edible like it should have been in the first place. But if I make a map that relies on this feature then it'd be nice to find some way of warning the player e.g. if old version of eduke then automatically open a door sector which exposes wall with writing on that tells them they have the wrong version.
The other version detection that'd be nice is to only include a CON file if version >= some number is running as that'd allow libraries to be able to utilise newer features whilst remaining backwards compatible as it were.
TTFN,
Jon
#1809 Posted 03 January 2016 - 01:29 PM
You could always use EVENT_INIT and echo a quote with a required version string. However if it's something that will error out on older versions then I have no idea.
#1810 Posted 03 January 2016 - 04:47 PM
addvar sprite[THISACTOR].z 1024
A great deal of writing CON code involves getting struct members into variables and then manipulating those variables before putting them back into the structs. It makes for a lot of typing and it reduces readability.
#1811 Posted 04 January 2016 - 01:58 AM
Mblackwell, on 03 January 2016 - 01:29 PM, said:
Kinda what I wanted to
Trooper Dan, on 03 January 2016 - 04:47 PM, said:
addvar sprite[THISACTOR].z 1024
I could hazard a guess (and only a guess). Firstly it is an example of a read-modify-write operation of which I can't think of any others, everything seems to be a read or a modify or a write.
Secondly I suspect the original code may not be that well structured, why else would there be a need to use seperate "addvar" and "addvarvar" for example ?
But maybe something has changed - I noticed recently (r5499) that "set" can now be used to replace setvarvar, if it replaces setvar as well then excellent
Trooper Dan, on 03 January 2016 - 04:47 PM, said:
Totally agree. It would also save a few temp vars for me as I often find I end up loading struct members into temp vars at start of a function as they get used in multiple paths of the code.
TTFN,
Jon
#1812 Posted 04 January 2016 - 02:24 AM
Trooper Dan, on 03 January 2016 - 04:47 PM, said:
addvar sprite[THISACTOR].z 1024
A great deal of writing CON code involves getting struct members into variables and then manipulating those variables before putting them back into the structs. It makes for a lot of typing and it reduces readability.
Because it would be better to use Lua instead of rewriting the entire CON language to become more useful.
This post has been edited by Fox: 04 January 2016 - 02:24 AM
#1813 Posted 04 January 2016 - 08:50 PM
Trooper Dan, on 03 January 2016 - 04:47 PM, said:
addvar sprite[THISACTOR].z 1024
It has to do with how we represent parameters in bytecode when we parse the CONs. We no longer think it would be prohibitively difficult, but instead a matter subject to cost/benefit analysis on our development time--something which is starting to tilt toward benefit thanks to the Bombshell prequel!
The Mechanic, on 04 January 2016 - 01:58 AM, said:
Yes!
#1814 Posted 04 January 2016 - 09:23 PM
The Mechanic, on 04 January 2016 - 01:58 AM, said:
Check out the list in the latest gamedef.c under "const tokenmap_t altkeyw"
#1815 Posted 09 January 2016 - 10:29 PM
Like when you shoot a mob that moves or you don't perfectly point at it, you will still hit it with your weapon.

Help
Duke4.net
DNF #1
Duke 3D #1


