Skip to content

Commit 0470150

Browse files
committed
initial
0 parents  commit 0470150

34 files changed

Lines changed: 5571 additions & 0 deletions

.github/workflows/release.yml

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
package:
13+
name: Package mod
14+
runs-on: ubuntu-latest
15+
16+
steps:
17+
- name: Check out repository
18+
uses: actions/checkout@v5
19+
with:
20+
fetch-depth: 0
21+
22+
- name: Validate release version
23+
shell: bash
24+
run: |
25+
set -euo pipefail
26+
27+
VERSION="$(jq -r '.version' mod.txt)"
28+
29+
if [[ "${GITHUB_REF_TYPE}" == "tag" && "${GITHUB_REF_NAME}" != "v${VERSION}" ]]; then
30+
echo "::error::tag (${GITHUB_REF_NAME}) does not match mod version (v${VERSION})"
31+
exit 1
32+
fi
33+
34+
echo "version=$VERSION" >> "$GITHUB_ENV"
35+
36+
- name: Generate update metadata
37+
shell: bash
38+
run: |
39+
set -euo pipefail
40+
41+
ident="$(jq -r '.updates[0].identifier // empty' mod.txt)"
42+
version="$(jq -r '.version' mod.txt)"
43+
repo="$GITHUB_REPOSITORY"
44+
45+
if [[ -z "$ident" ]]; then
46+
echo "has_update_metadata=false" >> "$GITHUB_ENV"
47+
echo "No mod.txt updates[0].identifier configured; skipping update metadata."
48+
exit 0
49+
fi
50+
51+
mkdir -p generated
52+
jq -n \
53+
--arg ident "$ident" \
54+
--arg version "$version" \
55+
--arg download_url "https://github.com/$repo/releases/download/v$version/RandomContract.zip" \
56+
--arg patchnotes_url "https://github.com/$repo/releases/tag/v$version" \
57+
'[{
58+
ident: $ident,
59+
version: $version,
60+
download_url: $download_url,
61+
patchnotes_url: $patchnotes_url
62+
}]' > generated/update_meta.json
63+
64+
echo "has_update_metadata=true" >> "$GITHUB_ENV"
65+
66+
- name: Build SuperBLT zip
67+
shell: bash
68+
run: |
69+
set -euo pipefail
70+
71+
rm -rf package RandomContract.zip
72+
mkdir -p package/RandomContract
73+
cp -R core.lua mod.txt data hooks loc modules package/RandomContract/
74+
75+
if [[ "${has_update_metadata}" == "true" ]]; then
76+
cp generated/update_meta.json package/RandomContract/update_meta.json
77+
fi
78+
79+
cd package
80+
zip -r ../RandomContract.zip RandomContract
81+
82+
- name: Get previous tag
83+
id: previous-tag
84+
shell: bash
85+
run: |
86+
set -euo pipefail
87+
88+
git fetch --tags --force
89+
previous_tag="$(git --no-pager tag --sort=creatordate --merged "${GITHUB_REF_NAME}" | grep -v "^${GITHUB_REF_NAME}$" | tail -1 || true)"
90+
echo "previous_tag=$previous_tag" >> "$GITHUB_OUTPUT"
91+
92+
- name: Generate changelog
93+
id: changelog
94+
if: ${{ steps.previous-tag.outputs.previous_tag != '' }}
95+
uses: requarks/changelog-action@v1
96+
with:
97+
token: ${{ github.token }}
98+
fromTag: ${{ github.ref_name }}
99+
toTag: ${{ steps.previous-tag.outputs.previous_tag }}
100+
writeToFile: false
101+
restrictToTypes: feat,fix,perf
102+
useGitmojis: false
103+
includeInvalidCommits: false
104+
105+
- name: Write release notes
106+
env:
107+
CHANGELOG: ${{ steps.changelog.outputs.changes }}
108+
PREVIOUS_TAG: ${{ steps.previous-tag.outputs.previous_tag }}
109+
shell: bash
110+
run: |
111+
set -euo pipefail
112+
113+
printf 'Random Contract %s\n' "$version" > release-notes.md
114+
115+
if [[ -n "$CHANGELOG" ]]; then
116+
printf '\n%s\n' "$CHANGELOG" >> release-notes.md
117+
elif [[ -z "$PREVIOUS_TAG" ]]; then
118+
printf '\nInitial release.\n' >> release-notes.md
119+
else
120+
printf '\nMaintenance release.\n' >> release-notes.md
121+
fi
122+
123+
- name: Upload release asset
124+
env:
125+
GITHUB_TOKEN: ${{ github.token }}
126+
TAG: ${{ github.ref_name }}
127+
shell: bash
128+
run: |
129+
set -euo pipefail
130+
131+
assets=(RandomContract.zip)
132+
if [[ "${has_update_metadata}" == "true" ]]; then
133+
assets+=(generated/update_meta.json)
134+
fi
135+
136+
if gh release view "$TAG" >/dev/null 2>&1; then
137+
gh release edit "$TAG" --notes-file release-notes.md
138+
gh release upload "$TAG" "${assets[@]}" --clobber
139+
else
140+
gh release create "$TAG" "${assets[@]}" \
141+
--title "$TAG" \
142+
--notes-file release-notes.md
143+
fi
144+
145+
- name: Publish update metadata
146+
if: ${{ env.has_update_metadata == 'true' }}
147+
env:
148+
TAG: ${{ github.ref_name }}
149+
shell: bash
150+
run: |
151+
set -euo pipefail
152+
153+
cp generated/update_meta.json update_meta.json
154+
155+
if git diff --quiet -- update_meta.json; then
156+
echo "update_meta.json already matches $TAG"
157+
exit 0
158+
fi
159+
160+
git config user.name "github-actions[bot]"
161+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
162+
git add update_meta.json
163+
git commit -m "chore: update release metadata for $TAG"
164+
git push origin HEAD:main

