Loadout implementation issue

More
21 years 2 months ago #17702 by Flamineo
Note: this is a 'tedious implementation detail' thread as opposed to another 'what should loadout look like to the player' -- all are welcome, of course, but it's unlikely to be of much interest except to the script bunnies among us. I'm putting it up here in the hope that EricMan64 or others who've worked with loadout code might have some useful insight.

To the point. I've been going round in circles, wrecking various bits of code along the way, trying to address the issue of loadout initialisation: specifically, any loadout code needs to be able to map subsim objects to their corresponding sim ini file template[] numbers.

This isn't a problem for any sim I've already been meddling with: I just slap an int property on each subsim binding it to its template[] number.

The difficulty occurs when I first look at a sim that's been created by Sim.Create() (or iShip.Create()) -- this won't have the int properties yet, so I need another way of identifying the correspondence. I can't see any obvious relationship between the order in which the engine stores subsim objects (Sim.NthSubsim()) and their template[] numbers. This reduces me to messing around with name and/or class comparisons. It is possible to map subsims to template entries in cases where only one subsim of a given class exists, but if a ship has, say, two PBC subsims, I can't pin down any way for the loadout code to tell which one corresponds to which of the two template[] entries that originally created them.

Can anyone see a way round this? I have two (1.5, really), but I'm not very keen on either of them.

The first option is to give up on retaining compatibility with Sim.Create() and iShip.Create() -- if we require all Epic packages to get their ships initially from flm_lo.CreateShip(<url>, <name>), I can attach the information I need when a ship is first created, which neatly removes the problem, but at the high cost of requiring all other packages to go through mine for ship creation.

The second option is not that dissimilar: I can strip all existing subsims from a sim, and replace them from its ini file, attaching the template[] references as I go -- this is, of course, actually all the aforementioned iShip.Create() wrapper does in practice, anyway. The difference is that we wouldn't require it to be done for all ships, but only ones that the loadout code is interested in.

The further problem here is that, in fact, the loadout code is interested in all ships, anyway: as well as allowing us to alter what subsims are loaded where, the loadout package exports SaveLoadout() and RestoreLoadout() functions for use by GrandpaTrout's save-anywhere code -- those functions store subsim state information (damage and operational status) that are also subject to the need for a template[] reference if they're to be restored accurately. The strip-and-rebuild initialisation can't be done at the last minute without potentially losing state information on the stripped subsims -- so it has to be done as early as possible, and we end up back at the first option, with breaking iShip.Create() compatibility being the only way to guarantee the accuracy of the save/restore state functions.

I'd really prefer not to require all scripts to go through a wrapper like this, but I've run out of other ideas. I feel sure I'm missing something obvious. Help?

Please Log in or Create an account to join the conversation.

More
21 years 2 months ago #5065 by MajorTom
What about&#058;
prototype int Sim.SubsimCount( hsim sim );
and
prototype hsubsim Sim.NthSubsim( hsim sim, int number );

How many subsims are you going to monitor? Would it be practible to run Sim.FindSubsimByName on all ships and slap a int property on the ones that don't already have it but should?

Edit: Sorry, after re-reading your 4th Paragraph, I realized you've already tried that. /edit


EOC/IWar2 Multiplayer Fansite

Please Log in or Create an account to join the conversation.

More
21 years 2 months ago #5066 by GrandpaTrout
I think I can help a little.

First, I am only planning on saving the state of player fleet ships. I know this puts a dent in save anywhere. It is a sacrifice I am willing to make to keep the save files from exploding.

