Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
# September
- [Laser weapons] given a tiny AoE to be able to damage small units in shallow water. As a side-effect, they can deal AoE damage to stacked air units.
- [T1 Air Constructors] -10 buildpower
- [Grunt, Pawn, Goblin] Script improvements. No longer fire sideways when switching targets mid-shot or going in and out of range
- [Mobile Jammers]
- Smuggler 48.3 -> 37 speed
- Deceiver, Tiresias: 39 -> 35 speed, 1550 -> 1300 energycost
- Umbra 33 -> 43 speed, 1700 -> 2000 energycost
- [Heavy Ships] -15 -> -8 minimum water depth - Able to pass into same shallow waters as other ships.
- [Legion changes]
- Perdition doesn't gain extra range from elevation
- Martyr damages are added to its team's damage dealt
Expand Down
6 changes: 6 additions & 0 deletions common/configs/keybind_catalog.json
Original file line number Diff line number Diff line change
Expand Up @@ -866,6 +866,12 @@
"7",
"8"
]
},
{
"prefix": "keybindprofile ",
"label": "actions.keybindProfiles.activate",
"description": "actions.keybindProfiles.activateDescription",
"membersFrom": "profiles"
}
]
},
Expand Down
2 changes: 2 additions & 0 deletions common/configs/keybind_catalog.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,11 @@
"additionalProperties": false,
"properties": {
"prefix": { "type": "string", "description": "Action id prefix." },
"description": { "type": "string", "description": "i18n key for a sentence saying what the actions in this family do, for a tooltip. Shared by every row the prefix matches, so it says what the family does rather than any one member. Optional, and falls back the same way an action entry's does." },
"label": { "type": "string", "description": "i18n key for the display label, interpolated per matched action." },
"unit": { "type": "boolean", "description": "When true, the arg after the prefix is a unit codename resolved to its translated human name." },
"members": { "type": "array", "items": { "type": "string" }, "description": "The args this family covers, appended to the prefix to form each action. Listing them makes the rows exist whether or not anything is bound, so unbinding one leaves it there to bind again. Omit for families that cannot be enumerated (buildunit_ is per unit) and they are discovered from what is bound." },
"membersFrom": { "type": "string", "enum": ["profiles"], "description": "Members this file cannot list because they are per player, named by where a surface reads them from instead. \"profiles\" is the name of every selectable keybind profile, shipped and the player's own, other than the active one, which a key could only switch to from itself. Use in place of members, not alongside it." },
"icon": { "type": "string", "description": "VFS path of a picture shared by every action in the family, drawn on its key in the keyboard overview. Optional." },
"alwaysModifier": { "type": "string", "enum": ["any"], "description": "Modifier this action always tolerates, so a surface neither shows it nor lets the player pick it. \"any\" binds with the engine's Any+ qualifier and fires whatever is held. Fixed per action rather than chosen." }
}
Expand Down
36 changes: 33 additions & 3 deletions common/configs/keybinds.README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,16 @@ form each action. Listing them makes those rows exist whether or not anything is
unbinding one leaves it there to bind again. Families that cannot be enumerated - `buildunit_`
is per unit - list none and are discovered from what is bound instead.

Where the members exist but are the player's rather than the game's, the entry names where
to read them with `"membersFrom"` instead of listing them. The one source is `"profiles"`,
which is what `keybindprofile ` covers: one bindable action per profile, named after it, so
a key means the same profile whatever is active.

That source is every selectable profile, shipped and the player's own, except the active
one - switching to the profile already loaded can only do nothing. A key that already names
the active profile is still read from the keymap and listed, so there is somewhere to remove
it from.

An entry may carry `"alwaysModifier"`, naming a modifier the action always tolerates so no
surface shows it or lets the player pick it:

Expand Down Expand Up @@ -121,7 +131,11 @@ Structure lives in the schemas; these are the operations, which a schema can't e
Every surface answers the same questions from the same facts.

