Compare commits
1 Commits
devtest-20
...
devtest-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c113fd7b6 |
4
.github/workflows/ci.yaml
vendored
4
.github/workflows/ci.yaml
vendored
@@ -2,13 +2,14 @@ name: Continuous Integration
|
||||
|
||||
on:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
branches: [ bleed ]
|
||||
|
||||
jobs:
|
||||
linux-mono:
|
||||
name: Linux (mono)
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-16.04
|
||||
|
||||
steps:
|
||||
- name: Clone Repository
|
||||
@@ -37,7 +38,6 @@ jobs:
|
||||
- name: Check Code
|
||||
shell: powershell
|
||||
run: |
|
||||
dotnet nuget locals all --clear
|
||||
.\make.ps1 check
|
||||
Invoke-Expression "$home\.nuget\packages\nunit.consolerunner\3.11.1\tools\nunit3-console.exe --noresult bin/OpenRA.Test.dll"
|
||||
|
||||
|
||||
107
.github/workflows/documentation.yml
vendored
107
.github/workflows/documentation.yml
vendored
@@ -1,107 +0,0 @@
|
||||
name: Deploy Documentation
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: 'Git Tag'
|
||||
required: true
|
||||
default: 'release-xxxxxxxx'
|
||||
|
||||
jobs:
|
||||
wiki:
|
||||
name: Update Wiki
|
||||
if: github.repository == 'openra/openra'
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Clone Repository
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.inputs.tag }}
|
||||
|
||||
- name: Prepare Environment
|
||||
run: |
|
||||
make all
|
||||
|
||||
- name: Clone Wiki
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: openra/openra.wiki
|
||||
token: ${{ secrets.DOCS_TOKEN }}
|
||||
path: wiki
|
||||
|
||||
- name: Update Wiki (Playtest)
|
||||
if: startsWith(github.event.inputs.tag, 'playtest-')
|
||||
env:
|
||||
GIT_TAG: ${{ github.event.inputs.tag }}
|
||||
run: |
|
||||
./utility.sh all --settings-docs "${GIT_TAG}" > "wiki/Settings (playtest).md"
|
||||
|
||||
- name: Update Wiki (Release)
|
||||
if: startsWith(github.event.inputs.tag, 'release-')
|
||||
env:
|
||||
GIT_TAG: ${{ github.event.inputs.tag }}
|
||||
run: |
|
||||
./utility.sh all --settings-docs "${GIT_TAG}" > "wiki/Settings.md"
|
||||
|
||||
- name: Push Wiki
|
||||
env:
|
||||
GIT_TAG: ${{ github.event.inputs.tag }}
|
||||
run: |
|
||||
cd wiki
|
||||
git config --local user.email "actions@github.com"
|
||||
git config --local user.name "GitHub Actions"
|
||||
git add --all
|
||||
git commit -m "Update auto-generated documentation for ${GIT_TAG}"
|
||||
git push origin master
|
||||
|
||||
docs:
|
||||
name: Update docs.openra.net
|
||||
if: github.repository == 'openra/openra'
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Clone Repository
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.inputs.tag }}
|
||||
|
||||
- name: Prepare Environment
|
||||
run: |
|
||||
make all
|
||||
|
||||
- name: Clone docs.openra.net
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: openra/docs
|
||||
token: ${{ secrets.DOCS_TOKEN }}
|
||||
path: docs
|
||||
|
||||
- name: Update docs.openra.net (Playtest)
|
||||
if: startsWith(github.event.inputs.tag, 'playtest-')
|
||||
env:
|
||||
GIT_TAG: ${{ github.event.inputs.tag }}
|
||||
run: |
|
||||
./utility.sh all --docs "${GIT_TAG}" > "docs/api/playtest/traits.md"
|
||||
./utility.sh all --weapon-docs "${GIT_TAG}" > "docs/api/playtest/weapons.md"
|
||||
./utility.sh all --lua-docs "${GIT_TAG}" > "docs/api/playtest/lua.md"
|
||||
|
||||
- name: Update docs.openra.net (Release)
|
||||
if: startsWith(github.event.inputs.tag, 'release-')
|
||||
env:
|
||||
GIT_TAG: ${{ github.event.inputs.tag }}
|
||||
run: |
|
||||
./utility.sh all --docs "${GIT_TAG}" > "docs/api/release/traits.md"
|
||||
./utility.sh all --weapon-docs "${GIT_TAG}" > "docs/api/release/weapons.md"
|
||||
./utility.sh all --lua-docs "${GIT_TAG}" > "docs/api/release/lua.md"
|
||||
|
||||
- name: Push docs.openra.net
|
||||
env:
|
||||
GIT_TAG: ${{ github.event.inputs.tag }}
|
||||
run: |
|
||||
cd docs
|
||||
git config --local user.email "actions@github.com"
|
||||
git config --local user.name "GitHub Actions"
|
||||
git add --all
|
||||
git commit -m "Update auto-generated documentation for ${GIT_TAG}"
|
||||
git push origin master
|
||||
|
||||
86
.github/workflows/itch.yml
vendored
86
.github/workflows/itch.yml
vendored
@@ -1,86 +0,0 @@
|
||||
name: Deploy itch.io Packages
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: 'Git Tag'
|
||||
required: true
|
||||
default: 'release-xxxxxxxx'
|
||||
|
||||
jobs:
|
||||
itch:
|
||||
name: Deploy to itch.io
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.repository == 'openra/openra'
|
||||
steps:
|
||||
- name: Download Packages
|
||||
run: |
|
||||
wget -q "https://github.com/${{ github.repository }}/releases/download/${{ github.event.inputs.tag }}/OpenRA-${{ github.event.inputs.tag }}-x64.exe"
|
||||
wget -q "https://github.com/${{ github.repository }}/releases/download/${{ github.event.inputs.tag }}/OpenRA-${{ github.event.inputs.tag }}-x64-winportable.zip" -O "OpenRA-${{ github.event.inputs.tag }}-x64-win-itch.zip"
|
||||
wget -q "https://github.com/${{ github.repository }}/releases/download/${{ github.event.inputs.tag }}/OpenRA-${{ github.event.inputs.tag }}.dmg"
|
||||
wget -q "https://github.com/${{ github.repository }}/releases/download/${{ github.event.inputs.tag }}/OpenRA-Dune-2000-x86_64.AppImage"
|
||||
wget -q "https://github.com/${{ github.repository }}/releases/download/${{ github.event.inputs.tag }}/OpenRA-Red-Alert-x86_64.AppImage"
|
||||
wget -q "https://github.com/${{ github.repository }}/releases/download/${{ github.event.inputs.tag }}/OpenRA-Tiberian-Dawn-x86_64.AppImage"
|
||||
wget -q "https://raw.githubusercontent.com/${{ github.repository }}/${{ github.event.inputs.tag }}/packaging/.itch.toml"
|
||||
zip -u "OpenRA-${{ github.event.inputs.tag }}-x64-win-itch.zip" .itch.toml
|
||||
|
||||
- name: Publish Windows Installer
|
||||
uses: josephbmanley/butler-publish-itchio-action@master
|
||||
env:
|
||||
BUTLER_CREDENTIALS: ${{ secrets.BUTLER_CREDENTIALS }}
|
||||
CHANNEL: win
|
||||
ITCH_GAME: openra
|
||||
ITCH_USER: openra-developers
|
||||
VERSION: ${{ github.event.inputs.tag }}
|
||||
PACKAGE: OpenRA-${{ github.event.inputs.tag }}}-x64.exe
|
||||
|
||||
- name: Publish Windows Itch Bundle
|
||||
uses: josephbmanley/butler-publish-itchio-action@master
|
||||
env:
|
||||
BUTLER_CREDENTIALS: ${{ secrets.BUTLER_CREDENTIALS }}
|
||||
CHANNEL: itch
|
||||
ITCH_GAME: openra
|
||||
ITCH_USER: openra-developers
|
||||
VERSION: ${{ github.event.inputs.tag }}
|
||||
PACKAGE: OpenRA-${{ github.event.inputs.tag }}-x64-win-itch.zip
|
||||
|
||||
- name: Publish macOS Package
|
||||
uses: josephbmanley/butler-publish-itchio-action@master
|
||||
env:
|
||||
BUTLER_CREDENTIALS: ${{ secrets.BUTLER_CREDENTIALS }}
|
||||
CHANNEL: macos
|
||||
ITCH_GAME: openra
|
||||
ITCH_USER: openra-developers
|
||||
VERSION: ${{ github.event.inputs.tag }}
|
||||
PACKAGE: OpenRA-${{ github.event.inputs.tag }}}.dmg
|
||||
|
||||
- name: Publish RA AppImage
|
||||
uses: josephbmanley/butler-publish-itchio-action@master
|
||||
env:
|
||||
BUTLER_CREDENTIALS: ${{ secrets.BUTLER_CREDENTIALS }}
|
||||
CHANNEL: linux-ra
|
||||
ITCH_GAME: openra
|
||||
ITCH_USER: openra-developers
|
||||
VERSION: ${{ github.event.inputs.tag }}
|
||||
PACKAGE: OpenRA-Red-Alert-x86_64.AppImage
|
||||
|
||||
- name: Publish TD AppImage
|
||||
uses: josephbmanley/butler-publish-itchio-action@master
|
||||
env:
|
||||
BUTLER_CREDENTIALS: ${{ secrets.BUTLER_CREDENTIALS }}
|
||||
CHANNEL: linux-cnc
|
||||
ITCH_GAME: openra
|
||||
ITCH_USER: openra-developers
|
||||
VERSION: ${{ github.event.inputs.tag }}
|
||||
PACKAGE: OpenRA-Tiberian-Dawn-x86_64.AppImage
|
||||
|
||||
- name: Publish D2k AppImage
|
||||
uses: josephbmanley/butler-publish-itchio-action@master
|
||||
env:
|
||||
BUTLER_CREDENTIALS: ${{ secrets.BUTLER_CREDENTIALS }}
|
||||
CHANNEL: linux-d2k
|
||||
ITCH_GAME: openra
|
||||
ITCH_USER: openra-developers
|
||||
VERSION: ${{ github.event.inputs.tag }}
|
||||
PACKAGE: OpenRA-Dune-2000-x86_64.AppImage
|
||||
186
.github/workflows/packaging.yml
vendored
186
.github/workflows/packaging.yml
vendored
@@ -8,33 +8,9 @@ on:
|
||||
- 'devtest-*'
|
||||
|
||||
jobs:
|
||||
source:
|
||||
name: Source Tarball
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Clone Repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Prepare Environment
|
||||
run: echo "GIT_TAG=${GITHUB_REF#refs/tags/}" >> ${GITHUB_ENV}
|
||||
|
||||
- name: Package Source
|
||||
run: |
|
||||
mkdir -p build/source
|
||||
./packaging/source/buildpackage.sh "${GIT_TAG}" "${PWD}/build/source"
|
||||
|
||||
- name: Upload Packages
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
tag: ${{ github.ref }}
|
||||
overwrite: true
|
||||
file_glob: true
|
||||
file: build/source/*
|
||||
|
||||
linux:
|
||||
name: Linux AppImages
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-16.04
|
||||
steps:
|
||||
- name: Clone Repository
|
||||
uses: actions/checkout@v2
|
||||
@@ -88,7 +64,7 @@ jobs:
|
||||
|
||||
windows:
|
||||
name: Windows Installers
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-16.04
|
||||
steps:
|
||||
- name: Clone Repository
|
||||
uses: actions/checkout@v2
|
||||
@@ -96,8 +72,10 @@ jobs:
|
||||
- name: Prepare Environment
|
||||
run: |
|
||||
echo "GIT_TAG=${GITHUB_REF#refs/tags/}" >> ${GITHUB_ENV}
|
||||
sudo apt-get update
|
||||
sudo apt-get install nsis
|
||||
wget https://mirrors.edge.kernel.org/ubuntu/pool/universe/n/nsis/nsis-common_3.04-1_all.deb
|
||||
wget https://mirrors.edge.kernel.org/ubuntu/pool/universe/n/nsis/nsis_3.04-1_amd64.deb
|
||||
sudo dpkg -i nsis-common_3.04-1_all.deb
|
||||
sudo dpkg -i nsis_3.04-1_amd64.deb
|
||||
|
||||
- name: Package Installers
|
||||
run: |
|
||||
@@ -112,3 +90,155 @@ jobs:
|
||||
overwrite: true
|
||||
file_glob: true
|
||||
file: build/windows/*
|
||||
|
||||
itch:
|
||||
name: Deploy to itch.io
|
||||
runs-on: ubuntu-16.04
|
||||
if: github.repository == 'openra/openra' && startsWith(github.ref, 'refs/tags/release-')
|
||||
needs: [linux, macos, windows]
|
||||
steps:
|
||||
- name: Prepare Environment
|
||||
run: |
|
||||
echo "GIT_TAG=${GITHUB_REF#refs/tags/}" >> ${GITHUB_ENV}
|
||||
|
||||
- name: Download Packages
|
||||
run: |
|
||||
wget -q "https://github.com/${{ github.repository }}/releases/download/${GIT_TAG}/OpenRA-${GIT_TAG}-x64.exe"
|
||||
wget -q "https://github.com/${{ github.repository }}/releases/download/${GIT_TAG}/OpenRA-${GIT_TAG}-x64-winportable.zip" -O "OpenRA-${GIT_TAG}-x64-win-itch.zip"
|
||||
wget -q "https://github.com${{ github.repository }}/releases/download/${GIT_TAG}/OpenRA-${GIT_TAG}.dmg"
|
||||
wget -q "https://github.com/${{ github.repository }}/releases/download/${GIT_TAG}/OpenRA-Dune-2000-x86_64.AppImage"
|
||||
wget -q "https://github.com/${{ github.repository }}/releases/download/${GIT_TAG}/OpenRA-Red-Alert-x86_64.AppImage"
|
||||
wget -q "https://github.com/${{ github.repository }}/releases/download/${GIT_TAG}/OpenRA-Tiberian-Dawn-x86_64.AppImage"
|
||||
wget -q "https://raw.githubusercontent.com/${{ github.repository }}/${GIT_TAG}/packaging/.itch.toml"
|
||||
zip -u "OpenRA-${GIT_TAG}-x64-win-itch.zip" .itch.toml
|
||||
|
||||
- name: Publish Windows Installer
|
||||
uses: josephbmanley/butler-publish-itchio-action@master
|
||||
env:
|
||||
BUTLER_CREDENTIALS: ${{ secrets.BUTLER_CREDENTIALS }}
|
||||
CHANNEL: win
|
||||
ITCH_GAME: openra
|
||||
ITCH_USER: openra-developers
|
||||
VERSION: ${{ env.GIT_TAG }}
|
||||
PACKAGE: OpenRA-${{ env.GIT_TAG }}}-x64.exe"
|
||||
|
||||
- name: Publish Windows Itch Bundle
|
||||
uses: josephbmanley/butler-publish-itchio-action@master
|
||||
env:
|
||||
BUTLER_CREDENTIALS: ${{ secrets.BUTLER_CREDENTIALS }}
|
||||
CHANNEL: itch
|
||||
ITCH_GAME: openra
|
||||
ITCH_USER: openra-developers
|
||||
VERSION: ${{ env.GIT_TAG }}
|
||||
PACKAGE: OpenRA-${{ env.GIT_TAG }}-x64-win-itch.zip
|
||||
|
||||
- name: Publish macOS Package
|
||||
uses: josephbmanley/butler-publish-itchio-action@master
|
||||
env:
|
||||
BUTLER_CREDENTIALS: ${{ secrets.BUTLER_CREDENTIALS }}
|
||||
CHANNEL: macos
|
||||
ITCH_GAME: openra
|
||||
ITCH_USER: openra-developers
|
||||
VERSION: ${{ env.GIT_TAG }}
|
||||
PACKAGE: OpenRA-${{ env.GIT_TAG }}}.dmg"
|
||||
|
||||
- name: Publish RA AppImage
|
||||
uses: josephbmanley/butler-publish-itchio-action@master
|
||||
env:
|
||||
BUTLER_CREDENTIALS: ${{ secrets.BUTLER_CREDENTIALS }}
|
||||
CHANNEL: linux-ra
|
||||
ITCH_GAME: openra
|
||||
ITCH_USER: openra-developers
|
||||
VERSION: ${{ env.GIT_TAG }}
|
||||
PACKAGE: OpenRA-Red-Alert-x86_64.AppImage
|
||||
|
||||
- name: Publish TD AppImage
|
||||
uses: josephbmanley/butler-publish-itchio-action@master
|
||||
env:
|
||||
BUTLER_CREDENTIALS: ${{ secrets.BUTLER_CREDENTIALS }}
|
||||
CHANNEL: linux-cnc
|
||||
ITCH_GAME: openra
|
||||
ITCH_USER: openra-developers
|
||||
VERSION: ${{ env.GIT_TAG }}
|
||||
PACKAGE: OpenRA-Tiberian-Dawn-x86_64.AppImage
|
||||
|
||||
- name: Publish D2k AppImage
|
||||
uses: josephbmanley/butler-publish-itchio-action@master
|
||||
env:
|
||||
BUTLER_CREDENTIALS: ${{ secrets.BUTLER_CREDENTIALS }}
|
||||
CHANNEL: linux-d2k
|
||||
ITCH_GAME: openra
|
||||
ITCH_USER: openra-developers
|
||||
VERSION: ${{ env.GIT_TAG }}
|
||||
PACKAGE: OpenRA-Dune-2000-x86_64.AppImage
|
||||
|
||||
docs:
|
||||
name: Update Docs
|
||||
if: github.repository == 'openra/openra' && (startsWith(github.ref, 'refs/tags/playtest-') || startsWith(github.ref, 'refs/tags/release-'))
|
||||
runs-on: ubuntu-16.04
|
||||
needs: [linux, macos, windows]
|
||||
steps:
|
||||
- name: Clone Repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Prepare Environment
|
||||
run: |
|
||||
echo "GIT_TAG=${GITHUB_REF#refs/tags/}" >> ${GITHUB_ENV}
|
||||
make all
|
||||
|
||||
- name: Clone Wiki
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: openra/openra.wiki
|
||||
token: ${{ secrets.DOCS_TOKEN }}
|
||||
path: wiki
|
||||
|
||||
- name: Update Wiki (Playtest)
|
||||
if: startsWith(github.ref, 'refs/tags/playtest-')
|
||||
run: |
|
||||
./utility.sh all --settings-docs "${GIT_TAG}" > "wiki/Settings (playtest).md"
|
||||
|
||||
- name: Update Wiki (Release)
|
||||
if: startsWith(github.ref, 'refs/tags/release-')
|
||||
run: |
|
||||
./utility.sh all --settings-docs "${GIT_TAG}" > "wiki/Settings.md"
|
||||
|
||||
- name: Push Wiki
|
||||
run: |
|
||||
cd wiki
|
||||
git config --local user.email "actions@github.com"
|
||||
git config --local user.name "GitHub Actions"
|
||||
git add --all
|
||||
git commit -m "Update auto-generated documentation for ${GIT_TAG}"
|
||||
git push origin master
|
||||
|
||||
- name: Clone docs.openra.net
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: openra/docs.git
|
||||
token: ${{ secrets.DOCS_TOKEN }}
|
||||
path: docs
|
||||
|
||||
- name: Update docs.openra.net (Playtest)
|
||||
if: startsWith(github.ref, 'refs/tags/playtest-')
|
||||
run: |
|
||||
./utility.sh all --docs "${GIT_TAG}" > "docs/playtest/traits.md"
|
||||
./utility.sh all --weapon-docs "${GIT_TAG}" > "docs/playtest/weapons.md"
|
||||
./utility.sh all --lua-docs "${GIT_TAG}" > "docs/playtest/lua.md"
|
||||
|
||||
- name: Update docs.openra.net (Release)
|
||||
if: startsWith(github.ref, 'refs/tags/release-')
|
||||
run: |
|
||||
./utility.sh all --docs "${GIT_TAG}" > "docs/release/traits.md"
|
||||
./utility.sh all --weapon-docs "${GIT_TAG}" > "docs/release/weapons.md"
|
||||
./utility.sh all --lua-docs "${GIT_TAG}" > "docs/release/lua.md"
|
||||
|
||||
- name: Push docs.openra.net
|
||||
run: |
|
||||
cd docs
|
||||
git config --local user.email "actions@github.com"
|
||||
git config --local user.name "GitHub Actions"
|
||||
git add --all
|
||||
git commit -m "Update auto-generated documentation for ${GIT_TAG}"
|
||||
git push origin master
|
||||
|
||||
|
||||
20
.vscode/launch.json
vendored
20
.vscode/launch.json
vendored
@@ -11,8 +11,9 @@
|
||||
"type": "mono"
|
||||
},
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/bin/OpenRA.exe",
|
||||
"args": ["Game.Mod=cnc", "Engine.EngineDir=.."],
|
||||
"program": "${workspaceRoot}/OpenRA.Game.exe",
|
||||
"cwd": "${workspaceRoot}",
|
||||
"args": ["Game.Mod=cnc"],
|
||||
"preLaunchTask": "build",
|
||||
},
|
||||
{
|
||||
@@ -25,8 +26,9 @@
|
||||
"type": "mono"
|
||||
},
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/bin/OpenRA.exe",
|
||||
"args": ["Game.Mod=ra", "Engine.EngineDir=.."],
|
||||
"program": "${workspaceRoot}/OpenRA.Game.exe",
|
||||
"cwd": "${workspaceRoot}",
|
||||
"args": ["Game.Mod=ra"],
|
||||
"preLaunchTask": "build",
|
||||
},
|
||||
{
|
||||
@@ -39,8 +41,9 @@
|
||||
"type": "mono"
|
||||
},
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/bin/OpenRA.exe",
|
||||
"args": ["Game.Mod=d2k", "Engine.EngineDir=.."],
|
||||
"program": "${workspaceRoot}/OpenRA.Game.exe",
|
||||
"cwd": "${workspaceRoot}",
|
||||
"args": ["Game.Mod=d2k"],
|
||||
"preLaunchTask": "build",
|
||||
},
|
||||
{
|
||||
@@ -53,8 +56,9 @@
|
||||
"type": "mono"
|
||||
},
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/bin/OpenRA.exe",
|
||||
"args": ["Game.Mod=ts", "Engine.EngineDir=.."],
|
||||
"program": "${workspaceRoot}/OpenRA.Game.exe",
|
||||
"cwd": "${workspaceRoot}",
|
||||
"args": ["Game.Mod=ts"],
|
||||
"preLaunchTask": "build",
|
||||
},
|
||||
]
|
||||
|
||||
37
Makefile
37
Makefile
@@ -15,10 +15,6 @@
|
||||
# to compile and install Red Alert, Tiberian Dawn, and Dune 2000, run:
|
||||
# make [prefix=/foo] [bindir=/bar/bin] install
|
||||
#
|
||||
# to compile and install Red Alert, Tiberian Dawn, and Dune 2000
|
||||
# using system libraries for native dependencies, run:
|
||||
# make [prefix=/foo] [bindir=/bar/bin] TARGETPLATFORM=unix-generic install
|
||||
#
|
||||
# to install Linux startup scripts, desktop files, icons, and MIME metadata
|
||||
# make install-linux-shortcuts
|
||||
#
|
||||
@@ -52,6 +48,10 @@ bindir ?= $(prefix)/bin
|
||||
libdir ?= $(prefix)/lib
|
||||
gameinstalldir ?= $(libdir)/openra
|
||||
|
||||
BIN_INSTALL_DIR = $(DESTDIR)$(bindir)
|
||||
DATA_INSTALL_DIR = $(DESTDIR)$(datadir)
|
||||
OPENRA_INSTALL_DIR = $(DESTDIR)$(gameinstalldir)
|
||||
|
||||
# Toolchain
|
||||
CWD = $(shell pwd)
|
||||
MSBUILD = msbuild -verbosity:m -nologo
|
||||
@@ -61,8 +61,7 @@ RM_R = $(RM) -r
|
||||
RM_F = $(RM) -f
|
||||
RM_RF = $(RM) -rf
|
||||
|
||||
# Only for use in target version:
|
||||
VERSION := $(shell git name-rev --name-only --tags --no-undefined HEAD 2>/dev/null || (c=$$(git rev-parse --short HEAD 2>/dev/null) && echo git-$$c))
|
||||
VERSION = $(shell git name-rev --name-only --tags --no-undefined HEAD 2>/dev/null || echo git-`git rev-parse --short HEAD`)
|
||||
|
||||
# Detect target platform for dependencies if not given by the user
|
||||
ifndef TARGETPLATFORM
|
||||
@@ -99,10 +98,7 @@ clean:
|
||||
check:
|
||||
@echo
|
||||
@echo "Compiling in debug mode..."
|
||||
@$(MSBUILD) -t:build -restore -p:Configuration=Debug -p:TargetPlatform=$(TARGETPLATFORM)
|
||||
ifeq ($(TARGETPLATFORM), unix-generic)
|
||||
@./configure-system-libraries.sh
|
||||
endif
|
||||
@$(MSBUILD) -t:build -restore -p:Configuration=Debug
|
||||
@echo
|
||||
@echo "Checking runtime assemblies..."
|
||||
@$(OPENRA_UTILITY) all --check-runtime-assemblies $(WHITELISTED_OPENRA_ASSEMBLIES) $(WHITELISTED_THIRDPARTY_ASSEMBLIES) $(WHITELISTED_CORE_ASSEMBLIES)
|
||||
@@ -137,21 +133,18 @@ test: all
|
||||
############# LOCAL INSTALLATION AND DOWNSTREAM PACKAGING ##############
|
||||
#
|
||||
version: VERSION mods/ra/mod.yaml mods/cnc/mod.yaml mods/d2k/mod.yaml mods/ts/mod.yaml mods/modcontent/mod.yaml mods/all/mod.yaml
|
||||
ifeq ($(VERSION),)
|
||||
$(error Unable to determine new version (requires git or override of variable VERSION))
|
||||
endif
|
||||
@sh -c '. ./packaging/functions.sh; set_engine_version "$(VERSION)" .'
|
||||
@sh -c '. ./packaging/functions.sh; set_mod_version "$(VERSION)" mods/ra/mod.yaml mods/cnc/mod.yaml mods/d2k/mod.yaml mods/ts/mod.yaml mods/modcontent/mod.yaml mods/all/mod.yaml'
|
||||
@sh -c '. ./packaging/functions.sh; set_engine_version $(VERSION) .'
|
||||
@sh -c '. ./packaging/functions.sh; set_mod_version $(VERSION) mods/ra/mod.yaml mods/cnc/mod.yaml mods/d2k/mod.yaml mods/ts/mod.yaml mods/modcontent/mod.yaml mods/all/mod.yaml'
|
||||
|
||||
install:
|
||||
@sh -c '. ./packaging/functions.sh; install_assemblies_mono $(CWD) $(DESTDIR)$(gameinstalldir) $(TARGETPLATFORM) True True True'
|
||||
@sh -c '. ./packaging/functions.sh; install_data $(CWD) $(DESTDIR)$(gameinstalldir) cnc d2k ra'
|
||||
@sh -c '. ./packaging/functions.sh; install_assemblies_mono $(CWD) $(OPENRA_INSTALL_DIR) $(TARGETPLATFORM) True True True'
|
||||
@sh -c '. ./packaging/functions.sh; install_data $(CWD) $(OPENRA_INSTALL_DIR) cnc d2k ra'
|
||||
|
||||
install-linux-shortcuts:
|
||||
@sh -c '. ./packaging/functions.sh; install_linux_shortcuts $(CWD) "$(DESTDIR)" "$(gameinstalldir)" "$(bindir)" "$(datadir)" "$(shell head -n1 VERSION)" cnc d2k ra'
|
||||
@sh -c '. ./packaging/functions.sh; install_linux_shortcuts $(CWD) $(OPENRA_INSTALL_DIR) $(BIN_INSTALL_DIR) $(DATA_INSTALL_DIR) $(VERSION) cnc d2k ra'
|
||||
|
||||
install-linux-appdata:
|
||||
@sh -c '. ./packaging/functions.sh; install_linux_appdata $(CWD) "$(DESTDIR)" "$(datadir)" cnc d2k ra'
|
||||
@sh -c '. ./packaging/functions.sh; install_linux_appdata $(CWD) $(DATA_INSTALL_DIR) cnc d2k ra'
|
||||
|
||||
help:
|
||||
@echo 'to compile, run:'
|
||||
@@ -167,11 +160,7 @@ help:
|
||||
@echo ' make test'
|
||||
@echo
|
||||
@echo 'to compile and install Red Alert, Tiberian Dawn, and Dune 2000 run:'
|
||||
@echo ' make [prefix=/foo] [TARGETPLATFORM=unix-generic] install'
|
||||
@echo
|
||||
@echo 'to compile and install Red Alert, Tiberian Dawn, and Dune 2000'
|
||||
@echo 'using system libraries for native dependencies, run:'
|
||||
@echo ' make [prefix=/foo] [bindir=/bar/bin] TARGETPLATFORM=unix-generic install'
|
||||
@echo ' make [prefix=/foo] install'
|
||||
@echo
|
||||
@echo 'to install Linux startup scripts, desktop files, icons, and MIME metadata'
|
||||
@echo ' make install-linux-shortcuts'
|
||||
|
||||
@@ -934,11 +934,9 @@ namespace OpenRA
|
||||
AdvertiseOnline = false
|
||||
};
|
||||
|
||||
// Always connect to local games using the same loopback connection
|
||||
// Exposing multiple endpoints introduces a race condition on the client's PlayerIndex (sometimes 0, sometimes 1)
|
||||
// This would break the Restart button, which relies on the PlayerIndex always being the same for local servers
|
||||
var endpoints = new List<IPEndPoint>
|
||||
{
|
||||
new IPEndPoint(IPAddress.IPv6Loopback, 0),
|
||||
new IPEndPoint(IPAddress.Loopback, 0)
|
||||
};
|
||||
server = new Server.Server(endpoints, settings, ModData, ServerType.Local);
|
||||
|
||||
@@ -119,11 +119,8 @@ namespace OpenRA
|
||||
IsBot = runtimePlayer.IsBot,
|
||||
FactionName = runtimePlayer.Faction.Name,
|
||||
FactionId = runtimePlayer.Faction.InternalName,
|
||||
DisplayFactionName = runtimePlayer.DisplayFaction.Name,
|
||||
DisplayFactionId = runtimePlayer.DisplayFaction.InternalName,
|
||||
Color = runtimePlayer.Color,
|
||||
Team = client.Team,
|
||||
Handicap = client.Handicap,
|
||||
SpawnPoint = runtimePlayer.SpawnPoint,
|
||||
IsRandomFaction = runtimePlayer.Faction.InternalName != client.Faction,
|
||||
IsRandomSpawnPoint = runtimePlayer.DisplaySpawnPoint == 0,
|
||||
@@ -160,14 +157,9 @@ namespace OpenRA
|
||||
public string FactionId;
|
||||
public Color Color;
|
||||
|
||||
/// <summary>The faction (including Random, etc.) that was selected in the lobby.</summary>
|
||||
public string DisplayFactionName;
|
||||
public string DisplayFactionId;
|
||||
|
||||
/// <summary>The team ID on start-up, or 0 if the player is not part of a team.</summary>
|
||||
public int Team;
|
||||
public int SpawnPoint;
|
||||
public int Handicap;
|
||||
|
||||
/// <summary>True if the faction was chosen at random; otherwise, false.</summary>
|
||||
public bool IsRandomFaction;
|
||||
|
||||
@@ -166,7 +166,6 @@ namespace OpenRA
|
||||
public void QueryRemoteMapDetails(string repositoryUrl, IEnumerable<string> uids, Action<MapPreview> mapDetailsReceived = null, Action queryFailed = null)
|
||||
{
|
||||
var maps = uids.Distinct()
|
||||
.Where(uid => uid != null)
|
||||
.Select(uid => previews[uid])
|
||||
.Where(p => p.Status == MapStatus.Unavailable)
|
||||
.ToDictionary(p => p.Uid, p => p);
|
||||
|
||||
@@ -50,9 +50,6 @@ namespace OpenRA
|
||||
public bool LockTeam = false;
|
||||
public int Team = 0;
|
||||
|
||||
public bool LockHandicap = false;
|
||||
public int Handicap = 0;
|
||||
|
||||
public string[] Allies = { };
|
||||
public string[] Enemies = { };
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@ namespace OpenRA.Network
|
||||
public readonly string Faction;
|
||||
public readonly int SpawnPoint;
|
||||
public readonly int Team;
|
||||
public readonly int Handicap;
|
||||
public readonly string Slot;
|
||||
public readonly string Bot;
|
||||
public readonly bool IsAdmin;
|
||||
@@ -40,7 +39,6 @@ namespace OpenRA.Network
|
||||
Faction = client.Faction;
|
||||
SpawnPoint = client.SpawnPoint;
|
||||
Team = client.Team;
|
||||
Handicap = client.Handicap;
|
||||
Slot = client.Slot;
|
||||
Bot = client.Bot;
|
||||
IsAdmin = client.IsAdmin;
|
||||
@@ -55,7 +53,6 @@ namespace OpenRA.Network
|
||||
client.Faction = Faction;
|
||||
client.SpawnPoint = SpawnPoint;
|
||||
client.Team = Team;
|
||||
client.Handicap = Handicap;
|
||||
client.Slot = Slot;
|
||||
client.Bot = Bot;
|
||||
client.IsAdmin = IsAdmin;
|
||||
|
||||
@@ -144,7 +144,6 @@ namespace OpenRA.Network
|
||||
|
||||
public ClientState State = ClientState.Invalid;
|
||||
public int Team;
|
||||
public int Handicap;
|
||||
public string Slot; // Slot ID, or null for observer
|
||||
public string Bot; // Bot type, null for real clients
|
||||
public int BotControllerClientIndex; // who added the bot to the slot
|
||||
@@ -194,7 +193,6 @@ namespace OpenRA.Network
|
||||
public bool LockFaction;
|
||||
public bool LockColor;
|
||||
public bool LockTeam;
|
||||
public bool LockHandicap;
|
||||
public bool LockSpawn;
|
||||
public bool Required;
|
||||
|
||||
|
||||
@@ -58,14 +58,13 @@ namespace OpenRA
|
||||
public readonly bool Playable = true;
|
||||
public readonly int ClientIndex;
|
||||
public readonly CPos HomeLocation;
|
||||
public readonly int Handicap;
|
||||
public readonly PlayerReference PlayerReference;
|
||||
public readonly bool IsBot;
|
||||
public readonly string BotType;
|
||||
public readonly Shroud Shroud;
|
||||
public readonly FrozenActorLayer FrozenActorLayer;
|
||||
|
||||
/// <summary>The faction (including Random, etc.) that was selected in the lobby.</summary>
|
||||
/// <summary>The faction (including Random, etc) that was selected in the lobby.</summary>
|
||||
public readonly FactionInfo DisplayFaction;
|
||||
|
||||
/// <summary>The spawn point index that was assigned for client-based players.</summary>
|
||||
@@ -81,8 +80,7 @@ namespace OpenRA
|
||||
{
|
||||
get
|
||||
{
|
||||
// Players in mission maps must not leave the player view
|
||||
return !inMissionMap && (spectating || WinState != WinState.Undefined);
|
||||
return spectating || WinState != WinState.Undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,8 +179,6 @@ namespace OpenRA
|
||||
HomeLocation = assignSpawnPoints?.AssignHomeLocation(world, client, playerRandom) ?? pr.HomeLocation;
|
||||
SpawnPoint = assignSpawnPoints?.SpawnPointForPlayer(this) ?? client.SpawnPoint;
|
||||
DisplaySpawnPoint = client.SpawnPoint;
|
||||
|
||||
Handicap = client.Handicap;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -198,7 +194,6 @@ namespace OpenRA
|
||||
DisplayFaction = ResolveDisplayFaction(world, pr.Faction);
|
||||
HomeLocation = pr.HomeLocation;
|
||||
SpawnPoint = DisplaySpawnPoint = 0;
|
||||
Handicap = pr.Handicap;
|
||||
}
|
||||
|
||||
if (!spectating)
|
||||
|
||||
@@ -18,7 +18,6 @@ namespace OpenRA.Primitives
|
||||
static class LongBitSetAllocator<T> where T : class
|
||||
{
|
||||
static readonly Cache<string, long> Bits = new Cache<string, long>(Allocate);
|
||||
static long allBits = 1;
|
||||
static long nextBits = 1;
|
||||
|
||||
static long Allocate(string value)
|
||||
@@ -26,7 +25,6 @@ namespace OpenRA.Primitives
|
||||
lock (Bits)
|
||||
{
|
||||
var bits = nextBits;
|
||||
allBits |= bits;
|
||||
nextBits <<= 1;
|
||||
|
||||
if (nextBits == 0)
|
||||
@@ -87,8 +85,6 @@ namespace OpenRA.Primitives
|
||||
nextBits = 1;
|
||||
}
|
||||
}
|
||||
|
||||
public static long Mask { get { return allBits; } }
|
||||
}
|
||||
|
||||
// Opitmized BitSet to be used only when guaranteed to be no more than 64 values.
|
||||
@@ -118,7 +114,6 @@ namespace OpenRA.Primitives
|
||||
|
||||
public static bool operator ==(LongBitSet<T> me, LongBitSet<T> other) { return me.bits == other.bits; }
|
||||
public static bool operator !=(LongBitSet<T> me, LongBitSet<T> other) { return !(me == other); }
|
||||
public static LongBitSet<T> operator ~(LongBitSet<T> me) { return new LongBitSet<T>(me.bits ^ LongBitSetAllocator<T>.Mask); }
|
||||
|
||||
public bool Equals(LongBitSet<T> other) { return other == this; }
|
||||
public override bool Equals(object obj) { return obj is LongBitSet<T> && Equals((LongBitSet<T>)obj); }
|
||||
|
||||
@@ -93,8 +93,6 @@ namespace OpenRA.Server
|
||||
c.SpawnPoint = pr.Spawn;
|
||||
if (pr.LockTeam)
|
||||
c.Team = pr.Team;
|
||||
if (pr.LockHandicap)
|
||||
c.Team = pr.Handicap;
|
||||
|
||||
c.Color = pr.LockColor ? pr.Color : c.PreferredColor;
|
||||
}
|
||||
@@ -439,7 +437,6 @@ namespace OpenRA.Server
|
||||
Faction = "Random",
|
||||
SpawnPoint = 0,
|
||||
Team = 0,
|
||||
Handicap = 0,
|
||||
State = Session.ClientState.Invalid,
|
||||
};
|
||||
|
||||
|
||||
@@ -256,8 +256,6 @@ namespace OpenRA
|
||||
public int IntroductionPromptVersion = 0;
|
||||
|
||||
public MPGameFilters MPGameFilters = MPGameFilters.Waiting | MPGameFilters.Empty | MPGameFilters.Protected | MPGameFilters.Started;
|
||||
|
||||
public bool PauseShellmap = false;
|
||||
}
|
||||
|
||||
public class Settings
|
||||
|
||||
@@ -32,7 +32,6 @@ namespace OpenRA
|
||||
readonly List<IEffect> effects = new List<IEffect>();
|
||||
readonly List<IEffect> unpartitionedEffects = new List<IEffect>();
|
||||
readonly List<ISync> syncedEffects = new List<ISync>();
|
||||
readonly GameSettings gameSettings;
|
||||
|
||||
readonly Queue<Action<World>> frameEndActions = new Queue<Action<World>>();
|
||||
|
||||
@@ -227,7 +226,6 @@ namespace OpenRA
|
||||
};
|
||||
|
||||
RulesContainTemporaryBlocker = map.Rules.Actors.Any(a => a.Value.HasTraitInfo<ITemporaryBlockerInfo>());
|
||||
gameSettings = Game.Settings.Game;
|
||||
}
|
||||
|
||||
public void AddToMaps(Actor self, IOccupySpace ios)
|
||||
@@ -426,9 +424,7 @@ namespace OpenRA
|
||||
wasLoadingGameSave = false;
|
||||
}
|
||||
|
||||
// Allow users to pause the shellmap via the settings menu
|
||||
// Some traits initialize important state during the first tick, so we must allow it to tick at least once
|
||||
if (!Paused && (Type != WorldType.Shellmap || !gameSettings.PauseShellmap || WorldTick == 0))
|
||||
if (!Paused)
|
||||
{
|
||||
WorldTick++;
|
||||
|
||||
|
||||
@@ -82,9 +82,6 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
|
||||
protected override bool CanAttack(Actor self, in Target target)
|
||||
{
|
||||
if (IsTraitPaused)
|
||||
return false;
|
||||
|
||||
if (state == PopupState.Closed)
|
||||
{
|
||||
state = PopupState.Transitioning;
|
||||
@@ -106,9 +103,6 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
|
||||
void INotifyIdle.TickIdle(Actor self)
|
||||
{
|
||||
if (IsTraitDisabled || IsTraitPaused)
|
||||
return;
|
||||
|
||||
if (state == PopupState.Open && idleTicks++ > info.CloseDelay)
|
||||
{
|
||||
var facingOffset = new WVec(0, -1024, 0).Rotate(WRot.FromYaw(info.DefaultFacing));
|
||||
|
||||
@@ -79,8 +79,8 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
[Desc("The condition to grant to self while disguised.")]
|
||||
public readonly string DisguisedCondition = null;
|
||||
|
||||
[Desc("Player relationships the owner of the disguise target needs.")]
|
||||
public readonly PlayerRelationship ValidRelationships = PlayerRelationship.Ally | PlayerRelationship.Neutral | PlayerRelationship.Enemy;
|
||||
[Desc("What diplomatic stances can this actor disguise as.")]
|
||||
public readonly PlayerRelationship ValidStances = PlayerRelationship.Ally | PlayerRelationship.Neutral | PlayerRelationship.Enemy;
|
||||
|
||||
[Desc("Target types of actors that this actor disguise as.")]
|
||||
public readonly BitSet<TargetableType> TargetTypes = new BitSet<TargetableType>("Disguise");
|
||||
@@ -299,7 +299,7 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor)
|
||||
{
|
||||
var stance = self.Owner.RelationshipWith(target.Owner);
|
||||
if (!info.ValidRelationships.HasStance(stance))
|
||||
if (!info.ValidStances.HasStance(stance))
|
||||
return false;
|
||||
|
||||
return info.TargetTypes.Overlaps(target.GetAllTargetTypes());
|
||||
@@ -308,7 +308,7 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
public override bool CanTargetFrozenActor(Actor self, FrozenActor target, TargetModifiers modifiers, ref string cursor)
|
||||
{
|
||||
var stance = self.Owner.RelationshipWith(target.Owner);
|
||||
if (!info.ValidRelationships.HasStance(stance))
|
||||
if (!info.ValidStances.HasStance(stance))
|
||||
return false;
|
||||
|
||||
return info.TargetTypes.Overlaps(target.Info.GetAllTargetTypes());
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
|
||||
protected override bool ShouldRender(Actor self)
|
||||
{
|
||||
return infiltrators.Any(i => Info.ValidRelationships.HasStance(i.RelationshipWith(self.World.RenderPlayer)));
|
||||
return infiltrators.Any(i => Info.ValidStances.HasStance(i.RelationshipWith(self.World.RenderPlayer)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,8 +30,8 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
[Desc("Color to use for the target line.")]
|
||||
public readonly Color TargetLineColor = Color.Crimson;
|
||||
|
||||
[Desc("Player relationships the owner of the infiltration target needs.")]
|
||||
public readonly PlayerRelationship ValidRelationships = PlayerRelationship.Neutral | PlayerRelationship.Enemy;
|
||||
[Desc("What diplomatic stances can be infiltrated by this actor.")]
|
||||
public readonly PlayerRelationship ValidStances = PlayerRelationship.Neutral | PlayerRelationship.Enemy;
|
||||
|
||||
[Desc("Behaviour when entering the target.",
|
||||
"Possible values are Exit, Suicide, Dispose.")]
|
||||
@@ -101,10 +101,10 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
{
|
||||
case TargetType.Actor:
|
||||
return Info.Types.Overlaps(target.Actor.GetEnabledTargetTypes()) &&
|
||||
Info.ValidRelationships.HasStance(self.Owner.RelationshipWith(target.Actor.Owner));
|
||||
Info.ValidStances.HasStance(self.Owner.RelationshipWith(target.Actor.Owner));
|
||||
case TargetType.FrozenActor:
|
||||
return target.FrozenActor.IsValid && Info.Types.Overlaps(target.FrozenActor.TargetTypes) &&
|
||||
Info.ValidRelationships.HasStance(self.Owner.RelationshipWith(target.FrozenActor.Owner));
|
||||
Info.ValidStances.HasStance(self.Owner.RelationshipWith(target.FrozenActor.Owner));
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -136,7 +136,7 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor)
|
||||
{
|
||||
var stance = self.Owner.RelationshipWith(target.Owner);
|
||||
if (!info.ValidRelationships.HasStance(stance))
|
||||
if (!info.ValidStances.HasStance(stance))
|
||||
return false;
|
||||
|
||||
return info.Types.Overlaps(target.GetAllTargetTypes());
|
||||
@@ -145,7 +145,7 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
public override bool CanTargetFrozenActor(Actor self, FrozenActor target, TargetModifiers modifiers, ref string cursor)
|
||||
{
|
||||
var stance = self.Owner.RelationshipWith(target.Owner);
|
||||
if (!info.ValidRelationships.HasStance(stance))
|
||||
if (!info.ValidStances.HasStance(stance))
|
||||
return false;
|
||||
|
||||
return info.Types.Overlaps(target.Info.GetAllTargetTypes());
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
return self.World.NoPlayersMask;
|
||||
|
||||
// Friendly units should move around!
|
||||
return info.BlockFriendly ? ~self.Owner.AlliedPlayersMask : self.World.AllPlayersMask;
|
||||
return info.BlockFriendly ? self.Owner.EnemyPlayersMask : self.World.AllPlayersMask;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,9 +23,6 @@ namespace OpenRA.Mods.Cnc.Traits.Render
|
||||
[Desc("This actor has turret art with facings baked into the sprite.")]
|
||||
public class WithEmbeddedTurretSpriteBodyInfo : WithSpriteBodyInfo, Requires<TurretedInfo>, Requires<BodyOrientationInfo>
|
||||
{
|
||||
[Desc("Number of facings for gameplay calculations. -1 indicates auto-detection from the sequence.")]
|
||||
public readonly int QuantizedFacings = -1;
|
||||
|
||||
public override object Create(ActorInitializer init) { return new WithEmbeddedTurretSpriteBody(init, this); }
|
||||
|
||||
public override IEnumerable<IActorPreview> RenderPreviewSprites(ActorPreviewInitializer init, RenderSpritesInfo rs, string image, int facings, PaletteReference p)
|
||||
@@ -46,7 +43,6 @@ namespace OpenRA.Mods.Cnc.Traits.Render
|
||||
|
||||
public class WithEmbeddedTurretSpriteBody : WithSpriteBody
|
||||
{
|
||||
readonly WithEmbeddedTurretSpriteBodyInfo info;
|
||||
readonly Turreted turreted;
|
||||
|
||||
static Func<WAngle> MakeTurretFacingFunc(Actor self)
|
||||
@@ -56,23 +52,22 @@ namespace OpenRA.Mods.Cnc.Traits.Render
|
||||
return () => turreted.WorldOrientation.Yaw;
|
||||
}
|
||||
|
||||
public WithEmbeddedTurretSpriteBody(ActorInitializer init, WithEmbeddedTurretSpriteBodyInfo info)
|
||||
public WithEmbeddedTurretSpriteBody(ActorInitializer init, WithSpriteBodyInfo info)
|
||||
: base(init, info, MakeTurretFacingFunc(init.Self))
|
||||
{
|
||||
this.info = info;
|
||||
turreted = init.Self.TraitsImplementing<Turreted>().FirstOrDefault();
|
||||
}
|
||||
|
||||
protected override void TraitEnabled(Actor self)
|
||||
{
|
||||
base.TraitEnabled(self);
|
||||
turreted.QuantizedFacings = info.QuantizedFacings >= 0 ? info.QuantizedFacings : DefaultAnimation.CurrentSequence.Facings;
|
||||
turreted.QuantizedFacings = DefaultAnimation.CurrentSequence.Facings;
|
||||
}
|
||||
|
||||
protected override void DamageStateChanged(Actor self)
|
||||
{
|
||||
base.DamageStateChanged(self);
|
||||
turreted.QuantizedFacings = info.QuantizedFacings >= 0 ? info.QuantizedFacings : DefaultAnimation.CurrentSequence.Facings;
|
||||
turreted.QuantizedFacings = DefaultAnimation.CurrentSequence.Facings;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
protected override void Tick(World world)
|
||||
{
|
||||
// Cancel the OG if we can't use the power
|
||||
if (!manager.Powers.TryGetValue(order, out var p) || !p.Active || !p.Ready)
|
||||
if (!manager.Powers.ContainsKey(order))
|
||||
world.CancelInputMode();
|
||||
}
|
||||
|
||||
|
||||
@@ -174,7 +174,7 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
protected override void Tick(World world)
|
||||
{
|
||||
// Cancel the OG if we can't use the power
|
||||
if (!manager.Powers.TryGetValue(order, out var p) || !p.Active || !p.Ready)
|
||||
if (!manager.Powers.ContainsKey(order))
|
||||
world.CancelInputMode();
|
||||
}
|
||||
|
||||
@@ -274,7 +274,7 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
protected override void Tick(World world)
|
||||
{
|
||||
// Cancel the OG if we can't use the power
|
||||
if (!manager.Powers.TryGetValue(order, out var p) || !p.Active || !p.Ready)
|
||||
if (!manager.Powers.ContainsKey(order))
|
||||
world.CancelInputMode();
|
||||
}
|
||||
|
||||
|
||||
@@ -142,13 +142,6 @@ namespace OpenRA.Mods.Common.Activities
|
||||
// We don't know where the target actually is, so move to where we last saw it
|
||||
if (useLastVisibleTarget)
|
||||
{
|
||||
// HACK: Bot players ignore the standard visibility checks in target.Recalculate,
|
||||
// which means that targetIsHiddenActor is always false, allowing lastVisibleMaximumRange
|
||||
// to be assigned zero range by attackAircraft.GetMaximumRangeVersusTarget for e.g. cloaked actors.
|
||||
// Catch and cancel this edge case to avoid the aircraft stopping mid-air!
|
||||
if (self.Owner.IsBot && lastVisibleMaximumRange == WDist.Zero)
|
||||
return true;
|
||||
|
||||
// We've reached the assumed position but it is not there - give up
|
||||
if (checkTarget.IsInRange(pos, lastVisibleMaximumRange))
|
||||
return true;
|
||||
|
||||
@@ -124,7 +124,7 @@ namespace OpenRA.Mods.Common.Activities
|
||||
foreach (var t in enterActor.TraitsImplementing<INotifyCapture>())
|
||||
t.OnCapture(enterActor, self, oldOwner, self.Owner, captures.Info.CaptureTypes);
|
||||
|
||||
if (self.Owner.RelationshipWith(oldOwner).HasStance(captures.Info.PlayerExperienceRelationships))
|
||||
if (self.Owner.RelationshipWith(oldOwner).HasStance(captures.Info.PlayerExperienceStances))
|
||||
self.Owner.PlayerActor.TraitOrDefault<PlayerExperience>()?.GiveExperience(captures.Info.PlayerExperience);
|
||||
|
||||
if (captures.Info.ConsumedByCapture)
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace OpenRA.Mods.Common.Activities
|
||||
// Make sure we can still repair the target before entering
|
||||
// (but not before, because this may stop the actor in the middle of nowhere)
|
||||
var stance = self.Owner.RelationshipWith(enterActor.Owner);
|
||||
if (enterHealth == null || enterHealth.DamageState == DamageState.Undamaged || enterEngineerRepariable == null || enterEngineerRepariable.IsTraitDisabled || !info.ValidRelationships.HasStance(stance))
|
||||
if (enterHealth == null || enterHealth.DamageState == DamageState.Undamaged || enterEngineerRepariable == null || enterEngineerRepariable.IsTraitDisabled || !info.ValidStances.HasStance(stance))
|
||||
{
|
||||
Cancel(self, true);
|
||||
return false;
|
||||
@@ -61,7 +61,7 @@ namespace OpenRA.Mods.Common.Activities
|
||||
return;
|
||||
|
||||
var stance = self.Owner.RelationshipWith(enterActor.Owner);
|
||||
if (!info.ValidRelationships.HasStance(stance))
|
||||
if (!info.ValidStances.HasStance(stance))
|
||||
return;
|
||||
|
||||
if (enterHealth.DamageState == DamageState.Undamaged)
|
||||
|
||||
@@ -23,14 +23,16 @@ namespace OpenRA.Mods.Common.Effects
|
||||
readonly RallyPoint rp;
|
||||
readonly Animation flag;
|
||||
readonly Animation circles;
|
||||
readonly ExitInfo[] exits;
|
||||
|
||||
List<WPos> targetLineNodes = new List<WPos> { };
|
||||
List<CPos> cachedLocations;
|
||||
|
||||
public RallyPointIndicator(Actor building, RallyPoint rp)
|
||||
public RallyPointIndicator(Actor building, RallyPoint rp, ExitInfo[] exits)
|
||||
{
|
||||
this.building = building;
|
||||
this.rp = rp;
|
||||
this.exits = exits;
|
||||
|
||||
if (rp.Info.Image != null)
|
||||
{
|
||||
@@ -71,8 +73,22 @@ namespace OpenRA.Mods.Common.Effects
|
||||
if (targetLineNodes.Count == 0)
|
||||
return;
|
||||
|
||||
var exit = building.NearestExitOrDefault(targetLineNodes[0]);
|
||||
targetLineNodes.Insert(0, building.CenterPosition + (exit?.Info.SpawnOffset ?? WVec.Zero));
|
||||
var exitPos = building.CenterPosition;
|
||||
|
||||
// Find closest exit
|
||||
var dist = int.MaxValue;
|
||||
foreach (var exit in exits)
|
||||
{
|
||||
var ep = building.CenterPosition + exit.SpawnOffset;
|
||||
var len = (targetLineNodes[0] - ep).Length;
|
||||
if (len < dist)
|
||||
{
|
||||
dist = len;
|
||||
exitPos = ep;
|
||||
}
|
||||
}
|
||||
|
||||
targetLineNodes.Insert(0, exitPos);
|
||||
}
|
||||
|
||||
IEnumerable<IRenderable> IEffect.Render(WorldRenderer wr) { return SpriteRenderable.None; }
|
||||
|
||||
@@ -319,7 +319,7 @@ namespace OpenRA.Mods.Common.FileFormats
|
||||
// Annoyingly, the complete table is not applied until the frame
|
||||
// *after* the one that contains the 8th chunk.
|
||||
// Do we have a set of partial lookup tables ready to apply?
|
||||
if (currentChunkBuffer == chunkBufferParts && chunkBufferParts != 0)
|
||||
if (currentChunkBuffer == chunkBufferParts)
|
||||
{
|
||||
if (!cbpIsCompressed)
|
||||
cbf = (byte[])cbp.Clone();
|
||||
|
||||
@@ -96,8 +96,8 @@ namespace OpenRA.Mods.Common.Projectiles
|
||||
[Desc("Terrain where the projectile explodes instead of bouncing.")]
|
||||
public readonly HashSet<string> InvalidBounceTerrain = new HashSet<string>();
|
||||
|
||||
[Desc("Trigger the explosion if the projectile touches an actor thats owner has these player relationships.")]
|
||||
public readonly PlayerRelationship ValidBounceBlockerRelationships = PlayerRelationship.Enemy | PlayerRelationship.Neutral;
|
||||
[Desc("If projectile touches an actor with one of these stances during or after the first bounce, trigger explosion.")]
|
||||
public readonly PlayerRelationship ValidBounceBlockerStances = PlayerRelationship.Enemy | PlayerRelationship.Neutral;
|
||||
|
||||
[Desc("Altitude above terrain below which to explode. Zero effectively deactivates airburst.")]
|
||||
public readonly WDist AirburstAltitude = WDist.Zero;
|
||||
@@ -319,7 +319,7 @@ namespace OpenRA.Mods.Common.Projectiles
|
||||
if (checkTargetType && !Target.FromActor(victim).IsValidFor(firedBy))
|
||||
continue;
|
||||
|
||||
if (!info.ValidBounceBlockerRelationships.HasStance(firedBy.Owner.RelationshipWith(victim.Owner)))
|
||||
if (!info.ValidBounceBlockerStances.HasStance(firedBy.Owner.RelationshipWith(victim.Owner)))
|
||||
continue;
|
||||
|
||||
// If the impact position is within any actor's HitShape, we have a direct hit
|
||||
|
||||
@@ -21,14 +21,12 @@ namespace OpenRA.Mods.Common.Scripting
|
||||
{
|
||||
readonly SpawnMapActors sma;
|
||||
readonly World world;
|
||||
readonly GameSettings gameSettings;
|
||||
|
||||
public MapGlobal(ScriptContext context)
|
||||
: base(context)
|
||||
{
|
||||
sma = context.World.WorldActor.Trait<SpawnMapActors>();
|
||||
world = context.World;
|
||||
gameSettings = Game.Settings.Game;
|
||||
|
||||
// Register map actors as globals (yuck!)
|
||||
foreach (var kv in sma.Actors)
|
||||
@@ -111,9 +109,6 @@ namespace OpenRA.Mods.Common.Scripting
|
||||
[Desc("Returns true if there is only one human player.")]
|
||||
public bool IsSinglePlayer { get { return Context.World.LobbyInfo.NonBotPlayers.Count() == 1; } }
|
||||
|
||||
[Desc("Returns true if this is a shellmap and the player has paused animations.")]
|
||||
public bool IsPausedShellmap { get { return Context.World.Type == WorldType.Shellmap && gameSettings.PauseShellmap; } }
|
||||
|
||||
[Desc("Returns the value of a `ScriptLobbyDropdown` selected in the game lobby.")]
|
||||
public LuaValue LobbyOption(string id)
|
||||
{
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using Eluant;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Scripting;
|
||||
using OpenRA.Traits;
|
||||
|
||||
@@ -36,18 +34,10 @@ namespace OpenRA.Mods.Common.Scripting
|
||||
[Desc("Maximum health of the actor.")]
|
||||
public int MaxHealth { get { return health.MaxHP; } }
|
||||
|
||||
[Desc("Kill the actor. damageTypes may be omitted, specified as a string, or as table of strings.")]
|
||||
public void Kill(object damageTypes = null)
|
||||
[Desc("Kill the actor.")]
|
||||
public void Kill()
|
||||
{
|
||||
Damage damage;
|
||||
if (damageTypes is string d)
|
||||
damage = new Damage(health.MaxHP, new BitSet<DamageType>(new[] { d }));
|
||||
else if (damageTypes is LuaTable t && t.TryGetClrValue(out string[] ds))
|
||||
damage = new Damage(health.MaxHP, new BitSet<DamageType>(ds));
|
||||
else
|
||||
damage = new Damage(health.MaxHP);
|
||||
|
||||
health.InflictDamage(Self, Self, damage, true);
|
||||
health.InflictDamage(Self, Self, new Damage(health.MaxHP), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,16 +52,6 @@ namespace OpenRA.Mods.Common.Scripting
|
||||
}
|
||||
}
|
||||
|
||||
[Desc("The player's handicap level.")]
|
||||
public int Handicap
|
||||
{
|
||||
get
|
||||
{
|
||||
var c = Player.World.LobbyInfo.Clients.FirstOrDefault(i => i.Index == Player.ClientIndex);
|
||||
return c?.Handicap ?? 0;
|
||||
}
|
||||
}
|
||||
|
||||
[Desc("Returns true if the player is a bot.")]
|
||||
public bool IsBot { get { return Player.IsBot; } }
|
||||
|
||||
|
||||
@@ -43,7 +43,6 @@ namespace OpenRA.Mods.Common.Server
|
||||
{ "name", Name },
|
||||
{ "faction", Faction },
|
||||
{ "team", Team },
|
||||
{ "handicap", Handicap },
|
||||
{ "spawn", Spawn },
|
||||
{ "clear_spawn", ClearPlayerSpawn },
|
||||
{ "color", PlayerColor },
|
||||
@@ -246,7 +245,6 @@ namespace OpenRA.Mods.Common.Server
|
||||
client.Slot = null;
|
||||
client.SpawnPoint = 0;
|
||||
client.Team = 0;
|
||||
client.Handicap = 0;
|
||||
client.Color = Color.White;
|
||||
server.SyncLobbyClients();
|
||||
CheckAutoStart(server);
|
||||
@@ -379,7 +377,6 @@ namespace OpenRA.Mods.Common.Server
|
||||
Faction = "Random",
|
||||
SpawnPoint = 0,
|
||||
Team = 0,
|
||||
Handicap = 0,
|
||||
State = Session.ClientState.NotReady,
|
||||
BotControllerClientIndex = controllerClientIndex
|
||||
};
|
||||
@@ -739,7 +736,6 @@ namespace OpenRA.Mods.Common.Server
|
||||
targetClient.Slot = null;
|
||||
targetClient.SpawnPoint = 0;
|
||||
targetClient.Team = 0;
|
||||
targetClient.Handicap = 0;
|
||||
targetClient.Color = Color.White;
|
||||
targetClient.State = Session.ClientState.NotReady;
|
||||
server.SendMessage("{0} moved {1} to spectators.".F(client.Name, targetClient.Name));
|
||||
@@ -828,42 +824,6 @@ namespace OpenRA.Mods.Common.Server
|
||||
}
|
||||
}
|
||||
|
||||
static bool Handicap(S server, Connection conn, Session.Client client, string s)
|
||||
{
|
||||
lock (server.LobbyInfo)
|
||||
{
|
||||
var parts = s.Split(' ');
|
||||
var targetClient = server.LobbyInfo.ClientWithIndex(Exts.ParseIntegerInvariant(parts[0]));
|
||||
|
||||
// Only the host can change other client's info
|
||||
if (targetClient.Index != client.Index && !client.IsAdmin)
|
||||
return true;
|
||||
|
||||
// Map has disabled handicap changes
|
||||
if (server.LobbyInfo.Slots[targetClient.Slot].LockHandicap)
|
||||
return true;
|
||||
|
||||
if (!Exts.TryParseIntegerInvariant(parts[1], out var handicap))
|
||||
{
|
||||
Log.Write("server", "Invalid handicap: {0}", s);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handicaps may be set between 0 - 95% in steps of 5%
|
||||
var options = Enumerable.Range(0, 20).Select(i => 5 * i);
|
||||
if (!options.Contains(handicap))
|
||||
{
|
||||
Log.Write("server", "Invalid handicap: {0}", s);
|
||||
return false;
|
||||
}
|
||||
|
||||
targetClient.Handicap = handicap;
|
||||
server.SyncLobbyClients();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static bool ClearPlayerSpawn(S server, Connection conn, Session.Client client, string s)
|
||||
{
|
||||
var spawnPoint = Exts.ParseIntegerInvariant(s);
|
||||
@@ -1043,7 +1003,6 @@ namespace OpenRA.Mods.Common.Server
|
||||
LockFaction = pr.LockFaction,
|
||||
LockColor = pr.LockColor,
|
||||
LockTeam = pr.LockTeam,
|
||||
LockHandicap = pr.LockHandicap,
|
||||
LockSpawn = pr.LockSpawn,
|
||||
Required = pr.Required,
|
||||
};
|
||||
|
||||
@@ -22,6 +22,9 @@ namespace OpenRA.Mods.Common.Server
|
||||
{
|
||||
lock (server.LobbyInfo)
|
||||
{
|
||||
if (server.LobbyInfo.ClientWithIndex(conn.PlayerIndex).IsAdmin)
|
||||
return;
|
||||
|
||||
var defaults = new Session.Global();
|
||||
LobbyCommands.LoadMapSettings(server, defaults, server.Map.Rules);
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[Desc("Accepted `DeliversCash` types. Leave empty to accept all types.")]
|
||||
public readonly HashSet<string> ValidTypes = new HashSet<string>();
|
||||
|
||||
[Desc("Player relationships the owner of the delivering actor needs.")]
|
||||
public readonly PlayerRelationship ValidRelationships = PlayerRelationship.Ally;
|
||||
[Desc("Stance the delivering actor needs to enter.")]
|
||||
public readonly PlayerRelationship ValidStances = PlayerRelationship.Ally;
|
||||
|
||||
[Desc("Play a randomly selected sound from this list when accepting cash.")]
|
||||
public readonly string[] Sounds = { };
|
||||
@@ -31,7 +31,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
public class AcceptsDeliveredCash : INotifyCashTransfer
|
||||
{
|
||||
readonly AcceptsDeliveredCashInfo info;
|
||||
AcceptsDeliveredCashInfo info;
|
||||
|
||||
public AcceptsDeliveredCash(Actor self, AcceptsDeliveredCashInfo info)
|
||||
{
|
||||
|
||||
@@ -20,8 +20,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[Desc("Accepted `DeliversExperience` types. Leave empty to accept all types.")]
|
||||
public readonly HashSet<string> ValidTypes = new HashSet<string>();
|
||||
|
||||
[Desc("Player relationships the owner of the delivering actor needs.")]
|
||||
public readonly PlayerRelationship ValidRelationships = PlayerRelationship.Ally;
|
||||
[Desc("Stance the delivering actor needs to enter.")]
|
||||
public readonly PlayerRelationship ValidStances = PlayerRelationship.Ally;
|
||||
|
||||
public override object Create(ActorInitializer init) { return new AcceptsDeliveredExperience(init.Self, this); }
|
||||
}
|
||||
|
||||
@@ -68,8 +68,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
public WeaponInfo WeaponInfo { get; private set; }
|
||||
public WDist ModifiedRange { get; private set; }
|
||||
|
||||
public readonly PlayerRelationship TargetRelationships = PlayerRelationship.Enemy;
|
||||
public readonly PlayerRelationship ForceTargetRelationships = PlayerRelationship.Enemy | PlayerRelationship.Neutral | PlayerRelationship.Ally;
|
||||
public readonly PlayerRelationship TargetStances = PlayerRelationship.Enemy;
|
||||
public readonly PlayerRelationship ForceTargetStances = PlayerRelationship.Enemy | PlayerRelationship.Neutral | PlayerRelationship.Ally;
|
||||
|
||||
// TODO: instead of having multiple Armaments and unique AttackBase,
|
||||
// an actor should be able to have multiple AttackBases with
|
||||
|
||||
@@ -377,7 +377,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
return Armaments.Where(a =>
|
||||
!a.IsTraitDisabled
|
||||
&& (owner == null || (forceAttack ? a.Info.ForceTargetRelationships : a.Info.TargetRelationships).HasStance(self.Owner.RelationshipWith(owner)))
|
||||
&& (owner == null || (forceAttack ? a.Info.ForceTargetStances : a.Info.TargetStances).HasStance(self.Owner.RelationshipWith(owner)))
|
||||
&& a.Weapon.IsValidAgainst(t, self.World, self));
|
||||
}
|
||||
|
||||
@@ -408,7 +408,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
var stances = PlayerRelationship.None;
|
||||
foreach (var armament in Armaments)
|
||||
if (!armament.IsTraitDisabled)
|
||||
stances |= armament.Info.TargetRelationships;
|
||||
stances |= armament.Info.TargetStances;
|
||||
|
||||
return stances;
|
||||
}
|
||||
|
||||
@@ -326,7 +326,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
return activeTargetPriorities.Any(ati =>
|
||||
{
|
||||
// Incompatible stances
|
||||
if (!ati.ValidRelationships.HasStance(self.Owner.RelationshipWith(owner)))
|
||||
if (!ati.ValidStances.HasStance(self.Owner.RelationshipWith(owner)))
|
||||
return false;
|
||||
|
||||
// Incompatible target types
|
||||
@@ -348,11 +348,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
return chosenTarget;
|
||||
|
||||
var targetsInRange = self.World.FindActorsInCircle(self.CenterPosition, scanRange)
|
||||
.Select(Target.FromActor);
|
||||
|
||||
if (allowMove || ab.Info.TargetFrozenActors)
|
||||
targetsInRange = targetsInRange
|
||||
.Concat(self.Owner.FrozenActorLayer.FrozenActorsInCircle(self.World, self.CenterPosition, scanRange)
|
||||
.Select(Target.FromActor)
|
||||
.Concat(self.Owner.FrozenActorLayer.FrozenActorsInCircle(self.World, self.CenterPosition, scanRange)
|
||||
.Select(Target.FromFrozenActor));
|
||||
|
||||
foreach (var target in targetsInRange)
|
||||
@@ -394,7 +391,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
return false;
|
||||
|
||||
// Incompatible stances
|
||||
if (!ati.ValidRelationships.HasStance(self.Owner.RelationshipWith(owner)))
|
||||
if (!ati.ValidStances.HasStance(self.Owner.RelationshipWith(owner)))
|
||||
return false;
|
||||
|
||||
// Incompatible target types
|
||||
|
||||
@@ -23,8 +23,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[Desc("Target types that can't be AutoTargeted.", "Overrules ValidTargets.")]
|
||||
public readonly BitSet<TargetableType> InvalidTargets;
|
||||
|
||||
[Desc("Relationships between actor's and target's owner needed for AutoTargeting.")]
|
||||
public readonly PlayerRelationship ValidRelationships = PlayerRelationship.Ally | PlayerRelationship.Neutral | PlayerRelationship.Enemy;
|
||||
[Desc("Stances between actor's and target's owner which can be AutoTargeted.")]
|
||||
public readonly PlayerRelationship ValidStances = PlayerRelationship.Ally | PlayerRelationship.Neutral | PlayerRelationship.Enemy;
|
||||
|
||||
[Desc("ValidTargets with larger priorities will be AutoTargeted before lower priorities.")]
|
||||
public readonly int Priority = 1;
|
||||
|
||||
@@ -37,8 +37,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[Desc("Should visibility (Shroud, Fog, Cloak, etc) be considered when searching for capturable targets?")]
|
||||
public readonly bool CheckCaptureTargetsForVisibility = true;
|
||||
|
||||
[Desc("Player relationships that capturers should attempt to target.")]
|
||||
public readonly PlayerRelationship CapturableRelationships = PlayerRelationship.Enemy | PlayerRelationship.Neutral;
|
||||
[Desc("Player stances that capturers should attempt to target.")]
|
||||
public readonly PlayerRelationship CapturableStances = PlayerRelationship.Enemy | PlayerRelationship.Neutral;
|
||||
|
||||
public override object Create(ActorInitializer init) { return new CaptureManagerBotModule(init.Self, this); }
|
||||
}
|
||||
@@ -133,7 +133,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
return;
|
||||
|
||||
var randPlayer = world.Players.Where(p => !p.Spectating
|
||||
&& Info.CapturableRelationships.HasStance(player.RelationshipWith(p))).Random(world.LocalRandom);
|
||||
&& Info.CapturableStances.HasStance(player.RelationshipWith(p))).Random(world.LocalRandom);
|
||||
|
||||
var targetOptions = Info.CheckCaptureTargetsForVisibility
|
||||
? GetVisibleActorsBelongingToPlayer(randPlayer)
|
||||
|
||||
@@ -132,7 +132,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
// Use for proactive targeting.
|
||||
public bool IsPreferredEnemyUnit(Actor a)
|
||||
{
|
||||
if (a == null || a.IsDead || Player.RelationshipWith(a.Owner) != PlayerRelationship.Enemy || a.Info.HasTraitInfo<HuskInfo>() || a.Info.HasTraitInfo<AircraftInfo>())
|
||||
if (a == null || a.IsDead || Player.RelationshipWith(a.Owner) != PlayerRelationship.Enemy || a.Info.HasTraitInfo<HuskInfo>())
|
||||
return false;
|
||||
|
||||
var targetTypes = a.GetEnabledTargetTypes();
|
||||
|
||||
@@ -53,7 +53,8 @@ namespace OpenRA.Mods.Common.Traits.BotModules.Squads
|
||||
|
||||
if (AttackOrFleeFuzzy.Default.CanAttack(owner.Units, enemyUnits))
|
||||
{
|
||||
owner.Bot.QueueOrder(new Order("AttackMove", null, Target.FromCell(owner.World, owner.TargetActor.Location), false, groupedActors: owner.Units.ToArray()));
|
||||
foreach (var u in owner.Units)
|
||||
owner.Bot.QueueOrder(new Order("AttackMove", u, Target.FromCell(owner.World, owner.TargetActor.Location), false));
|
||||
|
||||
// We have gathered sufficient units. Attack the nearest enemy unit.
|
||||
owner.FuzzyStateMachine.ChangeState(owner, new GroundUnitsAttackMoveState(), true);
|
||||
@@ -67,10 +68,6 @@ namespace OpenRA.Mods.Common.Traits.BotModules.Squads
|
||||
|
||||
class GroundUnitsAttackMoveState : GroundStateBase, IState
|
||||
{
|
||||
int lastUpdatedTick;
|
||||
CPos? lastLeaderLocation;
|
||||
Actor lastTarget;
|
||||
|
||||
public void Activate(Squad owner) { }
|
||||
|
||||
public void Tick(Squad owner)
|
||||
@@ -94,27 +91,6 @@ namespace OpenRA.Mods.Common.Traits.BotModules.Squads
|
||||
if (leader == null)
|
||||
return;
|
||||
|
||||
if (leader.Location != lastLeaderLocation)
|
||||
{
|
||||
lastLeaderLocation = leader.Location;
|
||||
lastUpdatedTick = owner.World.WorldTick;
|
||||
}
|
||||
|
||||
if (owner.TargetActor != lastTarget)
|
||||
{
|
||||
lastTarget = owner.TargetActor;
|
||||
lastUpdatedTick = owner.World.WorldTick;
|
||||
}
|
||||
|
||||
// HACK: Drop back to the idle state if we haven't moved in 2.5 seconds
|
||||
// This works around the squad being stuck trying to attack-move to a location
|
||||
// that they cannot path to, generating expensive pathfinding calls each tick.
|
||||
if (owner.World.WorldTick > lastUpdatedTick + 63)
|
||||
{
|
||||
owner.FuzzyStateMachine.ChangeState(owner, new GroundUnitsIdleState(), true);
|
||||
return;
|
||||
}
|
||||
|
||||
var ownUnits = owner.World.FindActorsInCircle(leader.CenterPosition, WDist.FromCells(owner.Units.Count) / 3)
|
||||
.Where(a => a.Owner == owner.Units.First().Owner && owner.Units.Contains(a)).ToHashSet();
|
||||
|
||||
@@ -123,9 +99,8 @@ namespace OpenRA.Mods.Common.Traits.BotModules.Squads
|
||||
// Since units have different movement speeds, they get separated while approaching the target.
|
||||
// Let them regroup into tighter formation.
|
||||
owner.Bot.QueueOrder(new Order("Stop", leader, false));
|
||||
|
||||
var units = owner.Units.Where(a => !ownUnits.Contains(a)).ToArray();
|
||||
owner.Bot.QueueOrder(new Order("AttackMove", null, Target.FromCell(owner.World, leader.Location), false, groupedActors: units));
|
||||
foreach (var unit in owner.Units.Where(a => !ownUnits.Contains(a)))
|
||||
owner.Bot.QueueOrder(new Order("AttackMove", unit, Target.FromCell(owner.World, leader.Location), false));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -138,7 +113,8 @@ namespace OpenRA.Mods.Common.Traits.BotModules.Squads
|
||||
owner.FuzzyStateMachine.ChangeState(owner, new GroundUnitsAttackState(), true);
|
||||
}
|
||||
else
|
||||
owner.Bot.QueueOrder(new Order("AttackMove", null, Target.FromCell(owner.World, owner.TargetActor.Location), false, groupedActors: owner.Units.ToArray()));
|
||||
foreach (var a in owner.Units)
|
||||
owner.Bot.QueueOrder(new Order("AttackMove", a, Target.FromCell(owner.World, owner.TargetActor.Location), false));
|
||||
}
|
||||
|
||||
if (ShouldFlee(owner))
|
||||
@@ -150,10 +126,6 @@ namespace OpenRA.Mods.Common.Traits.BotModules.Squads
|
||||
|
||||
class GroundUnitsAttackState : GroundStateBase, IState
|
||||
{
|
||||
int lastUpdatedTick;
|
||||
CPos? lastLeaderLocation;
|
||||
Actor lastTarget;
|
||||
|
||||
public void Activate(Squad owner) { }
|
||||
|
||||
public void Tick(Squad owner)
|
||||
@@ -173,28 +145,6 @@ namespace OpenRA.Mods.Common.Traits.BotModules.Squads
|
||||
}
|
||||
}
|
||||
|
||||
var leader = owner.Units.ClosestTo(owner.TargetActor.CenterPosition);
|
||||
if (leader.Location != lastLeaderLocation)
|
||||
{
|
||||
lastLeaderLocation = leader.Location;
|
||||
lastUpdatedTick = owner.World.WorldTick;
|
||||
}
|
||||
|
||||
if (owner.TargetActor != lastTarget)
|
||||
{
|
||||
lastTarget = owner.TargetActor;
|
||||
lastUpdatedTick = owner.World.WorldTick;
|
||||
}
|
||||
|
||||
// HACK: Drop back to the idle state if we haven't moved in 2.5 seconds
|
||||
// This works around the squad being stuck trying to attack-move to a location
|
||||
// that they cannot path to, generating expensive pathfinding calls each tick.
|
||||
if (owner.World.WorldTick > lastUpdatedTick + 63)
|
||||
{
|
||||
owner.FuzzyStateMachine.ChangeState(owner, new GroundUnitsIdleState(), true);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var a in owner.Units)
|
||||
if (!BusyAttack(a))
|
||||
owner.Bot.QueueOrder(new Order("Attack", a, Target.FromActor(owner.TargetActor), false));
|
||||
|
||||
@@ -78,7 +78,8 @@ namespace OpenRA.Mods.Common.Traits.BotModules.Squads
|
||||
|
||||
if (AttackOrFleeFuzzy.Default.CanAttack(owner.Units, enemyUnits))
|
||||
{
|
||||
owner.Bot.QueueOrder(new Order("AttackMove", null, Target.FromCell(owner.World, owner.TargetActor.Location), false, groupedActors: owner.Units.ToArray()));
|
||||
foreach (var u in owner.Units)
|
||||
owner.Bot.QueueOrder(new Order("AttackMove", u, Target.FromCell(owner.World, owner.TargetActor.Location), false));
|
||||
|
||||
// We have gathered sufficient units. Attack the nearest enemy unit.
|
||||
owner.FuzzyStateMachine.ChangeState(owner, new NavyUnitsAttackMoveState(), true);
|
||||
@@ -92,10 +93,6 @@ namespace OpenRA.Mods.Common.Traits.BotModules.Squads
|
||||
|
||||
class NavyUnitsAttackMoveState : NavyStateBase, IState
|
||||
{
|
||||
int lastUpdatedTick;
|
||||
CPos? lastLeaderLocation;
|
||||
Actor lastTarget;
|
||||
|
||||
public void Activate(Squad owner) { }
|
||||
|
||||
public void Tick(Squad owner)
|
||||
@@ -119,27 +116,6 @@ namespace OpenRA.Mods.Common.Traits.BotModules.Squads
|
||||
if (leader == null)
|
||||
return;
|
||||
|
||||
if (leader.Location != lastLeaderLocation)
|
||||
{
|
||||
lastLeaderLocation = leader.Location;
|
||||
lastUpdatedTick = owner.World.WorldTick;
|
||||
}
|
||||
|
||||
if (owner.TargetActor != lastTarget)
|
||||
{
|
||||
lastTarget = owner.TargetActor;
|
||||
lastUpdatedTick = owner.World.WorldTick;
|
||||
}
|
||||
|
||||
// HACK: Drop back to the idle state if we haven't moved in 2.5 seconds
|
||||
// This works around the squad being stuck trying to attack-move to a location
|
||||
// that they cannot path to, generating expensive pathfinding calls each tick.
|
||||
if (owner.World.WorldTick > lastUpdatedTick + 63)
|
||||
{
|
||||
owner.FuzzyStateMachine.ChangeState(owner, new NavyUnitsIdleState(), true);
|
||||
return;
|
||||
}
|
||||
|
||||
var ownUnits = owner.World.FindActorsInCircle(leader.CenterPosition, WDist.FromCells(owner.Units.Count) / 3)
|
||||
.Where(a => a.Owner == owner.Units.First().Owner && owner.Units.Contains(a)).ToHashSet();
|
||||
|
||||
@@ -148,9 +124,8 @@ namespace OpenRA.Mods.Common.Traits.BotModules.Squads
|
||||
// Since units have different movement speeds, they get separated while approaching the target.
|
||||
// Let them regroup into tighter formation.
|
||||
owner.Bot.QueueOrder(new Order("Stop", leader, false));
|
||||
|
||||
var units = owner.Units.Where(a => !ownUnits.Contains(a)).ToArray();
|
||||
owner.Bot.QueueOrder(new Order("AttackMove", null, Target.FromCell(owner.World, leader.Location), false, groupedActors: units));
|
||||
foreach (var unit in owner.Units.Where(a => !ownUnits.Contains(a)))
|
||||
owner.Bot.QueueOrder(new Order("AttackMove", unit, Target.FromCell(owner.World, leader.Location), false));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -163,7 +138,8 @@ namespace OpenRA.Mods.Common.Traits.BotModules.Squads
|
||||
owner.FuzzyStateMachine.ChangeState(owner, new NavyUnitsAttackState(), true);
|
||||
}
|
||||
else
|
||||
owner.Bot.QueueOrder(new Order("AttackMove", null, Target.FromCell(owner.World, owner.TargetActor.Location), false, groupedActors: owner.Units.ToArray()));
|
||||
foreach (var a in owner.Units)
|
||||
owner.Bot.QueueOrder(new Order("AttackMove", a, Target.FromCell(owner.World, owner.TargetActor.Location), false));
|
||||
}
|
||||
|
||||
if (ShouldFlee(owner))
|
||||
@@ -175,10 +151,6 @@ namespace OpenRA.Mods.Common.Traits.BotModules.Squads
|
||||
|
||||
class NavyUnitsAttackState : NavyStateBase, IState
|
||||
{
|
||||
int lastUpdatedTick;
|
||||
CPos? lastLeaderLocation;
|
||||
Actor lastTarget;
|
||||
|
||||
public void Activate(Squad owner) { }
|
||||
|
||||
public void Tick(Squad owner)
|
||||
@@ -198,28 +170,6 @@ namespace OpenRA.Mods.Common.Traits.BotModules.Squads
|
||||
}
|
||||
}
|
||||
|
||||
var leader = owner.Units.ClosestTo(owner.TargetActor.CenterPosition);
|
||||
if (leader.Location != lastLeaderLocation)
|
||||
{
|
||||
lastLeaderLocation = leader.Location;
|
||||
lastUpdatedTick = owner.World.WorldTick;
|
||||
}
|
||||
|
||||
if (owner.TargetActor != lastTarget)
|
||||
{
|
||||
lastTarget = owner.TargetActor;
|
||||
lastUpdatedTick = owner.World.WorldTick;
|
||||
}
|
||||
|
||||
// HACK: Drop back to the idle state if we haven't moved in 2.5 seconds
|
||||
// This works around the squad being stuck trying to attack-move to a location
|
||||
// that they cannot path to, generating expensive pathfinding calls each tick.
|
||||
if (owner.World.WorldTick > lastUpdatedTick + 63)
|
||||
{
|
||||
owner.FuzzyStateMachine.ChangeState(owner, new NavyUnitsIdleState(), true);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var a in owner.Units)
|
||||
if (!BusyAttack(a))
|
||||
owner.Bot.QueueOrder(new Order("Attack", a, Target.FromActor(owner.TargetActor), false));
|
||||
|
||||
@@ -55,7 +55,10 @@ namespace OpenRA.Mods.Common.Traits.BotModules.Squads
|
||||
Backoff--;
|
||||
}
|
||||
else
|
||||
owner.Bot.QueueOrder(new Order("AttackMove", null, Target.FromCell(owner.World, owner.TargetActor.Location), false, groupedActors: owner.Units.ToArray()));
|
||||
{
|
||||
foreach (var a in owner.Units)
|
||||
owner.Bot.QueueOrder(new Order("AttackMove", a, Target.FromCell(owner.World, owner.TargetActor.Location), false));
|
||||
}
|
||||
}
|
||||
|
||||
public void Deactivate(Squad owner) { }
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
// This is important because p may have side-effects that trigger a desync if not
|
||||
// called on the same exits in the same order!
|
||||
var all = Exits(actor, productionType)
|
||||
.OrderByDescending(e => e.Info.Priority)
|
||||
.OrderBy(e => e.Info.Priority)
|
||||
.ThenBy(e => (actor.World.Map.CenterOfCell(actor.Location + e.Info.ExitCell) - pos).LengthSquared)
|
||||
.ToList();
|
||||
|
||||
|
||||
@@ -75,7 +75,13 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
void INotifyCreated.Created(Actor self)
|
||||
{
|
||||
self.World.Add(new RallyPointIndicator(self, this));
|
||||
// Display only the first level of priority
|
||||
var priorityExits = self.Info.TraitInfos<ExitInfo>()
|
||||
.GroupBy(e => e.Priority)
|
||||
.FirstOrDefault();
|
||||
|
||||
var exits = priorityExits != null ? priorityExits.ToArray() : new ExitInfo[0];
|
||||
self.World.Add(new RallyPointIndicator(self, this, exits));
|
||||
}
|
||||
|
||||
public void OnOwnerChanged(Actor self, Player oldOwner, Player newOwner)
|
||||
|
||||
@@ -22,8 +22,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[Desc("CaptureTypes (from the Captures trait) that are able to capture this.")]
|
||||
public readonly BitSet<CaptureType> Types = default(BitSet<CaptureType>);
|
||||
|
||||
[Desc("What player relationships the target's owner needs to be captured by this actor.")]
|
||||
public readonly PlayerRelationship ValidRelationships = PlayerRelationship.Neutral | PlayerRelationship.Enemy;
|
||||
[Desc("What diplomatic stances can be captured by this actor.")]
|
||||
public readonly PlayerRelationship ValidStances = PlayerRelationship.Neutral | PlayerRelationship.Enemy;
|
||||
|
||||
[Desc("Cancel the actor's current activity when getting captured.")]
|
||||
public readonly bool CancelActivity = false;
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
// Actors with FrozenUnderFog should therefore not disable the Capturable trait.
|
||||
var stance = captor.Owner.RelationshipWith(frozenActor.Owner);
|
||||
return frozenActor.Info.TraitInfos<CapturableInfo>()
|
||||
.Any(c => c.ValidRelationships.HasStance(stance) && captures.Info.CaptureTypes.Overlaps(c.Types));
|
||||
.Any(c => c.ValidStances.HasStance(stance) && captures.Info.CaptureTypes.Overlaps(c.Types));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,13 +108,13 @@ namespace OpenRA.Mods.Common.Traits
|
||||
allyCapturableTypes = neutralCapturableTypes = enemyCapturableTypes = default(BitSet<CaptureType>);
|
||||
foreach (var c in enabledCapturable)
|
||||
{
|
||||
if (c.Info.ValidRelationships.HasStance(PlayerRelationship.Ally))
|
||||
if (c.Info.ValidStances.HasStance(PlayerRelationship.Ally))
|
||||
allyCapturableTypes = allyCapturableTypes.Union(c.Info.Types);
|
||||
|
||||
if (c.Info.ValidRelationships.HasStance(PlayerRelationship.Neutral))
|
||||
if (c.Info.ValidStances.HasStance(PlayerRelationship.Neutral))
|
||||
neutralCapturableTypes = neutralCapturableTypes.Union(c.Info.Types);
|
||||
|
||||
if (c.Info.ValidRelationships.HasStance(PlayerRelationship.Enemy))
|
||||
if (c.Info.ValidStances.HasStance(PlayerRelationship.Enemy))
|
||||
enemyCapturableTypes = enemyCapturableTypes.Union(c.Info.Types);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,8 +43,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[Desc("Experience granted to the capturing player.")]
|
||||
public readonly int PlayerExperience = 0;
|
||||
|
||||
[Desc("Relationships that the structure's previous owner needs to have for the capturing player to receive Experience.")]
|
||||
public readonly PlayerRelationship PlayerExperienceRelationships = PlayerRelationship.Enemy;
|
||||
[Desc("Stance that the structure's previous owner needs to have for the capturing player to receive Experience.")]
|
||||
public readonly PlayerRelationship PlayerExperienceStances = PlayerRelationship.Enemy;
|
||||
|
||||
[Desc("Cursor to display when the health of the target actor is above the sabotage threshold.")]
|
||||
public readonly string SabotageCursor = "capture";
|
||||
|
||||
@@ -30,8 +30,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
"Ignored if 0 (actors are selected regardless of vertical distance).")]
|
||||
public readonly WDist MaximumVerticalOffset = WDist.Zero;
|
||||
|
||||
[Desc("What player relationships are affected.")]
|
||||
public readonly PlayerRelationship ValidRelationships = PlayerRelationship.Ally;
|
||||
[Desc("What diplomatic stances are affected.")]
|
||||
public readonly PlayerRelationship ValidStances = PlayerRelationship.Ally;
|
||||
|
||||
[Desc("Condition is applied permanently to this actor.")]
|
||||
public readonly bool AffectsParent = false;
|
||||
@@ -111,7 +111,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
return;
|
||||
|
||||
var stance = self.Owner.RelationshipWith(a.Owner);
|
||||
if (!Info.ValidRelationships.HasStance(stance))
|
||||
if (!Info.ValidStances.HasStance(stance))
|
||||
return;
|
||||
|
||||
var external = a.TraitsImplementing<ExternalCondition>()
|
||||
@@ -135,7 +135,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
if ((produced.CenterPosition - self.CenterPosition).HorizontalLengthSquared <= Info.Range.LengthSquared)
|
||||
{
|
||||
var stance = self.Owner.RelationshipWith(produced.Owner);
|
||||
if (!Info.ValidRelationships.HasStance(stance))
|
||||
if (!Info.ValidStances.HasStance(stance))
|
||||
return;
|
||||
|
||||
var external = produced.TraitsImplementing<ExternalCondition>()
|
||||
|
||||
@@ -17,8 +17,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
public class CreatesShroudInfo : AffectsShroudInfo
|
||||
{
|
||||
[Desc("Relationship the watching player needs to see the generated shroud.")]
|
||||
public readonly PlayerRelationship ValidRelationships = PlayerRelationship.Neutral | PlayerRelationship.Enemy;
|
||||
[Desc("Stance the watching player needs to see the generated shroud.")]
|
||||
public readonly PlayerRelationship ValidStances = PlayerRelationship.Neutral | PlayerRelationship.Enemy;
|
||||
|
||||
public override object Create(ActorInitializer init) { return new CreatesShroud(init.Self, this); }
|
||||
}
|
||||
@@ -43,7 +43,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
protected override void AddCellsToPlayerShroud(Actor self, Player p, PPos[] uv)
|
||||
{
|
||||
if (!info.ValidRelationships.HasStance(self.Owner.RelationshipWith(p)))
|
||||
if (!info.ValidStances.HasStance(self.Owner.RelationshipWith(p)))
|
||||
return;
|
||||
|
||||
p.Shroud.AddSource(this, Shroud.SourceType.Shroud, uv);
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
if (IsTraitDisabled || !self.IsAtGroundLevel() || !Info.CrushClasses.Overlaps(crushClasses))
|
||||
return self.World.NoPlayersMask;
|
||||
|
||||
return Info.CrushedByFriendlies ? self.World.AllPlayersMask : ~self.Owner.AlliedPlayersMask;
|
||||
return Info.CrushedByFriendlies ? self.World.AllPlayersMask : self.Owner.EnemyPlayersMask;
|
||||
}
|
||||
|
||||
bool CrushableInner(BitSet<CrushClass> crushClasses, Player crushOwner)
|
||||
|
||||
@@ -99,7 +99,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor)
|
||||
{
|
||||
var targetInfo = target.Info.TraitInfoOrDefault<AcceptsDeliveredCashInfo>();
|
||||
if (targetInfo == null || !targetInfo.ValidRelationships.HasStance(target.Owner.RelationshipWith(self.Owner)))
|
||||
if (targetInfo == null || !targetInfo.ValidStances.HasStance(target.Owner.RelationshipWith(self.Owner)))
|
||||
return false;
|
||||
|
||||
if (targetInfo.ValidTypes.Count == 0)
|
||||
@@ -112,7 +112,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
public override bool CanTargetFrozenActor(Actor self, FrozenActor target, TargetModifiers modifiers, ref string cursor)
|
||||
{
|
||||
var targetInfo = target.Info.TraitInfoOrDefault<AcceptsDeliveredCashInfo>();
|
||||
if (targetInfo == null || !targetInfo.ValidRelationships.HasStance(target.Owner.RelationshipWith(self.Owner)))
|
||||
if (targetInfo == null || !targetInfo.ValidStances.HasStance(target.Owner.RelationshipWith(self.Owner)))
|
||||
return false;
|
||||
|
||||
if (targetInfo.ValidTypes.Count == 0)
|
||||
|
||||
@@ -109,7 +109,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
return false;
|
||||
|
||||
var targetInfo = target.Info.TraitInfoOrDefault<AcceptsDeliveredExperienceInfo>();
|
||||
if (targetInfo == null || !targetInfo.ValidRelationships.HasStance(target.Owner.RelationshipWith(self.Owner)))
|
||||
if (targetInfo == null || !targetInfo.ValidStances.HasStance(target.Owner.RelationshipWith(self.Owner)))
|
||||
return false;
|
||||
|
||||
if (targetInfo.ValidTypes.Count == 0)
|
||||
@@ -129,7 +129,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
return false;
|
||||
|
||||
var targetInfo = target.Info.TraitInfoOrDefault<AcceptsDeliveredExperienceInfo>();
|
||||
if (targetInfo == null || !targetInfo.ValidRelationships.HasStance(target.Owner.RelationshipWith(self.Owner)))
|
||||
if (targetInfo == null || !targetInfo.ValidStances.HasStance(target.Owner.RelationshipWith(self.Owner)))
|
||||
return false;
|
||||
|
||||
if (targetInfo.ValidTypes.Count == 0)
|
||||
|
||||
@@ -47,8 +47,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[Desc("Color to use for the target line.")]
|
||||
public readonly Color TargetLineColor = Color.Crimson;
|
||||
|
||||
public readonly PlayerRelationship TargetRelationships = PlayerRelationship.Enemy | PlayerRelationship.Neutral;
|
||||
public readonly PlayerRelationship ForceTargetRelationships = PlayerRelationship.Enemy | PlayerRelationship.Neutral | PlayerRelationship.Ally;
|
||||
public readonly PlayerRelationship TargetStances = PlayerRelationship.Enemy | PlayerRelationship.Neutral;
|
||||
public readonly PlayerRelationship ForceTargetStances = PlayerRelationship.Enemy | PlayerRelationship.Neutral | PlayerRelationship.Ally;
|
||||
|
||||
[Desc("Cursor to display when hovering over a demolishable target.")]
|
||||
public readonly string Cursor = "c4";
|
||||
@@ -118,10 +118,10 @@ namespace OpenRA.Mods.Common.Traits
|
||||
return false;
|
||||
|
||||
var stance = target.Owner.RelationshipWith(self.Owner);
|
||||
if (!info.TargetRelationships.HasStance(stance) && !modifiers.HasModifier(TargetModifiers.ForceAttack))
|
||||
if (!info.TargetStances.HasStance(stance) && !modifiers.HasModifier(TargetModifiers.ForceAttack))
|
||||
return false;
|
||||
|
||||
if (!info.ForceTargetRelationships.HasStance(stance) && modifiers.HasModifier(TargetModifiers.ForceAttack))
|
||||
if (!info.ForceTargetStances.HasStance(stance) && modifiers.HasModifier(TargetModifiers.ForceAttack))
|
||||
return false;
|
||||
|
||||
return target.TraitsImplementing<IDemolishable>().Any(i => i.IsValidTarget(target, self));
|
||||
@@ -130,10 +130,10 @@ namespace OpenRA.Mods.Common.Traits
|
||||
public override bool CanTargetFrozenActor(Actor self, FrozenActor target, TargetModifiers modifiers, ref string cursor)
|
||||
{
|
||||
var stance = target.Owner.RelationshipWith(self.Owner);
|
||||
if (!info.TargetRelationships.HasStance(stance) && !modifiers.HasModifier(TargetModifiers.ForceAttack))
|
||||
if (!info.TargetStances.HasStance(stance) && !modifiers.HasModifier(TargetModifiers.ForceAttack))
|
||||
return false;
|
||||
|
||||
if (!info.ForceTargetRelationships.HasStance(stance) && modifiers.HasModifier(TargetModifiers.ForceAttack))
|
||||
if (!info.ForceTargetStances.HasStance(stance) && modifiers.HasModifier(TargetModifiers.ForceAttack))
|
||||
return false;
|
||||
|
||||
return target.Info.TraitInfos<IDemolishableInfo>().Any(i => i.IsValidTarget(target.Info, self));
|
||||
|
||||
@@ -33,8 +33,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
"Possible values are Exit, Suicide, Dispose.")]
|
||||
public readonly EnterBehaviour EnterBehaviour = EnterBehaviour.Dispose;
|
||||
|
||||
[Desc("What player relationship the target's owner needs to be repaired by this actor.")]
|
||||
public readonly PlayerRelationship ValidRelationships = PlayerRelationship.Ally;
|
||||
[Desc("What diplomatic stances allow target to be repaired by this actor.")]
|
||||
public readonly PlayerRelationship ValidStances = PlayerRelationship.Ally;
|
||||
|
||||
[Desc("Sound to play when repairing is done.")]
|
||||
public readonly string RepairSound = null;
|
||||
@@ -117,7 +117,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
if (!engineerRepairable.Info.Types.IsEmpty && !engineerRepairable.Info.Types.Overlaps(info.Types))
|
||||
return false;
|
||||
|
||||
if (!info.ValidRelationships.HasStance(target.Owner.RelationshipWith(self.Owner)))
|
||||
if (!info.ValidStances.HasStance(target.Owner.RelationshipWith(self.Owner)))
|
||||
return false;
|
||||
|
||||
if (target.GetDamageState() == DamageState.Undamaged)
|
||||
@@ -139,7 +139,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
if (!engineerRepairable.Types.IsEmpty && !engineerRepairable.Types.Overlaps(info.Types))
|
||||
return false;
|
||||
|
||||
if (!info.ValidRelationships.HasStance(target.Owner.RelationshipWith(self.Owner)))
|
||||
if (!info.ValidStances.HasStance(target.Owner.RelationshipWith(self.Owner)))
|
||||
return false;
|
||||
|
||||
if (target.DamageState == DamageState.Undamaged)
|
||||
|
||||
@@ -23,8 +23,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[Desc("Percentage of the killed actor's Cost or CustomSellValue to be given.")]
|
||||
public readonly int Percentage = 10;
|
||||
|
||||
[Desc("Player relationships the attacking player needs to receive the bounty.")]
|
||||
public readonly PlayerRelationship ValidRelationships = PlayerRelationship.Neutral | PlayerRelationship.Enemy;
|
||||
[Desc("Stance the attacking player needs to receive the bounty.")]
|
||||
public readonly PlayerRelationship ValidStances = PlayerRelationship.Neutral | PlayerRelationship.Enemy;
|
||||
|
||||
[Desc("Whether to show a floating text announcing the won bounty.")]
|
||||
public readonly bool ShowBounty = true;
|
||||
@@ -64,7 +64,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
if (e.Attacker == null || e.Attacker.Disposed || IsTraitDisabled)
|
||||
return;
|
||||
|
||||
if (!Info.ValidRelationships.HasStance(e.Attacker.Owner.RelationshipWith(self.Owner)))
|
||||
if (!Info.ValidStances.HasStance(e.Attacker.Owner.RelationshipWith(self.Owner)))
|
||||
return;
|
||||
|
||||
if (!Info.DeathTypes.IsEmpty && !e.Damage.DamageTypes.Overlaps(Info.DeathTypes))
|
||||
|
||||
@@ -21,8 +21,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[Desc("If -1, use the value of the unit cost.")]
|
||||
public readonly int Experience = -1;
|
||||
|
||||
[Desc("Player relationships the attacking player needs to receive the experience.")]
|
||||
public readonly PlayerRelationship ValidRelationships = PlayerRelationship.Neutral | PlayerRelationship.Enemy;
|
||||
[Desc("Stance the attacking player needs to receive the experience.")]
|
||||
public readonly PlayerRelationship ValidStances = PlayerRelationship.Neutral | PlayerRelationship.Enemy;
|
||||
|
||||
[Desc("Percentage of the `Experience` value that is being granted to the killing actor.")]
|
||||
public readonly int ActorExperienceModifier = 10000;
|
||||
@@ -59,7 +59,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
if (exp == 0 || e.Attacker == null || e.Attacker.Disposed)
|
||||
return;
|
||||
|
||||
if (!info.ValidRelationships.HasStance(e.Attacker.Owner.RelationshipWith(self.Owner)))
|
||||
if (!info.ValidStances.HasStance(e.Attacker.Owner.RelationshipWith(self.Owner)))
|
||||
return;
|
||||
|
||||
exp = Util.ApplyPercentageModifiers(exp, experienceModifiers);
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
@@ -30,9 +28,6 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[Desc("Chance (out of 100) the unit has to enter panic mode when attacking.")]
|
||||
public readonly int AttackPanicChance = 20;
|
||||
|
||||
[Desc("The terrain types that this actor should avoid running on to while panicking.")]
|
||||
public readonly HashSet<string> AvoidTerrainTypes = new HashSet<string>();
|
||||
|
||||
[SequenceReference(prefix: true)]
|
||||
public readonly string PanicSequencePrefix = "panic-";
|
||||
|
||||
@@ -44,7 +39,6 @@ namespace OpenRA.Mods.Common.Traits
|
||||
readonly ScaredyCatInfo info;
|
||||
readonly Mobile mobile;
|
||||
readonly Actor self;
|
||||
readonly Func<CPos, bool> avoidTerrainFilter;
|
||||
|
||||
[Sync]
|
||||
int panicStartedTick;
|
||||
@@ -58,9 +52,6 @@ namespace OpenRA.Mods.Common.Traits
|
||||
this.self = self;
|
||||
this.info = info;
|
||||
mobile = self.Trait<Mobile>();
|
||||
|
||||
if (info.AvoidTerrainTypes.Count > 0)
|
||||
avoidTerrainFilter = c => info.AvoidTerrainTypes.Contains(self.World.Map.GetTerrainInfo(c).Type);
|
||||
}
|
||||
|
||||
public void Panic()
|
||||
@@ -88,10 +79,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
if (!Panicking)
|
||||
return;
|
||||
|
||||
// Note: This is just a modified copy of Mobile.Nudge
|
||||
var cell = mobile.GetAdjacentCell(self.Location, avoidTerrainFilter);
|
||||
if (cell != null)
|
||||
self.QueueActivity(false, mobile.MoveTo(cell.Value, 0));
|
||||
mobile.Nudge(self);
|
||||
}
|
||||
|
||||
void INotifyDamage.Damaged(Actor self, AttackInfo e)
|
||||
|
||||
@@ -19,8 +19,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[Desc("Range of the deflection.")]
|
||||
public readonly WDist Range = WDist.Zero;
|
||||
|
||||
[Desc("What player relationships are affected.")]
|
||||
public readonly PlayerRelationship DeflectionRelationships = PlayerRelationship.Ally | PlayerRelationship.Neutral | PlayerRelationship.Enemy;
|
||||
[Desc("What diplomatic stances are affected.")]
|
||||
public readonly PlayerRelationship DeflectionStances = PlayerRelationship.Ally | PlayerRelationship.Neutral | PlayerRelationship.Enemy;
|
||||
|
||||
[Desc("Chance of deflecting missiles.")]
|
||||
public readonly int Chance = 100;
|
||||
@@ -31,7 +31,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
public class JamsMissiles : ConditionalTrait<JamsMissilesInfo>
|
||||
{
|
||||
public WDist Range { get { return IsTraitDisabled ? WDist.Zero : Info.Range; } }
|
||||
public PlayerRelationship DeflectionStances { get { return Info.DeflectionRelationships; } }
|
||||
public PlayerRelationship DeflectionStances { get { return Info.DeflectionStances; } }
|
||||
public int Chance { get { return Info.Chance; } }
|
||||
|
||||
public JamsMissiles(JamsMissilesInfo info)
|
||||
|
||||
@@ -364,14 +364,14 @@ namespace OpenRA.Mods.Common.Traits
|
||||
self.QueueActivity(false, MoveTo(cell.Value, 0));
|
||||
}
|
||||
|
||||
public CPos? GetAdjacentCell(CPos nextCell, Func<CPos, bool> preferToAvoid = null)
|
||||
public CPos? GetAdjacentCell(CPos nextCell)
|
||||
{
|
||||
var availCells = new List<CPos>();
|
||||
var notStupidCells = new List<CPos>();
|
||||
foreach (CVec direction in CVec.Directions)
|
||||
{
|
||||
var p = ToCell + direction;
|
||||
if (CanEnterCell(p) && CanStayInCell(p) && (preferToAvoid == null || !preferToAvoid(p)))
|
||||
if (CanEnterCell(p) && CanStayInCell(p))
|
||||
availCells.Add(p);
|
||||
else if (p != nextCell && p != ToCell)
|
||||
notStupidCells.Add(p);
|
||||
|
||||
@@ -20,8 +20,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[Desc("This actor will remain visible (but not updated visually) under fog, once discovered.")]
|
||||
public class FrozenUnderFogInfo : TraitInfo, Requires<BuildingInfo>, IDefaultVisibilityInfo
|
||||
{
|
||||
[Desc("Players with these relationships can always see the actor.")]
|
||||
public readonly PlayerRelationship AlwaysVisibleRelationships = PlayerRelationship.Ally;
|
||||
[Desc("Players with these stances can always see the actor.")]
|
||||
public readonly PlayerRelationship AlwaysVisibleStances = PlayerRelationship.Ally;
|
||||
|
||||
public override object Create(ActorInitializer init) { return new FrozenUnderFog(init, this); }
|
||||
}
|
||||
@@ -106,7 +106,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
return true;
|
||||
|
||||
var stance = self.Owner.RelationshipWith(byPlayer);
|
||||
return info.AlwaysVisibleRelationships.HasStance(stance) || IsVisibleInner(self, byPlayer);
|
||||
return info.AlwaysVisibleStances.HasStance(stance) || IsVisibleInner(self, byPlayer);
|
||||
}
|
||||
|
||||
void ITick.Tick(Actor self)
|
||||
|
||||
@@ -19,8 +19,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[Desc("The actor stays invisible under the shroud.")]
|
||||
public class HiddenUnderShroudInfo : TraitInfo, IDefaultVisibilityInfo
|
||||
{
|
||||
[Desc("Players with these relationships can always see the actor.")]
|
||||
public readonly PlayerRelationship AlwaysVisibleRelationships = PlayerRelationship.Ally;
|
||||
[Desc("Players with these stances can always see the actor.")]
|
||||
public readonly PlayerRelationship AlwaysVisibleStances = PlayerRelationship.Ally;
|
||||
|
||||
[Desc("Possible values are CenterPosition (reveal when the center is visible) and ",
|
||||
"Footprint (reveal when any footprint cell is visible).")]
|
||||
@@ -56,7 +56,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
return true;
|
||||
|
||||
var stance = self.Owner.RelationshipWith(byPlayer);
|
||||
return Info.AlwaysVisibleRelationships.HasStance(stance) || IsVisibleInner(self, byPlayer);
|
||||
return Info.AlwaysVisibleStances.HasStance(stance) || IsVisibleInner(self, byPlayer);
|
||||
}
|
||||
|
||||
IEnumerable<IRenderable> IRenderModifier.ModifyRender(Actor self, WorldRenderer wr, IEnumerable<IRenderable> r)
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
[Desc("Modifies the damage applied to this actor based on the owner's handicap.")]
|
||||
public class HandicapDamageMultiplierInfo : TraitInfo
|
||||
{
|
||||
public override object Create(ActorInitializer init) { return new HandicapDamageMultiplier(init.Self); }
|
||||
}
|
||||
|
||||
public class HandicapDamageMultiplier : IDamageModifier
|
||||
{
|
||||
readonly Actor self;
|
||||
|
||||
public HandicapDamageMultiplier(Actor self)
|
||||
{
|
||||
this.self = self;
|
||||
}
|
||||
|
||||
int IDamageModifier.GetDamageModifier(Actor attacker, Damage damage)
|
||||
{
|
||||
// Equivalent to the health handicap from C&C3:
|
||||
// 5% handicap = 95% health = 105% damage
|
||||
// 50% handicap = 50% health = 200% damage
|
||||
// 95% handicap = 5% health = 2000% damage
|
||||
return 10000 / (100 - self.Owner.Handicap);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
[Desc("Modifies the damage applied by this actor based on the owner's handicap.")]
|
||||
public class HandicapFirepowerMultiplierInfo : TraitInfo
|
||||
{
|
||||
public override object Create(ActorInitializer init) { return new HandicapFirepowerMultiplier(init.Self); }
|
||||
}
|
||||
|
||||
public class HandicapFirepowerMultiplier : IFirepowerModifier
|
||||
{
|
||||
readonly Actor self;
|
||||
|
||||
public HandicapFirepowerMultiplier(Actor self)
|
||||
{
|
||||
this.self = self;
|
||||
}
|
||||
|
||||
int IFirepowerModifier.GetFirepowerModifier()
|
||||
{
|
||||
// Equivalent to the firepower handicap from C&C3:
|
||||
// 5% handicap = 95% firepower
|
||||
// 50% handicap = 50% firepower
|
||||
// 95% handicap = 5% firepower
|
||||
return 100 - self.Owner.Handicap;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
[Desc("Modifies the production time of this actor based on the producer's handicap.")]
|
||||
public class HandicapProductionTimeMultiplierInfo : TraitInfo<HandicapProductionTimeMultiplier>, IProductionTimeModifierInfo
|
||||
{
|
||||
int IProductionTimeModifierInfo.GetProductionTimeModifier(TechTree techTree, string queue)
|
||||
{
|
||||
// Equivalent to the build speed handicap from C&C3:
|
||||
// 5% handicap = 105% build time
|
||||
// 50% handicap = 150% build time
|
||||
// 95% handicap = 195% build time
|
||||
return 100 + techTree.Owner.Handicap;
|
||||
}
|
||||
}
|
||||
|
||||
public class HandicapProductionTimeMultiplier { }
|
||||
}
|
||||
@@ -12,7 +12,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
@@ -59,19 +58,15 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[NotificationReference("Speech")]
|
||||
public readonly string LeaveNotification = null;
|
||||
|
||||
public override object Create(ActorInitializer init) { return new MissionObjectives(init.Self.Owner, this); }
|
||||
public override object Create(ActorInitializer init) { return new MissionObjectives(init.World, this); }
|
||||
}
|
||||
|
||||
public class MissionObjectives : INotifyWinStateChanged, ISync, IResolveOrder, IWorldLoaded
|
||||
public class MissionObjectives : INotifyWinStateChanged, ISync, IResolveOrder
|
||||
{
|
||||
public readonly MissionObjectivesInfo Info;
|
||||
readonly List<MissionObjective> objectives = new List<MissionObjective>();
|
||||
readonly Player player;
|
||||
public ReadOnlyList<MissionObjective> Objectives;
|
||||
|
||||
Player[] enemies;
|
||||
Player[] allies;
|
||||
|
||||
[Sync]
|
||||
public int ObjectivesHash
|
||||
{
|
||||
@@ -88,21 +83,12 @@ namespace OpenRA.Mods.Common.Traits
|
||||
// The player's WinState is only updated when his allies have all completed their objective as well.
|
||||
public WinState WinStateCooperative { get; private set; }
|
||||
|
||||
public MissionObjectives(Player player, MissionObjectivesInfo info)
|
||||
public MissionObjectives(World world, MissionObjectivesInfo info)
|
||||
{
|
||||
Info = info;
|
||||
this.player = player;
|
||||
Objectives = new ReadOnlyList<MissionObjective>(objectives);
|
||||
}
|
||||
|
||||
void IWorldLoaded.WorldLoaded(World w, WorldRenderer wr)
|
||||
{
|
||||
// Players and NonCombatants are fixed once the game starts, but the result of IsAlliedWith
|
||||
// may change once players are marked as spectators, so cache these
|
||||
allies = player.World.Players.Where(p => !p.NonCombatant && player.IsAlliedWith(p)).ToArray();
|
||||
enemies = player.World.Players.Where(p => !p.NonCombatant && player.RelationshipWith(p) == PlayerRelationship.Enemy).ToArray();
|
||||
}
|
||||
|
||||
public int Add(Player player, string description, string type, bool required = true, bool inhibitAnnouncement = false)
|
||||
{
|
||||
var newID = objectives.Count;
|
||||
@@ -154,9 +140,10 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
void CheckIfGameIsOver(Player player)
|
||||
{
|
||||
var gameOver = player.World.Players.All(p => p.NonCombatant || p.WinState != WinState.Undefined || !p.HasObjectives);
|
||||
var players = player.World.Players.Where(p => !p.NonCombatant);
|
||||
|
||||
var gameOver = players.All(p => p.WinState != WinState.Undefined || !p.HasObjectives);
|
||||
if (gameOver)
|
||||
{
|
||||
Game.RunAfterDelay(Info.GameOverDelay, () =>
|
||||
{
|
||||
if (!Game.IsCurrentWorld(player.World))
|
||||
@@ -166,14 +153,17 @@ namespace OpenRA.Mods.Common.Traits
|
||||
player.World.SetPauseState(true);
|
||||
player.World.PauseStateLocked = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void INotifyWinStateChanged.OnPlayerWon(Player player)
|
||||
{
|
||||
var players = player.World.Players.Where(p => !p.NonCombatant);
|
||||
var enemies = players.Where(p => !p.IsAlliedWith(player));
|
||||
|
||||
if (Info.Cooperative)
|
||||
{
|
||||
WinStateCooperative = WinState.Won;
|
||||
var allies = players.Where(p => p.IsAlliedWith(player));
|
||||
|
||||
if (allies.All(p => p.PlayerActor.Trait<MissionObjectives>().WinStateCooperative == WinState.Won))
|
||||
{
|
||||
@@ -203,9 +193,13 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
void INotifyWinStateChanged.OnPlayerLost(Player player)
|
||||
{
|
||||
var players = player.World.Players.Where(p => !p.NonCombatant);
|
||||
var enemies = players.Where(p => !p.IsAlliedWith(player));
|
||||
|
||||
if (Info.Cooperative)
|
||||
{
|
||||
WinStateCooperative = WinState.Lost;
|
||||
var allies = players.Where(p => p.IsAlliedWith(player));
|
||||
|
||||
if (allies.Any(p => p.PlayerActor.Trait<MissionObjectives>().WinStateCooperative == WinState.Lost))
|
||||
{
|
||||
|
||||
@@ -412,11 +412,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
var hasPlayedSound = false;
|
||||
BeginProduction(new ProductionItem(this, order.TargetString, cost, playerPower, () => self.World.AddFrameEndTask(_ =>
|
||||
{
|
||||
// Make sure the item hasn't been invalidated between the ProductionItem ticking and this FrameEndTask running
|
||||
if (!Queue.Any(i => i.Done && i.Item == unit.Name))
|
||||
return;
|
||||
|
||||
var isBuilding = unit.HasTraitInfo<BuildingInfo>();
|
||||
|
||||
if (isBuilding && !hasPlayedSound)
|
||||
hasPlayedSound = Game.Sound.PlayNotification(rules, self.Owner, "Speech", Info.ReadyAudio, self.Owner.Faction.InternalName);
|
||||
else if (!isBuilding)
|
||||
|
||||
@@ -106,8 +106,6 @@ namespace OpenRA.Mods.Common.Traits
|
||||
return ret;
|
||||
}
|
||||
|
||||
public Player Owner { get { return player; } }
|
||||
|
||||
class Watcher
|
||||
{
|
||||
public readonly string Key;
|
||||
|
||||
@@ -20,8 +20,8 @@ namespace OpenRA.Mods.Common.Traits.Radar
|
||||
{
|
||||
public readonly bool UseLocation = false;
|
||||
|
||||
[Desc("Player relationships who can view this actor on radar.")]
|
||||
public readonly PlayerRelationship ValidRelationships = PlayerRelationship.Ally | PlayerRelationship.Neutral | PlayerRelationship.Enemy;
|
||||
[Desc("Player stances who can view this actor on radar.")]
|
||||
public readonly PlayerRelationship ValidStances = PlayerRelationship.Ally | PlayerRelationship.Neutral | PlayerRelationship.Enemy;
|
||||
|
||||
public override object Create(ActorInitializer init) { return new AppearsOnRadar(this); }
|
||||
}
|
||||
@@ -42,7 +42,7 @@ namespace OpenRA.Mods.Common.Traits.Radar
|
||||
public void PopulateRadarSignatureCells(Actor self, List<(CPos Cell, Color Color)> destinationBuffer)
|
||||
{
|
||||
var viewer = self.World.RenderPlayer ?? self.World.LocalPlayer;
|
||||
if (IsTraitDisabled || (viewer != null && !Info.ValidRelationships.HasStance(self.Owner.RelationshipWith(viewer))))
|
||||
if (IsTraitDisabled || (viewer != null && !Info.ValidStances.HasStance(self.Owner.RelationshipWith(viewer))))
|
||||
return;
|
||||
|
||||
var color = Game.Settings.Game.UsePlayerStanceColors ? self.Owner.PlayerStanceColor(self) : self.Owner.Color;
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
class CashTricklerBarInfo : TraitInfo, Requires<CashTricklerInfo>
|
||||
{
|
||||
[Desc("Defines to which players the bar is to be shown.")]
|
||||
public readonly PlayerRelationship DisplayRelationships = PlayerRelationship.Ally;
|
||||
public readonly PlayerRelationship DisplayStances = PlayerRelationship.Ally;
|
||||
|
||||
public readonly Color Color = Color.Magenta;
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
float ISelectionBar.GetValue()
|
||||
{
|
||||
var viewer = self.World.RenderPlayer ?? self.World.LocalPlayer;
|
||||
if (viewer != null && !info.DisplayRelationships.HasStance(self.Owner.RelationshipWith(viewer)))
|
||||
if (viewer != null && !info.DisplayStances.HasStance(self.Owner.RelationshipWith(viewer)))
|
||||
return 0;
|
||||
|
||||
var complete = cashTricklers.Min(ct => (float)ct.Ticks / ct.Info.Interval);
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
class SupportPowerChargeBarInfo : ConditionalTraitInfo
|
||||
{
|
||||
[Desc("Defines to which players the bar is to be shown.")]
|
||||
public readonly PlayerRelationship DisplayRelationships = PlayerRelationship.Ally;
|
||||
public readonly PlayerRelationship DisplayStances = PlayerRelationship.Ally;
|
||||
|
||||
public readonly Color Color = Color.Magenta;
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
return 0;
|
||||
|
||||
var viewer = self.World.RenderPlayer ?? self.World.LocalPlayer;
|
||||
if (viewer != null && !Info.DisplayRelationships.HasStance(self.Owner.RelationshipWith(viewer)))
|
||||
if (viewer != null && !Info.DisplayStances.HasStance(self.Owner.RelationshipWith(viewer)))
|
||||
return 0;
|
||||
|
||||
return 1 - (float)power.RemainingTicks / power.TotalTicks;
|
||||
|
||||
@@ -24,8 +24,8 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
[Desc("Position in the actor's selection box to draw the decoration.")]
|
||||
public readonly string Position = "TopLeft";
|
||||
|
||||
[Desc("Player relationships who can view the decoration.")]
|
||||
public readonly PlayerRelationship ValidRelationships = PlayerRelationship.Ally;
|
||||
[Desc("Player stances who can view the decoration.")]
|
||||
public readonly PlayerRelationship ValidStances = PlayerRelationship.Ally;
|
||||
|
||||
[Desc("Should this be visible only when selected?")]
|
||||
public readonly bool RequiresSelection = false;
|
||||
@@ -82,7 +82,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
if (self.World.RenderPlayer != null)
|
||||
{
|
||||
var stance = self.Owner.RelationshipWith(self.World.RenderPlayer);
|
||||
if (!Info.ValidRelationships.HasStance(stance))
|
||||
if (!Info.ValidStances.HasStance(stance))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,10 +29,8 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
public readonly string DefaultAttackSequence = null;
|
||||
|
||||
[SequenceReference(dictionaryReference: LintDictionaryReference.Values)]
|
||||
[Desc("Attack sequence to use for each armament.",
|
||||
"A dictionary of [armament name]: [sequence name(s)].",
|
||||
"Multiple sequence names can be defined to specify per-burst animations.")]
|
||||
public readonly Dictionary<string, string[]> AttackSequences = new Dictionary<string, string[]>();
|
||||
[Desc("Attack sequence to use for each armament.")]
|
||||
public readonly Dictionary<string, string> AttackSequences = new Dictionary<string, string>();
|
||||
|
||||
[SequenceReference]
|
||||
public readonly string[] IdleSequences = { };
|
||||
@@ -135,21 +133,11 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
}
|
||||
}
|
||||
|
||||
void Attacking(Actor self, Armament a, Barrel barrel)
|
||||
public void Attacking(Actor self, in Target target, Armament a)
|
||||
{
|
||||
var info = GetDisplayInfo();
|
||||
var sequence = info.DefaultAttackSequence;
|
||||
|
||||
if (info.AttackSequences.TryGetValue(a.Info.Name, out var sequences) && sequences.Length > 0)
|
||||
{
|
||||
sequence = sequences[0];
|
||||
|
||||
// Find the sequence corresponding to this barrel/burst.
|
||||
if (barrel != null && sequences.Length > 1)
|
||||
for (var i = 0; i < sequences.Length; i++)
|
||||
if (a.Barrels[i] == barrel)
|
||||
sequence = sequences[i];
|
||||
}
|
||||
if (!info.AttackSequences.TryGetValue(a.Info.Name, out var sequence))
|
||||
sequence = info.DefaultAttackSequence;
|
||||
|
||||
if (!string.IsNullOrEmpty(sequence) && DefaultAnimation.HasSequence(NormalizeInfantrySequence(self, sequence)))
|
||||
{
|
||||
@@ -160,9 +148,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
|
||||
void INotifyAttack.PreparingAttack(Actor self, in Target target, Armament a, Barrel barrel)
|
||||
{
|
||||
// HACK: The FrameEndTask makes sure that this runs after Tick(), preventing that from
|
||||
// overriding the animation when an infantry unit stops to attack
|
||||
self.World.AddFrameEndTask(_ => Attacking(self, a, barrel));
|
||||
Attacking(self, target, a);
|
||||
}
|
||||
|
||||
void INotifyAttack.Attacking(Actor self, in Target target, Armament a, Barrel barrel) { }
|
||||
|
||||
@@ -40,9 +40,9 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
[Desc("If set, the color of the owning player will be used instead of `Color`.")]
|
||||
public readonly bool UsePlayerColor = false;
|
||||
|
||||
[Desc("Player relationships which will be able to see the circle.",
|
||||
[Desc("Stances of players which will be able to see the circle.",
|
||||
"Valid values are combinations of `None`, `Ally`, `Enemy` and `Neutral`.")]
|
||||
public readonly PlayerRelationship ValidRelationships = PlayerRelationship.Ally;
|
||||
public readonly PlayerRelationship ValidStances = PlayerRelationship.Ally;
|
||||
|
||||
[Desc("When to show the range circle. Valid values are `Always`, and `WhenSelected`")]
|
||||
public readonly RangeCircleVisibility Visible = RangeCircleVisibility.WhenSelected;
|
||||
@@ -91,7 +91,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
return false;
|
||||
|
||||
var p = self.World.RenderPlayer;
|
||||
return p == null || Info.ValidRelationships.HasStance(self.Owner.RelationshipWith(p)) || (p.Spectating && !p.NonCombatant);
|
||||
return p == null || Info.ValidStances.HasStance(self.Owner.RelationshipWith(p)) || (p.Spectating && !p.NonCombatant);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[Desc("Reveal this actor's last position when killed.")]
|
||||
public class RevealOnDeathInfo : ConditionalTraitInfo
|
||||
{
|
||||
[Desc("Relationships relative to the actors' owner that shroud will be revealed for.")]
|
||||
public readonly PlayerRelationship RevealForRelationships = PlayerRelationship.Ally;
|
||||
[Desc("Stances relative to the actors' owner that shroud will be revealed for.")]
|
||||
public readonly PlayerRelationship RevealForStances = PlayerRelationship.Ally;
|
||||
|
||||
[Desc("Duration of the reveal.")]
|
||||
public readonly int Duration = 25;
|
||||
@@ -66,7 +66,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
w.Add(new RevealShroudEffect(self.CenterPosition, info.Radius,
|
||||
info.RevealGeneratedShroud ? Shroud.SourceType.Visibility : Shroud.SourceType.PassiveVisibility,
|
||||
owner, info.RevealForRelationships, duration: info.Duration));
|
||||
owner, info.RevealForStances, duration: info.Duration));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[Desc("The armament types which trigger revealing.")]
|
||||
public readonly string[] ArmamentNames = { "primary", "secondary" };
|
||||
|
||||
[Desc("Player relationships relative to the target player this actor will be revealed to during firing.")]
|
||||
public readonly PlayerRelationship RevealForRelationships = PlayerRelationship.Ally;
|
||||
[Desc("Stances relative to the target player this actor will be revealed to during firing.")]
|
||||
public readonly PlayerRelationship RevealForStancesRelativeToTarget = PlayerRelationship.Ally;
|
||||
|
||||
[Desc("Duration of the reveal.")]
|
||||
public readonly int Duration = 25;
|
||||
@@ -60,7 +60,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
self.World.AddFrameEndTask(w => w.Add(new RevealShroudEffect(self.CenterPosition, info.Radius,
|
||||
info.RevealGeneratedShroud ? Shroud.SourceType.Visibility : Shroud.SourceType.PassiveVisibility,
|
||||
targetPlayer, info.RevealForRelationships, duration: info.Duration)));
|
||||
targetPlayer, info.RevealForStancesRelativeToTarget, duration: info.Duration)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,8 +16,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[Desc("Reveals shroud and fog across the whole map while active.")]
|
||||
public class RevealsMapInfo : ConditionalTraitInfo
|
||||
{
|
||||
[Desc("Relationships the watching player needs to see the shroud removed.")]
|
||||
public readonly PlayerRelationship ValidRelationships = PlayerRelationship.Ally;
|
||||
[Desc("Stance the watching player needs to see the shroud removed.")]
|
||||
public readonly PlayerRelationship ValidStances = PlayerRelationship.Ally;
|
||||
|
||||
[Desc("Can this actor reveal shroud generated by the `GeneratesShroud` trait?")]
|
||||
public readonly bool RevealGeneratedShroud = true;
|
||||
@@ -38,7 +38,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
protected void AddCellsToPlayerShroud(Actor self, Player p, PPos[] uv)
|
||||
{
|
||||
if (!Info.ValidRelationships.HasStance(self.Owner.RelationshipWith(p)))
|
||||
if (!Info.ValidStances.HasStance(self.Owner.RelationshipWith(p)))
|
||||
return;
|
||||
|
||||
p.Shroud.AddSource(this, type, uv);
|
||||
|
||||
@@ -17,8 +17,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
public class RevealsShroudInfo : AffectsShroudInfo
|
||||
{
|
||||
[Desc("Relationships the watching player needs to see the shroud removed.")]
|
||||
public readonly PlayerRelationship ValidRelationships = PlayerRelationship.Ally;
|
||||
[Desc("Stance the watching player needs to see the shroud removed.")]
|
||||
public readonly PlayerRelationship ValidStances = PlayerRelationship.Ally;
|
||||
|
||||
[Desc("Can this actor reveal shroud generated by the GeneratesShroud trait?")]
|
||||
public readonly bool RevealGeneratedShroud = true;
|
||||
@@ -49,7 +49,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
protected override void AddCellsToPlayerShroud(Actor self, Player p, PPos[] uv)
|
||||
{
|
||||
if (!info.ValidRelationships.HasStance(self.Owner.RelationshipWith(p)))
|
||||
if (!info.ValidStances.HasStance(self.Owner.RelationshipWith(p)))
|
||||
return;
|
||||
|
||||
p.Shroud.AddSource(this, type, uv);
|
||||
|
||||
@@ -21,8 +21,8 @@ namespace OpenRA.Mods.Common.Traits.Sound
|
||||
[Desc("Voice to play.")]
|
||||
public readonly string Voice = null;
|
||||
|
||||
[Desc("Player relationships who can hear this voice.")]
|
||||
public readonly PlayerRelationship ValidRelationships = PlayerRelationship.Ally | PlayerRelationship.Neutral | PlayerRelationship.Enemy;
|
||||
[Desc("Player stances who can hear this voice.")]
|
||||
public readonly PlayerRelationship ValidStances = PlayerRelationship.Ally | PlayerRelationship.Neutral | PlayerRelationship.Enemy;
|
||||
|
||||
[Desc("Play the voice to the owning player even if Stance.Ally is not included in ValidStances.")]
|
||||
public readonly bool PlayToOwner = true;
|
||||
@@ -53,7 +53,7 @@ namespace OpenRA.Mods.Common.Traits.Sound
|
||||
if (player == null)
|
||||
return;
|
||||
|
||||
if (Info.ValidRelationships.HasStance(self.Owner.RelationshipWith(player)))
|
||||
if (Info.ValidStances.HasStance(self.Owner.RelationshipWith(player)))
|
||||
self.PlayVoice(Info.Voice);
|
||||
else if (Info.PlayToOwner && self.Owner == player)
|
||||
self.PlayVoice(Info.Voice);
|
||||
|
||||
@@ -39,8 +39,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[Desc("Sound to instantly play at the targeted area.")]
|
||||
public readonly string OnFireSound = null;
|
||||
|
||||
[Desc("Player relationships which condition can be applied to.")]
|
||||
public readonly PlayerRelationship ValidRelationships = PlayerRelationship.Ally;
|
||||
[Desc("Player stances which condition can be applied to.")]
|
||||
public readonly PlayerRelationship ValidStances = PlayerRelationship.Ally;
|
||||
|
||||
[SequenceReference]
|
||||
[Desc("Sequence to play for granting actor when activated.",
|
||||
@@ -96,7 +96,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
return units.Distinct().Where(a =>
|
||||
{
|
||||
if (!info.ValidRelationships.HasStance(Self.Owner.RelationshipWith(a.Owner)))
|
||||
if (!info.ValidStances.HasStance(Self.Owner.RelationshipWith(a.Owner)))
|
||||
return false;
|
||||
|
||||
return a.TraitsImplementing<ExternalCondition>()
|
||||
@@ -137,7 +137,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
protected override void Tick(World world)
|
||||
{
|
||||
// Cancel the OG if we can't use the power
|
||||
if (!manager.Powers.TryGetValue(order, out var p) || !p.Active || !p.Ready)
|
||||
if (!manager.Powers.ContainsKey(order))
|
||||
world.CancelInputMode();
|
||||
}
|
||||
|
||||
|
||||
@@ -94,8 +94,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[Desc("Can the camera reveal shroud generated by the GeneratesShroud trait?")]
|
||||
public readonly bool RevealGeneratedShroud = true;
|
||||
|
||||
[Desc("Reveal cells to players with these relationships only.")]
|
||||
public readonly PlayerRelationship CameraRelationships = PlayerRelationship.Ally;
|
||||
[Desc("Reveal cells to players with these stances only.")]
|
||||
public readonly PlayerRelationship CameraStances = PlayerRelationship.Ally;
|
||||
|
||||
[Desc("Amount of time before detonation to spawn the camera.")]
|
||||
public readonly int CameraSpawnAdvance = 25;
|
||||
@@ -180,7 +180,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
var type = info.RevealGeneratedShroud ? Shroud.SourceType.Visibility
|
||||
: Shroud.SourceType.PassiveVisibility;
|
||||
|
||||
self.World.AddFrameEndTask(w => w.Add(new RevealShroudEffect(targetPosition, info.CameraRange, type, self.Owner, info.CameraRelationships,
|
||||
self.World.AddFrameEndTask(w => w.Add(new RevealShroudEffect(targetPosition, info.CameraRange, type, self.Owner, info.CameraStances,
|
||||
info.FlightDelay - info.CameraSpawnAdvance, info.CameraSpawnAdvance + info.CameraRemoveDelay)));
|
||||
}
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
void IOrderGenerator.Tick(World world)
|
||||
{
|
||||
// Cancel the OG if we can't use the power
|
||||
if (!manager.Powers.TryGetValue(order, out var p) || !p.Active || !p.Ready)
|
||||
if (!manager.Powers.ContainsKey(order))
|
||||
world.CancelInputMode();
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
public readonly string IncomingSpeechNotification = null;
|
||||
|
||||
[Desc("Defines to which players the timer is shown.")]
|
||||
public readonly PlayerRelationship DisplayTimerRelationships = PlayerRelationship.None;
|
||||
public readonly PlayerRelationship DisplayTimerStances = PlayerRelationship.None;
|
||||
|
||||
[Desc("Beacons are only supported on the Airstrike, Paratroopers, and Nuke powers")]
|
||||
public readonly bool DisplayBeacon = false;
|
||||
|
||||
@@ -309,7 +309,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
protected override void Tick(World world)
|
||||
{
|
||||
// Cancel the OG if we can't use the power
|
||||
if (!manager.Powers.TryGetValue(order, out var p) || !p.Active || !p.Ready)
|
||||
if (!manager.Powers.ContainsKey(order))
|
||||
world.CancelInputMode();
|
||||
}
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[Translate]
|
||||
public readonly string Description = "";
|
||||
|
||||
[Desc("Player relationships who can view the description.")]
|
||||
public readonly PlayerRelationship ValidRelationships = PlayerRelationship.Ally | PlayerRelationship.Neutral | PlayerRelationship.Enemy;
|
||||
[Desc("Player stances who can view the description.")]
|
||||
public readonly PlayerRelationship ValidStances = PlayerRelationship.Ally | PlayerRelationship.Neutral | PlayerRelationship.Enemy;
|
||||
|
||||
public override object Create(ActorInitializer init) { return new TooltipDescription(init.Self, this); }
|
||||
}
|
||||
@@ -53,7 +53,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
if (Owner == null || forPlayer == null)
|
||||
return false;
|
||||
|
||||
return Info.ValidRelationships.HasStance(Owner.RelationshipWith(forPlayer));
|
||||
return Info.ValidStances.HasStance(Owner.RelationshipWith(forPlayer));
|
||||
}
|
||||
|
||||
public string TooltipText
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
@@ -29,9 +27,6 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[Desc("Maximum amount of ticks the actor will sit idly before starting to wander.")]
|
||||
public readonly int MaxMoveDelay = 0;
|
||||
|
||||
[Desc("The terrain types that this actor should avoid wandering on to.")]
|
||||
public readonly HashSet<string> AvoidTerrainTypes = new HashSet<string>();
|
||||
|
||||
public override object Create(ActorInitializer init) { return new Wanders(init.Self, this); }
|
||||
}
|
||||
|
||||
@@ -80,8 +75,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
return;
|
||||
|
||||
var targetCell = PickTargetLocation();
|
||||
if (targetCell.HasValue)
|
||||
DoAction(self, targetCell.Value);
|
||||
if (targetCell != CPos.Zero)
|
||||
DoAction(self, targetCell);
|
||||
}
|
||||
|
||||
void INotifyIdle.TickIdle(Actor self)
|
||||
@@ -89,7 +84,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
TickIdle(self);
|
||||
}
|
||||
|
||||
CPos? PickTargetLocation()
|
||||
CPos PickTargetLocation()
|
||||
{
|
||||
var target = self.CenterPosition + new WVec(0, -1024 * effectiveMoveRadius, 0).Rotate(WRot.FromFacing(self.World.SharedRandom.Next(255)));
|
||||
var targetCell = self.World.Map.CellContaining(target);
|
||||
@@ -100,15 +95,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
if (++ticksIdle % info.ReduceMoveRadiusDelay == 0)
|
||||
effectiveMoveRadius--;
|
||||
|
||||
// We'll be back the next tick; better to sit idle for a few seconds than prolong this tick indefinitely with a loop
|
||||
return null;
|
||||
}
|
||||
|
||||
if (info.AvoidTerrainTypes.Count > 0)
|
||||
{
|
||||
var terrainType = self.World.Map.GetTerrainInfo(targetCell).Type;
|
||||
if (Info.AvoidTerrainTypes.Contains(terrainType))
|
||||
return null;
|
||||
return CPos.Zero; // We'll be back the next tick; better to sit idle for a few seconds than prolong this tick indefinitely with a loop
|
||||
}
|
||||
|
||||
ticksIdle = 0;
|
||||
|
||||
@@ -60,11 +60,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
IsBot = client.Bot != null,
|
||||
FactionName = resolvedFaction.Name,
|
||||
FactionId = resolvedFaction.InternalName,
|
||||
DisplayFactionName = clientFaction.Name,
|
||||
DisplayFactionId = clientFaction.InternalName,
|
||||
Color = client.Color,
|
||||
Team = client.Team,
|
||||
Handicap = client.Handicap,
|
||||
SpawnPoint = resolvedSpawnPoint,
|
||||
IsRandomFaction = clientFaction.RandomFactionMembers.Any(),
|
||||
IsRandomSpawnPoint = client.SpawnPoint == 0,
|
||||
|
||||
@@ -214,10 +214,6 @@ namespace OpenRA.Mods.Common.Traits
|
||||
if (factionInit != null && factionInit.Value == Owner.Faction)
|
||||
return false;
|
||||
|
||||
var healthInit = init as HealthInit;
|
||||
if (healthInit != null && healthInit.Value == 100)
|
||||
return false;
|
||||
|
||||
// TODO: Other default values will need to be filtered
|
||||
// here after we have built a properties panel
|
||||
return true;
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version. For more
|
||||
* information, see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class RenameStances : UpdateRule
|
||||
{
|
||||
public override string Name { get { return "Renamed player 'Stances' to 'Relationships'."; } }
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return "'Stances' in regards to a player have been renamed to 'Relationships'.\n" +
|
||||
"The yaml values did not change.";
|
||||
}
|
||||
}
|
||||
|
||||
readonly (string TraitName, string OldName, string NewName)[] traits =
|
||||
{
|
||||
("Disguise", "ValidStances", "ValidRelationships"),
|
||||
("Infiltrates", "ValidStances", "ValidRelationships"),
|
||||
("AcceptsDeliveredCash", "ValidStances", "ValidRelationships"),
|
||||
("AcceptsDeliveredExperience", "ValidStances", "ValidRelationships"),
|
||||
("Armament", "TargetStances", "TargetRelationships"),
|
||||
("Armament", "ForceTargetStances", "ForceTargetRelationships"),
|
||||
("AutoTargetPriority", "ValidStances", "ValidRelationships"),
|
||||
("CaptureManagerBotModule", "CapturableStances", "CapturableRelationships"),
|
||||
("Capturable", "ValidStances", "ValidRelationships"),
|
||||
("Captures", "PlayerExperienceStances", "PlayerExperienceRelationships"),
|
||||
("ProximityExternalCondition", "ValidStances", "ValidRelationships"),
|
||||
("CreatesShroud", "ValidStances", "ValidRelationships"),
|
||||
("Demolition", "TargetStances", "TargetRelationships"),
|
||||
("Demolition", "ForceTargetStances", "ForceTargetRelationships"),
|
||||
("EngineerRepair", "ValidStances", "ValidRelationships"),
|
||||
("GivesBounty", "ValidStances", "ValidRelationships"),
|
||||
("GivesExperience", "ValidStances", "ValidRelationships"),
|
||||
("JamsMissiles", "DeflectionStances", "DeflectionRelationships"),
|
||||
("FrozenUnderFog", "AlwaysVisibleStances", "AlwaysVisibleRelationships"),
|
||||
("HiddenUnderShroud", "AlwaysVisibleStances", "AlwaysVisibleRelationships"),
|
||||
("HiddenUnderFog", "AlwaysVisibleStances", "AlwaysVisibleRelationships"),
|
||||
("AppearsOnRadar", "ValidStances", "ValidRelationships"),
|
||||
("CashTricklerBar", "DisplayStances", "DisplayRelationships"),
|
||||
("SupportPowerChargeBar", "DisplayStances", "DisplayRelationships"),
|
||||
("WithAmmoPipsDecoration", "ValidStances", "ValidRelationships"),
|
||||
("WithCargoPipsDecoration", "ValidStances", "ValidRelationships"),
|
||||
("WithDecoration", "ValidStances", "ValidRelationships"),
|
||||
("WithHarvesterPipsDecoration", "ValidStances", "ValidRelationships"),
|
||||
("WithNameTagDecoration", "ValidStances", "ValidRelationships"),
|
||||
("WithResourceStoragePipsDecoration", "ValidStances", "ValidRelationships"),
|
||||
("WithTextDecoration", "ValidStances", "ValidRelationships"),
|
||||
("WithRangeCircle", "ValidStances", "ValidRelationships"),
|
||||
("RevealOnDeath", "RevealForStances", "RevealForRelationships"),
|
||||
("RevealOnFire", "RevealForStancesRelativeToTarget", "RevealForRelationships"),
|
||||
("RevealsMap", "ValidStances", "ValidRelationships"),
|
||||
("RevealsShroud", "ValidStances", "ValidRelationships"),
|
||||
("VoiceAnnouncement", "ValidStances", "ValidRelationships"),
|
||||
("GrantExternalConditionPower", "ValidStances", "ValidRelationships"),
|
||||
("NukePower", "CameraStances", "CameraRelationships"),
|
||||
("NukePower", "DisplayTimerStances", "DisplayTimerRelationships"),
|
||||
("AttackOrderPower", "DisplayTimerStances", "DisplayTimerRelationships"),
|
||||
("ChronoshiftPower", "DisplayTimerStances", "DisplayTimerRelationships"),
|
||||
("DropPodsPower", "DisplayTimerStances", "DisplayTimerRelationships"),
|
||||
("GpsPower", "DisplayTimerStances", "DisplayTimerRelationships"),
|
||||
("GrantPrerequisiteChargeDrainPower", "DisplayTimerStances", "DisplayTimerRelationships"),
|
||||
("IonCannonPower", "DisplayTimerStances", "DisplayTimerRelationships"),
|
||||
("AirstrikePower", "DisplayTimerStances", "DisplayTimerRelationships"),
|
||||
("GrantExternalConditionPower", "DisplayTimerStances", "DisplayTimerRelationships"),
|
||||
("ParatroopersPower", "DisplayTimerStances", "DisplayTimerRelationships"),
|
||||
("ProduceActorPower", "DisplayTimerStances", "DisplayTimerRelationships"),
|
||||
("SpawnActorPower", "DisplayTimerStances", "DisplayTimerRelationships"),
|
||||
("TooltipDescription", "ValidStances", "ValidRelationships")
|
||||
};
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
|
||||
{
|
||||
foreach (var field in traits)
|
||||
foreach (var traitNode in actorNode.ChildrenMatching(field.TraitName))
|
||||
traitNode.RenameChildrenMatching(field.OldName, field.NewName);
|
||||
|
||||
yield break;
|
||||
}
|
||||
|
||||
public override IEnumerable<string> UpdateWeaponNode(ModData modData, MiniYamlNode weaponNode)
|
||||
{
|
||||
foreach (var projectileNode in weaponNode.ChildrenMatching("Projectile"))
|
||||
projectileNode.RenameChildrenMatching("ValidBounceBlockerStances", "ValidBounceBlockerRelationships");
|
||||
|
||||
foreach (var warheadNode in weaponNode.ChildrenMatching("Warhead"))
|
||||
warheadNode.RenameChildrenMatching("ValidStances", "ValidRelationships");
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -73,7 +73,6 @@ namespace OpenRA.Mods.Common.UpdateRules
|
||||
new RenameSelfHealing(),
|
||||
new ReplaceBurns(),
|
||||
new RemoveMuzzleSplitFacings(),
|
||||
new RenameStances(),
|
||||
new RemoveTurnToDock(),
|
||||
new RenameSmudgeSmokeFields(),
|
||||
new RenameCircleContrast(),
|
||||
|
||||
@@ -218,9 +218,6 @@ namespace OpenRA.Mods.Common
|
||||
if (t.IsGenericType && t.GetGenericTypeDefinition().GetInterfaces().Any(e => e.IsGenericType && e.GetGenericTypeDefinition() == typeof(IEnumerable<>)))
|
||||
return "Collection of {0}".F(FriendlyTypeName(t.GetGenericArguments().First()));
|
||||
|
||||
if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>))
|
||||
return "{0} (optional)".F(t.GetGenericArguments().Select(FriendlyTypeName).First());
|
||||
|
||||
if (t == typeof(int) || t == typeof(uint))
|
||||
return "Integer";
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ namespace OpenRA.Mods.Common.Warheads
|
||||
public override bool IsValidAgainst(Actor victim, Actor firedBy)
|
||||
{
|
||||
var stance = firedBy.Owner.RelationshipWith(victim.Owner);
|
||||
if (!ValidRelationships.HasStance(stance))
|
||||
if (!ValidStances.HasStance(stance))
|
||||
return false;
|
||||
|
||||
// A target type is valid if it is in the valid targets list, and not in the invalid targets list.
|
||||
|
||||
@@ -31,8 +31,8 @@ namespace OpenRA.Mods.Common.Warheads
|
||||
[Desc("What types of targets are unaffected.", "Overrules ValidTargets.")]
|
||||
public readonly BitSet<TargetableType> InvalidTargets;
|
||||
|
||||
[Desc("What player relationships are affected.")]
|
||||
public readonly PlayerRelationship ValidRelationships = PlayerRelationship.Ally | PlayerRelationship.Neutral | PlayerRelationship.Enemy;
|
||||
[Desc("What diplomatic stances are affected.")]
|
||||
public readonly PlayerRelationship ValidStances = PlayerRelationship.Ally | PlayerRelationship.Neutral | PlayerRelationship.Enemy;
|
||||
|
||||
[Desc("Can this warhead affect the actor that fired it.")]
|
||||
public readonly bool AffectsParent = false;
|
||||
@@ -63,7 +63,7 @@ namespace OpenRA.Mods.Common.Warheads
|
||||
return false;
|
||||
|
||||
var stance = firedBy.Owner.RelationshipWith(victim.Owner);
|
||||
if (!ValidRelationships.HasStance(stance))
|
||||
if (!ValidStances.HasStance(stance))
|
||||
return false;
|
||||
|
||||
// A target type is valid if it is in the valid targets list, and not in the invalid targets list.
|
||||
@@ -81,7 +81,7 @@ namespace OpenRA.Mods.Common.Warheads
|
||||
|
||||
// AffectsParent checks do not make sense for FrozenActors, so skip to stance checks
|
||||
var stance = firedBy.Owner.RelationshipWith(victim.Owner);
|
||||
if (!ValidRelationships.HasStance(stance))
|
||||
if (!ValidStances.HasStance(stance))
|
||||
return false;
|
||||
|
||||
// A target type is valid if it is in the valid targets list, and not in the invalid targets list.
|
||||
|
||||
@@ -268,8 +268,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
|
||||
case "delete":
|
||||
{
|
||||
// Yaml path may be specified relative to a named directory (e.g. ^SupportDir) or the detected disc path
|
||||
var sourcePath = i.Value.Value.StartsWith("^") ? Platform.ResolvePath(i.Value.Value) : Path.Combine(path, i.Value.Value);
|
||||
var sourcePath = Path.Combine(path, i.Value.Value);
|
||||
|
||||
// Try as an absolute path
|
||||
if (!File.Exists(sourcePath))
|
||||
sourcePath = Platform.ResolvePath(i.Value.Value);
|
||||
|
||||
Log.Write("debug", "Deleting {0}", sourcePath);
|
||||
File.Delete(sourcePath);
|
||||
@@ -322,8 +325,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
|
||||
static void ExtractFromPackage(ExtractionType type, string path, MiniYaml actionYaml, List<string> extractedFiles, Action<string> updateMessage)
|
||||
{
|
||||
// Yaml path may be specified relative to a named directory (e.g. ^SupportDir) or the detected disc path
|
||||
var sourcePath = actionYaml.Value.StartsWith("^") ? Platform.ResolvePath(actionYaml.Value) : Path.Combine(path, actionYaml.Value);
|
||||
var sourcePath = Path.Combine(path, actionYaml.Value);
|
||||
|
||||
// Try as an absolute path
|
||||
if (!File.Exists(sourcePath))
|
||||
sourcePath = Platform.ResolvePath(actionYaml.Value);
|
||||
|
||||
using (var source = File.OpenRead(sourcePath))
|
||||
{
|
||||
@@ -378,8 +384,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
|
||||
static void ExtractFromMSCab(string path, MiniYaml actionYaml, List<string> extractedFiles, Action<string> updateMessage)
|
||||
{
|
||||
// Yaml path may be specified relative to a named directory (e.g. ^SupportDir) or the detected disc path
|
||||
var sourcePath = actionYaml.Value.StartsWith("^") ? Platform.ResolvePath(actionYaml.Value) : Path.Combine(path, actionYaml.Value);
|
||||
var sourcePath = Path.Combine(path, actionYaml.Value);
|
||||
|
||||
// Try as an absolute path
|
||||
if (!File.Exists(sourcePath))
|
||||
sourcePath = Platform.ResolvePath(actionYaml.Value);
|
||||
|
||||
using (var source = File.OpenRead(sourcePath))
|
||||
{
|
||||
@@ -409,8 +418,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
|
||||
static void ExtractFromISCab(string path, MiniYaml actionYaml, List<string> extractedFiles, Action<string> updateMessage)
|
||||
{
|
||||
// Yaml path may be specified relative to a named directory (e.g. ^SupportDir) or the detected disc path
|
||||
var sourcePath = actionYaml.Value.StartsWith("^") ? Platform.ResolvePath(actionYaml.Value) : Path.Combine(path, actionYaml.Value);
|
||||
var sourcePath = Path.Combine(path, actionYaml.Value);
|
||||
|
||||
// Try as an absolute path
|
||||
if (!File.Exists(sourcePath))
|
||||
sourcePath = Platform.ResolvePath(actionYaml.Value);
|
||||
|
||||
var volumeNode = actionYaml.Nodes.FirstOrDefault(n => n.Key == "Volumes");
|
||||
if (volumeNode == null)
|
||||
|
||||
@@ -624,7 +624,6 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
LobbyUtils.SetupEditableColorWidget(template, slot, client, orderManager, shellmapWorld, colorPreview);
|
||||
LobbyUtils.SetupEditableFactionWidget(template, slot, client, orderManager, factions);
|
||||
LobbyUtils.SetupEditableTeamWidget(template, slot, client, orderManager, map);
|
||||
LobbyUtils.SetupEditableHandicapWidget(template, slot, client, orderManager, map);
|
||||
LobbyUtils.SetupEditableSpawnWidget(template, slot, client, orderManager, map);
|
||||
LobbyUtils.SetupEditableReadyWidget(template, slot, client, orderManager, map);
|
||||
}
|
||||
@@ -641,7 +640,6 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
if (isHost)
|
||||
{
|
||||
LobbyUtils.SetupEditableTeamWidget(template, slot, client, orderManager, map);
|
||||
LobbyUtils.SetupEditableHandicapWidget(template, slot, client, orderManager, map);
|
||||
LobbyUtils.SetupEditableSpawnWidget(template, slot, client, orderManager, map);
|
||||
LobbyUtils.SetupPlayerActionWidget(template, slot, client, orderManager, worldRenderer,
|
||||
lobby, () => panel = PanelType.Kick, () => panel = PanelType.Players);
|
||||
@@ -650,7 +648,6 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
{
|
||||
LobbyUtils.SetupNameWidget(template, slot, client, orderManager, worldRenderer);
|
||||
LobbyUtils.SetupTeamWidget(template, slot, client);
|
||||
LobbyUtils.SetupHandicapWidget(template, slot, client);
|
||||
LobbyUtils.SetupSpawnWidget(template, slot, client);
|
||||
}
|
||||
|
||||
@@ -755,6 +752,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
|
||||
void UpdateDiscordStatus()
|
||||
{
|
||||
var mapTitle = map.Title;
|
||||
var numberOfPlayers = 0;
|
||||
var slots = 0;
|
||||
|
||||
@@ -773,11 +771,6 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
}
|
||||
}
|
||||
|
||||
// Add extra slots to keep the join button active for spectators
|
||||
if (numberOfPlayers == slots && orderManager.LobbyInfo.GlobalSettings.AllowSpectators)
|
||||
slots = numberOfPlayers + 1;
|
||||
|
||||
var details = map.Title + " - " + orderManager.LobbyInfo.GlobalSettings.ServerName;
|
||||
if (updateDiscordStatus)
|
||||
{
|
||||
string secret = null;
|
||||
@@ -788,8 +781,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
}
|
||||
|
||||
var state = skirmishMode ? DiscordState.InSkirmishLobby : DiscordState.InMultiplayerLobby;
|
||||
DiscordService.UpdateStatus(state, mapTitle, secret, numberOfPlayers, slots);
|
||||
|
||||
DiscordService.UpdateStatus(state, details, secret, numberOfPlayers, slots);
|
||||
updateDiscordStatus = false;
|
||||
}
|
||||
else
|
||||
@@ -797,7 +790,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
if (!skirmishMode)
|
||||
DiscordService.UpdatePlayers(numberOfPlayers, slots);
|
||||
|
||||
DiscordService.UpdateDetails(details);
|
||||
DiscordService.UpdateDetails(mapTitle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -813,8 +806,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
Ui.CloseWindow();
|
||||
|
||||
var state = skirmishMode ? DiscordState.PlayingSkirmish : DiscordState.PlayingMultiplayer;
|
||||
var details = map.Title + " - " + orderManager.LobbyInfo.GlobalSettings.ServerName;
|
||||
DiscordService.UpdateStatus(state, details);
|
||||
DiscordService.UpdateStatus(state);
|
||||
|
||||
onStart();
|
||||
}
|
||||
|
||||
@@ -146,25 +146,6 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
dropdown.ShowDropDown("TEAM_DROPDOWN_TEMPLATE", 150, options, setupItem);
|
||||
}
|
||||
|
||||
public static void ShowHandicapDropDown(DropDownButtonWidget dropdown, Session.Client client,
|
||||
OrderManager orderManager)
|
||||
{
|
||||
Func<int, ScrollItemWidget, ScrollItemWidget> setupItem = (ii, itemTemplate) =>
|
||||
{
|
||||
var item = ScrollItemWidget.Setup(itemTemplate,
|
||||
() => client.Handicap == ii,
|
||||
() => orderManager.IssueOrder(Order.Command("handicap {0} {1}".F(client.Index, ii))));
|
||||
|
||||
var label = "{0}%".F(ii);
|
||||
item.Get<LabelWidget>("LABEL").GetText = () => label;
|
||||
return item;
|
||||
};
|
||||
|
||||
// Handicaps may be set between 0 - 95% in steps of 5%
|
||||
var options = Enumerable.Range(0, 20).Select(i => 5 * i);
|
||||
dropdown.ShowDropDown("TEAM_DROPDOWN_TEMPLATE", 150, options, setupItem);
|
||||
}
|
||||
|
||||
public static void ShowSpawnDropDown(DropDownButtonWidget dropdown, Session.Client client,
|
||||
OrderManager orderManager, IEnumerable<int> spawnPoints)
|
||||
{
|
||||
@@ -581,29 +562,6 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
HideChildWidget(parent, "TEAM_DROPDOWN");
|
||||
}
|
||||
|
||||
public static void SetupEditableHandicapWidget(Widget parent, Session.Slot s, Session.Client c, OrderManager orderManager, MapPreview map)
|
||||
{
|
||||
var dropdown = parent.Get<DropDownButtonWidget>("HANDICAP_DROPDOWN");
|
||||
dropdown.IsVisible = () => true;
|
||||
dropdown.IsDisabled = () => s.LockTeam || orderManager.LocalClient.IsReady;
|
||||
dropdown.OnMouseDown = _ => ShowHandicapDropDown(dropdown, c, orderManager);
|
||||
|
||||
var handicapLabel = new CachedTransform<int, string>(h => "{0}%".F(h));
|
||||
dropdown.GetText = () => handicapLabel.Update(c.Handicap);
|
||||
|
||||
HideChildWidget(parent, "HANDICAP");
|
||||
}
|
||||
|
||||
public static void SetupHandicapWidget(Widget parent, Session.Slot s, Session.Client c)
|
||||
{
|
||||
var team = parent.Get<LabelWidget>("HANDICAP");
|
||||
team.IsVisible = () => true;
|
||||
|
||||
var handicapLabel = new CachedTransform<int, string>(h => "{0}%".F(h));
|
||||
team.GetText = () => handicapLabel.Update(c.Handicap);
|
||||
HideChildWidget(parent, "HANDICAP_DROPDOWN");
|
||||
}
|
||||
|
||||
public static void SetupEditableSpawnWidget(Widget parent, Session.Slot s, Session.Client c, OrderManager orderManager, MapPreview map)
|
||||
{
|
||||
var dropdown = parent.Get<DropDownButtonWidget>("SPAWN_DROPDOWN");
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user