Duke4.net Forums: EDuke32 Scripting - Duke4.net Forums

Jump to content

  • 124 Pages +
  • « First
  • 120
  • 121
  • 122
  • 123
  • 124
  • You cannot start a new topic
  • You cannot reply to this topic

EDuke32 Scripting  "CON coding help"

User is offline   eniojr 

#3631

Quote

AWOL project has ladders. You might try digging around in the cons for reference. Its been a long time since I looked but I think it wasn't spread out all over.

Thanks a lot! First I'll finish with Dukeplus. If I have no luck, I'll try AWOL.
0

User is online   Danukem 

  • Duke Plus Developer

#3632

View PostMark, on 14 December 2024 - 07:01 PM, said:

AWOL project has ladders. You might try digging around in the cons for reference. Its been a long time since I looked but I think it wasn't spread out all over.


Remember back in February when I refactored and simplified the DP ladder code for your mod? Good times. :lol:
0

User is offline   Reaper_Man 

  • Once and Future King

#3633

View PostDanukem, on 14 December 2024 - 12:15 PM, said:

EVENT_GAME still has its uses because sometimes you need the context of the actor to do things, such as killit. There are also problems with certain things such as spawning if they are done from the world events. What I do is have the default case of my EVENT_GAME switch set the sprite to not process the event any more by setting the no events flag. What that means is, any sprite that doesn't have specific code for it in the event will only go through the event one time.

EDIT: I've never done it before but I wonder if you could safely delete a sprite from within a WORLD event with changesrpitestat SPRITENUMBER 1024

EDIT2: Not sure about that, and apparently it isn't what the CON command does

 vInstruction(CON_KILLIT):
                insptr++;
                vm.flags |= VM_KILL;
                return;


The flag for killit seems to be listed here at the end: https://wiki.eduke32.com/wiki/Htflags as SFLAG_QUEUEDFORDELETE?
But I think the flag listed in the wiki is for the sprite deletion queue which is different (the queue for decals). So I'm still not sure.


So the vm.flags property is different than the htflags and friends we have exposed to CON. We don't have access to it. It also doesn't really get used much.

To mimic killit functionality, you can set the sprite statnum to STAT_MISC and set the .xrepeat to 0. This is also great because it works on non-actor sprites, which mostly comes in handy if you are using custom statnums to run code on sprites but you don't want them to be full-blown actors. We'll come back to that in a sec.

Anyway, any sprite with the VM_KILL flag runs VM_DeleteSprite(), which runs A_DeleteSprite(), which is down in the BUILD part of the game engine and actually deletes the sprite. This is also where EVENT_KILLIT happens. I'm pretty sure there you can catch the sprite's statnum and xrepeat to verify the change.

More importantly, internally hardcoded actors don't use VM_KILL at all. There is no internal "killit". For example, all of the internally flagged enemies run this code to delete themselves if they are tagged on a higher difficulty or monsters are turned off:

            if ((pSprite->lotag > ud.player_skill) || ud.monsters_off == 1)
            {
                pSprite->xrepeat=pSprite->yrepeat=0;
                changespritestat(newSprite, STAT_MISC);
                goto SPAWN_END;
            }