Second, when a player purchases or captures a ship, the loadout wrapper can be called. At that point, the ship is yours. This reduces full loadout to just 1-20 ships, instead of 100-2000 that might be possible if we did every ship in the game. (Especially true if I get Stephen's idea to work, and can unplace ships. Goodbye chessboard, hello complete simulation).

Matching Sim to Template:

If I understand right, the problem is matching a subsim back to its hard point mount location number. Sim.Create() does nothing to make these backward links.

What about this idea for doing the matchup: You find the template file for the ship, you loop on the template entries. You find the subsim that matches each template entry, you attach a "hard point" property with the backward link number. To handle multiple instances of the same subsim, you just keep looking until you find one that does not have the hard point property yet.

By loop end you should have all the subsims accounted and back linked.

Of course I am assuming that subsims keep a template name property. I am also assuming that all subsims that have physical shape changes on the ships have been removed, and replaced with invisible ones.


-Gtrout

Please Log in or Create an account to join the conversation.

More
21 years 2 months ago #5079 by Flamineo

originally posted by GrandpaTrout
First, I am only planning on saving the state of player fleet ships. I know this puts a dent in save anywhere. It is a sacrifice I am willing to make to keep the save files from exploding.

That's probably sensible, at least for 'phase one' -- maybe we could look at it again at a later point? It doesn't make that much difference to me how many times I have to get this to work, as player ships shouldn't really have any special properties from my point of view; the number of ships being saved and restored will certainly have storage and CPU load implications, but it doesn't increase complexity.

Not saving NPS ship states for now is ok with me, but I think we should offset it by imposing some limit on when saving is possible. A few options suggest themselves, but the least dodgy is probably to base it on a minimum distance of the nearest NP ship from the player's fleet: if you reload a save made in the middle of a firefight and find you're exactly where you left off, but all NP ships are suddenly back at full hp and RU, you're not going to be best pleased, but we can probably get away with the fudge as long as they're not too nearby. It'll be a sledgehammer incentive not to abuse the feature, if nothing else.

Aside: it's struck me that a global lock counter might be needed to let some (one-off scripted or generated) missions temporarily disallow saving, if they're in the middle of some operation complex enough that they can't or don't want to try to persist its state across a save/reload. Shouldn't be difficult to add, so probably best not addressed until the need actually arises.

To handle multiple instances of the same subsim, you just keep looking until you find one that does not have the hard point property yet.

Yep, that's as far as I can get: unfortunately, I can't see anything short of a complete strip-and-rebuild done as early as possible after sim instantiation that'll make the final leap to establishing which of two PBC subsim objects corresponds to which of two PBC template[] numbers. It should be possible to save the states reliably, but when I restore them it'll be down to chance which template[] number gets which state -- since the template[] number determines position, this isn't a good thing. This may be overly pedantic: it's quite likely many people wouldn't even notice if their broken PBC suddenly switches places with their working one, but, having pursued this as far as 'nearly accurate', I'd like to go the rest of the way if at all possible.

Of course I am assuming that subsims keep a template name property.

Once I've been meddling with them, they have a CT_ int property if it's relevant (if it's not, they're welded on, in which case their url can safely be read from their parent's [Subsims] block), but by default they don't -- I think the only reliable identifying characteristic of a subsim object is its name. I'll wander off on a quick tangent on this, because I'm currently not filtering significant vs insignificant too well -- hell, might be useful to someone. You can get the class for most subsims, if you have to, via property checks, but I'm already using a hash in the Text database with name as key and class as value for that. If a subsim has a corresponding cargo type, you can do a (fairly grotesquely inefficient) reverse lookup of the name to get a CT_ enum, from which you can reach the subsim url via an iCargo.Find. Unless it's a missile magazine, in which case you'll (unmodded) get the sim url for the corresponding cargo pod -- since there's an ini file property trail from the subsim to the cargo pod (via the weapon), but not the other way, I think we should reverse this -- someone at PS set that particular relationship up on a Friday afternoon, IMO.

Final problem with resolving url from a subsim alone is that, unmodded, some subsims don't correspond to any cargo type, because they're always and only fixed subsystems (crew, reactor, dock ports) -- we could theoretically address that by making all subsystems load-out-able, but I'm not sure what we'd gain (dockports in loadout!? -- actually, I suppose you could give them a cargo_space requirement, which wouldn't be a million miles from the Spartacus's extra cannon set-up). Anyway, most of this is incidental if (a) we have a reliable way to bind subsims to template[] numbers and (b) you never want to derive a url from a subsim that isn't attached to a parent -- within those assumptions, I think we've got all the info we should need.

I am also assuming that all subsims that have physical shape changes on the ships have been removed, and replaced with invisible ones.

That could look odd on some ships, but it may be the workable. From what little time I've spend looking for visual side-effects of loadout changes, it appears to me so for that there simply aren't any: a sim's avatar looks as if it's defined at iShip.Create(), and nothing you do to it thereafter affects it. I have no idea how iShip.CreatePlayerShip() manages, but since it's a high-level interface to the same bunch of C++-native exceptional cases that iLoadout exposes (or doesn't), we may be wasting our time trying to duplicate it. It's arguably going to look equally odd if someone's stripped off all their guns to carry a torpedo meant for a larger class of ship, but they're still looking in-game at four guns and two missile launchers. I really haven't looked far into this yet, though, so I could be completely wrong.

While I've got missile peculiarities on my mind: have you thought at all about how you want to cope with the player unloading partial pods of missiles? As far as I remember, last consensus point on this issue was that a single (magazine, not launcher) hardpoint holds an indefinite number of missiles, limited only by cargo space. Of course, I can straightforwardly use the 'holds' property to convert, for instance, one seeker pod to 40 seekers, but what do I do when the player decides to return 17 seekers to inventory? I was never sure how the unmodded game was coping with this, to be honest -- the lack of resource drains meant I was never short enough of anything to bother looking.

Please Log in or Create an account to join the conversation.

More
21 years 2 months ago #5084 by EricMan64
I'm not exactly sure why you'd need to know which template number each subsim goes with. As far as Sim.NthSubsim() goes, the subsims are orriginally attached to the ship at the same numbers as the template numbers. If you mess with the subsims, you're likely to screw up that subsim ordering.

An option that's basically an in between to the two you mentioned, I'd make it so there's some 'initialise' function that can be called for the ship handle. This function would be called right after the actual ship creation function since otherwise the subsim orders would be off. The difference between this method and the new create ship function method is that you only need to do this extra code when you need the ships subsims to have the references. Otherwise it's not necessary.

Oh, I think I know why you need the template numbers. You need to know where the subsim goes when you remove it and need to put the mounpoint back in its place. I'd strongly suggest you do what I did and just leave the mountpoint subsims on the ship. That way, all the added and removed subsims happen with Sim.NthSubsim() numbers higher than the mountpoints. The mountpoint numbers never get messed with, and they always match up with the template numbers.

From what little time I've spend looking for visual side-effects of loadout changes, it appears to me so for that there simply aren't any: a sim's avatar looks as if it's defined at iShip.Create(), and nothing you do to it thereafter affects it.

I can confirm that just adding the subsims doesn't create the visual image of the ship. I assume the PS loadout code just identifies what extra avatar to attach and does so on its own as separate code. I haven't tried replacing that code myself since new loadouts are basically there for working with nonplayer ships that aren't usually designed for the extra weapon avatars themeselves anyway.

have you thought at all about how you want to cope with the player unloading partial pods of missiles?

Oh yeah, thanks for reminding me. I hadn't even though about what I was going to do yet for that in my code. I think with my code, if you unload and reload a pod right now, it'll be full again. That's what'll happen until I decide what to do and write special code to work with missiles. It shouldn't be too difficult.

Please Log in or Create an account to join the conversation.

More
21 years 1 month ago #5103 by Flamineo
Thanks for the input -- it's helpful at this point being able to compare notes.

originally posted by EricMan64
As far as Sim.NthSubsim() goes, the subsims are orriginally attached to the ship at the same numbers as the template numbers. If you mess with the subsims, you're likely to screw up that subsim ordering.

I've probably broken my installation, or maybe I'm plain looking at the wrong ini file, but my (well, GrandpaTrout's, this being the Epic test start-game script) ini:/sims/ships/player/fast_attack_prefitted has subsims in an order bearing no resemblance to its template[] entries (this is before I've done anything peculiar to it). If ships started out with their subsims in the right order, I'd just rely on that and bind their numbers as early as possible, but if it's not consistently the case, I'm not sure the strip-and-rebuild approach can be avoided. I'm not ecstatic about requiring an initialisation call immediately after ship creation (particularly since it requires all sorts of faffing about with undocking and redocking to prevent the game getting upset about me destroying dock ports when they're in use), but I don't see how else to guarantee the accurate mapping of subsims to template numbers.

I don't think leaving mountpoint subsims on ships is going to make sense for Epic: one of the requirements I'm working to is that the loadout code has to work for every ship in the game, coping gracefully with prefitted ships that never had mount points in the first place (more like unmodded NP than player ships in this respect). Everything a mountpoint subsim would tell me is in the indexed hardpoint ini data, anyway -- if the subsim numbers weren't (seemingly) being juggled about by iShip.Create(), that'd do me (or are you saying that mountpoints appear in template[] order, but other subsims don't?). Additionally, Shane would likely make with the blunt instruments were I to decide at this stage that I need mountpoint subsims on every ship.

On the ammo count issue, what I reckon we want to do is store the inventory count as number of rounds, rather than number of pods, and add a special case to the pod/inventory conversion that equates a pod to 40 (or whatever) rounds in inventory (and just refuses to make a pod if you can't fill it). I think that should work best from the point of view of a loadout system that allows ammo-based weapons to carry arbitrary numbers of rounds limited by cargo space, but I don't object if anyone's dead set on some alternative.

GrandpaTrout: on a vaguely related note, I think we need an iMultiplay.LinkShipWeapons() somewhere in the Epic final setup routine -- the two PBCs are selecting as separate weapons for me until I call it.

[edit]
I still don't know what the avatar story is, either, but it has occurred to me the game might be making some creative use of animation channels to make subsim renderings appear and disappear -- of course, I don't know the channel mechanism well, so that could be utter nonsense. I've raised it on Buda5's general forum -- if anyone outside PS can answer this one definitively, that's probably where they'll be found.
[/edit]

Please Log in or Create an account to join the conversation.