PDA

View Full Version : NPCData, ComboData, SpriteData



ZoriaRPG
06-27-2017, 10:04 PM
I've started the long work on adding the following pointers, and their associated functions.

NPCData-> Read/Write or otherwise edit/use the enemy editor data by script.

ComboData-> Read/Write or otherwise edit/use the combo tables by script.

SpriteData-> Read/Write or otherwise edit/use the weapon/misc sprites data by script.

The general format for the functions is GetMember(int id) , returning the member of the class at index 'id', SetMember(int id, int v), setting the member 'id' of a given class to the value 'v'. Similarly, for arrays and flags, GetMember(int id, int index), GetMember(int id, int flag), Setmember(int id, int index, int v), SetMember(int id, int flag, int id).

All of these are set up to run through macros.

Tamamo
06-28-2017, 05:51 AM
You do realize some shit is suppose to be read only for a reason right ZoriaRPG?
I don't even know if you know what your doing anymore... O_O

Dimentio
06-28-2017, 06:23 AM
You do realize some shit is suppose to be read only for a reason right ZoriaRPG?
I don't even know if you know what your doing anymore... O_O

How is making useful variables write-able bad, if you make them work as you'd expect? Are you just against the adding of any new feature?

ZoriaRPG
06-28-2017, 07:57 AM
You do realize some shit is suppose to be read only for a reason right ZoriaRPG?
I don't even know if you know what your doing anymore... O_O

Of course I know what I'm doing. Writing occurs to the buffers, not the physical tables; just as with itemdata, and it is not retained/written out. There is absolutely no difference in writing to guysbuf[id].member. than writing to itemsbuf[id].member; and similarly, writing to ComboData[id].member is lready partially implemented, albeit poorly, with SetCombo* functions. This also has appropriate approval, and blessings and is tied into other improvements.

This stuff was not read-only in the past. it was flat-out, never implemented; and FWIW, some stuff is read-only because no-one ever finished it in the past, or they were unable to work out issues that arose at the time. If any of the setters prove to be unstable, or buggy, I can disable them until we find a suitable work-around, but I do not anticipate much havoc, save from users who fail to read the documentation.

In conclusion, you are again seemingly complaining, purely to complain. Nothing new there, but thank you for stopping by.

Tamamo
06-28-2017, 08:12 AM
Seems likeyou've finally realized we're every one's on AGN is an asshole and life in general.
This isn't going to be a change. Thank you for responding promptly. You deserver a clap.

https://images.gr-assets.com/hostedimages/1407310509ra/10673073.gif

ZoriaRPG
06-28-2017, 09:08 AM
Seems likeyou've finally realized we're every one's on AGN is an asshole and life in general.
This isn't going to be a change. Thank you for responding promptly. You deserver a clap.




Aye, as after eleven years, I clearly never caught on. You know, if we keep having these little rows, as amusing as the mental banter is, eventually one of us will need to buy the other a drink.

https://thumbs.dreamstime.com/z/glass-bottle-gin-branch-juniper-berries-vintage-vector-engraving-illustration-label-poster-web-invitation-77627442.jpg

DarkDragon
06-28-2017, 01:05 PM
I've started the long work on adding the following pointers, and their associated functions.

NPCData-> Read/Write or otherwise edit/use the enemy editor data by script.

ComboData-> Read/Write or otherwise edit/use the combo tables by script.

SpriteData-> Read/Write or otherwise edit/use the weapon/misc sprites data by script.

The general format for the functions is GetMember(int id) , returning the member of the class at index 'id', SetMember(int id, int v), setting the member 'id' of a given class to the value 'v'. Similarly, for arrays and flags, GetMember(int id, int index), GetMember(int id, int flag), Setmember(int id, int index, int v), SetMember(int id, int flag, int id).

All of these are set up to run through macros.

Tried to post this last night but was blocked by some server issues; I think I already mentioned all of this to you in chat but I'm pasting it here for the record.

These function the same as Game->LoadItemData, right? Why not mimic its syntax?

