FreeSpace Releases > Scripting Releases
Change Name Script
FelixJim:
For a mission idea I had, I wanted to change a ship's name. Knowing that this was impossible an extremely bad idea, I FREDed a solution which involved some ship-create and ship-vanish trickery. I got this working, but found it was quite messy every single time I wanted to do it. Instead I decided to try and write a script that did this for me. It's worth noting that my entire experience in programming is the first few chapters of a beginners book of C++ a few years ago, and although this script seems to work, I've so little experience in this sort of thing I don't know where the pitfalls are, and I'm sure I've included an awful lot of bad practices if nothing else. I'm basically putting this out here for the critique I need so I know where I'm going wrong (bound to be something on a first attempt).
tl;dr: This isn't a release so much as a "please give advice" (although feel free if you do want to use it despite the lack of guarantees that it will work).
--- Code: ---#Conditional Hooks
$Application: FS2_Open
$On Game Init:
[
--Swap first ship (old) with a similar ship (new) to give the illusion that the ship's name has changed
--Most obvious omission is the lack of any control over orders - will need to FRED these back in
cn = function (old, new)
local oldship = mn.Ships[old] --Create a handle for the old ship
local newship = mn.createShip(new, oldship.Class, oldship.Orientation, oldship.Position) --Create the new ship
--Copy over information from the old to the new ship
mn.runSEXP("ship-copy-damage !" .. old .. "! !" .. new .. "!")
newship.Team = oldship.Team
newship.AfterburnerFuelLeft = oldship.AfterburnerFuelLeft
newship.CountermeasuresLeft = oldship.CountermeasuresLeft
newship.WeaponEnergyLeft = oldship.WeaponEnergyLeft
--Physics
--This seems to be the cleanest way to keep the ship moving uninterrupted, but requires a delay before changing back (ohgodno)
newship.Physics.ForwardAccelerationTime = 0
local i = 1
while cn_ph[1][i] ~= nil and cn_ph[i][1] ~= false do --Find the first empty row of cn_ph
i = i + 1
end
cn_ph[1][i] = newship.Name --Copy over information needed to later change back the forward acceleration
cn_ph[2][i] = oldship.Physics.ForwardAccelerationTime
cn_ph[3][i] = mn.getMissionTime()+1
--Transfer Cargo
--This causes a null vec3d error... but not on its own. Most likely related to Mantis ticket 0002787, but doesn't cause any problems here
local dock = oldship.Class.Model.Dockingbays --Get a handle on the dockingbays
if #dock > 0 then --Requires a docking point
local dockname = dock[1]:getName() --Pick the first dockingbay
mn.runSEXP("jettison-cargo-delay !" .. old .. "! !0!") --Make sure old's dockingbay is free
mn.runSEXP("set-docked !" .. old .. "! !" .. dockname .. "! !" .. new .. "! !" .. dockname .. "!") --New doesn't move here
mn.runSEXP("transfer-cargo !" .. old .. "! !" .. new .. "!") --Transfer the cargo
mn.runSEXP("jettison-cargo-delay !" .. old .. "! !0!") --Undock ships
end
--If player knows what the old ship's cargo is, should know new cargo too
if (mn.evaluateSEXP("(is-cargo-known-delay !0! !" .. old .. "!)")) then
mn.runSEXP("set-scanned !" .. new .. "!")
end
--If player has old ship targeted, should now target new ship
if hv.Player.Target == oldship then
hv.Player.Target = newship
end
--If old ship is on escort list, new ship should be too (not necessarily same priority)
if #mn.EscortShips > 0 then --Don't bother doing anything if no ships are escorted
for i=1,#mn.EscortShips do --Cycle through escort ships to check if any are the old ship
if mn.EscortShips[i] == oldship then
mn.runSEXP("add-remove-escort !" .. new .. "! !50!") --Add new ship to escort list
break --No need to run through rest of escort list
end
end
end
mn.runSEXP("ship-vanish !" .. old .. "!") --Vanish the old ship
end
]
$On Gameplay Start:
[
cn_ph = {} --Global table used for the delay required during physics section of cn()
for i=1,3 do --3 columns
cn_ph[i] = {} --dynamic # of rows
end
]
$State: GS_STATE_GAME_PLAY
$On Frame:
[
if cn_ph ~= nil then --Prevent calling before creation or after housekeeping
for i=1,table.getn(cn_ph) do --Cycle through cn_ph for entries to change the forward acceleration back from the physics section of cn()
if cn_ph[1][i] and mn.getMissionTime() > cn_ph[3][i] then
mn.Ships[cn_ph[1][i]].Physics.ForwardAccelerationTime = cn_ph[2][i]
cn_ph[1][i] = false --Free up this row to be used again (other columns will just be overwritten)
end
end
end
]
$On Mission End:
[
--Housekeeping
cn_ph = nil
]
#End
--- End code ---
One thing that has just occurred to me is that a ship named "false" very well might screw parts of this up... oops. Anyway, I'll see what you make of it as it is.
EDIT: I forgot to mention the known limitations of the script. Anything non-standard about the ship (changed loadout, for example) won't be preserved (could probably add this in, but as I don't need it for my use I won't bother unless others are interested in using it). The ship's orders will have to be re-given - I can see how to give orders via scripting, but I don't think you can access the ship's current orders, so it wouldn't know what orders to give. With regards to the motion of the ship, I've tried to build the script to give best results when the ship is following a waypoint and has already reached top speed; any other situation might cause a second of odd behaviour. I can't see a way to access the escort priority of the ship either, so if the original ship was in the escort list the new ship will be too, but always at priority 50, regardless of what the original ship was at. If the original ship has no docking points then the cargo won't be copied over. And as I mentioned before, if the new ship's name is "false", then I think it's forward acceleration will be permanently reduced to 0 (unverified). And... I think that's it.
EDIT2: No it isn't. If the original ship was docked to something this won't be preserved. I don't think this is possible, I'm not sure. This is a kind of hacky way of going about a simple name change, so there's probably a million and one other details that are lost (whether the ship is protected, other ships' orders regarding the original ship.... pretty much any of the Additional Ship Properties or locked weapons/afterburner, callsign, alt name, texture replacement, departure info are all things that are coming to mind even as I write). I'd really like to have a list of all the information the engine stores about a ship so I can tick things off as handled, potentially handleable or "you will need to reset this manually via sexp once script has run", but I haven't a clue where/how I'd get such a list.
mjn.mixael:
Tagged. I'm interested in this.
FelixJim:
Interested enough to test it at all? I was hoping for a bit more of a response, but I'd be glad of any feedback.
zookeeper:
Here's what I'd do...
--- Code: ---#Conditional Hooks
$Application: FS2_Open
$On Game Init: [
cn = function(oldname, newname)
mn.Ships[oldname].Name = newname
end
]
--- End code ---
What makes you think that would be an extremely bad idea, especially in comparison to your method?
Admiral MS:
--- Quote from: zookeeper on February 08, 2013, 03:04:09 am ---Here's what I'd do...
--- Code: ---#Conditional Hooks
$Application: FS2_Open
$On Game Init: [
cn = function(oldname, newname)
mn.Ships[oldname].Name = newname
end
]
--- End code ---
What makes you think that would be an extremely bad idea, especially in comparison to your method?
--- End quote ---
When I saw this thread the first time I thought the same and tested it but for some reason the game ignored the change of .Name completely outside of scripting. What I found is that at least in my test cases the game didn't seem to care about two ships having identical names when one of them is created after mission start.
Then some general things I noticed in FelixJim's script:
I can't see any reason why you want to delay the physics setup at all (and even if a delay is necessary one frame should be fine).
Setup of docking and escort lists is something I would do in FRED using normal variables and events because both can be accessed or are known by the FREDer and can be really mission specific and tricky.
Ship create makes it hard to use that ship in events (FRED should complain all the time).
Navigation
[0] Message Index
[#] Next page
Go to full version