Files
moonwell-core/setup-modules.sh
T
2026-03-09 21:50:11 +04:00

533 lines
20 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ENV_FILE="${ENV_FILE:-$ROOT_DIR/.env}"
if [[ -f "$ENV_FILE" ]]; then
set -a
# shellcheck disable=SC1090
source "$ENV_FILE"
set +a
fi
ETC_DIR="${ACORE_ETC_DIR:-$ROOT_DIR/env/dist/etc}"
MODULES_ETC_DIR="${ACORE_MODULES_ETC_DIR:-$ETC_DIR/modules}"
WORLD_CONF="${WORLD_CONF:-$ETC_DIR/worldserver.conf}"
DRY_RUN=0
FORCE_PLAYERBOTS="${FORCE_PLAYERBOTS:-${ACORE_PLAYERBOTS_FORCE:-0}}"
: "${ACORE_WORLD_ENABLE_PLAYER_SETTINGS:=1}"
: "${ACORE_WORLD_CONSOLE_ENABLE:=0}"
: "${ACORE_WORLD_DBC_ENFORCE_ITEM_ATTRIBUTES:=0}"
: "${ACORE_WORLD_INSTANCE_IGNORE_RAID:=1}"
: "${ACORE_WORLD_RATE_CREATURE_ELITE_ELITE_DAMAGE:=0.80}"
: "${ACORE_WORLD_RATE_CREATURE_RARE_DAMAGE:=0.80}"
: "${ACORE_WORLD_RATE_CREATURE_RAREELITE_DAMAGE:=0.75}"
: "${ACORE_WORLD_RATE_CREATURE_WORLDBOSS_DAMAGE:=1}"
: "${ACORE_WORLD_RATE_CREATURE_ELITE_ELITE_SPELL_DAMAGE:=0.80}"
: "${ACORE_WORLD_RATE_CREATURE_RARE_SPELL_DAMAGE:=0.80}"
: "${ACORE_WORLD_RATE_CREATURE_RAREELITE_SPELL_DAMAGE:=0.75}"
: "${ACORE_WORLD_RATE_CREATURE_WORLDBOSS_SPELL_DAMAGE:=1}"
: "${ACORE_WORLD_RATE_CREATURE_ELITE_ELITE_HP:=0.75}"
: "${ACORE_WORLD_RATE_CREATURE_RARE_HP:=0.70}"
: "${ACORE_WORLD_RATE_CREATURE_RAREELITE_HP:=0.65}"
: "${ACORE_WORLD_RATE_CREATURE_WORLDBOSS_HP:=1}"
: "${ACORE_AUTOBALANCE_MIN_PLAYERS:=1}"
: "${ACORE_AUTOBALANCE_MIN_PLAYERS_HEROIC:=1}"
: "${ACORE_AUTOBALANCE_MIN_PLAYERS_RAID:=1}"
: "${ACORE_AUTOBALANCE_MIN_PLAYERS_RAID_HEROIC:=1}"
: "${ACORE_AUTOBALANCE_INFLECTION_POINT_RAID:=0.75}"
: "${ACORE_AUTOBALANCE_INFLECTION_POINT_RAID_BOSS_MODIFIER:=1.35}"
: "${ACORE_AUTOBALANCE_INFLECTION_POINT_RAID_HEROIC:=0.80}"
: "${ACORE_AUTOBALANCE_INFLECTION_POINT_RAID_HEROIC_BOSS_MODIFIER:=1.45}"
: "${ACORE_AUTOBALANCE_STAT_MODIFIER_BOSS_DAMAGE:=0.85}"
: "${ACORE_AUTOBALANCE_STAT_MODIFIER_HEROIC_BOSS_DAMAGE:=0.75}"
: "${ACORE_AUTOBALANCE_STAT_MODIFIER_RAID_GLOBAL:=0.85}"
: "${ACORE_AUTOBALANCE_STAT_MODIFIER_RAID_DAMAGE:=0.75}"
: "${ACORE_AUTOBALANCE_STAT_MODIFIER_RAID_BOSS_HEALTH:=0.70}"
: "${ACORE_AUTOBALANCE_STAT_MODIFIER_RAID_BOSS_DAMAGE:=0.55}"
: "${ACORE_AUTOBALANCE_STAT_MODIFIER_RAID_HEROIC_GLOBAL:=0.75}"
: "${ACORE_AUTOBALANCE_STAT_MODIFIER_RAID_HEROIC_DAMAGE:=0.70}"
: "${ACORE_AUTOBALANCE_STAT_MODIFIER_RAID_HEROIC_BOSS_HEALTH:=0.60}"
: "${ACORE_AUTOBALANCE_STAT_MODIFIER_RAID_HEROIC_BOSS_DAMAGE:=0.45}"
: "${ACORE_PROGRESSION_ENABLE:=1}"
: "${ACORE_PROGRESSION_SIMPLE_CONFIG_OVERRIDE:=1}"
: "${ACORE_PROGRESSION_STARTING_PROGRESSION:=0}"
: "${ACORE_PROGRESSION_LIMIT:=0}"
: "${ACORE_PROGRESSION_ENFORCE_GROUP_RULES:=1}"
: "${ACORE_PROGRESSION_TBC_RACES_UNLOCK:=8}"
: "${ACORE_PROGRESSION_DK_UNLOCK:=13}"
: "${ACORE_PROGRESSION_DK_STARTING:=13}"
: "${ACORE_PROGRESSION_MC_AQUAL_COOLDOWN_REDUCTION:=60}"
: "${ACORE_PROGRESSION_PVP_GEAR_REQUIREMENTS:=0}"
: "${ACORE_AOE_LOOT_ENABLE:=1}"
: "${ACORE_AOE_LOOT_MESSAGE:=0}"
: "${ACORE_AOE_LOOT_RANGE:=55.0}"
: "${ACORE_AOE_LOOT_GROUP:=1}"
: "${ACORE_ELUNA_ENABLED:=true}"
: "${ACORE_ELUNA_TRACEBACK:=false}"
: "${ACORE_ELUNA_SCRIPT_PATH:=lua_scripts}"
: "${ACORE_ELUNA_PLAYER_ANNOUNCE_RELOAD:=false}"
: "${ACORE_ELUNA_REQUIRE_PATHS:=}"
: "${ACORE_ELUNA_REQUIRE_CPATHS:=}"
: "${ACORE_LEARNSPELLS_GAMEMASTERS:=0}"
: "${ACORE_LEARNSPELLS_CLASS_SPELLS:=1}"
: "${ACORE_LEARNSPELLS_PROFICIENCIES:=1}"
: "${ACORE_LEARNSPELLS_SPELLS_FROM_QUESTS:=1}"
: "${ACORE_LEARNSPELLS_RIDING_APPRENTICE:=0}"
: "${ACORE_LEARNSPELLS_RIDING_JOURNEYMAN:=0}"
: "${ACORE_LEARNSPELLS_RIDING_EXPERT:=0}"
: "${ACORE_LEARNSPELLS_RIDING_ARTISAN:=0}"
: "${ACORE_LEARNSPELLS_RIDING_COLD_WEATHER_FLYING:=0}"
: "${ACORE_PLAYERBOTS_ENABLED:=1}"
: "${ACORE_PLAYERBOTS_RANDOM_BOT_AUTOLOGIN:=${AC_AI_PLAYERBOT_RANDOM_BOT_AUTOLOGIN:-0}}"
: "${ACORE_PLAYERBOTS_MIN_RANDOM_BOTS:=0}"
: "${ACORE_PLAYERBOTS_MAX_RANDOM_BOTS:=0}"
: "${ACORE_PLAYERBOTS_RANDOM_BOT_ACCOUNT_COUNT:=0}"
: "${ACORE_PLAYERBOTS_DELETE_RANDOM_BOT_ACCOUNTS:=0}"
: "${ACORE_PLAYERBOTS_MAX_ADDED_BOTS:=9}"
: "${ACORE_PLAYERBOTS_ADDCLASS_COMMAND:=1}"
: "${ACORE_PLAYERBOTS_ADDCLASS_ACCOUNT_POOL_SIZE:=3}"
: "${ACORE_PLAYERBOTS_DISABLED_WITHOUT_REAL_PLAYER:=1}"
: "${ACORE_PLAYERBOTS_GROUP_INVITATION_PERMISSION:=2}"
: "${ACORE_PLAYERBOTS_KEEP_ALTS_IN_GROUP:=1}"
: "${ACORE_PLAYERBOTS_BOT_AUTOLOGIN:=0}"
: "${ACORE_PLAYERBOTS_ALLOW_ACCOUNT_BOTS:=1}"
: "${ACORE_PLAYERBOTS_ALLOW_GUILD_BOTS:=1}"
: "${ACORE_PLAYERBOTS_ALLOW_TRUSTED_ACCOUNT_BOTS:=1}"
: "${ACORE_PLAYERBOTS_SUMMON_WHEN_GROUP:=1}"
: "${ACORE_PLAYERBOTS_AUTO_TRAIN_SPELLS:=yes}"
: "${ACORE_PLAYERBOTS_SYNC_QUEST_WITH_PLAYER:=1}"
: "${ACORE_PLAYERBOTS_SYNC_LEVEL_WITH_PLAYERS:=1}"
: "${ACORE_PLAYERBOTS_APPLY_INSTANCE_STRATEGIES:=1}"
: "${ACORE_PLAYERBOTS_RANDOM_BOT_INVITE_PLAYER:=0}"
: "${ACORE_PLAYERBOTS_RANDOM_BOT_JOIN_LFG:=0}"
: "${ACORE_PLAYERBOTS_RANDOM_BOT_LOGIN_AT_STARTUP:=0}"
: "${ACORE_PLAYERBOTS_BOT_CHEATS:=food,taxi,raid}"
: "${ACORE_PLAYERBOTS_RANDOM_BOT_ARENA_TEAM_2V2_COUNT:=0}"
: "${ACORE_PLAYERBOTS_RANDOM_BOT_ARENA_TEAM_3V3_COUNT:=0}"
: "${ACORE_PLAYERBOTS_RANDOM_BOT_ARENA_TEAM_5V5_COUNT:=0}"
: "${ACORE_PLAYERBOTS_DELETE_RANDOM_BOT_ARENA_TEAMS:=0}"
usage() {
cat <<EOF
Usage: $(basename "$0") [--dry-run] [--force-playerbots]
Configures AzerothCore module configs for this repository layout.
Options:
--dry-run Show actions without changing files
--force-playerbots Write playerbots.conf even if the current core disables mod-playerbots
-h, --help Show this help
EOF
}
log() {
printf '[setup-modules] %s\n' "$*"
}
write_file() {
local target="$1"
local tmp
tmp="$(mktemp)"
cat > "$tmp"
if [[ -f "$target" ]] && cmp -s "$tmp" "$target"; then
rm -f "$tmp"
log "unchanged ${target#$ROOT_DIR/}"
return
fi
if (( DRY_RUN )); then
rm -f "$tmp"
log "would write ${target#$ROOT_DIR/}"
return
fi
mkdir -p "$(dirname "$target")"
mv "$tmp" "$target"
log "wrote ${target#$ROOT_DIR/}"
}
sync_file() {
local source="$1"
local target="$2"
if [[ ! -f "$source" ]]; then
log "skip missing ${source#$ROOT_DIR/}"
return
fi
if [[ -f "$target" ]] && cmp -s "$source" "$target"; then
log "unchanged ${target#$ROOT_DIR/}"
return
fi
if (( DRY_RUN )); then
log "would sync ${source#$ROOT_DIR/} -> ${target#$ROOT_DIR/}"
return
fi
mkdir -p "$(dirname "$target")"
cp "$source" "$target"
log "synced ${target#$ROOT_DIR/}"
}
escape_regex() {
printf '%s' "$1" | sed 's/[][(){}.^$*+?|\\/]/\\&/g'
}
set_config_value() {
local file="$1"
local key="$2"
local value="$3"
local pattern
local desired_line
pattern="$(escape_regex "$key")"
desired_line="${key} = ${value}"
if [[ ! -f "$file" ]]; then
if (( DRY_RUN )); then
log "would create ${file#$ROOT_DIR/}"
else
mkdir -p "$(dirname "$file")"
: > "$file"
log "created ${file#$ROOT_DIR/}"
fi
fi
if [[ -f "$file" ]] && grep -Eq "^[[:space:]]*${pattern}[[:space:]]*=" "$file"; then
local current_line
current_line="$(grep -E "^[[:space:]]*${pattern}[[:space:]]*=" "$file" | head -n 1 | sed -E 's/^[[:space:]]*//')"
if [[ "$current_line" == "$desired_line" ]]; then
log "unchanged ${key} in ${file#$ROOT_DIR/}"
return
fi
if (( DRY_RUN )); then
log "would set ${key} in ${file#$ROOT_DIR/} to ${value}"
return
fi
sed -i -E "0,/^[[:space:]]*${pattern}[[:space:]]*=/{s|^[[:space:]]*${pattern}[[:space:]]*=.*$|${desired_line}|}" "$file"
log "set ${key} in ${file#$ROOT_DIR/}"
return
fi
if (( DRY_RUN )); then
log "would append ${key} to ${file#$ROOT_DIR/}"
return
fi
printf '\n%s = %s\n' "$key" "$value" >> "$file"
log "appended ${key} to ${file#$ROOT_DIR/}"
}
ensure_world_conf() {
if [[ -f "$WORLD_CONF" ]]; then
return
fi
local source=""
for candidate in \
"$ETC_DIR/worldserver.conf.dist" \
"$ROOT_DIR/src/server/apps/worldserver/worldserver.conf.dist"
do
if [[ -f "$candidate" ]]; then
source="$candidate"
break
fi
done
if [[ -z "$source" ]]; then
log "cannot find a worldserver.conf.dist source"
exit 1
fi
sync_file "$source" "$WORLD_CONF"
}
sync_module_dists() {
sync_file "$ROOT_DIR/modules/mod-aoe-loot/conf/mod_aoe_loot.conf.dist" \
"$MODULES_ETC_DIR/mod_aoe_loot.conf.dist"
sync_file "$ROOT_DIR/modules/mod-autobalance/conf/AutoBalance.conf.dist" \
"$MODULES_ETC_DIR/AutoBalance.conf.dist"
sync_file "$ROOT_DIR/modules/mod-eluna/conf/mod_eluna.conf.dist" \
"$MODULES_ETC_DIR/mod_eluna.conf.dist"
sync_file "$ROOT_DIR/modules/mod-individual-progression/conf/individualProgression.conf.dist" \
"$MODULES_ETC_DIR/individualProgression.conf.dist"
sync_file "$ROOT_DIR/modules/mod-learnspells/conf/mod_learnspells.conf.dist" \
"$MODULES_ETC_DIR/mod_learnspells.conf.dist"
sync_file "$ROOT_DIR/modules/mod-playerbots/conf/playerbots.conf.dist" \
"$MODULES_ETC_DIR/playerbots.conf.dist"
}
write_autobalance_conf() {
write_file "$MODULES_ETC_DIR/AutoBalance.conf.dist" <<EOF
[worldserver]
# Managed by ./setup-modules.sh
# Solo + small-group profile for dungeons and raids.
AutoBalance.MinPlayers = ${ACORE_AUTOBALANCE_MIN_PLAYERS}
AutoBalance.MinPlayers.Heroic = ${ACORE_AUTOBALANCE_MIN_PLAYERS_HEROIC}
AutoBalance.MinPlayers.Raid = ${ACORE_AUTOBALANCE_MIN_PLAYERS_RAID}
AutoBalance.MinPlayers.RaidHeroic = ${ACORE_AUTOBALANCE_MIN_PLAYERS_RAID_HEROIC}
# So raids scale down harder at low player counts.
AutoBalance.InflectionPointRaid = ${ACORE_AUTOBALANCE_INFLECTION_POINT_RAID}
AutoBalance.InflectionPointRaid.BossModifier = ${ACORE_AUTOBALANCE_INFLECTION_POINT_RAID_BOSS_MODIFIER}
AutoBalance.InflectionPointRaidHeroic = ${ACORE_AUTOBALANCE_INFLECTION_POINT_RAID_HEROIC}
AutoBalance.InflectionPointRaidHeroic.BossModifier = ${ACORE_AUTOBALANCE_INFLECTION_POINT_RAID_HEROIC_BOSS_MODIFIER}
# Keep 5-man bosses manageable in solo runs.
AutoBalance.StatModifier.Boss.Damage = ${ACORE_AUTOBALANCE_STAT_MODIFIER_BOSS_DAMAGE}
AutoBalance.StatModifierHeroic.Boss.Damage = ${ACORE_AUTOBALANCE_STAT_MODIFIER_HEROIC_BOSS_DAMAGE}
# Raid tuning for solo / duo / incomplete groups.
AutoBalance.StatModifierRaid.Global = ${ACORE_AUTOBALANCE_STAT_MODIFIER_RAID_GLOBAL}
AutoBalance.StatModifierRaid.Damage = ${ACORE_AUTOBALANCE_STAT_MODIFIER_RAID_DAMAGE}
AutoBalance.StatModifierRaid.Boss.Health = ${ACORE_AUTOBALANCE_STAT_MODIFIER_RAID_BOSS_HEALTH}
AutoBalance.StatModifierRaid.Boss.Damage = ${ACORE_AUTOBALANCE_STAT_MODIFIER_RAID_BOSS_DAMAGE}
AutoBalance.StatModifierRaidHeroic.Global = ${ACORE_AUTOBALANCE_STAT_MODIFIER_RAID_HEROIC_GLOBAL}
AutoBalance.StatModifierRaidHeroic.Damage = ${ACORE_AUTOBALANCE_STAT_MODIFIER_RAID_HEROIC_DAMAGE}
AutoBalance.StatModifierRaidHeroic.Boss.Health = ${ACORE_AUTOBALANCE_STAT_MODIFIER_RAID_HEROIC_BOSS_HEALTH}
AutoBalance.StatModifierRaidHeroic.Boss.Damage = ${ACORE_AUTOBALANCE_STAT_MODIFIER_RAID_HEROIC_BOSS_DAMAGE}
EOF
}
write_individual_progression_conf() {
write_file "$MODULES_ETC_DIR/individualProgression.conf.dist" <<EOF
[worldserver]
# Managed by ./setup-modules.sh
# Sequential progression profile: Classic -> TBC -> WotLK.
IndividualProgression.Enable = ${ACORE_PROGRESSION_ENABLE}
IndividualProgression.SimpleConfigOverride = ${ACORE_PROGRESSION_SIMPLE_CONFIG_OVERRIDE}
IndividualProgression.StartingProgression = ${ACORE_PROGRESSION_STARTING_PROGRESSION}
IndividualProgression.ProgressionLimit = ${ACORE_PROGRESSION_LIMIT}
# Keep progression integrity for grouped players.
IndividualProgression.EnforceGroupRules = ${ACORE_PROGRESSION_ENFORCE_GROUP_RULES}
# Unlocks.
IndividualProgression.TbcRacesUnlockProgression = ${ACORE_PROGRESSION_TBC_RACES_UNLOCK}
IndividualProgression.DeathKnightUnlockProgression = ${ACORE_PROGRESSION_DK_UNLOCK}
IndividualProgression.DeathKnightStartingProgression = ${ACORE_PROGRESSION_DK_STARTING}
# Solo-friendly quality-of-life for MC rune handling.
IndividualProgression.MoltenCore.AqualEssenceCooldownReduction = ${ACORE_PROGRESSION_MC_AQUAL_COOLDOWN_REDUCTION}
# PvE-focused progression.
IndividualProgression.PvPGearRequirements = ${ACORE_PROGRESSION_PVP_GEAR_REQUIREMENTS}
EOF
}
write_aoe_loot_conf() {
write_file "$MODULES_ETC_DIR/mod_aoe_loot.conf.dist" <<EOF
# Managed by ./setup-modules.sh
AOELoot.Enable = ${ACORE_AOE_LOOT_ENABLE}
AOELoot.Message = ${ACORE_AOE_LOOT_MESSAGE}
AOELoot.Range = ${ACORE_AOE_LOOT_RANGE}
AOELoot.Group = ${ACORE_AOE_LOOT_GROUP}
EOF
}
write_eluna_conf() {
write_file "$MODULES_ETC_DIR/mod_eluna.conf.dist" <<EOF
[worldserver]
# Managed by ./setup-modules.sh
Eluna.Enabled = ${ACORE_ELUNA_ENABLED}
Eluna.TraceBack = ${ACORE_ELUNA_TRACEBACK}
Eluna.ScriptPath = "${ACORE_ELUNA_SCRIPT_PATH}"
Eluna.PlayerAnnounceReload = ${ACORE_ELUNA_PLAYER_ANNOUNCE_RELOAD}
Eluna.RequirePaths = "${ACORE_ELUNA_REQUIRE_PATHS}"
Eluna.RequireCPaths = "${ACORE_ELUNA_REQUIRE_CPATHS}"
EOF
}
write_learnspells_conf() {
write_file "$MODULES_ETC_DIR/mod_learnspells.conf.dist" <<EOF
[worldserver]
# Managed by ./setup-modules.sh
LearnSpells.Gamemasters = ${ACORE_LEARNSPELLS_GAMEMASTERS}
LearnSpells.ClassSpells = ${ACORE_LEARNSPELLS_CLASS_SPELLS}
LearnSpells.Proficiencies = ${ACORE_LEARNSPELLS_PROFICIENCIES}
LearnSpells.SpellsFromQuests = ${ACORE_LEARNSPELLS_SPELLS_FROM_QUESTS}
LearnSpells.Riding.Apprentice = ${ACORE_LEARNSPELLS_RIDING_APPRENTICE}
LearnSpells.Riding.Journeyman = ${ACORE_LEARNSPELLS_RIDING_JOURNEYMAN}
LearnSpells.Riding.Expert = ${ACORE_LEARNSPELLS_RIDING_EXPERT}
LearnSpells.Riding.Artisan = ${ACORE_LEARNSPELLS_RIDING_ARTISAN}
LearnSpells.Riding.ColdWeatherFlying = ${ACORE_LEARNSPELLS_RIDING_COLD_WEATHER_FLYING}
EOF
}
playerbots_supported() {
if [[ ! -d "$ROOT_DIR/modules/mod-playerbots" ]]; then
return 1
fi
if [[ -f "$ROOT_DIR/conf/config.cmake" ]] && \
grep -Eq '^set\(MODULE_MOD-PLAYERBOTS "disabled"' "$ROOT_DIR/conf/config.cmake"; then
return 1
fi
return 0
}
write_playerbots_conf() {
if ! [[ -f "$ROOT_DIR/modules/mod-playerbots/conf/playerbots.conf.dist" ]]; then
log "skip playerbots: module config source not found"
return
fi
if ! playerbots_supported && (( ! FORCE_PLAYERBOTS )); then
log "skip playerbots: current local overrides still disable mod-playerbots"
return
fi
write_file "$MODULES_ETC_DIR/playerbots.conf.dist" <<EOF
# Managed by ./setup-modules.sh
AiPlayerbot.Enabled = ${ACORE_PLAYERBOTS_ENABLED}
AiPlayerbot.RandomBotAutologin = ${ACORE_PLAYERBOTS_RANDOM_BOT_AUTOLOGIN}
AiPlayerbot.MinRandomBots = ${ACORE_PLAYERBOTS_MIN_RANDOM_BOTS}
AiPlayerbot.MaxRandomBots = ${ACORE_PLAYERBOTS_MAX_RANDOM_BOTS}
AiPlayerbot.RandomBotAccountCount = ${ACORE_PLAYERBOTS_RANDOM_BOT_ACCOUNT_COUNT}
AiPlayerbot.DeleteRandomBotAccounts = ${ACORE_PLAYERBOTS_DELETE_RANDOM_BOT_ACCOUNTS}
AiPlayerbot.DisabledWithoutRealPlayer = ${ACORE_PLAYERBOTS_DISABLED_WITHOUT_REAL_PLAYER}
AiPlayerbot.MaxAddedBots = ${ACORE_PLAYERBOTS_MAX_ADDED_BOTS}
AiPlayerbot.AddClassCommand = ${ACORE_PLAYERBOTS_ADDCLASS_COMMAND}
AiPlayerbot.AddClassAccountPoolSize = ${ACORE_PLAYERBOTS_ADDCLASS_ACCOUNT_POOL_SIZE}
AiPlayerbot.GroupInvitationPermission = ${ACORE_PLAYERBOTS_GROUP_INVITATION_PERMISSION}
AiPlayerbot.KeepAltsInGroup = ${ACORE_PLAYERBOTS_KEEP_ALTS_IN_GROUP}
AiPlayerbot.BotAutologin = ${ACORE_PLAYERBOTS_BOT_AUTOLOGIN}
AiPlayerbot.AllowAccountBots = ${ACORE_PLAYERBOTS_ALLOW_ACCOUNT_BOTS}
AiPlayerbot.AllowGuildBots = ${ACORE_PLAYERBOTS_ALLOW_GUILD_BOTS}
AiPlayerbot.AllowTrustedAccountBots = ${ACORE_PLAYERBOTS_ALLOW_TRUSTED_ACCOUNT_BOTS}
AiPlayerbot.SummonWhenGroup = ${ACORE_PLAYERBOTS_SUMMON_WHEN_GROUP}
AiPlayerbot.AutoTrainSpells = ${ACORE_PLAYERBOTS_AUTO_TRAIN_SPELLS}
AiPlayerbot.SyncQuestWithPlayer = ${ACORE_PLAYERBOTS_SYNC_QUEST_WITH_PLAYER}
AiPlayerbot.SyncLevelWithPlayers = ${ACORE_PLAYERBOTS_SYNC_LEVEL_WITH_PLAYERS}
AiPlayerbot.ApplyInstanceStrategies = ${ACORE_PLAYERBOTS_APPLY_INSTANCE_STRATEGIES}
AiPlayerbot.RandomBotInvitePlayer = ${ACORE_PLAYERBOTS_RANDOM_BOT_INVITE_PLAYER}
AiPlayerbot.RandomBotJoinLfg = ${ACORE_PLAYERBOTS_RANDOM_BOT_JOIN_LFG}
AiPlayerbot.RandomBotLoginAtStartup = ${ACORE_PLAYERBOTS_RANDOM_BOT_LOGIN_AT_STARTUP}
AiPlayerbot.RandomBotArenaTeam2v2Count = ${ACORE_PLAYERBOTS_RANDOM_BOT_ARENA_TEAM_2V2_COUNT}
AiPlayerbot.RandomBotArenaTeam3v3Count = ${ACORE_PLAYERBOTS_RANDOM_BOT_ARENA_TEAM_3V3_COUNT}
AiPlayerbot.RandomBotArenaTeam5v5Count = ${ACORE_PLAYERBOTS_RANDOM_BOT_ARENA_TEAM_5V5_COUNT}
AiPlayerbot.DeleteRandomBotArenaTeams = ${ACORE_PLAYERBOTS_DELETE_RANDOM_BOT_ARENA_TEAMS}
AiPlayerbot.BotCheats = "${ACORE_PLAYERBOTS_BOT_CHEATS}"
EOF
}
configure_worldserver() {
ensure_world_conf
set_config_value "$WORLD_CONF" "Console.Enable" "$ACORE_WORLD_CONSOLE_ENABLE"
set_config_value "$WORLD_CONF" "EnablePlayerSettings" "$ACORE_WORLD_ENABLE_PLAYER_SETTINGS"
set_config_value "$WORLD_CONF" "DBC.EnforceItemAttributes" "$ACORE_WORLD_DBC_ENFORCE_ITEM_ATTRIBUTES"
set_config_value "$WORLD_CONF" "Instance.IgnoreRaid" "$ACORE_WORLD_INSTANCE_IGNORE_RAID"
set_config_value "$WORLD_CONF" "Rate.Creature.Elite.Elite.Damage" "$ACORE_WORLD_RATE_CREATURE_ELITE_ELITE_DAMAGE"
set_config_value "$WORLD_CONF" "Rate.Creature.Elite.RARE.Damage" "$ACORE_WORLD_RATE_CREATURE_RARE_DAMAGE"
set_config_value "$WORLD_CONF" "Rate.Creature.Elite.RAREELITE.Damage" "$ACORE_WORLD_RATE_CREATURE_RAREELITE_DAMAGE"
set_config_value "$WORLD_CONF" "Rate.Creature.Elite.WORLDBOSS.Damage" "$ACORE_WORLD_RATE_CREATURE_WORLDBOSS_DAMAGE"
set_config_value "$WORLD_CONF" "Rate.Creature.Elite.Elite.SpellDamage" "$ACORE_WORLD_RATE_CREATURE_ELITE_ELITE_SPELL_DAMAGE"
set_config_value "$WORLD_CONF" "Rate.Creature.Elite.RARE.SpellDamage" "$ACORE_WORLD_RATE_CREATURE_RARE_SPELL_DAMAGE"
set_config_value "$WORLD_CONF" "Rate.Creature.Elite.RAREELITE.SpellDamage" "$ACORE_WORLD_RATE_CREATURE_RAREELITE_SPELL_DAMAGE"
set_config_value "$WORLD_CONF" "Rate.Creature.Elite.WORLDBOSS.SpellDamage" "$ACORE_WORLD_RATE_CREATURE_WORLDBOSS_SPELL_DAMAGE"
set_config_value "$WORLD_CONF" "Rate.Creature.Elite.Elite.HP" "$ACORE_WORLD_RATE_CREATURE_ELITE_ELITE_HP"
set_config_value "$WORLD_CONF" "Rate.Creature.Elite.RARE.HP" "$ACORE_WORLD_RATE_CREATURE_RARE_HP"
set_config_value "$WORLD_CONF" "Rate.Creature.Elite.RAREELITE.HP" "$ACORE_WORLD_RATE_CREATURE_RAREELITE_HP"
set_config_value "$WORLD_CONF" "Rate.Creature.Elite.WORLDBOSS.HP" "$ACORE_WORLD_RATE_CREATURE_WORLDBOSS_HP"
}
ensure_runtime_dirs() {
if (( DRY_RUN )); then
log "would ensure ${MODULES_ETC_DIR#$ROOT_DIR/}"
log "would ensure env/dist/logs"
log "would ensure lua_scripts"
return
fi
mkdir -p "$MODULES_ETC_DIR"
mkdir -p "$ROOT_DIR/env/dist/logs"
mkdir -p "$ROOT_DIR/lua_scripts"
}
cleanup_legacy_module_overrides() {
local legacy_files=(
"$MODULES_ETC_DIR/AutoBalance.conf"
"$MODULES_ETC_DIR/individualProgression.conf"
"$MODULES_ETC_DIR/mod_aoe_loot.conf"
"$MODULES_ETC_DIR/mod_eluna.conf"
"$MODULES_ETC_DIR/mod_learnspells.conf"
"$MODULES_ETC_DIR/playerbots.conf"
)
local path
for path in "${legacy_files[@]}"; do
if [[ ! -e "$path" ]]; then
continue
fi
if (( DRY_RUN )); then
log "would remove legacy override ${path#$ROOT_DIR/}"
continue
fi
rm -f "$path"
done
}
main() {
while (($#)); do
case "$1" in
--dry-run)
DRY_RUN=1
;;
--force-playerbots)
FORCE_PLAYERBOTS=1
;;
-h|--help)
usage
exit 0
;;
*)
printf 'Unknown option: %s\n\n' "$1" >&2
usage >&2
exit 1
;;
esac
shift
done
log "root: $ROOT_DIR"
log "etc: $ETC_DIR"
ensure_runtime_dirs
sync_module_dists
cleanup_legacy_module_overrides
configure_worldserver
write_autobalance_conf
write_individual_progression_conf
write_aoe_loot_conf
write_eluna_conf
write_learnspells_conf
write_playerbots_conf
log "module bootstrap completed"
}
main "$@"