Regarding the ability to write to the buffers during the game: some values in the buffer are read when enemies are created, and will not change if you write to the buffer after the enemy is already on screen. Others are read when enemies move, are hit, etc. It's a random hodgepodge of behaviors based on the particular way each enemy is coded up in guys.cpp. Exposing the internal .qst file buffers with write access permanently locks in the current behavior of every enemy, since there will be no other way to ensure that scripts continue to function in the future. This may (or may not) hamper future attempts at making enemies more customizable or scriptable, so think carefully before opening that bottle, because it won't close again. At a minimum, all developers need to be made aware that the guys.cpp behavior can no longer be changed, and quest authors need to understand the dangers of writing to the buffers while enemies are using those values dynamically (best would be full documentation of how every enemy uses the buffer values during play, but that may not be feasible). All of the above also applies to combos etc.

Also it should be made clear in the documentation that changes to any .qst file buffers do not persist across quest save/load or reset. You might think that's obvious, but I've gotten related questions about why scripted changes to the ZC GUI do not persist... ;)

Tamamo
06-28-2017, 09:48 PM
DarkDragon
guys.cpp are such a mind fuck of spaghetti code the entire thing should of been rewritten years ago. But I agree that we should leave enemy behavior data read only. Messing with that shit can cause serious problems if you expose the buffer.

DarkDragon
06-29-2017, 01:12 PM
It was rewritten, mostly, by Gleeok and Saffith a few years ago, in AngelScript, but it's probably no longer possible to attempt something like this without breaking currently quests with scripts. I think the only plausible path forward (in the long-term, not short-term, mind you) is to make scripted equivalents of all enemies keep the current enemy logic around (in a dark deprecated corner) for old quests and scripts to use if necessary.

Tamamo
06-29-2017, 07:35 PM
Heh, they removed that so long ago DarkDragon it's irrelevant.
IIRC they we're never trully finished, although all implemented. Why? Because they were broken. Every single one of them.
And we still to this day dont know why.

Saffith
06-29-2017, 10:36 PM
Eh, they were removed because at that point I was burned out and depressed and basically doing stupid things at random. The conversion was really easy, though, at least as far as I got with it. But yeah, there was some issue with reading the return values from animate(), I guess? Worked fine for me, not at all for Gleeok. We never did figure out what it was, but then, we didn't exactly try.

Tamamo
06-29-2017, 11:00 PM
Exactly... And for your information, I spent a whole week trying to solve the problem.
Guess I wasted a week of my life. Thanks for the affirmation...

Gleeok
06-30-2017, 12:25 AM
I'm still against moving c++ code to scripts just on principle alone. If you think guys are a pain to debug or work with now, just wait until you have no debugging support whatsoever. My argument is that built-in enemy (i.e., editor edited or legacy) behavior should be a separate code path from customized (scripted) behavior.

jman2050
06-30-2017, 03:29 AM
In general I think that compartmentalizing the scripting environment into various arbitrary categories is a mistake. That was never the intent of ZASM/ZScript in the first place and really the distinction between stuff like "global" scripts and "FFC" and "item" scripts only really exists to tether specific programmable functionality into specific use cases as already defined in the engine itself. i.e. the only reason you'd use an item script over an FFC script is that you want whatever stuff you've programmed to happen to occur specifically when using an item as defined in the ZC engine itself. You could just as well make an FFC script with the exact same functionality and design in what way it's activated yourself. In the same way while the ability to attach scripts to enemies defined in the enemy editor directly would be convenient, that doesn't stop people from programatically making Fire enemies with custom attributes and custom behavior on their own terms without worrying about ZC's enemy code at all.

In general I think worrying about how any advancements in the scripting environment will clash with legacy code is a pointless exercise. The legacy code has to exist in some form because it's used in every quest. Whether it's the same kludgey spaghetti code we've had for 10+ years or refactored to be easier to manage and integrate with future changes or even converted to scripts entirely is immaterial to the end user and becomes merely a question on which will be easier to manage on the development end. Rather than trying to further entrench the scripting environment into the legacy code (or vice versa) I think the setup we've had up to this point is perfectly fine. ZC behavior will be ZC behavior and scripting will be an open sandbox that allows users to extend or even outright replace ZC's functionality with their own. Not that I'm saying things can't be improved in areas where the legacy code remains a rigid restriction, but those improvements should primarily be focused on improving the end user's ease-of-use and freedom. Stuff like making scripting more modular so scripts can act more independently of each other, better ability to use generic scripts without modification, improvements to the language itself, and even improvements to ZC's engine to accommodate ambitions that are otherwise difficult or impossible to accomplish. Allowing scrolling and rooms not conforming to the same 16x11 play area we've had since 1999 to state one example, or finally moving away from the limitations of 8-bit palettes.

