592 lines
22 KiB
Bash
592 lines
22 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:=}"
|
|
#
|
|
# Local Lua module SQL bootstrap.
|
|
: "${ACORE_IMPORT_START_ZONE_RACE_TELEPORTERS_SQL:=1}"
|
|
|
|
: "${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.
|
|
If ac-database is already running, it also imports local Lua-module bootstrap SQL.
|
|
|
|
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/}"
|
|
}
|
|
|
|
require_integer_flag() {
|
|
local name="$1"
|
|
local value="$2"
|
|
|
|
if ! [[ "$value" =~ ^[01]$ ]]; then
|
|
printf '%s must be 0 or 1, got: %s\n' "$name" "$value" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
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/}"
|
|
}
|
|
|
|
database_service_running() {
|
|
if ! command -v docker >/dev/null 2>&1; then
|
|
return 1
|
|
fi
|
|
|
|
docker compose ps --status running --services 2>/dev/null | grep -qx 'ac-database'
|
|
}
|
|
|
|
import_world_sql_file() {
|
|
local file_path="$1"
|
|
|
|
if [[ ! -f "$file_path" ]]; then
|
|
log "skip missing ${file_path#$ROOT_DIR/}"
|
|
return
|
|
fi
|
|
|
|
if (( DRY_RUN )); then
|
|
log "would import ${file_path#$ROOT_DIR/} into acore_world"
|
|
return
|
|
fi
|
|
|
|
docker compose exec -T ac-database bash -lc \
|
|
"mysql --default-character-set=utf8mb4 -uroot -p\"\$MYSQL_ROOT_PASSWORD\" acore_world" < "$file_path"
|
|
log "imported ${file_path#$ROOT_DIR/} into acore_world"
|
|
}
|
|
|
|
import_local_lua_module_sql() {
|
|
local start_zone_race_teleporters_sql="$ROOT_DIR/lua_scripts/StartZoneRaceTeleporters/sql/world/start_zone_race_teleporters.sql"
|
|
|
|
if [[ "$ACORE_IMPORT_START_ZONE_RACE_TELEPORTERS_SQL" == "0" ]]; then
|
|
log "StartZoneRaceTeleporters SQL import disabled, skipped"
|
|
return
|
|
fi
|
|
|
|
if ! database_service_running; then
|
|
log "skip StartZoneRaceTeleporters SQL: ac-database is not running"
|
|
return
|
|
fi
|
|
|
|
import_world_sql_file "$start_zone_race_teleporters_sql"
|
|
}
|
|
|
|
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"
|
|
|
|
require_integer_flag "ACORE_IMPORT_START_ZONE_RACE_TELEPORTERS_SQL" "$ACORE_IMPORT_START_ZONE_RACE_TELEPORTERS_SQL"
|
|
|
|
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
|
|
import_local_lua_module_sql
|
|
|
|
log "module bootstrap completed"
|
|
}
|
|
|
|
main "$@"
|