ID:973934
 
Applies to:DM Language
Status: Open

Issue hasn't been assigned a status value.
I am requesting some new parameters and features in the flick() procedures. Namely it would be very nice if we could do the following:

Create an on-the-fly icon state by specifying a list of icon-state|frame|delay|direction(optional) which would then allow us to reduce redundant icon_states which adds a burden to overlay drawing, etc.

For instance, I have one icon_state for hurt which is simply the second frame from my icon_state "dying" and then an empty frame so that the character flashes. Rather than have a separate icon_state for this, it would be nice if I could just flick(frame("dying",2,1),frame(null,null,1)) or something similar in DM rather than have a bloated base icon/overlay file.

The versatility of this would be endless, I could take the middle frame of my slash animation, do a sequence of each of the 4 directions and presto I would have a spin attack.


PS: I am aware of the icon procedures already in place, what I am requesting would not require modification to icon files as that is more resource intensive, but rather make more versatile use of existing icons already pre-loading in the RSC.
So, what you actually want...is to be able to use icon() in flick.
What you described with the icon state and frame etc...
var/icon/hurt = icon('yer file.dmi', "dying", yerframe, yerdir)
flick(hurt, yerobject)

So, if you want something like that, this might? be merged into id:105994, which also gives the workaround of using image objects.

Either way, it'd still require loading icons into the resource, as far as I know, because of the way icons are handled, something about frames and whatever, it'd still have to be created as a new icon.
Itd be a start, but I think that if every time a character was smacked by something I had to create a new icon file it might cause me some distress. It would be nice if the way icons were handled were modified slightly to address this inconvenience.
In terms of actual disk storage, a frame is no different to an icon state, so I don't think you are getting the improvement (on the downloaded RSC size?) you think you are for a bunch of cases. Each are PNG data chunks.