I guess this is more just a random hodgepodge of thoughts relating to the direction of ZC rather than a direct response to the topic at hand, so sorry for that. In general I'm not against exposing more of the engine's properties to user editing but DarkDragon has already clearly laid out the dangers of doing so. The good part though is that as long as you guys don't actually release anything, you don't have to worry about those consequences for the time being! :P

ZoriaRPG
06-30-2017, 06:35 AM
I'm still against moving c++ code to scripts just on principle alone. If you think guys are a pain to debug or work with now, just wait until you have no debugging support whatsoever. My argument is that built-in enemy (i.e., editor edited or legacy) behavior should be a separate code path from customized (scripted) behavior.


That was my original plan. Add an npc type, 'Scripted', and that type (and all offshoots) use scripted behaviour. The other internal npcs are preserved as-is. Thus, any new npcs that we add after that point, would all be scripts that the user can edit. This is a bit forward of the present formulae.


In general I think that compartmentalizing the scripting environment into various arbitrary categories is a mistake. That was never the intent of ZASM/ZScript in the first place and really the distinction between stuff like "global" scripts and "FFC" and "item" scripts only really exists to tether specific programmable functionality into specific use cases as already defined in the engine itself. i.e. the only reason you'd use an item script over an FFC script is that you want whatever stuff you've programmed to happen to occur specifically when using an item as defined in the ZC engine itself. You could just as well make an FFC script with the exact same functionality and design in what way it's activated yourself. In the same way while the ability to attach scripts to enemies defined in the enemy editor directly would be convenient, that doesn't stop people from programatically making Fire enemies with custom attributes and custom behavior on their own terms without worrying about ZC's enemy code at all.

In general I think worrying about how any advancements in the scripting environment will clash with legacy code is a pointless exercise. The legacy code has to exist in some form because it's used in every quest. Whether it's the same kludgey spaghetti code we've had for 10+ years or refactored to be easier to manage and integrate with future changes or even converted to scripts entirely is immaterial to the end user and becomes merely a question on which will be easier to manage on the development end. Rather than trying to further entrench the scripting environment into the legacy code (or vice versa) I think the setup we've had up to this point is perfectly fine. ZC behavior will be ZC behavior and scripting will be an open sandbox that allows users to extend or even outright replace ZC's functionality with their own. Not that I'm saying things can't be improved in areas where the legacy code remains a rigid restriction, but those improvements should primarily be focused on improving the end user's ease-of-use and freedom. Stuff like making scripting more modular so scripts can act more independently of each other, better ability to use generic scripts without modification, improvements to the language itself, and even improvements to ZC's engine to accommodate ambitions that are otherwise difficult or impossible to accomplish. Allowing scrolling and rooms not conforming to the same 16x11 play area we've had since 1999 to state one example, or finally moving away from the limitations of 8-bit palettes.

I guess this is more just a random hodgepodge of thoughts relating to the direction of ZC rather than a direct response to the topic at hand, so sorry for that. In general I'm not against exposing more of the engine's properties to user editing but DarkDragon has already clearly laid out the dangers of doing so. The good part though is that as long as you guys don't actually release anything, you don't have to worry about those consequences for the time being! :P

Whle I agree with most of this, I feel that segregating things into class/pointer format makes it a bit easier to remember, rather than dumping everything at the global level. It makes far more sense to have Graphics->Draw, for what we will be doing, and Graphics->Palette, than splitting these between screen and game, IMO. If a function is attached to a script type that is associated with a pointer, and therefore has a 'this', pointer, then it belongs in that class. Otherwise, I would, as a scripter, rather know that all the audio functions are under Audio->, rather than Game-> and (global)->.

Hell, I would rather that the extant stuff was categorised, as it is easy enough to trip yourself up on the pointer type for some of this stuff. It will also make things a bit cleaner when reading them, as the pointer type illustrates the purpose of a function in a broader scope, so the script code itself is cleaner as a result.