The player's own profiles live in `LuaUI/Config/keybind_profiles.json`, in the same
shape as the shipped ones plus an `active` field naming the selected profile. That file
shape as the shipped ones plus an `active` field naming the selected profile and a
`written` field recording the keymap last emitted - `{ "name": <profile>, "stamp": <stamp> }`.
The stamp stands for the bindings the file holds rather than its bytes, so changing how the
file is emitted does not make every player's keymap read as edited; it is taken over the same
normalised `<keyset> <action>` lines a comparison uses, plus the meta key. That file
is per-install rather than shared, but its format is the contract - a surface that can
read one can read the other.

Expand All @@ -148,12 +162,28 @@ the clipboard and what Import reads back, and the same text a player would put i
reload. Reloading clears the keymap first, which is why a profile has to define every
binding it wants. It does not clear the meta key, so always write that line: leave it out
and whatever the last profile set stays. A profile naming no key wants the engine's own,
`space`; `fakemeta none` asks for no Meta modifier at all.
`space`; `fakemeta none` asks for no Meta modifier at all. Record what was written in the
store as `written`, above - a surface that skips this makes the next launch read its own
output as a keymap the player hand-wrote.
- **Reconcile on load.** Either side can have moved since the keymap was written: a game
update changes a shipped profile, or a tool changes the store between sessions. Compare the
keymap on disk against `written.stamp`. Equal means nobody has touched the file, so the
store is the authority and the selected profile is written out again, carrying whichever
change it was. Unequal means the player edited the file themselves, and that is kept as a
profile of theirs rather than overwritten. Where there is no stamp to compare - a store from
before this was recorded, or a player who points the engine at a keymap file of their own -
fall back to matching the whole keymap against every profile first, which still says nobody
edited it and stops a file being copied afresh on every launch. That older test cannot tell a
profile that changed from a file that did, so do not change a shipped profile in the same
release that starts recording stamps.
- **Edit a binding.** Only in the player's own profiles. Shipped profiles are read-only,
so the first edit made while one is selected forks it into a copy and edits that.
- **Create / rename / delete.** Names are the identity, so they must stay unique across
both files; disambiguate rather than overwrite. Deleting the active profile means
falling back and applying whatever is left.
falling back and applying whatever is left. A name is also an id inside the keymaps,
because `keybindprofile <name>` is what a key switching to that profile is bound to, so
a rename has to rewrite those binds everywhere they appear and a delete has to drop
them - in every profile, not just the one being changed.

### Same rules, different plumbing

Expand Down
6 changes: 6 additions & 0 deletions gamedata/alldefs_post.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1067,6 +1067,12 @@ local function weaponDef_Post(name, wDef)
end
end

if wDef.weapontype == "BeamLaser" and wDef.impactonly == 1 then
wDef.impactonly = nil
wDef.areaofeffect = 11
wDef.edgeeffectiveness = 1
end