That being said, you're right that there are a few things that you need to "run as the actor" to work properly. ifcansee and ifpdistl are the 2 I've run into most recently (and for Reasons, I couldn't use canseespr and regular dist). So there are times where EVENT_GAME is the right tool for the job. But depending on what stuff you're doing, you may have less overhead without a loss of functionality by running it in EVENT_WORLD instead.

Lastly, another thing you can do if you really need to "run code as the actor" is to simply... become the actor, as far as the script is concerned. This is what the userdef property vm_sprite is used for. It doesn't just turn THISACTOR into a different sprite, you literally begin running code as that sprite. This is how we use custom statnums.

Basically, a sprite with the statnum STAT_ACTOR is, in literal terms, what lets a sprite be a defined actor and run code from actor/useractor blocks in a CON script. But it also does a lot of other stuff internally - physics, running game events, so on - so if you need something (like say an effect particle) to run some code but don't need the overhead of it being a whole actor, you can use a custom statnum. This is really cool because you can do stuff like this (simplified for this example):


/*
// Handle game system state machines
*/

appendevent EVENT_WORLD
{
    // Process AI Director
    for WORLDI sprofstat STAT_AIDIRECTOR
    {
        setu .vm_sprite WORLDI  // Become the sprite we are iterating on
        setu .vm_player myconnectindex  // Update which sprite the Player is

        ife GM_ACTIVE TRUE
            state ai_director
    }
endevent


/*
// AI Director state machine
*/

defstate ai_director
{
    [ an actual ton of code ]
}
ends


/*
// Init system effectors
*/

appendevent EVENT_ENTERLEVEL
{
    for ACTORI allsprites
    {
        // Init AI Director
        ife sprite[ACTORI].picnum AI_DIRECTOR
            seta[ACTORI].statnum STAT_AIDIRECTOR
    }
}
endevent


So what we're doing here is setting the sprite AI_DIRECTOR to the statnum STAT_AIDIRECTOR when the map loads. Then, every gametic in EVENT_WORLD, it does a sprofstat loop for all sprites with statnum STAT_AIDIRECTOR, and then steps into that sprite and runs code as that sprite. In other words, we're running code like we're an actor without being an actor.

This is a poor example of how to use it but it's what I have open right now. Instead imagine doing this for things like particle visual effects, or non-actor sprites that need to run a little bit of code but don't need to be full-on actors. We have something like 40 custom stats in AWOL because basically everything that isn't an enemy but runs code in some way is a custom statnum. Enemy corpses are a custom statnum, because that way you can stop them from being actors (which again comes with a ton of overhead) while also checking for nearby explosions to gib them.

I have to credit Mblackwell for turning me on to this, a while ago he was like "hey you should look at vm_sprite". EVENT_WORLD and custom statnums is this insanely powerful tool, it seems like overkill but it lets you run tons of code on non-actors and shed an enormous amount of overhead from the performance budget.
2

User is online   Danukem 

  • Duke Plus Developer

#3634

Yeah good stuff. I have been using custom stats for a while now and do have such loops in world events already. I didn't know that about STAT_MISC combined with xrepeat 0 though so that's handy for deleting things "externally". I started using custom statnums heavily in 2020 to improve performance because I needed to loop through certain sprites that I was using as navigation nodes for actors and it helped for that. Since then it has become a "go to move" for a lot of effector type sprites.

Also that's good info about .vm_sprite and .vm_player -- I will probably use that at some point to get around the limitations of not having the individual context in world events
0

User is offline   Reaper_Man 

  • Once and Future King

#3635

Something else you can also do is store the current sprite's ID in a global gamevar before running remote code on another sprite, and then resume "being" our current sprite when we're done. So like:

    // Save ourself
    set HOST_ID THISACTOR
    for ACTORI sprofstat STAT_SOMETHING
    {
        setu .vm_sprite ACTORI
        [ execute remote code ]
    }

    // Return to ourself
    setu .vm_sprite HOST_ID


Or you can imagine using this with like .htmovflags to run remote code on a sprite we bump into for example.
0

User is offline   VGames 

  • Extra Crispy

#3636

Do you have to use a for loop in the EVENT_WORLD to increase performance or can a switch be used instead to make it easier to have multiple cases for actors that need to do the same thing? If I used a for loop I’d have a ton of ifactor statements.

Also wouldn’t adding that no events sprite stat to the default case in a switch while in EVENT_GAME like Dan said take care of the actors that aren’t called in EVENT_GAME? I didn’t see a response to that.

The custom stats is something I definitely need to look into. My mod is heavy in gibs and debris and effects. Anything to further optimize frame rate is a must. Thanks for pointing that stuff out.
0

User is offline   Reaper_Man 

  • Once and Future King

#3637

There's nothing wrong with having lots of ifactor calls, or for that matter using a switch statement. "ifactor" (and the equivalent I mentioned earlier of checking .picnum) and switch statements in general are very cheap, so don't worry about that sort of stuff.

The reason you use a for loop in the case of custom statnums is so that you can search through a smaller pool of sprites. Rather than searching through allsprites, or even STAT_ACTOR. That is where and why you're getting the performance savings.

In the case of custom debris and effects, again what we did in AWOL was have a defined statnum for each particle type, and then each of those statnums would be looped through in EVENT_WORLD and the code for that particle type would be run on those sprites. Here's an excerpt from awol_vfx.con:

// Perform particle logic
appendevent EVENT_WORLD
{
    for PARTICLE_I sprofstat STAT_EMBER
    {
        setu .vm_sprite PARTICLE_I // set our "THISACTOR" to the current id
        setu .vm_player myconnectindex // set our player to our currently connected player

        state particle_ember
        state particle_deleteme
    }

    for PARTICLE_I sprofstat STAT_SMALLFIRE
    {
        setu .vm_sprite PARTICLE_I
        setu .vm_player myconnectindex

        state particle_smallfire
        state particle_deleteme
    }


This continues on for a while for all of our particle types. The state particle_deleteme is where we do checks if we need to delete the particle early - too far away, not visible, and so on - and it just does the .xrepeat 0 / .statnum STAT_MISC thing mentioned before to "mark for deletion". Also I'm not sure if I was clear about that before. Setting the statnum to STAT_MISC stops the sprite from executing code (as an actor, at least), and setting .xrepeat to 0 is most explicitly what makes the sprite get deleted. At the end of the gametic, after CON scripting has completed, the engine looks for anything with an invalid sprite size (IE .xrepeat 0) and deletes it with A_DeleteSprite() down in the BUILD part of the engine.

Anyway. I'm not sure what use case you had in mind for a switch statement here. If you want to post your code we can take a look. But there's nothing inherently wrong with using a switch statement in this sort of context. The for loop is what says "run this code on every sprite with statnum STAT_PARTICLE", for example. If you had all of your particle types sharing the same statnum, and then wanted to run separate code on them based on their picnum, you could use a switch like that maybe? To adapt the previous code to this method:

appendevent EVENT_WORLD
{
    for PARTICLE_I sprofstat STAT_PARTICLE
    {
        setu .vm_sprite PARTICLE_I // set our "THISACTOR" to the current id
        setu .vm_player myconnectindex // set our player to our currently connected player

        // Remember, we are now running as the sprite PARTICLE_I so we need to check our own picnum instead of "sprite[PARTICLE_I].picnum"
        switch sprite[].picnum
        {
            case SOME_PARTICLE
                state particle_ember
                break

            case OTHER_PARTICLE
                state particle_smallfire
                break

            default
                [ some failsafe code ]
                break
        }
        endswitch

        state particle_deleteme
    }
}
endevent


I don't see why this wouldn't work in theory, but personally I would just use a separate statnum for each particle type. That would be more robust, easier to read, and statnums are free so there's effectively no limitation to them.
0

User is offline   VGames 

  • Extra Crispy

#3638

Yeah, this is more or less what I was getting at. This looks like it would work for me. I don't like having a bunch of ifactor statements. A switch is cleaner, and you can have lots of actors doing the same thing without individual if statements for each one.

I messed around with this already and there's a lot of drawbacks that I'm already seeing. Like with corpses, I gave them a custom stat and I have the world event call on statements to make them react to getting hit and what not. But they no longer react to explosion damage correctly, and they don't fall to the floor as they should. If the ground moves, they just hover. Same goes for gibs or debris actors that are given their own custom stats. May there be too many limits when using the WORLD event? Even with these issues aside I'm not seeing a big performance increase and i've got gibs, debris, and corpses using custom stats.
0

User is online   Danukem 

  • Duke Plus Developer

#3639

Performance in most mods is a non-issue most of the time. So unless you create a situation where framerate is dropping very significantly (ideally below 40) due in large part to code, it's pretty difficult to assess performance gains from code optimization.
0

User is offline   VGames 

  • Extra Crispy

#3640

Understood. My main issue that I've seen so far is lots of gibs or debris being created at one time. I guess there's no sort of coding cleanup or optimization that can fix this since this seems to be more or less an eduke limitation. I have seen some performance increase by using that no events sprite flag you mentioned in the default case for EVENT_GAME. So, thanks for that.
0

User is offline   Reaper_Man 

  • Once and Future King

#3641

Right, that's the performance lottery. "Is it more expensive to try and be smart about it, than just run the bad code?" I agree that you don't NEED to worry about these sort of things, particularly from a performance perspective, if you're making a small mod. I think there's benefits to doing these things if you're making a whole Total Conversion. And I think it's always good to do best practices, no matter how big or small the project is.

You can make your corpses interact with the physics engine still by forcing them to move. The problem is that if you set them to a new statnum, they stop being actors and therefore stop doing movement stuff. Here's how we handle it in AWOL:

// Process logic for corpses without making them actors
appendevent EVENT_WORLD
{
    for ACTORI sprofstat STAT_CORPSE
    {
        setu .vm_sprite ACTORI
        setu .vm_player myconnectindex

        fall

        action 0
        move 0

        state enemy_elite_display  // Ignore for this example, this handles their palette and custom sprite display
    }
}
endevent


So because they're now a non-actor statnum, you have to tell them to do the same sort of actor things like movement, have a new "ifhitweapon" block, and so on.
0

User is offline   VGames 

  • Extra Crispy

#3642

Yeah I didn’t think about the move 0 command. I’ll keep at it and see if it helps the performance.

What would be a good way to go about keeping lots of gibs and debris from spawning at the same time? I’ve got code that checks current frame rates before spawning random amounts of gibs and debris but when lots of stuff is spawned at once this doesn't help as much.
0

User is offline   Reaper_Man 

  • Once and Future King

#3643

How many is "lots" exactly? And do you know why they're causing such a performance hit? IIRC you should be able to have a couple thousand sprites being drawn without any real performance issues. Now if all of them are actors doing actor-y things, that's going to be a different story.

How are you checking the framerate exactly, and how do you use that to determine spawns?
0

User is online   Danukem 

  • Duke Plus Developer

#3644

His wording strongly suggests he gets lag spikes at the time of spawn; I don't think he's saying that the framerate stays low for long after they spawn. Spawning is one of the more expensive things you can do, and could be made much more expensive if he has a lot of code they are all running in EVENT_EGS or EVENT_SPAWN. I also wonder if you can get lag at spawn from having a lot of per-actor gamevars.

With jibs and debris I recommend going for more quality over quantity. For example, if you have the jib sprite include blood flying off of it on its animation, then that's a tremendous savings versus spawning little blood sprites from it as a trail. But if you really think you need a lot of those sprites, you can spread out the spawn over several tics -- the jibbing actor doesn't have to delerte immediately, it could turn invisible and spawn say 25% of them per tic over 4 tics and then delete.
1

User is offline   VGames 

  • Extra Crispy

#3645

Yeah the issue is lag spikes at the spawn point of the gibs and debris. The mod runs great after the initial spawns. And yes the jibs and debris are all actors that do actor stuff and yes they got code in EVENT_SPAWN and EVENT_EGS so everything you’re saying makes perfect sense why they have lag spikes when lots of them are spawned. And I when I say lots I mean like 15+ enemies exploding at one time.
I tried having the enemies spawn a separate actor that calls on statements that spawn the gibs so that I could have them do exactly what you said. Spawn gibs over 4 or 5 tics and then delete itself but no matter what I do they never run through the entire list of gibs that are to be spawned. Usually the gibs that are to be spawned at like 4 or 5 tics don’t spawn at all no matter how long I have the gib spawning actor wait to kill itself. And in general the amount of gibs that are spawned with this method are lackluster. However I do have gibs that create trails of blood and so that’s something I can look into for sure. It’s not really noticeable anyways so it’s not needed. I understand quality over quantity but in this case I really want as big of a quantity as possible. I don’t think I’ve seen this many gibs and debris in a duke mod before and what I’ve got going I’m very happy about. Thanks for the tips.
0

User is offline   Reaper_Man 

  • Once and Future King

#3646

For testing purposes, can you instead spawn a non-actor sprite or something else that doesn't run code and see if you still get the on-spawn hitching? Or isolate the spawning code into a clean project and test just that. Basically try to rule out whether the problem is spawning stuff in general (as Dan said, spawning is expensive), or if the problem is within the context of the rest of the mod and other code running at-spawn.

Another way you can get around the "spawning is expensive" problem by recycling debris/gibs. This is a concept known as object pooling. Say you have a pool of 100 persistent debris objects, another pool for dibs, and so on. When it comes time to spawn one, you would check how many objects are in your pool. If you have room for more (IE less than 100) you spawn in a new one like normal. But if you have a full pool of objects, rather than spawning a new one, you'd find the oldest debris object and recycle it. Move it into position, re-initialize its animation, movement, etc. just like you would for a new one. This way you skip all of the on-spawn overhead, and you have a finite amount of those objects.

As far as it not spawning enough, add some logging to output something every time it's supposed to be spawning something. It's impossible to say what the issue is there without more context of the entire project or what else is going on.
0

User is offline   eniojr 

#3647

I have a big announcement to make: I managed to add the ladder effect, as well as the jump pad! And I did it using Dukeplus codes! The ladder effect is working perfectly, as is the jump pad effect, and neither interferes with the other. I can now add both effects to my maps, because they are ready to use. Since the file has more than 750 lines, I will attach it to the post, so as not to clutter the post with codes.

What happened is that I ended up doing a deep investigation of all the variables related to the ladder code, and in one of the Dukeplus files I ended up finding all the codes that were still missing, so I put them inside a state that I made myself (state ladderinteraction) and put the call to this state inside onevent EVENT_GAME, at the end of the block. I also realized that what was missing for the player to be able to interact with the ladder was "getactor[THISACTOR].picnum picnum", which I put right at the beginning of the EVENT_GAME block.

But then I realized that when I interacted with JUMPAD first, it kept preventing me from interacting with the ladder later. So I had to make some adjustments to the JUMPAD timers, and now it no longer interferes with the interaction with the ladder.

Oh, and I found these missing codes for interacting with the ladder through manual research on my own, without using the AI ​​assistant.

Attached File(s)



This post has been edited by eniojr: 16 December 2024 - 08:15 AM

0

User is offline   VGames 

  • Extra Crispy

#3648

View PostReaper_Man, on 16 December 2024 - 07:53 AM, said:

For testing purposes, can you instead spawn a non-actor sprite or something else that doesn't run code and see if you still get the on-spawn hitching? Or isolate the spawning code into a clean project and test just that. Basically try to rule out whether the problem is spawning stuff in general (as Dan said, spawning is expensive), or if the problem is within the context of the rest of the mod and other code running at-spawn.

Another way you can get around the "spawning is expensive" problem by recycling debris/gibs. This is a concept known as object pooling. Say you have a pool of 100 persistent debris objects, another pool for dibs, and so on. When it comes time to spawn one, you would check how many objects are in your pool. If you have room for more (IE less than 100) you spawn in a new one like normal. But if you have a full pool of objects, rather than spawning a new one, you'd find the oldest debris object and recycle it. Move it into position, re-initialize its animation, movement, etc. just like you would for a new one. This way you skip all of the on-spawn overhead, and you have a finite amount of those objects.

As far as it not spawning enough, add some logging to output something every time it's supposed to be spawning something. It's impossible to say what the issue is there without more context of the entire project or what else is going on.


That pool idea sounds like something that I can work towards. Only allow so many to spawn within a given pool allowance. Thanks for the great tips guys. I’ll try and put this to use and work at it some more.
0

User is online   Danukem 

  • Duke Plus Developer

#3649

View PostVGames, on 16 December 2024 - 06:25 AM, said:

no matter what I do they never run through the entire list of gibs that are to be spawned. Usually the gibs that are to be spawned at like 4 or 5 tics don’t spawn at all no matter how long I have the gib spawning actor wait to kill itself. And in general the amount of gibs that are spawned with this method are lackluster.


So in other words your code doesn't work as intended and you don't know why. You don't seem to know how to debug it.
0

User is offline   eniojr 

#3650

One of the parts I was having the most difficulty with was the EVENT_GAME onevent. At first I still didn't understand that it was necessary to have an associated switch, as well as a specific code to activate the effect inside the case. Here is my EVENT_GAME onevent:


onevent EVENT_GAME
{
    getactor[THISACTOR].picnum picnum

    switch picnum
    {
        case LADDER
        {
            ifvare monstflags 1
            {
                ifvare monstatus 0
                {
                    setvar monstatus 1
                    setvar temp 0
                    whilevarn temp 16384
                    {
                        getactor[temp].picnum picnum
                        ifvare picnum LADDER ifvarvarn temp THISACTOR
                        {
                            getactorvar[temp].monstflags tempb
                            ifvare tempb 1
                            {
                                getactorvar[temp].hitag tempc
                                ifvarvare hitag tempc
                                {
                                    setvarvar myspawner temp
                                    setvar monstatus 1
                                    setvar temp 16383

                                    getactor[THISACTOR].z z
                                    getactor[myspawner].z mz
                                    ifvarvarg z mz 
                                    {
                                        setvar mtype 1
                                        setvarvar topladder mz
                                    }
                                }
                            }
                        }
                        addvar temp 1
                    }
                }

                ifvare mtype 1 ifvare dodge 0
                {
                    getplayer[THISACTOR].posz mz
                    ifp pducking subvar mz 4096
                    getactor[THISACTOR].z z
                    addvar z 1024

                    ifvarvarg mz topladder ifvarvarl mz z
                    {
                        getplayer[THISACTOR].i target
                        ldist xydist THISACTOR target

                        ifangdiffl 384 ifvarl xydist 384
                        {
                            ifvare onladder 0
                            {
                                getplayer[THISACTOR].posx lastladderx
                                getplayer[THISACTOR].posy lastladdery
                            }
                            setvar onladder 3

                            ifvarn lotag 0 setvarvar laddersound lotag else setvar laddersound -1
                        }
                    }
                }   
            }
            break
        }
		case APLAYER 
        {
        ifvarg onladder 0 state ladderinteraction
        break
        }
    }
    endswitch
}
endevent



And here were the missing codes for the effect to work:

state ladderinteraction
{
    // Lógica de interação com a escada
    ifvarg fpress 0 subvar fpress 1
    ifvarg bpress 0 subvar bpress 1
    ifvarl onladder 0 addvar onladder 1

    ifvarg onladder 0 state laddercode

    ifp ponground setvar nofalldamage 0
    ifvarn nofalldamage 0 setplayer[THISACTOR].falling_counter 0

    ifvarg bhold 7 { setvar btap 0 setvar bhold 0 }
    ifvarg fhold 7 { setvar ftap 0 setvar fhold 0 }
    ifvarg lhold 7 { setvar ltap 0 setvar lhold 0 }
    ifvarg rhold 7 { setvar rtap 0 setvar rhold 0 }

    ifvarvarn timer fpresstime setvar fhold 0
    ifvarvarn timer bpresstime setvar bhold 0

    setvarvar tempb timer
    subvarvar tempb fpresstime
    ifvarg tempb 4 setvar ftap 0

    setvarvar tempb timer
    subvarvar tempb bpresstime
    ifvarg tempb 4 setvar btap 0

    setvarvar tempb timer
    subvarvar tempb lpresstime
    ifvarg tempb 4 setvar ltap 0

    setvarvar tempb timer
    subvarvar tempb rpresstime
    ifvarg tempb 4 setvar rtap 0
}
ends


These codes that I put in the "state ladderinteraction" were inside "onevent EVENT_GAME", but were outside the "case LADDER". I had to do this, put them inside a separate state, otherwise I wouldn't have been able to make it work. And the effect is working just like in the Dukeplus mod. My modification now uses 3 specific sounds for when the player climbs the ladder, which gives a bit more realism.

It's true that my codes don't have a more simplified format or shortcuts yet, but at the moment I'm more concerned with knowing the basics of how to add new effects and other things to the game. As I learn more about the CON language and become more familiar with it, I'll feel more confident in dealing with the game's performance.

This post has been edited by eniojr: 16 December 2024 - 02:28 PM

0

User is online   Danukem 

  • Duke Plus Developer

#3651

Congratulations, you found the last block of missing code from DukePlus relating to the ladder and pasted it in. I'm not sure what you "learned" about CON from this, other than being more careful to copy all of the relevant code before pasting.
0

User is online   Danukem 

  • Duke Plus Developer

#3652

Why do we have such incredibly low standards in our community for people trying to code? Imagine if someone was posting about learning to map and all they did was talk about how they had a hard time copying and pasting parts of different released maps together. They would be a laughing stock. And yet I have seen essentially the same thing around here but with code many times.
1

User is offline   Reaper_Man 

  • Once and Future King

#3653

Because the language is opaque and questionably documented, and the plaintext distribution of any project's scripts means that every mod and Total Conversion is effectively open source.

Sure, everyone has to start somewhere, and CON scripting being someone's entry point into the world of programming is always an interesting choice. But for every Dan Douglas who brings in fresh and genuine creativity, you have a dozen people who think "it works and that's all I care about" and just swim in the wake of those more motivated. Why bother learning to be better at something when one of a handful of people will just do it for you if you pester them enough?

Same as it ever was, though. There's always been a culture of reliance, rather than learning. Again, most people don't actually care to learn, they want it to "just work". Programming has always been the least-represented discipline in "the community" even in the 1.5 days. For whatever it's worth, in my observation, the hangers-on will eventually get bored and move on and never finish their projects because - it turns out - making a whole game is a lot of work.

Why "the community" is small and stagnant is a not-so-separate topic, but there's clearly no lack of broad interest in working with old game engines. Why new people gravitate towards other game communities rather than this one should be a source of introspection, but experience tells me it won't be.
0

User is offline   VGames 

  • Extra Crispy

#3654

View PostDanukem, on 16 December 2024 - 12:16 PM, said:

So in other words your code doesn't work as intended and you don't know why. You don't seem to know how to debug it.


Don’t jump to conclusions. I never said anything like that. I was merely telling you some drawbacks that I’ve seen. I’ve cleaned up the code even further and now have about a 25% increase in performance with noticeable reductions in fps spikes. So far I’ve got all the gibs and gore effects set up on timed releases and I’m currently implementing the same for debris and effects created by explosions. It’s getting better for sure. I’ll do the same for other effects as well to reduce the chances of them being spawned at the same time as much as possible. Then I’m going to look into giving as many actors as possible a custom stat to further reduce fps spikes. This is going very well.
0

User is offline   Reaper_Man 

  • Once and Future King

#3655

IMO Vgames I do think you have improved a lot in the past few years I've been seeing you post. I don't know if you've released something, like I haven't seen a full script or project to review, but you do seem to be understanding the language as well as "what is a programming".
0

User is offline   eniojr 

#3656

What I learned was to create a custom state and had it to load inside onevent EVENT_GAME. Don't forget that before I didn't knew about that switch thing related to case syntax. Back then I was lost about it.

I also did some improvements related to the accesscard and accessswitch codes. For example, now when the switch is locked, there are 2 variations of Duke's speech (something the AI wasn't capable to do). And I also added more colors to cards compared to Nuclear Showndown. I had to write codes manually in many occasions. The same thing for the ladder and jumpad effects.

It's just those var and varvar things that still confuses me.

For those who are just starting out in CON, it can be confusing and you end up getting lost. And the documentation regarding these syntaxes is not very intuitive. This is because most of these syntaxes are explained separately. Furthermore, the best way to understand how these syntaxes work within a specific context is through sample models for different purposes, which is limited on the Eduke32 website.

And so you end up having to poke around in mod codes if you want to add or change something that is not documented on that website. Because what is there, for someone who is not a programming expert, does not seem to be enough. More explanatory models are needed, for example, to create new buttons, add effects, new card colors, models that you only find in mods, and even spread across files.

It took a lot of effort, because I had to look for codes in different files related to something specific and organize everything in a single file related to that thing, which was not easy at all. So much so that I had to add lines of code that I ended up having to write myself, even though they were simple. There is also the issue of having a correct order for the codes to work properly.

For example, regarding the ladder codes, I had to test the order of the codes, until I saw that first it should be in this sequence: state pythagoras > state laddercode > state checkwall > state ladderinteraction > eventloadactor LADDER > onevent EVENT_GAME > onevent EVENT_MOVEFORWARD > onevent EVENT_MOVEBACKWARD > onevent EVENT_JUMP > onevent EVENT_PROCESSINPUT and finally, separate the codes for JUMPAD, so there would be no conflict in the loading order. And then it finally worked.

Because of these limitations of explanatory models on the website, I end up not understanding everything that is in the codes for mods and effects and other things that I end up wanting to incorporate into the game. But at least there are certain syntaxes that I already have a certain understanding of, precisely because I had to test codes and their values ​​on several occasions.

That's why I say that what is documented in Eduke32 is more for those who already have a prior understanding of programming language, but for those who are starting from scratch... Unless it's to do simpler things that don't require a lot of code, like breakable objects and simple monsters and babes or simply change something that is already in the game.

So yes, I ended up learning new things that weren't explained on the official website.

Everyone has a different way of starting to learn programming from scratch...

And my way of starting to learn this is by starting to learn the coding patterns, and not specific syntaxes. Once I understand the coding pattern better, I start to understand the use of the syntaxes a little better. In other words, my way of learning this depends a lot on the context the codes that are used.

Maybe that's why I end up having more difficulty with these syntaxes.
0

User is offline   Reaper_Man 

  • Once and Future King

#3657

View Posteniojr, on 17 December 2024 - 07:17 AM, said:

For those who are just starting out in CON, it can be confusing and you end up getting lost. And the documentation regarding these syntaxes is not very intuitive. This is because most of these syntaxes are explained separately. Furthermore, the best way to understand how these syntaxes work within a specific context is through sample models for different purposes, which is limited on the Eduke32 website.

Sure, but that isn't what you've done here. Or at very least that's not the way you've presented yourself.

You are correct that seeing working examples, or even real-world usage, of specific commands is a good way to learn how to use them. But you didn't use the DukePlus ladder code as a jumping off point, or a way to learn about syntax and usage. You copied it wholesale into your own mod, because you want ladders, and you want it to "just work". And then to make it worse, you came here proud of your "accomplishment" and seem to want others to commend you.

You didn't have difficulty understanding syntax. You had difficulty knowing what code to copy and paste. You literally said as much.
0

User is offline   Mark 

#3658

I'll take a different approach and admit I'm too lazy to learn some of the basics and it makes things tough. Nobody to blame but me. I've done a lot of my own coding from scratch over the years and have had many successes and my fair share of failures. But I could be much further along if I buckled down and learned more instead of floundering as I do. The previously mentioned "its good enough" mentality.

I also learned a lot in the beginning from copy/pasting code from mods and having to figure out what it took to get rid of the 26 errors that popped up along the way along with adding my own tweaks. These days I often hesitate to ask for help because I know I'm lacking in basics and when I get a helpful reply I can't make heads or tails of the technical response I receive and can be too embarassed to admit it. I'll make attempts to figure it out but it doesn't always end in success so I move on to something else. I feel bad because I wasted the time of the helper in that instance. I apologize.

And thanks for all the help you people have given to the community. I did what little I could by bundling together a lot of little code snippits from posts over the years into a "con code tricks" file and have posted it here and elsewhere and sent it to a few who requested it. I still refer to it for ideas.

This post has been edited by Mark: 17 December 2024 - 08:10 AM

0

User is offline   VGames 

  • Extra Crispy

#3659

View PostReaper_Man, on 17 December 2024 - 07:02 AM, said:

IMO Vgames I do think you have improved a lot in the past few years I've been seeing you post. I don't know if you've released something, like I haven't seen a full script or project to review, but you do seem to be understanding the language as well as "what is a programming".


Thank you. With help from here and loads of examples in existing mods I definitely have a good understanding of Con coding now and I’m trying to get more advanced with it. I use to mess with a lot pre eduke con coding a long time ago but it was never this in depth. Here’s a link to my mod since you didn’t know of it:

https://www.moddb.co...savior-of-babes

It’s doing well and has cut a nice little niche for itself in the duke modding community because of its gameplay style and mass carnage.

Would reducing the number of gamevars to the bare minimum needed help with performance? I’ve got lots of gamevars that I could probably reduce and just use the same ones for different situations instead of making one for each situation. But I wanted to know how taxing gamevar definitions are on the overall performance before I go about doing this because I’m sure I’m gonna run into things I’ll have to fix.
0

User is offline   Reaper_Man 

  • Once and Future King

#3660

I did know about that, but I guess I didn't realize it was "out". Whenever I have some time to kill I'll take a look over whatever code you have in there.

View PostVGames, on 17 December 2024 - 08:41 AM, said:

Would reducing the number of gamevars to the bare minimum needed help with performance? I’ve got lots of gamevars that I could probably reduce and just use the same ones for different situations instead of making one for each situation. But I wanted to know how taxing gamevar definitions are on the overall performance before I go about doing this because I’m sure I’m gonna run into things I’ll have to fix.


Reducing gamevars is both less about performance and more about memory, but also about performance. If you have any that are declared and never used, it would be a good idea to get rid of them. If you have 2 (or more) that get used for the same thing then you should refactor your code to just use 1. As a general rule, I have a handful of recurring per-actor vars that I use for all sorts of temporary math and checks: ACTORTEMP / ACTORTEMP2 / ACTORCHECK / ACTORCHECK2 . The "check" ones I try and reserve for anything that returns 0 or 1, and the "temp" ones I try and reserve for math related stuff. But I'll use them whenever necessary. There are very few instances where I need more than 4 temporary vars to accomplish a task.

The poor code pattern I see most often is declaring these sort of per-actor vars, for every actor or enemy or effect. A new "TEMP1" thru "TEMP4" for every enemy. You don't need 4 temporary per-actor vars for an enemy, 4 others for particles, so on. They're per-actor, which more accurately is per-sprite. They're individual to whoever is using them. Similarly, you probably don't need multiple global gamevars for common screen drawing effects. I'll see multiple different X/Y position gamevars to calculate screen drawing, but these can likely all be condensed down too.

I see these poor code patterns most often because A.) the gamevars are declared within the context of some sort of self-contained code snippet that was recycled, and B.) a bunch of code snippets get mushed together with no consideration for the larger project. As Dan said a few pages back, it's common for individual programmers or developers to maintain an internal library of functions, and therefore (at least in my personal scenario) only ever reusing the same handful of named global and per-actor vars.

A project should probably be more than a collection of random effects and disparate code.
0

Share this topic:


  • 124 Pages +
  • « First
  • 120
  • 121
  • 122
  • 123
  • 124
  • You cannot start a new topic
  • You cannot reply to this topic


All copyrights and trademarks not owned by Voidpoint, LLC are the sole property of their respective owners. Play Ion Fury! ;) © Voidpoint, LLC

Enter your sign in name and password


Sign in options