You know, Dimentio mentioned something about you having previously worked on some kind of engine modification to modify screen dimensions, permit pseudo-scrolling, or some such thing. Is there any fact to that, and if so, does any of that still exist, or would it be pertinent to the 2.6 process? I was considering working on a way to modify the screen draw dimensions, adding boundary points that can be modified (for smaller output, or custom scroll zones), and adding boundary points for all weapons, at which they automatically die; these set by quest data, or modified by script.

These are some examples of 'rules' that would be in the FFScript class, DarkDragon. WeaponLeftBoundary, WeaponRightBoundary, and so forth, as these are linked both to ZQuest, and to ZScript, and thus it seems logical (to me), to centralise them in FFRules[]. You can call them BananaRules[] if you want, but the point is to put anything that both the engine, and the script engine routinely access in there, unless it belongs as part of a class/struct, say, for weapon behaviour (other than global boundaries and such nonsense), or item animation (as part of the itemclass struct, on a per-item basis.

This would mean setting these flags by default for old quets based on the old QRs, and reading the class bits instead of QR bits on a per-item basis, or per-npc basi, or what-have-you, when determining how they work. That allows the same level of compatibility, with far more flexibility in the mechanics, and it (in theory) makes it easier to later integrate these things into scripted behaviour for weapon, and npc scripts.


Tried to post this last night but was blocked by some server issues; I think I already mentioned all of this to you in chat but I'm pasting it here for the record.

These function the same as Game->LoadItemData, right? Why not mimic its syntax?


Sure, I likely will, when these things are better defined, and they need a 'this pointer. For the moment, I need to determine what the actual results are of doing any of these things, to see what works, what does not work, and what requires sticky tape on the windows.

That is why they are all in their own branches.




Regarding the ability to write to the buffers during the game: some values in the buffer are read when enemies are created, and will not change if you write to the buffer after the enemy is already on screen. Others are read when enemies move, are hit, etc. It's a random hodgepodge of behaviors based on the particular way each enemy is coded up in guys.cpp. Exposing the internal .qst file buffers with write access permanently locks in the current behavior of every enemy, since there will be no other way to ensure that scripts continue to function in the future. This may (or may not) hamper future attempts at making enemies more customizable or scriptable, so think carefully before opening that bottle, because it won't close again. At a minimum, all developers need to be made aware that the guys.cpp behavior can no longer be changed, and quest authors need to understand the dangers of writing to the buffers while enemies are using those values dynamically (best would be full documentation of how every enemy uses the buffer values during play, but that may not be feasible). All of the above also applies to combos etc.

Also it should be made clear in the documentation that changes to any .qst file buffers do not persist across quest save/load or reset. You might think that's obvious, but I've gotten related questions about why scripted changes to the ZC GUI do not persist... ;)


I have in fact, considered adding two forms of work-arounds.

1. FIx the refresh cycle so that if any of these facets are changed, all of the elemts that are on display are also changed (on the enxt frame).
2. Add a Refresh() function to each of the pointers, so that the user cna direct them to redraw, refresh, or reload.

Some things, such as npc->SeHP() could be written so that the engine checks this, and if it changes, to do npcptr->HP = min(currentHP, npcdats->HP) for all npcs that exist of that type.

I'm not sure if this is desirable default behaviour, or if it should be called on a per-npc instance by the user.

Gleeok
06-30-2017, 07:09 AM
That was my original plan. Add an npc type, 'Scripted', and that type (and all offshoots) use scripted behaviour. The other internal npcs are preserved as-is. Thus, any new npcs that we add after that point, would all be scripts that the user can edit. This is a bit forward of the present formulae.

This was one of my next things to do, at least it was before I burned out... The idea is you just assign a script to the enemy in the editor and it becomes scripted. Of course enemies created by script won't even have this limitation. Every enemy script can inherit from different data. At least this is one of my ideas on how to organize it.




Some things, such as npc->SeHP() could be written so that the engine checks this, and if it changes, to do npcptr->HP = min(currentHP, npcdats->HP) for all npcs that exist of that type.
I'm not sure if this is desirable default behaviour, or if it should be called on a per-npc instance by the user.