-- Remove water splashes on lava maps
if modOptions.map_waterislava and wDef.weapontype == "TorpedoLauncher" then
wDef.explosiongenerator = "custom:blank"
Expand Down
2 changes: 1 addition & 1 deletion gamedata/movedefs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ local moveDatas = {
BOAT9 = {
crushstrength = CRUSH.HEAVY + 2,
footprint = 9,
minwaterdepth = DEPTH.SUBMERGED,
minwaterdepth = DEPTH.MIN_SHALLOW,
},

--critter_goldfish coracsub armacsub armserp corrsub armsubk correcl corshark corsub
Expand Down
4 changes: 4 additions & 0 deletions language/en/commands.json
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,10 @@
},
"spectating": {
"spectate": "Spectate team %{n}"
},
"keybindProfiles": {
"activate": "Switch to %{n}",
"activateDescription": "Loads this keybind profile, replacing every key you have bound."
}
},
"categories": {
Expand Down
39 changes: 32 additions & 7 deletions language/en/interface.json
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@
"allCategories": "All",
"search": "Search actions or keys...",
"boundTo": "Bound to %{keys}",
"boundToAny": "Also fires on this key with any modifier held",
"boundToAny": "Also fires on these keys with any modifier held",
"preset": "Preset",
"defaultTag": "Default",
"pressKey": "Press a key or mouse button...",
Expand Down Expand Up @@ -274,7 +274,7 @@
"conflictCapture": "Also bound to: %{actions}",
"defaultIn": "Default in %{name}: %{keys}",
"defaultNone": "Not bound in %{name}",
"revertHint": "Click to put the default keybind back.",
"revertTooltip": "Reset keybind back to %{keys}",
"revertNone": "none",
"revertChip": "default: %{keys}",
"presetDefault": "A default preset. It cannot be changed; editing it saves a new preset of your own.",
Expand All @@ -286,7 +286,7 @@
"import": "Import",
"importTooltip": "Read a preset from text on the clipboard and add it as a new preset.",
"keyboard": "Keyboard",
"keyboardTooltip": "Show this preset's keybinds laid out on a keyboard. Click Shift, Ctrl, Alt or Meta on it to see what the keys do with that held; click again for the list.",
"keyboardTooltip": "Show this preset's keybinds laid out on a keyboard.\nClick Shift, Ctrl, Alt or Meta on it to see what the keys do with that held.\nClick again for the list.",
"importTitle": "Import preset",
"importEmpty": "The clipboard is empty. Copy a preset's text first, then try again.",
"importSummary": "%{n} keybinds found",
Expand Down Expand Up @@ -393,10 +393,33 @@
"composition": "Composition",
"compositionDesc": "The team's unit value split by kind over the game, as shares of the whole.",
"foldHint": "Click to fold this team's players away, and again to show them.",
"legendHint": "Click to highlight this team and show its milestones; right-click to hide it.",
"blockHint": "The players of this ally team; each square is one of them.",
"all": "All",
"allHint": "Every team alike, with all their milestones on the chart.",
"allHint": "Clears the selection and shows hidden teams again, so every team is drawn alike.",
"allMilestones": "Every team's milestones go on the chart.",
"teams": "%{count} teams",
"players": "%{count} players",
"state": {
"hidden": "Hidden: left off the chart.",
"lit": "Selected: drawn in front at full strength, the others faded.",
"only": "Selected: on the chart.",
"counted": "Selected: counted in the composition.",
"some": "Some of its players are selected.",
"faded": "Not selected: faded behind the selected.",
"left": "Not selected: left off while others are selected.",
"notCounted": "Not selected: left out of the composition.",
"alike": "Nothing is selected: every team is drawn alike.",
"allCounted": "Nothing is selected: every team is counted in the composition.",
"milestones": "Its milestones are on the chart.",
"milestonesGroup": "Their milestones are on the chart."
},
"control": {
"click": "Click: select or deselect",
"clickGroup": "Click: select or deselect all its players",
"ctrlClick": "Ctrl+click: select only this one",
"ctrlClickGroup": "Ctrl+click: select only its players",
"rightClick": "Right-click: hide or show",
"rightClickGroup": "Right-click: hide or show all its players"
},
"waiting": "The first samples arrive after 15 seconds.",
"noData": "Nothing to plot for this stat yet."
},
Expand Down Expand Up @@ -430,7 +453,9 @@
"bars": "Bars",
"barsDesc": "A bar behind every number, scaled to the largest in its column.",
"milestones": "Milestones",
"milestonesDesc": "The highlighted team's milestones as unit pictures on the chart, every team's when none is highlighted; hover one for what it was."
"milestonesDesc": "Milestones as unit pictures on the chart, framed in their player's colour: the selected teams', every team's when none is selected. Hover one for whose it was and what.",
"selectedOnly": "Selected only",
"selectedOnlyDesc": "Only the teams selected in the bar above the chart are drawn. Off, every team is drawn and the selected ones stand out in front."
},
"damage": "Damage",
"damageDealt": "Dealt",
Expand Down
Loading
Loading