core.lua

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
_G.RandomContract = _G.RandomContract or {}
2+
3+
local RandomContract = _G.RandomContract
4+
5+
RandomContract.ModPath = RandomContract.ModPath or ModPath or "RandomContract/"
6+
RandomContract.SavePath = RandomContract.SavePath or ((SavePath or "") .. "RandomContract.json")
7+
8+
RandomContract.VERSION = 1
9+
RandomContract.LOBBY_ITEM_ID = "menu_roll_contract"
10+
RandomContract.MENU_ID = "random_contract_options"
11+
RandomContract.STEALTH_MENU_ID = "random_contract_stealth_options"
12+
RandomContract.LOUD_MENU_ID = "random_contract_loud_options"
13+
RandomContract.HEIST_POLICY_MENU_ID = "random_contract_heist_policy_options"
14+
RandomContract.POLICY_GLOBAL_EXCLUDE_MENU_ID = "random_contract_policy_global_exclude_options"
15+
RandomContract.POLICY_TACTIC_MENU_ID = "random_contract_policy_tactic_options"
16+
RandomContract.POLICY_STEALTH_PRESET_MENU_ID = "random_contract_policy_stealth_preset_options"
17+
RandomContract.POLICY_LOUD_PRESET_MENU_ID = "random_contract_policy_loud_preset_options"
18+
RandomContract.DEFAULT_HISTORY_LIMIT = 5
19+
RandomContract.MIN_HISTORY_LIMIT = 0
20+
RandomContract.MAX_HISTORY_LIMIT = 30
21+
RandomContract.HISTORY_LIMIT = RandomContract.DEFAULT_HISTORY_LIMIT
22+
RandomContract.SESSION_HISTORY_KEY = "random_contract_recent_history"
23+
RandomContract.DEFAULT_DIFFICULTY = "sm_wish"
24+
RandomContract.SELECT_COOLDOWN_SECONDS = 0.15
25+
RandomContract.LOBBY_SYNC_COALESCE_SECONDS = 0.35
26+
RandomContract.STEALTH_SEARCH_INPUT_ID = "random_contract_stealth_search"
27+
RandomContract.LOUD_SEARCH_INPUT_ID = "random_contract_loud_search"
28+
RandomContract.POLICY_GLOBAL_EXCLUDE_SEARCH_INPUT_ID = "random_contract_policy_global_exclude_search"
29+
RandomContract.POLICY_TACTIC_SEARCH_INPUT_ID = "random_contract_policy_tactic_search"
30+
RandomContract.POLICY_STEALTH_PRESET_SEARCH_INPUT_ID = "random_contract_policy_stealth_preset_search"
31+
RandomContract.POLICY_LOUD_PRESET_SEARCH_INPUT_ID = "random_contract_policy_loud_preset_search"
32+
RandomContract.HEIST_VISIBLE_CALLBACK_PREFIX = "random_contract_heist_visible_"
33+
34+
RandomContract.recent_history = RandomContract.recent_history or {}
35+
RandomContract.menu_search = RandomContract.menu_search or {}
36+
37+
RandomContract.DIFFICULTIES = {
38+
{ id = "normal", text_id = "menu_difficulty_normal", label_text_id = "random_contract_label_difficulty_normal", fallback = "Normal" },
39+
{ id = "hard", text_id = "menu_difficulty_hard", label_text_id = "random_contract_label_difficulty_hard", fallback = "Hard" },
40+
{ id = "overkill", text_id = "menu_difficulty_very_hard", label_text_id = "random_contract_label_difficulty_very_hard", fallback = "Very Hard" },
41+
{ id = "overkill_145", text_id = "menu_difficulty_overkill", label_text_id = "random_contract_label_difficulty_overkill", fallback = "Overkill" },
42+
{ id = "easy_wish", text_id = "menu_difficulty_easy_wish", label_text_id = "random_contract_label_difficulty_mayhem", fallback = "Mayhem" },
43+
{ id = "overkill_290", text_id = "menu_difficulty_apocalypse", label_text_id = "random_contract_label_difficulty_death_wish", fallback = "Death Wish" },
44+
{ id = "sm_wish", text_id = "menu_difficulty_sm_wish", label_text_id = "random_contract_label_difficulty_death_sentence", fallback = "Death Sentence" }
45+
}
46+
47+
local function merge_defaults(target, defaults)
48+
for key, value in pairs(defaults) do
49+
if type(value) == "table" then
50+
target[key] = target[key] or {}
51+
merge_defaults(target[key], value)
52+
elseif target[key] == nil then
53+
target[key] = value
54+
end
55+
end
56+
end
57+
58+
local function read_json_file(path)
59+
if not path or not json or type(json.decode) ~= "function" then
60+
return nil
61+
end
62+
63+
local file = io.open(path, "r")
64+
65+
if not file then
66+
return nil
67+
end
68+
69+
local data = file:read("*all")
70+
file:close()
71+
72+
if not data then
73+
return nil
74+
end
75+
76+
local ok, decoded = pcall(json.decode, data)
77+
78+
if ok and type(decoded) == "table" then
79+
return decoded
80+
end
81+
end
82+
83+
RandomContract.DEFAULT_JOB_POLICY = {
84+
extra_candidates = {},
85+
eligibility = {},
86+
recommended_exclusions = {
87+
stealth = {},
88+
loud = {}
89+
}
90+
}
91+
92+
RandomContract.JobPolicyPath = RandomContract.JobPolicyPath or (RandomContract.ModPath .. "data/job_policy.json")
93+
RandomContract.JobPolicy = RandomContract.JobPolicy or read_json_file(RandomContract.JobPolicyPath) or {}
94+
merge_defaults(RandomContract.JobPolicy, RandomContract.DEFAULT_JOB_POLICY)
95+
96+
for _, module_name in ipairs({
97+
"common/util",
98+
"common/settings",
99+
"contracts/policy",
100+
"contracts/jobs",
101+
"contracts/pool",
102+
"common/runtime",
103+
"network/authority",
104+
"lobby/view",
105+
"lobby/sync",
106+
"contracts/selection",
107+
"lobby/text",
108+
"lobby/label",
109+
"lobby/menu_items",
110+
"lobby/marker",
111+
"lobby/item",
112+
"lobby/input",
113+
"menu/search",
114+
"menu/setup",
115+
"menu/difficulty",
116+
"menu/tactic",
117+
"menu/settings",
118+
"menu/localization",
119+
"menu/populate",
120+
"menu/build",
121+
"menu/callbacks"
122+
}) do
123+
dofile(RandomContract.ModPath .. "modules/" .. module_name .. ".lua")
124+
end
125+
126+
return RandomContract