Assuming the frame you wanted was duplicate was actually identical, you can just copy/paste the frame into a new icon state and name it accordingly. You don't get savings on the disk compared to what you've proposed (although I suspect the PNG format may fold chunks like that together if it can, so hopefully the difference on disk isn't large), but I have this feeling that the disk size difference isn't a big deal in all but quite extreme cases.
Im less worried about storage and more worried about poor performance if constantly calling icon() procs when all I want to do is flick pre-existing frames of an icon. It seems like it would be hard on the server.
If you do
icon('icon.dmi', "icon_state") //or image?
a thousand times, it'll only be cached the first time. Afterwards, it'll just access the existing cache entry.
...at least, per user that sees the new icon, I'd guess.
It becomes more complicated when you consider overlays too, unfortunately. There may be some reasonable work around to the feature request I suppose, but it would be nice if there was a simple way to access all the pre-existing frame information.
If it's an icon on the player, and you are flicking to an icon state, presumably you don't even need the icon() call, as the state will do?

As for overlays, the problem is probably neater solved by the following feature request:

flicking overlays/underlays that also have the required icon state to flick to. Basically making it one operation (flick_all(state, atom)?) that can be done on the client side. This keeps the operation as a purely visual effect, like flick(), and while it's not as flexible as your solution, it is a solution that I think logically follows quite well.

Having "dying" states on armour overlays and "dying" states on the player makes for a fairly reasonable assumption that they are for the same purpose and animation.

=====

Basically, the issue is flick() is performed client side, using the client cache. So any solution you devise (in terms of feature request) needs to make the server send over frame data as well as the icon / icon reference to flick() on the client, and multiple so such records in your example. You can see how this, while not massive, starts to make up a fair little packet of data to build up on the server, and decode and act on the client.

Ideally, BYOND (and their developers) would like to minimise this, to make flick() as cheap and fire-and-forget on the server side as possible.
Well the issue is that you want to flick to a series of frames of different icon_states, but to accomplish that currently you would need to do something like blend() the overlays on to your base icon and then create the new state using icon(). The issue of course continues to be that you now have a very high number of permutations of overlays that can be on a player at a time, and constantly calling Blend() and creating new states on the fly has to have a significant resource impact. Also it is a bit unattractive when the new icon_state isn't preloaded in to the RSC, so the first time somebody sees the new state, they are likely to see a blank frame while the icon is loaded to their cache.

Right, to which I think the more direct solution is the age-old and much requested one: A mechanism for flicking overlays.

What you've proposed isn't really that feature, it's more complex than that, and possibly needlessly complex for the scenario you've outlined (which is a scenario that's probably quite common-place actually in paper-dolled games).

Hence I think a revision; as described in my above post, probably stands a better chance of being implemented as well as offering much of the benefit you're going for (if not more, in your specific case), at less of an effort to BYOND development.
Id be happy with your solution also, as long as it does not have a material impact on the performance of the game itself.
I think it would probably offer better performance than your solution (marginally), at a guess. The only things that need to go along the wire are the object reference and the icon state name, and both are directly available to the server at the call-site. From the server perspective, it's about as cheap as they come.
I'm a bit tired right now, so please forgive me if I am forgetting an existing way to do this, but I think another possible way to improve Flick() would be to offer a location parameter.

The point of this would basically be that you can flick any icon, with any icon state, in any location on the map with a simple call of the proc; its good for a lot of special effects. There's no point in having to create an object just to locate it correctly, and then flick an icon on it and delete it; yet I am pretty sure this has to be used in lots of cases.

I could be wrong on that, there is likely a few ways to do effects, but I don't think there is anything simpler than simply using Flick(). Also, I support the remake of this request Stephen101 mentioned above. It sounds better,and it may even handle what I was just trying to mention; to an extent. Big maybe there, though.
In response to Stephen001
Stephen001 wrote:
flicking overlays/underlays that also have the required icon state to flick to. Basically making it one operation (flick_all(state, atom)?) that can be done on the client side. This keeps the operation as a purely visual effect, like flick(), and while it's not as flexible as your solution, it is a solution that I think logically follows quite well.
-
Having "dying" states on armour overlays and "dying" states on the player makes for a fairly reasonable assumption that they are for the same purpose and animation.

There's some special rules regarding flick() and overlays that you can use to create this behavior now. When an overlay's icon, icon_state, or dir are left blank, it will assume the values of the object it's attached to. This applies to flick() as well.

So if your player has the icon 'Player.dmi' and icon_state of "", and your [cape] overlay has the icon 'Cape.dmi' and icon_state of "", then when you flick() the "Death" state on the player the cape overlay will also flick its "Death" state:
// Player.dmi: "" (Normal player state), "Death" (Player death animation)
// Cape.dmi: "" (Normal cape state), "Death" (Cape death animation)

mob
icon = 'Player.dmi'
icon_state = ""

New()
overlays += /obj/Item/Cape

verb/Test()
flick("Death", src)

obj/Item/Cape
icon = 'Cape.dmi'
icon_state = ""


It also works in reverse, where you can leave the cape's icon blank and have its normal icon in the player's icon file, and then flick() a "Death" icon instead of a state:
// Player.dmi: "Player" (Normal player state), "Cape" (Normal cape state)
// Death.dmi: "Player" (Player death animation), "Cape" (Cape death animation)

mob
icon = 'Player.dmi'
icon_state = "Player"

New()
overlays += /obj/Item/Cape

verb/Test()
world<<"HEAY!"
flick(image(icon='Death.dmi',icon_state=src.icon_state), src)

obj/Item/Cape
icon = null
icon_state = "Cape"


It puts some awkward restrictions on how you organize your icon files, but does work.

That said, I would love to see the ability to "build" an animation in flick()'s arguments. I was tempted to request it before. It would be useful for things like turning (I want to turn from the 30* state to the 120* state, flick 45*;60*;75*;90*;105*), fading (I want to fade from 100% to 80%, flick 95%;90%;85%), and more. Admittedly, the above two might be better handled by native "rotation" and "alpha" variables on the icons or atoms.