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
5 changes: 2 additions & 3 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,9 @@ jobs:
name: docs-html
path: target
- name: Deploy
uses: crazy-max/ghaction-github-pages@v1
uses: crazy-max/ghaction-github-pages@v2
with:
target_branch: gh-pages
build_dir: target # The folder the action should deploy.
committer_name: X2CommunityCore-Docs-Bot
env:
GITHUB_PAT: ${{ secrets.ACCESS_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
63 changes: 54 additions & 9 deletions .scripts/make_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import shutil

from enum import Enum
from typing import List, Optional
from typing import List, Optional, Iterable

HL_DOCS_KEYWORD = "HL-Docs:"
HL_INCLUDE_FOLLOWING = "HL-Include:"
Expand Down Expand Up @@ -195,18 +195,57 @@ def parse_file(self, file, filename):

doc_items = []

generate_builtin_features(doc_items)

parser = Parser(doc_items)
with open(file, errors='replace') as infile:
parser.parse_file(infile, file)

return doc_items


def merge_doc_refs(doc_items: List[dict]) -> List[dict]:
items = dict((i["feature"], i) for i in doc_items if not "ref" in i)
refs = [i for i in doc_items if "ref" in i]
def partition_items(doc_items: List[dict]) -> int:
"""
Partition the array and check for duplicates, returning the start index
of the refs (where features end)
"""
def cmp_doc_item(doc_item: dict) -> (bool, str):
is_feat = "feature" in doc_item
return (not is_feat,
doc_item["feature"] if is_feat else doc_item["ref"])

doc_items.sort(key=lambda i: cmp_doc_item(i))

first_def = None
seen = False
for idx, it in enumerate(doc_items):
if not "feature" in it:
break

def make_loc(it: dict) -> str:
if "texts" in it and len(it["texts"]) > 0:
return "at %s:%s" % (it["texts"][0]["file"],
it["texts"][0]["span"][0] + 1)
else:
return "due to builtin feature"

if first_def != None and it["feature"] == first_def["feature"]:
# Report duplicate feature definition
if not seen:
err("duplicate feature definition `%s`" % (it["feature"]),
False)
print("note: first definition %s" % (make_loc(first_def)))
seen = True
print("note: this definition %s" % (make_loc(it)))

else:
first_def = it
seen = False

return idx


def merge_doc_refs(doc_items: List[dict], refs_start: int) -> Iterable[dict]:
items = dict((i["feature"], i) for i in doc_items[:refs_start])
refs = doc_items[refs_start:]

for ref in refs:
if ref["ref"] in items:
Expand Down Expand Up @@ -254,7 +293,9 @@ def render_bugfix_page(item: dict, outdir: str):

def render_full_feature_page(item: dict, outdir: str):
if not "tags" in item:
err("Feature '%s' does not have a 'tags' key/annotation" % (item["feature"]), False)
err(
"Feature '%s' does not have a 'tags' key/annotation" %
(item["feature"]), False)
return

if "strategy" in item["tags"] and not "tactical" in item["tags"]:
Expand Down Expand Up @@ -322,7 +363,7 @@ def render_tag_page(tag: str, items: List[dict], outdir: str):
file.write("\n")


def render_docs(doc_items: List[dict], outdir: str):
def render_docs(doc_items: Iterable[dict], outdir: str):
ensure_dir(outdir)

outdir = os.path.join(outdir, "docs")
Expand Down Expand Up @@ -366,7 +407,10 @@ def main():
global exit_code
indirs, outdir, docsdir = parse_args()
copytree(docsdir, outdir)

doc_items = []
generate_builtin_features(doc_items)

for docdir in indirs:
for root, subdirs, files in os.walk(docdir):
for file in files:
Expand All @@ -376,7 +420,8 @@ def main():
if ext in known_exts:
doc_items.extend(process_file(infile, known_exts[ext]))

doc_items = merge_doc_refs(doc_items)
refs_start = partition_items(doc_items)
doc_items = merge_doc_refs(doc_items, refs_start)

if outdir != None:
render_docs(doc_items, outdir)
Expand Down
33 changes: 0 additions & 33 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,13 @@ RunPriorityGroup=RUN_STANDARD
- Triggers the events `OverrideUIArmoryScale`, `OverrideUIVIPScale`, and `OverrideCharCustomizationScale` for strategy unit scaling (#229)
- Triggers the event `RegionOutpostBuildStart` to add a strategy reward similar to the 'Resistance Network' resistance order, but for Radio Relays instead of Network Contacts. (#279)
- Triggers the event `GeoscapeFlightModeUpdate` to allow mods to respond to geoscape mode change (#358)
- Triggers the event `UIAvengerShortcuts_ShowCQResistanceOrders` to allow to override the presence of Resistance Orders button in `UIAvengerShortcuts` (#368)
- Triggers the event `Geoscape_ResInfoButtonVisible` to allow to override the visibility of resistance orders button in `UIStrategyMap_HUD` (#365)
- Triggers the event `NumCovertActionsToAdd` to allow mods to modfiy number of Covert Actions (#373)
- Triggers the event `CompleteRespecSoldier` when a training center soldier respec was completed. (#339)
- Triggers the events `UIArmory_WeaponUpgrade_SlotsUpdated` and `UIArmory_WeaponUpgrade_NavHelpUpdated`
in `UIArmory_WeaponUpgrade` (#417)
- Triggers the event `GetCovertActionEvents_Settings` to allow showing all covert actions in the correct order in the event queue (#391)
- Triggers the event `CovertActionRisk_AlterChanceModifier` when calculated covert action risks. (#434)
- Triggers the event `AllowDarkEventRisk` during XComGameState_CovertAction::EnableDarkEventRisk to allow alterations of standard logic (#434)
- Triggers the event `AllowDarkEventRisk` during XComGameState_CovertAction::CreateRisks to allow alterations of standard logic (#692)
- Triggers the event `UIStrategyPolicy_ScreenInit` at the end of UIStrategyPolicy::InitScreen (#440)
- Triggers the event `UIStrategyPolicy_ShowCovertActionsOnClose` on UIStrategyPolicy::CloseScreen call (#440)
- Triggers the event `CovertAction_ShouldBeVisible` on XComGameState_CovertAction::ShouldBeVisible call (#438)
- Triggers the event `CovertAction_CanInteract` on XComGameState_CovertAction::CanInteract call (#438)
- Triggers the event `CovertAction_ActionSelectedOverride` on XComGameState_CovertAction::DisplaySelectionPrompt call (#438)
Expand All @@ -70,7 +65,6 @@ RunPriorityGroup=RUN_STANDARD
- Triggers the event `CovertAction_ModifyNarrativeParamTag` on XComGameState_CovertAction::GetNarrative call (#438)
- Triggers the event `ShouldCleanupCovertAction` to allow mod control over Covert Action deletion. (#435)
- Triggers the event `BlackMarketGoodsReset` when the Black Market goods are reset (#473)
- Triggers the event `OverrideImageForItemAvaliable` to allow mods to override the image shown in eAlert_ItemAvailable (#491)
- Triggers the event `OverrideCurrentDoom` to allow mods to override doom amount for doom updates (#550)
- Triggers the event `PreEndOfMonth` to notify mods that the game is about to start its end-of-month processing (#539)
- Triggers the event `ProcessNegativeIncome` to allow mods to do their own processing when XCOM's income at the
Expand Down Expand Up @@ -110,17 +104,12 @@ RunPriorityGroup=RUN_STANDARD
- Triggers the event `CovertActionAllowCheckForProjectOverlap` to allow mods to forbid the "de-bunching" logic
on CA start (#584)
- Triggers the event `AllowActionToSpawnRandomly` to allow mods to prevent certain CAs from being randomly spawned (#594)
- Triggers the event `OverridePromotionUIClasses` to allow mods to override the UI classes used for the
three different promotion screens (#600)
- Triggers the event `OverrideRespecSoldierProjectPoints` to allow mods to customize how long it should
take to respec a given soldier (#624)
- Triggers the event `OverrideScienceScore` to allow mods to override the XCOM HQ science score, for
example to add their own bonuses or to remove scientists that are engaged in other activities.
- Triggers the event `CanTechBeInspired` to allow mods to block techs from being inspired, even if they
meet the vanilla game's conditions for it (#633)
- Triggers the event `OverrideMissionImage` to allow mods to customize mission's image (used in UIMission and subclasses) (#635)
- Triggers the event `UIResistanceReport_ShowCouncil` to allow mods to override whether the council guy (and his remarks)
is shown on the end-of-month report or not (#663)
- Triggers the event `OverrideNextRetaliationDisplay` to allow mods to customize and/or enable/disable "next retaliation"
display in `UIAdventOperations` (#667)
- Triggers the event `ItemAddedToSlot` & `ItemRemovedFromSlot` to allow mods to change Items that have been Equipped/Unequipped during runtime(#694)
Expand All @@ -132,7 +121,6 @@ RunPriorityGroup=RUN_STANDARD

### Modding Exposures
- Allows mods to add custom items to the Avenger Shortcuts (#163)
- UIScanButton now calls OnMouseEventDelegate (#483). Note: DO NOT call ProcessMouseEvents, just set the delegate directly
- Remove `private` from `X2AIBTBehaviorTree.Behaviors` so that mods can change the behavior trees without
overwriting all the necessary entries (#410)
- Removed `protectedwrite` from `AcquiredTraits`, `PendingTraits`, and `CuredTraits` in `XComGameState_Unit`, allowing Traits to be modified by external sources (#681)
Expand All @@ -154,11 +142,6 @@ RunPriorityGroup=RUN_STANDARD
- Class mods adding an eight rank will now interact better with classes with seven ranks (#1)
- Allow `XComGameState_WorldRegion::DestinationReached` to use any XCGS_GeoscapeEntity class (#443)
- Add AmbushMissionSource name property to XComGameState_CovertAction; mods can now specify the ambush mission on creation of Action GameState (#485)
- Customization localizations now picked up for Torso/Legs/Arms. If the TemplateName already
contains the parttype name (ie Torso/Legs/Arms), then the object name in the localization file
matches as for other parts (in particular this means Anarchy's Children localizations which already exist in the files
are picked up automatically). Otherwise, "_Torso"/"_Legs"/"_Arms" is appended to the template name
to create the unique object name. (#328)

### Fixes
- Fix an issue in base game where strategy X2EventListenerTemplates only
Expand Down Expand Up @@ -271,8 +254,6 @@ RunPriorityGroup=RUN_STANDARD
- Allow aliens and other teams to properly register non-XCOM unit locations to adjust their positions accordingly (#619)

### Fixes
- Fixed XCGS_Unit::GetStatModifiers() as XCGS_Unit::GetStatModifiersFixed(),
X2AbilityToHitCalc_StandardAim, the only vanilla user of this method, changed to match(#313)
- Allow abilities that deal damage without a source weapon to still display
their damage with psi flyovers (Psi Bomb, mod abilities) (#326)
- Make disorient reapply to disoriented units so that things like flashbangs can
Expand Down Expand Up @@ -307,18 +288,10 @@ RunPriorityGroup=RUN_STANDARD
- `AbilityTagExpandHandler_CH` expands vanilla AbilityTagExpandHandler to allow reflection

### Event Hooks
- Triggers the events `SoldierClassIcon`, `SoldierClassDisplayName`,
`SoldierClassSummary` that allow replacement of the class icon/display
name/summary dynamically e.g. depending on UnitState or Soldier Loadout,
and adds accessor functions for those to XComGameState_Unit. (#106)
- `GetPCSImageTuple` added to allow customising PCS Image string (#110)
- Triggers the event `OverrideHasHeavyWeapon` that allows to override the result of `XComGameState_Unit.HasHeavyWeapon` (#172)
- `OverrideItemMinEquipped` added to allow mods to override the min number of equipped items in a slot (#171)
- `AddConversation` added to allow mods to change narrative behavior before they are played (#204)
- `OverrideRandomizeAppearance` added to allow mods to block updating appearance when switching armors (#299)
- `XComGameState_Unit` triggers `SoldierRankName`, `SoldierShortRankName` and
`SoldierRankIcon` events that allow listeners to override the those particular
properties of a soldier's rank, i.e. rank name, short name and icon (#408)

### Configuration
- Able to list classes as excluded from AWC Skill Rolling, so they can still
Expand Down Expand Up @@ -381,16 +354,10 @@ RunPriorityGroup=RUN_STANDARD
flag on `XComGameState_Unit`. This behavior is gated behind the new `CHHelpers.PreserveProxyUnitData`
config variable. (#465)
- Adds CustomDeathAnimationName property to X2Action_Death that allows overriding the default death animations (#488)
- Change `GetScreen()` and `IsCurrentClass()` on `UIScreenStack` to take into account subclasses
by default. This is a breaking change but fixes a lot of problems with vanilla and mod code that
mistakenly ignores subclasses of screens, particularly those provided by mod. The original behavior
can still be accessed via new `GetScreen_CH()` and `IsCurrentClass_CH()`. (#290)
- Allow PCS granting PsiOffense to be equiped by other classes than PsiOperative (#602)
- Added Inventory Slots `eInvSlot_Wings` and `eInvSlot_ExtraBackpack`. (#678)

### Fixes
- Fixes game terminating SoundCue narrative moments after three seconds because
it assumes they didn't play at all. (#66)
- Fixes UIPanels animating in with a huge delay when they are direct child panels of
UIScreen (#341)
- Appearances now update correctly when a part change differs only by material override (#354)
Expand Down
12 changes: 12 additions & 0 deletions CookCommunityHighlander.bat
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,24 @@ echo Copying Engine.upk to SDK Highlander mod folder...
copy /Y "%SDKLocation%\XComGame\Published\CookedPCConsole\Engine.upk" "%SDKLocation%\XComGame\Mods\X2WOTCCommunityHighlander\CookedPCConsole\Engine.upk"
copy /Y "%SDKLocation%\XComGame\Published\CookedPCConsole\Engine.upk.uncompressed_size" "%SDKLocation%\XComGame\Mods\X2WOTCCommunityHighlander\CookedPCConsole\Engine.upk.uncompressed_size"

echo.
echo Copying Core.upk to local Highlander mod folder...
copy /Y "%SDKLocation%\XComGame\Published\CookedPCConsole\Core.upk" "%GameLocation%\XComGame\Mods\X2WOTCCommunityHighlander\CookedPCConsole\Core.upk"
copy /Y "%SDKLocation%\XComGame\Published\CookedPCConsole\Core.upk.uncompressed_size" "%GameLocation%\XComGame\Mods\X2WOTCCommunityHighlander\CookedPCConsole\Core.upk.uncompressed_size"

echo.
echo Copying Core.upk to SDK Highlander mod folder...
copy /Y "%SDKLocation%\XComGame\Published\CookedPCConsole\Core.upk" "%SDKLocation%\XComGame\Mods\X2WOTCCommunityHighlander\CookedPCConsole\Core.upk"
copy /Y "%SDKLocation%\XComGame\Published\CookedPCConsole\Core.upk.uncompressed_size" "%SDKLocation%\XComGame\Mods\X2WOTCCommunityHighlander\CookedPCConsole\Core.upk.uncompressed_size"

echo.
echo Cleaning up...
if exist "%GameLocation%\XComGame\Mods\X2WOTCCommunityHighlander\Script\XComGame.u" del "%GameLocation%\XComGame\Mods\X2WOTCCommunityHighlander\Script\XComGame.u"
if exist "%SDKLocation%\XComGame\Mods\X2WOTCCommunityHighlander\Script\XComGame.u" del "%SDKLocation%\XComGame\Mods\X2WOTCCommunityHighlander\Script\XComGame.u"
if exist "%GameLocation%\XComGame\Mods\X2WOTCCommunityHighlander\Script\Engine.u" del "%GameLocation%\XComGame\Mods\X2WOTCCommunityHighlander\Script\Engine.u"
if exist "%SDKLocation%\XComGame\Mods\X2WOTCCommunityHighlander\Script\Engine.u" del "%SDKLocation%\XComGame\Mods\X2WOTCCommunityHighlander\Script\Engine.u"
if exist "%GameLocation%\XComGame\Mods\X2WOTCCommunityHighlander\Script\Core.u" del "%GameLocation%\XComGame\Mods\X2WOTCCommunityHighlander\Script\Core.u"
if exist "%SDKLocation%\XComGame\Mods\X2WOTCCommunityHighlander\Script\Core.u" del "%SDKLocation%\XComGame\Mods\X2WOTCCommunityHighlander\Script\Core.u"

echo.
echo.
Expand Down
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,18 +153,20 @@ Start by building the mod through ModBuddy, as you normally would. Then, enter t

If a message like "Scripts are outdated. Would you like to rebuild now?" pops up, click "No".

The commands above create cooked files for your `XComGame` and `Engine` package replacements in
The commands above create cooked files for your `XComGame`, `Engine`, and `Core` package replacements in
`%STEAMLIBRARY%\steamapps\common\XCOM 2 War of the Chosen SDK\XComGame\Published\CookedPCConsole`:
```
XComGame.upk
XComGame.upk.uncompressed_size
Engine.upk
Engine.upk.uncompressed_size
Core.upk
Core.upk.uncompressed_size
```

Copy those files into a folder called `CookedPCConsole` inside the mod's output
folder. You will need to delete `Script\XComGame.u` and `Script\Engine.u`, now that we've put the
cooked script file in it's place.
folder. You will need to delete `Script\XComGame.u`, `Script\Engine.u` and `Script\Core.u`,
now that we've put the cooked script file in it's place.

Once you've done all that, the mod should now run in vanilla XCOM. Note that all
logging statements will be stripped from the Cooked version, so don't expect to
Expand Down
26 changes: 26 additions & 0 deletions X2WOTCCommunityHighlander/Src/Engine/Classes/AudioComponent.uc
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,32 @@ event OcclusionChanged(bool bNowOccluded)
}

/** called from native code when Wwise knows the duration of the currently playing event */
/// HL-Docs: feature:SoundCueNarrativeMoments; issue:66; tags:strategy,tactical
/// Allows mods to add their own voiceover using narrative moments (top-right corner comms box).
///
/// Narrative moments in the base game are realized using the WWise middleware. The middleware
/// runs in a background thread, so if audio (spuriously) fails to play, the middleware may take
/// a few frames to figure this out. If audio does fail to play, there must be a callback in order
/// to not deadlock the entire narrative moment system due to the audio never successfully finishing.
/// However, mods have to use `SoundCue` sounds instead, and the system considers every `SoundCue`
/// as failed to play. This ends every mod-added narrative moment prematurely after about three seconds.
///
/// This fix simply triggers the callback only when WWise is involved and silently eats the callback
/// if a `SoundCue` is involved.
///
/// ## Mini-tutorial on mod VO
///
/// This isn't strictly Highlander-related, but this is the best place to put it.
///
/// * Create a Speaker template (see `X2Character_DefaultCharacters.uc`)
/// * `Templates.AddItem(CreateSpeakerTemplate('Firebrand', "Firebrand", "img:///UILibrary_Common.Head_Firebrand", eGender_Female));`
/// * Compile the mod
/// * Import the `SoundNodeWave`
/// * Create a `SoundCue`, and create an `XComConversationNode` between the speaker and the `SoundNodeWave`
/// * Set the `SpokenText` and choose the `SpeakerTemplate` in the `SoundNodeWave`
/// * Create an `XComNarrativeMoment` archetype and reference the `SoundCue` in its `Conversations`
///
/// ![Editor Screenshot](https://i.imgur.com/goUwFkJ.png)
event AkCallbackSetDuration(float fSeconds)
{
// Start Issue #66 -- those events are explicitely Ak WWise-related
Expand Down
12 changes: 12 additions & 0 deletions X2WOTCCommunityHighlander/Src/XComGame/Classes/UIAlert.uc
Original file line number Diff line number Diff line change
Expand Up @@ -3415,6 +3415,18 @@ simulated function BuildItemAvailableAlert()
}

// Start issue #491
/// HL-Docs: feature:OverrideImageForItemAvaliable; issue:491; tags:strategy,ui
/// Allows overriding the image shown for an item in the `eAlert_ItemAvailable` alert.
///
/// This alert is triggered when a tech completes and makes available a new item for building, but, if it happens
/// to target a singular weapon (rather than the upgrade schematic), shows a weapon without
/// attachments (as specified in the Template's `strImage`). This event gives mods a chance to fix it.
///
/// ```unrealscript
/// ID: OverrideImageForItemAvaliable,
/// Data: [inout string ImagePath, in X2ItemTemplate ItemTemplate],
/// Source: UIAlert
/// ```
simulated function string GetImageForItemAvaliable(X2ItemTemplate ItemTemplate)
{
local XComLWTuple Tuple;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1126,7 +1126,16 @@ reliable client function array<UIAvengerShortcutMessage> GetCommandersQuartersMe
return Messages;
}

// Start issue #368
// Start issue #368
/// HL-Docs: feature:UIAvengerShortcuts_ShowCQResistanceOrders; issue:368; tags:strategy,ui
/// Allows overriding whether the resistance orders button should be shown in `UIAvengerShortcuts`.
/// Default: After the first month if any faction met.
///
/// ```unrealscript
/// ID: UIAvengerShortcuts_ShowCQResistanceOrders,
/// Data: [inout bool ShouldShow],
/// Source: UIAvengerShortcuts
/// ```
simulated protected function bool ShouldShowResistanceOrders()
{
local XComGameState_HeadquartersResistance ResHQ;
Expand Down
Loading