data/job_policy.json

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
{
2+
"extra_candidates": [
3+
"welcome_to_the_jungle_wrapper_prof",
4+
"crojob_wrapper"
5+
],
6+
"eligibility": {
7+
"mallcrasher": "any",
8+
"pal": "any",
9+
"kosugi": "stealth",
10+
"dark": "stealth",
11+
"cage": "stealth",
12+
"tag": "stealth",
13+
"fish": "stealth",
14+
"spa": "loud",
15+
"nmh": "loud",
16+
"crojob_wrapper": "loud",
17+
"welcome_to_the_jungle_wrapper": "any"
18+
},
19+
"recommended_exclusions": {
20+
"stealth": [
21+
"nightclub",
22+
"branchbank",
23+
"branchbank_prof",
24+
"branchbank_cash",
25+
"branchbank_deposit",
26+
"branchbank_gold",
27+
"branchbank_gold_prof",
28+
"family",
29+
"roberts",
30+
"gallery",
31+
"pal",
32+
"jewelry_store",
33+
"ukrainian_job",
34+
"ukrainian_job_prof",
35+
"four_stores",
36+
"mallcrasher"
37+
],
38+
"loud": [
39+
"branchbank",
40+
"branchbank_prof",
41+
"branchbank_cash",
42+
"branchbank_deposit",
43+
"branchbank_gold",
44+
"branchbank_gold_prof",
45+
"jewelry_store",
46+
"family",
47+
"ukrainian_job",
48+
"ukrainian_job_prof",
49+
"four_stores",
50+
"nightclub",
51+
"arm_wrapper",
52+
"arm_cro",
53+
"arm_und",
54+
"arm_hcm",
55+
"arm_par",
56+
"arm_fac",
57+
"gallery",
58+
"haunted",
59+
"mallcrasher"
60+
]
61+
}
62+
}

0 commit comments

Comments
 (0)