Very undesirable. Coupling these internally should be avoided at all cost.

ZoriaRPG
06-30-2017, 08:18 AM
This was one of my next things to do, at least it was before I burned out... The idea is you just assign a script to the enemy in the editor and it becomes scripted. Of course enemies created by script won't even have this limitation. Every enemy script can inherit from different data. At least this is one of my ideas on how to organize it.


The only issue I see arising from this, is that the enemy behaviour can change radically and unexpectedly, without setting tis type by script as well. That may not itself be a bad thing, but it may confuse some users. Otherwise, all fo this seems work-able. I was going to add a dedicated 'scripted' npc type, and then that npc derives its properties from the script assigned to it. DD wants to automatically populate enemy lists with scritped npcs provided by the script metadata.

It might be simpler just to have two npc categories to accomplish that. Stock, internal npcs, and scripted npcs, as two separate tables. I'm not too fond of having two distinct tables, but if the scripts are in charge of the table entries, rather than the table entry selecting a script, then I don;t see a good way to keep them from clashing.




Very undesirable. Coupling these internally should be avoided at all cost.

Do you mean forced-coupling, permissive coupling by command, or both? I need to add a refresh entry for npcs to Screen-> anyway, so that the user can reload them after changing npc values ont he screen, without needing to exit and reload the screen. I will likely need to do the same for other map stuff, but perhaps not. Adding a Refresn() function to the pointers seems a logical way to permit the user to reload all of the properties of a given object.

For npcs, I was leaning toward a per-npc thing, by instruction. Just, npc->Refresh(), to reload it from the full default state. Thus, if there is an instance of npc ID 17 on the screen, all of its values are re-loaded from npcdata[17]. That should nto itself be problematic, I would hope, as it would be useful even without adding npcdata. It is effectively 'respawn in place', without needing to kill and respawn it manually.

This could easily be a universal function for each object pointer, that clears any pointer to its default state. The only pointer for which this is probably not useful, is Game->...Game->Refresh() I guess would be the same as F6 Retry. Perhaps that is useful, after all. :kawaii: ...anyway...

I was not fond of the idea of forced linking, because that is just a way to limit flexibility in use.

Gleeok
07-02-2017, 07:12 AM
What the heck is dmisc?? I saw this in enemy class:



long dmisc1, dmisc2, dmisc3, dmisc4, dmisc5, dmisc6, dmisc7, dmisc8, dmisc9, dmisc10, dmisc11, dmisc12, dmisc13, dmisc14, dmisc15;


The enemy class keeps on getting bigger! Ahhhh!!!

..Seriously though, no clue.

Tamamo
07-02-2017, 09:36 AM
misc attributes 1 - 12 respectfully.
Originally we thought we would need more.
Why are you the one asking this question?

ZoriaRPG
07-03-2017, 12:11 AM
What the heck is dmisc?? I saw this in enemy class:



long dmisc1, dmisc2, dmisc3, dmisc4, dmisc5, dmisc6, dmisc7, dmisc8, dmisc9, dmisc10, dmisc11, dmisc12, dmisc13, dmisc14, dmisc15;


The enemy class keeps on getting bigger! Ahhhh!!!

..Seriously though, no clue.

I have already pushed those to ZScript, and I was going to add fields for them in the EE; as users do whine about being out of attribs for scripts, and these were there all along


Yeah, you're pretty much know what your doing now. I may be stubbon but i'm not oblivious.
When I say something is impossible, it clearly means it's only impossible for me.

Also, have you tried looking at the unimplemented enemies to see what can be done with them.
As far as I'm concerned. We can just swap out NPC_WALKING and NPC_STANDING. But it would be nice to see about adding the others, since sprites for those do exist in the classic tileset, and other tilesets as well.

I have not done anything with unimplemented types, and the reason is simple: I want to make as much of this work for the enemy types that exist in the engine (visible to the user) as possible, before compounding the job by adding more stuff to support later. I mean, if we are going with script-based npcs, why add more hardcoded npcs to the engine? Adding all of these class vars may also be a bit silly, but it will at least be usable in the next major release, whilst npc scripts, may not.

