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 

#3623

The AI ​​doesn't do everything for me, since I end up having to correct some things. So this means that I already have some understanding.

Note: repeated message, due to a problem when loading this site.

This post has been edited by eniojr: 14 December 2024 - 09:08 AM

0

User is offline   Mark 

#3624

I serched for EVENT_GAME in one of my projects. I found it in part of the Polymer flashlight code and again for disabling the player idle knucklecrack. So in the case of the knucklecrack its using a jackhammer instead of a toothpick.
0

User is offline   Danukem 

  • Duke Plus Developer

#3625

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.

This post has been edited by Danukem: 14 December 2024 - 01:02 PM

0

User is offline   eniojr 

#3626

I'm starting to understand better about onevent EVENT_GAME. First you define the event, then you set a switch to activate a specific case. For example, in Dukeplus, I saw that "case ladder" would be linked to switch picnum, this one inside onevent EVENT_GAME.

Now I just need to know how to activate this specific switch.

Before, I was trying to set "case ladder" as "state ladder", but that wasn't the right way to do it. What I need to know is to understand how the mod developer planned all this, why he made "case ladder" inside a game event instead of a separate "state ladder".

Another thing is about the order of states and events. Since they are in different files, it's hard for me to understand how to put everything in a single .CON file related to the effects I added in Legacy.

I put them in the following order in the script: gamevars and defines > state pythagoras > eventloadactor JUMPAD > useractor notenemy JUMPAD 0 > eventloadactor LADDER > state laddercode > state checkwall > onevent EVENT_GAME (with switch picnum and case ladder inside) > onevent EVENT_MOVEFORWARD > onevent EVENT_MOVEBACKWARD > onevent EVENT_TURNAROUND > onevent EVENT_JUMP > onevent EVENT_PROCESSINPUT.

I don't know if there's something else missing related to the files in Dukeplus. It seems not.

Of these, only the JUMPAD effect worked.

I'm no longer interested in mantling and dodge, so I discarded the codes related to them, leaving only the ones for jumpad and ladder. I did this to avoid possible conflicts.

I noticed that the events related to movement (forward and backward) would be related to the staircase effect, just as there is something in event_processinput that would also be related, since it seems to me that the staircase effect depends on the activation of an input, unlike the jumpad which would be independent of the use of directional keys.

This was the context I understood so far.

This post has been edited by eniojr: 14 December 2024 - 01:09 PM

0

User is offline   eniojr 

#3627

.

This post has been edited by eniojr: 14 December 2024 - 01:08 PM

0

User is offline   brullov 

  • Senior Artist at TGK

#3628

The DukePlus code was written many moons ago, I doubt even the author of it remembers how everything works. I would write it from scratch, it's much easier and more fun.
0

User is offline   eniojr 

#3629

There's Naferia mod, but ir's even more complex, so many interconnected codes, items, monsters, effects, characters, etc. It's a huge mess! Don't know any more mods that have a ladder effect. I tried messing with Naferia's mod, but gave up and returned to Dukeplus.

This post has been edited by eniojr: 14 December 2024 - 06:31 PM

0

User is offline   Mark 

#3630

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.
0

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 offline   Danukem 

  • Duke Plus Developer

#3632

 Mark, 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

 Danukem, 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 offline   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 offline   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 offline   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

 Reaper_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 offline   Danukem 

  • Duke Plus Developer

#3649

 VGames, 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 offline   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 offline   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

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