Repository navigation
Add weapon templates - #7850
Draft
dustinspace217 wants to merge 4 commits into
Draft
Add weapon templates#7850dustinspace217 wants to merge 4 commits into
dustinspace217 wants to merge 4 commits into
Conversation
Copies every member of a weapon class, following ship_info::clone, so a weapon can be created from another as ship templates do. The CLONE_UNIQUE_PTR macro moves from ship.cpp to utils/string_utils.h so both clone functions share it.
A #Weapon Templates section in weapons.tbl and *-wep.tbm holds $Template: entries that take the full weapon syntax. A weapon starts from one with +Use Template:, or from an already parsed weapon with +Use Weapon as Template:; a template can use another template. The rules follow ship templates: a template is never a weapon, +nocreate and +remove on a template are ignored with a warning, duplicate and missing names warn, a template or weapon naming itself warns, and a weapon that already exists ignores a template request with a warning. A template may declare $Subtype:, in which case it is parsed exactly as a weapon in that section would be. Without one it is parsed outside any section: no section-dependent defaults or fix-ups are applied to it, and the section-only fields are still accepted. A weapon built from such a template gets its section's missile flag default; where the section would have supplied a value the template left unset (homing free flight time, ballistic rearm rate) the engine warns instead of overwriting, so an explicit template value is never replaced by a default. The clone copies the animation set, so the set is re-keyed to the new weapon's name as ship clones are; the weapon parse now sets the set's name before reading $Animations: so that re-keying has something to work from. A substitution pattern that named the template now names the derived weapon. An inherited $On Create: program survives a derived entry that does not restate it. Every parse-time side table (delayed SSM entries, the legacy particle-spew buffer, pending proximity type and class names) is keyed by a string that tells templates and weapons apart, copied under the new name on a clone and dropped for templates after post-parse. The proximity lists were keyed by index into Weapon_info, which a template does not have and which the type sort reorders before the lists are consumed; the name key fixes both. A numeric $SSM: on a derived weapon retires an inherited named entry. weapon_close() now clears Weapons_inited and the pending proximity lists so the tables can be parsed again, which the unit tests rely on. Fixes scp-fs2open#7343
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What?
Adds weapon templates, the second of the two PRs discussed in #7343. A
#Weapon Templatessection in weapons.tbl and*-wep.tbmholds$Template:entries that take the full weapon syntax. A weapon starts from one with+Use Template:, or from an already parsed weapon with+Use Weapon as Template:, and a template can itself use a template. Templates never become weapons.This is stacked on #7847 (
weapon_info::clone()), so it carries that commit until #7847 merges; it opens as a draft for that reason.Why?
Modders asked for the same thing ships have had since #Ship Templates: a way to define a family of weapons once and vary a few fields per entry, without copying whole weapon blocks or worrying that a tweak for one campaign changes the balance of another. Today the only way to share a definition between two weapons is to paste it.
How?
The parse mirrors ship templates.
parse_weapon()takes a fourth parameter saying whether it is reading a$Template:entry; the entry then lands in a separateWeapon_templateslist instead ofWeapon_info, and the rest of the weapon parser runs unchanged on it. A weapon that names a template is created as usual and thenclone()d from it before its own fields are read, with its name put back andfirst_timeturned off so first-parse defaults do not overwrite template values. The rules follow ships:+nocreateon a template is ignored with a warning, duplicate and missing names warn, a template naming itself is refused.Templates and sections: a template may declare
$Subtype:and is then parsed exactly as a weapon in that section. Without one it is parsed outside any section: no section-dependent defaults or fix-ups touch it (the ballistic flag is not stripped, the rearm batch stays unset), and the section-only fields ($Freeflight Effect:,$On Create:and friends) are still accepted. A weapon built from an untyped template gets its section's missile flag default; where the section would have filled a value the template left unset (homing free flight time, ballistic rearm rate), the engine warns instead of overwriting, so an explicit template value is never replaced by a default. Declaring$Subtype:on a template avoids those warnings.Deliberate differences from ships, each for a reason in the code's history:
clone()copies the animation set with anoperator=that appends to a non-empty set.$Animations:parse now does. A$substitute:pattern that named the template now names the derived weapon, and an inherited$On Create:program survives a derived entry that does not restate it.Weapon_info, which a template does not have and which the type sort reorders before the lists are read; the name key fixes both. A numeric$SSM:on a derived weapon retires an inherited named entry.$Display Name:.weapon_close()now clearsWeapons_initedand the pending proximity lists so the tables can be parsed again, which the unit tests need.Known limits, same as a modular-table edit and as ship templates: a derived weapon that adds a capability its template lacked (homing, mine, interceptable, a shockwave) does not get that capability's first-parse defaults (seeker strength, weapon hitpoints, dinky shockwave) and should state them. A beam
+Index:on a derived weapon edits the inherited sections rather than warning. A beam-typed template cannot carry$On Create:, as a beam weapon cannot today.weapon_infoitself is unchanged.Testing?
test/src/weapon/weapons.cpp, each with its own table undertest/test_data/weapon/: inheritance, override, template-of-template, weapon-as-template, display names (hash, German, explicit), untyped-template behaviour (ballistic flag kept, rearm batch by section, free flight kept or warned), proximity lists, same-name template and weapon with$SSM:, numeric$SSM:override, substitution pattern, and every warning path pinned to its message. The bug-fixing tests were watched failing before each fix. Full suite 278 pass under--gtest_shuffle. Four hand mutants (nofirst_time = falseafter the clone, defaults forced off, name not restored, no template clear at init) each killed by the tests meant for them.-wep.tbmwith templates, run headless through fso-harness on OpenGL and on Vulkan: table validation clean apart from one pre-existing MediaVPs warning, a mission launched, and the derived weapons read back through Lua (inherited title and fire wait, own damage, a copy of a retail weapon with the original untouched, an untyped template used as a secondary).Anything Else?
The wiki pages for weapons.tbl will need a section on templates; I can write that once the syntax is settled here.
I used Claude Code to write the parser changes and the tests, and it ran the engine checks.