Some of these unimplemented enemies, such as Wizrobe (ice), don't need to exist as a specific enemy category. Adding an ice weapon and giving npcs access to it, is a far better solution. It also requires adding ice combo effects to the engine itself. :/ At least, I would think of ice magic affecting floors, in the same way as Trinexx does; and possibly Stun Link on contact.

I have no clue what 'standing' npcs were meant to do, unless they were intended to charge Link in LoS. There are no notes anywhere to aid in the archaeology.
Dimentio is the one who wanted to add wholly new npcs to the hardcoded base. I think that doing that is a long-term kludge, but everything relating to adding npcs hinges on npc scripts. I don't mind adding ptterns, move types, and other class values that can be used later anyway, but adding hardcoded movement that is not a pattern type to select; that can be applied to generic npcs, is another matter.

Are there any specific types that you want working?

Tamamo
07-03-2017, 07:28 AM
Umm It would be nice to see the Diagonal Traps working... That is a simple logic correction.
Circular Traps take a bit more work since their angle must be normalized.

If we actually managed to add scripted enemies this time around and they work for everybody that would be impressive.
But we're far too lazy. But the minute someone can prove they dont work after compiling from source...
You can say bye bye to your scripted enemies.

tk:dr I've given up on that dream. And you should too.

You can drop the standing and walking npcs.
Those were to be the only customizable npcs. Those existed before we had an enemy editor.

ZoriaRPG
07-03-2017, 08:30 AM
Umm It would be nice to see the Diagonal Traps working... That is a simple logic correction.
Circular Traps take a bit more work since their angle must be normalized.

If we actually managed to add scripted enemies this time around and they work for everybody that would be impressive.
But we're far too lazy. But the minute someone can prove they dont work after compiling from source...
You can say bye bye to your scripted enemies.

tk:dr I've given up on that dream. And you should too.

You can drop the standing and walking npcs.
Those were to be the only customizable npcs. Those existed before we had an enemy editor.

You should probably hold off on those comments, given that you are out of touch with the plan. DarkDragon is at this moment, working on a refactor of ZScript, that will introduce a number of elements. The reality is that he is on board for npc and weapon scripts, in this process, so while it is not guaranteed, it is probable that they will make it into at least 2.60. Essentially, we are all on the same general page for how we want to proceed, and everyone is working on facets with which they are comfortable, and competent.

I had nothing to do with the previous attempt at scripted npcs, and I don;t know what you did, or what Saffith did, save that it ultimately didn't happen. I'm sorry if you wasted time on that, but I also wasted a hell of a lot of time on stuff that I had to do over, or rip out and rework. Months of time, in some cases. It happens, and it also forced me into hiatus for a few months. At present, some of what I am doing is on hold, while DarkDragon and Gleeok finish some refactoring of sprites, and drawing.

Thus, I am working on what I can, and I'm focusing on getting 2.53 out the door. I ran into two very fun issues with it now, concerning MIDIs, and concerning InitD values not forwareding property as variables.

That one is weird, and is essentially this:
-=SPOILER=-


----------

I will look into diagonal traps; although on the subject of diagonal stuff, I need to finish the code for the diagonal hookshot: It needs sprites for the head and handle at angles, and the latching code needs to be refined.

Circular traps seem like they would be much, much, harder.

Anyway, you should take a visit to the land of the revised parser at some point, when we finish more of this nonsense. A lot of stuff that was deemed 'too difficult', or 'impossible' is in there now. I was holding off on adding a 'this' pointer for npcdata until we know if npc scripts are happening, as I used more simplified logic for NPCData, that did not require generating a pointer, in its present form.

I'm not sure if we will also have combo scripts, and similar, but in theory, we could have all of that in the end. It would certainly be an interesting turn of events.

Dimentio
07-04-2017, 03:12 PM
Dimentio is the one who wanted to add wholly new npcs to the hardcoded base.

Huh? From what I remember, you were the one who wanted to add Z3 bosses to the default package, and I agreed there, and then suddenly you went and were all "No, Z3 bosses are infringing". I'm all for the Scripted enemy type, as the less hardcoded stuff, the better.

Tamamo
07-04-2017, 06:40 PM
The entire project infringes, does Nintendo seem to care after 17 years? No.