diff -r edeae7661dca -r ed33ef8a0fc5 share/hedgewars/Data/Scripts/Multiplayer/Battalion.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/share/hedgewars/Data/Scripts/Multiplayer/Battalion.lua Sun May 14 14:06:51 2017 +0200 @@ -0,0 +1,1706 @@ +--[[ + ######################################################################## + Name: Battalion + Made by: Anachron + ######################################################################## +]]-- + +--[[ + + Readme: + https://github.com/Anachron/hw-battalion + + ######################################################################## +]]-- + +--[[ + ######################################################################## + Todo/Idea-List + ######################################################################## + + - Make Hogs sorted by rareness for teams with less hogs (more fair) + - Keep first picked up unused crate utitlity until next round + - Ship default scheme but let user overwrite it + - Make SuddenDeathWaterRise dynamic + - Make SuddenDeathTurns dynamic + - Add Hog Variants like Crazy Scientist or Astronaut + + ######################################################################## +]]-- + +--[[ + ############################################################################## + ### GENERAL SCRIPT LOADING AND VARIABLE INITIALISATION ### + ############################################################################## +]]-- + +HedgewarsScriptLoad("/Scripts/Locale.lua") +HedgewarsScriptLoad("/Scripts/Tracker.lua") +HedgewarsScriptLoad("/Scripts/Params.lua") + +-- List of all hog variants with belonging weapons, +-- hitpoints, chances and more +local variants = {} +local varName = "" +local newLine = ""--string.char(0x0A) +local gmAny = 0xFFFFFFFF +local version = "0.33" + +--[[ + ############################################################################## + ### VARIANT SETUP ### + ############################################################################## +]]-- + +varName = "Pyromancer" +variants[varName] = {} +variants[varName]["chance"] = 7 +variants[varName]["hat"] = "Gasmask" +variants[varName]["hp"] = 70 +variants[varName]["hogLimit"] = 2 +variants[varName]["weaponLimit"] = 1 +variants[varName]["weapons"] = {amFlamethrower, amMolotov, amWhip} +variants[varName]["helperLimit"] = 1 +variants[varName]["helpers"] = {amRope, amParachute} +variants[varName]["special"] = false + +varName = "Builder" +variants[varName] = {} +variants[varName]["chance"] = 10 +variants[varName]["hat"] = "constructor" +variants[varName]["hp"] = 100 +variants[varName]["hogLimit"] = 1 +variants[varName]["weaponLimit"] = 1 +variants[varName]["weapons"] = {amDynamite, amWhip, amHammer} +variants[varName]["helperLimit"] = 1 +variants[varName]["helpers"] = {amGirder, amBlowTorch} +variants[varName]["special"] = false + +varName = "Rifleman" +variants[varName] = {} +variants[varName]["chance"] = 7 +variants[varName]["hat"] = "Sniper" +variants[varName]["hp"] = 70 +variants[varName]["hogLimit"] = 2 +variants[varName]["weaponLimit"] = 1 +variants[varName]["weapons"] = {amRCPlane, amShotgun, amSniperRifle} +variants[varName]["helperLimit"] = 1 +variants[varName]["helpers"] = {amLowGravity, amParachute} +variants[varName]["special"] = false + +varName = "Warrior" +variants[varName] = {} +variants[varName]["chance"] = 12 +variants[varName]["hat"] = "spartan" +variants[varName]["hp"] = 120 +variants[varName]["hogLimit"] = 2 +variants[varName]["weaponLimit"] = 1 +variants[varName]["weapons"] = {amClusterBomb, amGrenade, amBazooka} +variants[varName]["helperLimit"] = 1 +variants[varName]["helpers"] = {amParachute, amRope} +variants[varName]["special"] = false + +varName = "Chef" +variants[varName] = {} +variants[varName]["chance"] = 7 +variants[varName]["hat"] = "chef" +variants[varName]["hp"] = 70 +variants[varName]["hogLimit"] = 1 +variants[varName]["weaponLimit"] = 1 +variants[varName]["weapons"] = {amCake, amKnife, amWhip} +variants[varName]["helperLimit"] = 1 +variants[varName]["helpers"] = {amRubber, amParachute} +variants[varName]["special"] = false + +varName = "Medic" +variants[varName] = {} +variants[varName]["chance"] = 12 +variants[varName]["hat"] = "war_desertmedic" +variants[varName]["hp"] = 120 +variants[varName]["hogLimit"] = 1 +variants[varName]["weaponLimit"] = 1 +variants[varName]["weapons"] = {amResurrector, amMine, amGasBomb} +variants[varName]["helperLimit"] = 1 +variants[varName]["helpers"] = {amTeleport, amParachute} +variants[varName]["special"] = false + +varName = "Ninja" +variants[varName] = {} +variants[varName]["chance"] = 8 +variants[varName]["hat"] = "NinjaTriangle" +variants[varName]["hp"] = 80 +variants[varName]["hogLimit"] = 2 +variants[varName]["weaponLimit"] = 1 +variants[varName]["weapons"] = {amSMine, amMine, amFirePunch} +variants[varName]["helperLimit"] = 1 +variants[varName]["helpers"] = {amRope, amParachute} +variants[varName]["special"] = false + +varName = "Athlete" +variants[varName] = {} +variants[varName]["chance"] = 8 +variants[varName]["hat"] = "footballhelmet" +variants[varName]["hp"] = 80 +variants[varName]["hogLimit"] = 1 +variants[varName]["weaponLimit"] = 1 +variants[varName]["weapons"] = {amBaseballBat, amFirePunch, amSeduction} +variants[varName]["helperLimit"] = 1 +variants[varName]["helpers"] = {amRope, amPickHammer} +variants[varName]["special"] = false + +varName = "Scientist" +variants[varName] = {} +variants[varName]["chance"] = 7 +variants[varName]["hat"] = "doctor" +variants[varName]["hp"] = 80 +variants[varName]["hogLimit"] = 1 +variants[varName]["weaponLimit"] = 1 +variants[varName]["weapons"] = {amPortalGun, amSineGun, amIceGun} +variants[varName]["helperLimit"] = 1 +variants[varName]["helpers"] = {amTeleport, amJetpack} +variants[varName]["special"] = false + +varName = "Air-General" +variants[varName] = {} +variants[varName]["chance"] = 5 +variants[varName]["hat"] = "war_desertofficer" +variants[varName]["hp"] = 50 +variants[varName]["hogLimit"] = 1 +variants[varName]["weaponLimit"] = 1 +variants[varName]["weapons"] = {amMineStrike, amNapalm, amAirAttack} +variants[varName]["helperLimit"] = 1 +variants[varName]["helpers"] = {amRope, amParachute} +variants[varName]["special"] = true + +varName = "Hunter" +variants[varName] = {} +variants[varName]["chance"] = 10 +variants[varName]["hat"] = "Skull" +variants[varName]["hp"] = 100 +variants[varName]["hogLimit"] = 1 +variants[varName]["weaponLimit"] = 1 +variants[varName]["weapons"] = {amBee, amMortar, amDrill} +variants[varName]["helperLimit"] = 1 +variants[varName]["helpers"] = {amRope, amParachute} +variants[varName]["special"] = false + +varName = "King" +variants[varName] = {} +variants[varName]["chance"] = 3 +variants[varName]["hat"] = "crown" +variants[varName]["hp"] = 60 +variants[varName]["hogLimit"] = 1 +variants[varName]["weaponLimit"] = 1 +variants[varName]["weapons"] = {amWatermelon, amHellishBomb, amBallgun} +variants[varName]["helperLimit"] = 1 +variants[varName]["helpers"] = {amRope, amParachute} +variants[varName]["special"] = true + +varName = "Knight" +variants[varName] = {} +variants[varName]["chance"] = 0 +variants[varName]["hat"] = "knight" +variants[varName]["hp"] = 80 +variants[varName]["hogLimit"] = 1 +variants[varName]["weaponLimit"] = 1 +variants[varName]["weapons"] = {amShotgun, amBazooka, amMine} +variants[varName]["helperLimit"] = 1 +variants[varName]["helpers"] = {amParachute, amRope} +variants[varName]["special"] = true + +--[[ + ############################################################################## + ### GENERAL VARIABLES USED FOR GAMEPLAY ### + ############################################################################## +]]-- + +local unused = {amSnowball, amDrillStrike, amTardis} +local lowWeaps = {amKamikaze} +local lowTresh = 25 + +local counter = {} -- Saves how many hogs of a variant a team has +local group = {} -- Saves randomized variants for all teams +local teamIndex = {} -- Temporary counter for amount of mutated hogs in team +local teamHogs = {} -- Saves a list of all hogs belonging to a team +local hogCount = {} -- Saves how many hogs a team has +local teamNames = {} -- Saves all teams and names +local hogInfo = {} -- Saves all hogs with their original values + +local LastHog = nil -- Last Hedgehog +local CurHog = nil -- Current Hedgehog +local LastTeam = nil -- Last Team +local CurTeam = nil -- Current Team +local TurnEnded = true -- Boolean whether current turn ended or not + +local mode = 'default' -- Which game type to play +local luck = 100 -- Multiplier for bonuses like crates +local strength = 1 -- Multiplier for more weapons +local mutate = false -- Whether or not to mutate the hogs + +local highHasBonusWeps = false -- whether or not a hog got bonus weapons on current turn +local highHasBonusHelp = false -- whether or not a hog got bonus helpers on current turn +local highPickupCount = 1 +local highPickupSDCount = 2 +local highHelperCount = 1 +local highHelperSDCount = 1 +local highEnemyKillHPBonus = 10 +local highFriendlyKillHPBonus = 15 +local highWeapons = {} -- Saves the weapons from kills +local highHelpers = {} -- Saves the helpers from kills +local highSpecialBonus = {amTeleport, amJetpack} +local highSpecialPool = {amExtraDamage, amVampiric} + +local kingLinkPerc = 50 -- Percentage of life to share from the team + +local pointsWepBase = 5 -- Game start points weapons +local pointsHlpBase = 2 -- Game start points helpers +local pointsKeepPerc = 80 -- Percentage of points to take to next round +local pointsWepTurn = 5 -- Round bonus points weapons +local pointsHlpTurn = 2 -- Round bonus points helpers +local pointsWepMax = 25 -- Maximum points for weapons +local pointsHlpMax = 10 -- Maximum points for helpers +local pointsKeepSDPerc = 60 -- Percentage of points to take to next round on SD +local pointsWepSDTurn = 7 -- Round bonus points weapons on SD +local pointsHlpSDTurn = 3 -- Round bonus points helpers on SD +local pointsWepSDMax = 35 -- Maximum points for weapons on SD +local pointsHlpSDMax = 15 -- Maximum points for helpers on SD + +local pointsWeaponVal = {} +pointsWeaponVal[amBazooka] = 5 +pointsWeaponVal[amShotgun] = 4 +pointsWeaponVal[amFirePunch] = 3 +pointsWeaponVal[amMine] = 5 +--pointsWeaponVal[amAirAttack] = 10 +pointsWeaponVal[amBee] = 6 +pointsWeaponVal[amClusterBomb] = 7 +pointsWeaponVal[amGrenade] = 5 +pointsWeaponVal[amDEagle] = 3 +pointsWeaponVal[amWhip] = 3 +pointsWeaponVal[amDynamite] = 7 +--pointsWeaponVal[amMineStrike] = 14 +pointsWeaponVal[amMortar] = 4 +pointsWeaponVal[amWatermelon] = 30 +pointsWeaponVal[amSniperRifle] = 3 +pointsWeaponVal[amBaseballBat] = 3 +pointsWeaponVal[amCake] = 7 +--pointsWeaponVal[amNapalm] = 11 +pointsWeaponVal[amDrill] = 6 +pointsWeaponVal[amHellishBomb] = 20 +pointsWeaponVal[amSineGun] = 4 +--pointsWeaponVal[amKamikaze] = 3 +--pointsWeaponVal[amBallgun] = 12 +--pointsWeaponVal[amPianoStrike] = 15 +pointsWeaponVal[amSnowball] = 2 +pointsWeaponVal[amMolotov] = 3 +pointsWeaponVal[amFlamethrower] = 4 +pointsWeaponVal[amRCPlane] = 7 +--pointsWeaponVal[amDrillStrike] = 12 +pointsWeaponVal[amGasBomb] = 2 +pointsWeaponVal[amHammer] = 3 +pointsWeaponVal[amSMine] = 4 +pointsWeaponVal[amAirMine] = 3 +pointsWeaponVal[amKnife] = 3 +pointsWeaponVal[amPortalGun] = 5 +--pointsWeaponVal[amIceGun] = 6 +pointsWeaponVal[amSeduction] = 2 + +local pointsHelperVal = {} +pointsHelperVal[amRope] = 5 +pointsHelperVal[amParachute] = 2 +--pointsHelperVal[amGirder] = 3 +pointsHelperVal[amBlowTorch] = 2 +pointsHelperVal[amLowGravity] = 3 +--pointsHelperVal[amRubber] = 4 +pointsHelperVal[amPickHammer] = 2 +pointsHelperVal[amTeleport] = 10 +pointsHelperVal[amJetpack] = 8 + +local pointsPerTeam = {} +local pointsToWep = {} -- List of [points] = {ammo1, ammo2} +local pointsToHlp = {} -- List of [points] = {ammo1, ammo2} +local wepPoints = {} +local hlpPoints = {} + +local suddenDeath = false + +local healthCrateChance = 7 +local utilCrateChance = 9 +local weaponCrateChance = 12 + +local healthCrateChanceSD = 12 +local utilCrateChanceSD = 16 +local weaponCrateChanceSD = 21 + +local emptyCrateChance = 7 +local bonusCrateChance = 5 +local cratePickupGap = 35 + +local utilities = {amInvulnerable, amVampiric, amExtraTime, amExtraDamage, amRope, amLandGun} +local autoSelectHelpers = {amRope, amParachute} + +local LastWaterLine = 0 -- Saves WaterLine to make sure a water rise wont trigger highland kill + +local helpers = {} +helpers[amSkip] = true +helpers[amRope] = true +helpers[amParachute] = true +helpers[amBlowTorch] = true +helpers[amGirder] = true +helpers[amTeleport] = true +helpers[amSwitch] = true +helpers[amJetpack] = true +helpers[amBirdy] = true +helpers[amPortalGun] = true +helpers[amResurrector] = true +helpers[amTardis] = true +helpers[amLandGun] = true +helpers[amRubber] = true +--helpers[amKamikaze] = true + +local posCaseAmmo = 1 +local posCaseHealth = 2 +local posCaseUtility = 4 +local posCaseDummy = 8 + +--[[ + ############################################################################## + ### GENERAL BONUS LUA FUNCTIONS ### + ############################################################################## +]]-- + +function swap(array, index1, index2) + array[index1], array[index2] = array[index2], array[index1] +end + +function shuffle(array) + local cnt = #array + while cnt > 1 do + local index = GetRandom(cnt) +1 + swap(array, index, cnt) + cnt = cnt - 1 + end +end + +function table.clone(org) + local copy = {} + for orig_key, orig_value in pairs(org) do + copy[orig_key] = orig_value + end + return copy +end + +--[[ + ############################################################################## + ### WEAPON, UTILITY AND AMMO FUNCTIONS ### + ############################################################################## +]]-- + +function clearHogAmmo(hog) + local lastNum = amRubber + + if amAirMine ~= nil then + lastNum = amAirMine + end + + for val=0,lastNum do + AddAmmo(hog, val, 0) + end +end + +function autoSelectAmmo(hog, var) + -- Check if hog has any "useful" helper, select helper, if yes + for key, val in pairs(autoSelectHelpers) do + if GetAmmoCount(hog, val) > 0 then + SetWeapon(val) + return + end + end +end + +function AddHogAmmo(hog, ammo) + -- Add weapons of variant + --for key, val in pairs(variants[var]["weapons"]) do + for key, val in pairs(ammo) do + --AddAmmo(hog, val, 1) + AddAmmo(hog, val, GetAmmoCount(hog, val) +1) + end +end + +function GetRandomAmmo(hog, sourceType) + local var = getHogInfo(hog, 'variant') + ammo = {} + local source = '' + + if variants[var] == nil then + return ammo + end + + if sourceType == "weapons" then + source = variants[var][sourceType] + sourceLimit = variants[var]["weaponLimit"] + elseif sourceType == "helpers" then + source = variants[var][sourceType] + sourceLimit = variants[var]["helperLimit"] + elseif sourceType == 'poolWeapons' then + if highWeapons[hog] == nil then + highWeapons[hog] = {} + end + source = highWeapons[hog] + if suddenDeath == false then + sourceLimit = highPickupCount + else + sourceLimit = highPickupSDCount + end + elseif sourceType == 'poolHelpers' then + if highHelpers[hog] == nil then + highHelpers[hog] = {} + end + source = highHelpers[hog] + if suddenDeath == false then + sourceLimit = highHelperCount + else + sourceLimit = highHelperSDCount + end + else + return ammo + end + + local varAmmo = {} + for key, val in pairs(source) do + varAmmo[key] = val + end + + -- If the amount of random weapons is equally to the amount of weapons possible + -- We don't need to randomize + if sourceLimit >= table.getn(source) then + return varAmmo + end + + local randIndex = 0 + local i = 0 + while i < sourceLimit and #varAmmo > 0 do + randIndex = GetRandom(#varAmmo) +1 + ammo[i] = varAmmo[randIndex] + + -- Shift last value to the current index + varAmmo[randIndex] = varAmmo[#varAmmo] + -- And remove the last index from the array + varAmmo[#varAmmo] = nil + i = i +1 + end + + return ammo +end + +function addTurnAmmo(hog) + -- Check if hog is valid + if hog == nil then + return + end + + -- Check if hog is alive + local hp = GetHealth(hog) + if hp == nil or hp <= 0 then + return + end + + -- Unless its points mode, get weapons normally by variant + if mode ~= "points" then + local maxHp = getHogInfo(hog, 'maxHp') + local hpPer = div(hp * 100, maxHp) + + local wep = getHogInfo(hog, 'weapons') + local hlp = getHogInfo(hog, 'helpers') + + if wep == nil or table.getn(wep) == 0 then + hogInfo[hog]['weapons'] = GetRandomAmmo(hog, "weapons") + wep = getHogInfo(hog, 'weapons') + end + + if hlp == nil or table.getn(hlp) == 0 then + hogInfo[hog]['helpers'] = GetRandomAmmo(hog, "helpers") + hlp = getHogInfo(hog, 'helpers') + end + + AddHogAmmo(hog, wep) + AddHogAmmo(hog, hlp) + + if mode == 'highland' then + local poolWeapons = GetRandomAmmo(hog, 'poolWeapons') + local poolHelpers = GetRandomAmmo(hog, 'poolHelpers') + + AddHogAmmo(hog, poolWeapons) + AddHogAmmo(hog, poolHelpers) + end + + if hpPer < lowTresh or suddenDeath == true then + AddHogAmmo(hog, lowWeaps) + end + -- We are on points mode, so we need to generate weapons based on points + else + setupPointsAmmo(hog) + end + + AddAmmo(hog, amSkip, -1) +end + +function setupPointsAmmo(hog) + local teamName = getHogInfo(hog, 'team') + local turnWepPoints = pointsPerTeam[teamName]['weapons'] + local turnHlpPoints = pointsPerTeam[teamName]['helpers'] + local weps = {} + local help = {} + + local wepPointsTmp = table.clone(wepPoints) + local wepMinPnt = wepPointsTmp[1] + local wepMaxPnt = wepPointsTmp[#wepPointsTmp] + + --AddCaption("Hog: " .. hog .. " Wep: " .. turnWepPoints .. " - Hlp: " .. turnHlpPoints, GetClanColor(GetHogClan(CurHog)), capgrpGameState) + --WriteLnToConsole("BEFORE ## Team: " .. teamName .. " Wep: " .. pointsPerTeam[teamName]['weapons'] .. " - Hlp: " .. pointsPerTeam[teamName]['helpers']) + + while true do + if turnWepPoints < wepMinPnt then + break + end + + if wepPointsTmp[#wepPointsTmp] > turnWepPoints then + while wepPointsTmp[#wepPointsTmp] > turnWepPoints do + table.remove(wepPointsTmp) + end + wepMaxPnt = turnWepPoints + end + + local randPoint = wepPointsTmp[GetRandom(#wepPointsTmp) +1] + local randWepList = pointsToWep[randPoint] + local randWep = randWepList[GetRandom(#randWepList) +1] + + table.insert(weps, randWep) + turnWepPoints = turnWepPoints -randPoint + end + + local hlpPointsTmp = table.clone(hlpPoints) + local hlpMinPnt = hlpPointsTmp[1] + local hlpMaxPnt = hlpPointsTmp[#hlpPointsTmp] + + while true do + if turnHlpPoints < hlpMinPnt then + break + end + + if hlpPointsTmp[#hlpPointsTmp] > turnHlpPoints then + while hlpPointsTmp[#hlpPointsTmp] > turnHlpPoints do + table.remove(hlpPointsTmp) + end + hlpMaxPnt = turnHlpPoints + end + + local randPoint = hlpPointsTmp[GetRandom(#hlpPointsTmp) +1] + local randHlpList = pointsToHlp[randPoint] + local randHlp = randHlpList[GetRandom(#randHlpList) +1] + + table.insert(help, randHlp) + turnHlpPoints = turnHlpPoints -randPoint + end + + AddHogAmmo(hog, weps) + AddHogAmmo(hog, help) + + -- Save remaining points + pointsPerTeam[teamName]['weaponsRem'] = turnWepPoints + pointsPerTeam[teamName]['helpersRem'] = turnHlpPoints + + -- Save already collected points so that they wont be "taxed" + pointsPerTeam[teamName]['weaponsFix'] = pointsPerTeam[teamName]['weapons'] + pointsPerTeam[teamName]['helpersFix'] = pointsPerTeam[teamName]['helpers'] + + --WriteLnToConsole("AFTER ## Team: " .. teamName .. " Wep: " .. pointsPerTeam[teamName]['weapons'] .. " - Hlp: " .. pointsPerTeam[teamName]['helpers']) +end + +--[[ + ############################################################################## + ### HOG SETUP FUNCTIONS ### + ############################################################################## +]]-- + +function MutateHog(hog) + local var = getHogInfo(hog, 'variant') + + SetHogName(hog, var) + SetHogHat(hog, variants[var]["hat"]) +end + +function GetRandomVariant() + local maxNum = 0 + + for key, val in pairs(variants) do + maxNum = maxNum + variants[key]["chance"] + end + + local rand = GetRandom(maxNum) + local lowBound = 0 + local highBound = 0 + local var = nil + + for key, val in pairs(variants) do + highBound = lowBound + variants[key]["chance"] + if rand <= highBound then + var = key + break + end + lowBound = highBound + end + + return var +end + +function addRandomVariantToTeam(team) + if counter[team] == nil then + counter[team] = {} + end + + while true do + local var = GetRandomVariant() + if counter[team][var] == nil and variants[var]["hogLimit"] > 0 then + counter[team][var] = 1 + break + elseif counter[team][var] ~= nil and counter[team][var] < variants[var]["hogLimit"] then + counter[team][var] = counter[team][var] +1 + break + end + end + + return var +end + +function setTeamHogs(team) + local maxHog = hogCount[team] + + group[team] = {} + counter[team] = {} + + if mode == 'king' then + maxHog = maxHog -1 + end + + for i=1,maxHog do + table.insert(group[team], group['all'][i]) + end + + if mode == 'king' then + counter[team]['King'] = 1 + table.insert(group[team], 'King') + end +end + +function countTeamHogs(hog) + local team = GetHogTeamName(hog) + + if hogCount[team] == nil then + hogCount[team] = 1 + teamHogs[team] = {} + else + hogCount[team] = hogCount[team] +1 + end + + teamHogs[team][hogCount[team]] = hog + + teamNames[team] = 1 +end + +function setHogVariant(hog) + local team = getHogInfo(hog, 'team') + + if teamIndex[team] == nil then + teamIndex[team] = 1 + else + teamIndex[team] = teamIndex[team] +1 + end + + local hogNum = teamIndex[team] + local hogVar = group[team][hogNum] + + hogInfo[hog]['variant'] = hogVar + SetHealth(hog, variants[hogVar]["hp"]) +end + +function getHogInfo(hog, info) + if hog == nil then + AddCaption(loc("ERROR [getHogInfo]: Hog") .. hog .. " is nil!", 0xFFFFFFFF, capgrpMessage) + WriteLnToConsole(loc("ERROR [getHogInfo]: Hog") .. hog .. " is nil!") + return + end + + if hogInfo[hog] == nil then + return nil + end + + return hogInfo[hog][info] +end + +function setHogInfo(hog) + if hog == nil then + AddCaption(loc("ERROR [setHogInfo]: Hog") .. hog .. " is nil!", 0xFFFFFFFF, capgrpMessage) + WriteLnToConsole(loc("ERROR [setHogInfo]: Hog") .. hog .. " is nil!") + return + end + + hogInfo[hog] = {} + hogInfo[hog]['maxHp'] = GetHealth(hog) + hogInfo[hog]['name'] = GetHogName(hog) + hogInfo[hog]['hat'] = GetHogHat(hog) + hogInfo[hog]['team'] = GetHogTeamName(hog) + hogInfo[hog]['clan'] = GetHogClan(hog) + hogInfo[hog]['clanColor'] = GetClanColor(hogInfo[hog]['clan']) +end + +--[[ + ############################################################################## + ### CRATE SPAWN AND PICKUP FUNCTIONS ### + ############################################################################## +]]-- + +--[[ + : Heals either 10 (95% chance) or 15 (5% chance) hitpoints + : Plus 10% of the hogs base hitpoints. + : + : Has a 7% chance to be empty. +]]-- +function onHealthCratePickup() + local factor = 2 + local msgColor = getHogInfo(CurHog, 'clanColor') + local healHp = 0 + PlaySound(sndShotgunReload) + + if GetRandom(100) < emptyCrateChance then + AddCaption(loc("empty crate"), msgColor, capgrpMessage) + return + elseif GetRandom(100) < bonusCrateChance then + factor = 3 + end + + local var = getHogInfo(CurHog, 'variant') + local hogHealth = GetHealth(CurHog) + healHp = 5 * factor + + -- Add extra 10% of hogs base hp to heal + healHp = healHp + div(getHogInfo(CurHog, 'maxHp'), 10) + + AddCaption(loc("+ ") .. healHp .. loc(" hp"), msgColor, capgrpMessage) + + SetEffect(CurHog, hePoisoned, 0) + SetHealth(CurHog, hogHealth + healHp) + local effect = AddVisualGear(GetX(CurHog), GetY(CurHog) +cratePickupGap, vgtHealthTag, healHp, false) + -- (vgUid, X, Y, dX, dY, Angle, Frame, FrameTicks, State, Timer, Tint) + SetVisualGearValues(effect, nil, nil, nil, nil, nil, nil, nil, nil, nil, msgColor) +end + +--[[ + : Adds either 1 (95% chance) or 2 (5% chance) random weapon(s) based on the hog variant. + : + : Has a 7% chance to be empty. +]]-- +function onWeaponCratePickup() + local factor = 1 * strength + local msgColor = GetClanColor(GetHogClan(CurHog)) + PlaySound(sndShotgunReload) + + if GetRandom(100) < emptyCrateChance then + AddCaption(loc("empty crate"), msgColor, capgrpMessage) + return + elseif GetRandom(100) < bonusCrateChance then + factor = 2 * strength + end + + local randIndex + local randAmmo + + if mode ~= 'points' then + local var = getHogInfo(CurHog, 'variant') + randIndex = GetRandom(table.getn(variants[var]["weapons"])) +1 + randAmmo = variants[var]["weapons"][randIndex] + else + local possibleWeapons = {} + + for key, val in pairs(pointsWeaponVal) do + if val > 2 and val < 8 then + table.insert(possibleWeapons, key) + end + end + + randIndex = GetRandom(table.getn(possibleWeapons)) +1 + randAmmo = possibleWeapons[randIndex] + end + + AddCaption(loc("+ ") .. factor .. loc(" ammo"), msgColor, capgrpMessage) + + AddAmmo(CurHog, randAmmo, GetAmmoCount(CurHog, randAmmo) +factor) + local effect = AddVisualGear(GetX(CurHog), GetY(CurHog) +cratePickupGap, vgtAmmo, 0, true) + -- (vgUid, X, Y, dX, dY, Angle, Frame, FrameTicks, State, Timer, Tint) + SetVisualGearValues(effect, nil, nil, nil, nil, nil, randAmmo, nil, nil, nil, msgColor) +end +--[[ + : Adds either 1 (95% chance) or 2 (5% chance) random helper(s) based on the hog variant. + : + : Has a 7% chance to be empty. +]]-- +function onUtilityCratePickup() + local factor = 1 * strength + local msgColor = GetClanColor(GetHogClan(CurHog)) + PlaySound(sndShotgunReload) + + if GetRandom(100) < emptyCrateChance then + AddCaption(loc("empty crate"), msgColor, capgrpMessage) + return + elseif GetRandom(100) < bonusCrateChance then + factor = 2 * strength + end + + local randIndex + local randUtility + + if mode ~= 'points' then + randIndex = GetRandom(table.getn(utilities)) +1 + randUtility = utilities[randIndex] + else + local possibleHelpers = {} + + for key, val in pairs(pointsHelperVal) do + table.insert(possibleHelpers, key) + end + + randIndex = GetRandom(table.getn(possibleHelpers)) +1 + randUtility = possibleHelpers[randIndex] + end + + AddCaption(loc("+ ") .. factor .. loc(" ammo"), msgColor, capgrpMessage) + + AddAmmo(CurHog, randUtility, GetAmmoCount(CurHog, randUtility) +factor) + local effect = AddVisualGear(GetX(CurHog), GetY(CurHog) +cratePickupGap, vgtAmmo, 0, true) + -- (vgUid, X, Y, dX, dY, Angle, Frame, FrameTicks, State, Timer, Tint) + SetVisualGearValues(effect, nil, nil, nil, nil, nil, randUtility, nil, nil, nil, msgColor) +end + +function onPickupCrate(crate) + local pos = GetGearPos(crate) + + -- Check if the crate is fake + if pos % posCaseDummy >= 1 then + if pos % posCaseDummy == posCaseAmmo then + onWeaponCratePickup() + elseif pos % posCaseDummy == posCaseHealth then + onHealthCratePickup() + elseif pos % posCaseDummy == posCaseUtility then + onUtilityCratePickup() + end + end +end + +function RandomTurnEvents() + if GetRandom(100) < weaponCrateChance then + SpawnFakeAmmoCrate(0, 0, false, false) + return 5000 + elseif GetRandom(100) < utilCrateChance then + SpawnFakeUtilityCrate(0, 0, false, false) + return 5000 + elseif GetRandom(100) < healthCrateChance then + SpawnFakeHealthCrate(0, 0, false, false) + return 5000 + end + return 0 +end + +--[[ + ############################################################################## + ### SUDDEN DEATH FUNCTIONS ### + ############################################################################## +]]-- + +function onSuddenDeathDamage(hog) + local hp = GetHealth(hog) + local maxHp = getHogInfo(hog, 'maxHp') + local newHp = 0 + local hpDec = 0 + local hpPer = div(hp * 100, maxHp) + + if hp > 1 then + local msgColor = GetClanColor(GetHogClan(hog)) + if hpPer <= 25 then + newHp = hp -2 + elseif hpPer <= 50 then + newHp = hp -3 + elseif hpPer <= 75 then + newHp = hp -4 + elseif hpPer <= 100 then + newHp = hp -5 + elseif hpPer <= 125 then + newHp = hp -6 + elseif hpPer <= 150 then + newHp = hp -7 + else + newHp = div(hp * 93, 100) + end + + if newHp <= 0 then + newHp = 1 + end + + hpDec = hp - newHp + + SetHealth(hog, newHp) + local effect = AddVisualGear(GetX(hog), GetY(hog) +cratePickupGap, vgtHealthTag, hpDec, false) + SetVisualGearValues(effect, nil, nil, nil, nil, nil, nil, nil, nil, nil, msgColor) + end +end + +function onSuddenDeathTurn() + runOnGears(onSuddenDeathDamage) +end + +function onSuddenDeath() + suddenDeath = true + + healthCrateChance = healthCrateChanceSD + utilCrateChance = utilCrateChanceSD + weaponCrateChance = weaponCrateChanceSD + + if mode == 'highland' then + highEnemyKillHPBonus = highEnemyKillHPBonus +5 + highFriendlyKillHPBonus = highFriendlyKillHPBonus +10 + end + + if mode ~= 'points' then + for key, val in pairs(variants) do + if not variants[key]["special"] then + variants[key]["weaponLimit"] = variants[key]["weaponLimit"] +1 + end + end + end + + if mode ~= 'points' then + for hog, val in pairs(hogInfo) do + hogInfo[hog]['weapons'] = {} + hogInfo[hog]['helpers'] = {} + end + + runOnGears(setupHogTurn) + end +end + +--[[ + ############################################################################## + ### GEAR TRACKING FUNCTIONS ### + ############################################################################## +]]-- + +function onGearAdd(gear) + local gearType = GetGearType(gear) + + if gearType == gtHedgehog then + trackGear(gear) + elseif gearType == gtRCPlane then + -- Limit bombs to 1 until 0.9.23 is released + SetHealth(gear, 1) + elseif gearType == gtAirBomb then + -- gearUid, Angle, Power, WDTimer, Radius, Density, Karma, DirAngle, AdvBounce, ImpactSound, ImpactSounds, Tint, Damage, Boom + SetGearValues(gear, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 15) + elseif gearType == gtCake then + -- gearUid, Angle, Power, WDTimer, Radius, Density, Karma, DirAngle, AdvBounce, ImpactSound, ImpactSounds, Tint, Damage, Boom + SetGearValues(gear, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 50) + elseif gearType == gtDEagleShot then + -- gearUid, Angle, Power, WDTimer, Radius, Density, Karma, DirAngle, AdvBounce, ImpactSound, ImpactSounds, Tint, Damage, Boom + SetGearValues(gear, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 12) + end +end + +function onHighlandKill(gear) + local deathVar = getHogInfo(gear, 'variant') + local killVar = getHogInfo(CurHog, 'variant') + local bonAmmo = {} + local deathMaxHP = getHogInfo(gear, 'maxHp') + local curHP = GetHealth(CurHog) + local newHP = 0 + local hpDiff = 0 + local addAmmo = false + + -- Killer hog is dead! Don't do anything + if curHP == nil or curHP <= 0 then + return + end + + -- Killer and victim is equal! Don't do anything + if CurHog == gear then + return + end + + -- Hog drowned because of water, not enemy + if LastWaterLine ~= WaterLine then + return + end + + -- Enemy kill! Add weapons to pool and to hog + if getHogInfo(gear, 'clan') ~= getHogInfo(CurHog, 'clan') then + + -- Initialize weapons if required + if highWeapons[CurHog] == nil then + highWeapons[CurHog] = {} + end + + if highHelpers[CurHog] == nil then + highHelpers[CurHog] = {} + end + + -- If not a special hog, use the victims weapons + if variants[deathVar]['special'] == false then + bonAmmo = variants[deathVar]['weapons'] + + if suddenDeath == true then + ammoCount = highPickupSDCount + else + ammoCount = highPickupCount + end + + -- Check if hog already got bonus weapons + if table.getn(highWeapons[CurHog]) == 0 and highHasBonusWeps == false then + highHasBonusWeps = true + addAmmo = true + end + + -- Pass turn bonus weapons to hog pool + for key, val in pairs(bonAmmo) do + local idx = table.getn(highWeapons[CurHog]) +1 + highWeapons[CurHog][idx] = val + end + -- It's a special hog, use special pool + else + bonAmmo = highSpecialBonus + + ammoCount = 1 + + -- Check if hog already got bonus helpers + if table.getn(highWeapons[CurHog]) == 0 and highHasBonusHelp == false then + highHasBonusHelp = true + addAmmo = true + end + + -- Pass turn bonus weapons to hog pool + for key, val in pairs(highSpecialPool) do + local idx = table.getn(highHelpers[CurHog]) +1 + highHelpers[CurHog][idx] = val + end + end + + if addAmmo then + local i = 1 + while i <= ammoCount and #bonAmmo > 0 do + local randAmmo = GetRandom(#bonAmmo) +1 + local randAmmoType = bonAmmo[randAmmo] + + -- Remove the randomized weapon so it cannot be picked up twice + table.remove(bonAmmo, randAmmo) + + AddAmmo(CurHog, randAmmoType, GetAmmoCount(CurHog, randAmmoType) +1) + + local effect = AddVisualGear(GetX(CurHog), GetY(CurHog) + (cratePickupGap * i), vgtAmmo, 0, true) + -- (vgUid, X, Y, dX, dY, Angle, Frame, FrameTicks, State, Timer, Tint) + SetVisualGearValues(effect, nil, nil, nil, nil, nil, randAmmoType, nil, nil, nil, nil) + + i = i +1 + end + end + + hpDiff = div(deathMaxHP * highEnemyKillHPBonus, 100) + newHP = curHP + hpDiff + SetHealth(CurHog, newHP) + + local effect = AddVisualGear(GetX(CurHog), GetY(CurHog) - cratePickupGap, vgtHealthTag, hpDiff, false) + -- (vgUid, X, Y, dX, dY, Angle, Frame, FrameTicks, State, Timer, Tint) + SetVisualGearValues(effect, nil, nil, nil, nil, nil, nil, nil, nil, nil, GetClanColor(GetHogClan(CurHog))) + -- Friendly fire! Remove all weapons and helpers from pool + else + highWeapons[CurHog] = {} + highHelpers[CurHog] = {} + + hpDiff = div(deathMaxHP * highFriendlyKillHPBonus, 100) + newHP = curHP - hpDiff + if newHP > 0 then + SetHealth(CurHog, newHP) + else + SetHealth(CurHog, 0) + end + + local effect = AddVisualGear(GetX(CurHog), GetY(CurHog) - cratePickupGap, vgtHealthTag, hpDiff, false) + -- (vgUid, X, Y, dX, dY, Angle, Frame, FrameTicks, State, Timer, Tint) + SetVisualGearValues(effect, nil, nil, nil, nil, nil, nil, nil, nil, nil, GetClanColor(GetHogClan(CurHog))) + end +end + +function onKingDeath(KingHog) + local team = getHogInfo(KingHog, 'team') + local msgColor = getHogInfo(KingHog, 'clanColor') + + AddCaption(team .. loc("s king died"), msgColor, capgrpGameState) + PlaySound(sndByeBye) + DismissTeam(team) + + -- for hog, val in pairs(hogInfo) do + -- if getHogInfo(hog, 'team') == team then + -- hp = GetHealth(hog) + -- if hp ~= nil and hp > 0 then + -- SetState(KingHog, gstHHDeath) + -- SetHealth(hog, 0) + -- SetGearValues(hog, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0) + -- end + -- end + -- end +end + +function onPointsKill(gear) + local deathVar = getHogInfo(gear, 'variant') + local killVar = getHogInfo(CurHog, 'variant') + local deathClan = getHogInfo(gear, 'clan') + local killClan = getHogInfo(CurHog, 'clan') + local team = getHogInfo(CurHog, 'team') + + local curHP = GetHealth(CurHog) + + -- Killer hog is dead! Don't do anything + if curHP == nil or curHP <= 0 then + return + end + + -- Hog drowned because of water, not enemy + if LastWaterLine ~= WaterLine then + return + end + + -- Same clan, friendly kill, skip + if killClan == deathClan then + return + end + + pointsPerTeam[team]['weapons'] = pointsPerTeam[team]['weapons'] + 2 + pointsPerTeam[team]['helpers'] = pointsPerTeam[team]['helpers'] + 1 + + local effect = AddVisualGear(GetX(CurHog) - (cratePickupGap / 2), GetY(CurHog), vgtHealthTag, 2, false) + -- (vgUid, X, Y, dX, dY, Angle, Frame, FrameTicks, State, Timer, Tint) + SetVisualGearValues(effect, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0xFFFFFFFF) + + local effect = AddVisualGear(GetX(CurHog) + (cratePickupGap / 2), GetY(CurHog), vgtHealthTag, 1, false) + -- (vgUid, X, Y, dX, dY, Angle, Frame, FrameTicks, State, Timer, Tint) + SetVisualGearValues(effect, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0x444444FF) +end + +function onGearDelete(gear) + trackDeletion(gear) + + if GetGearType(gear) == gtCase and band(GetGearMessage(gear), gmDestroy) ~= 0 then + onPickupCrate(gear) + end + + if GetGearType(gear) == gtHedgehog then + if mode ~= 'points' then + hogInfo[gear]['weapons'] = {} + hogInfo[gear]['helpers'] = {} + end + + -- If dying gear is a hog and mode is highland, check for kills + if mode == 'highland' then + onHighlandKill(gear) + -- If current hog is dying and we are on points mode, we need to save the unused weapons/helpers + elseif mode == 'points' and CurHog == gear then + savePoints(gear) + elseif mode == 'points' and CurHog ~= gear then + onPointsKill(gear) + end + + if mode == 'king' and getHogInfo(gear, 'variant') == 'King' then + onKingDeath(gear) + end + end +end + +--[[ + ############################################################################## + ### TURN BASED FUNCTIONS ### + ############################################################################## +]]-- + +function calcKingHP() + local teamKings = {} + local teamHealth = {} + + for hog, val in pairs(hogInfo) do + local hp = GetHealth(hog) + + if hp ~= nil and hp > 0 then + local team = getHogInfo(hog, 'team') + + if teamHealth[team] == nil then + teamHealth[team] = 0 + end + + if getHogInfo(hog, 'variant') == 'King' then + teamKings[team] = hog + else + teamHealth[team] = teamHealth[team] + hp + end + end + end + + for team, hog in pairs(teamKings) do + local hp = GetHealth(hog) + local newHP = div(teamHealth[team] * kingLinkPerc, 100) + local diff = newHP - hp + + -- Set hitpoints to 1 if no other hog is alive or only has 1 hitpoint + if newHP <= 0 then + newHP = 1 + diff = 0 + end + + if diff < 0 then + diff = -diff + end + + if hp ~= newHP then + SetHealth(hog, newHP) + local effect = AddVisualGear(GetX(hog), GetY(hog) - cratePickupGap, vgtHealthTag, diff, false) + -- (vgUid, X, Y, dX, dY, Angle, Frame, FrameTicks, State, Timer, Tint) + SetVisualGearValues(effect, nil, nil, nil, nil, nil, nil, nil, nil, nil, GetClanColor(GetHogClan(hog))) + end + end +end + +function setupHogTurn(hog) + clearHogAmmo(hog) + addTurnAmmo(hog) +end + +function onTurnEnd() + local anyHog = nil + for team, val in pairs(teamNames) do + -- Count amount of alive hogs in team + local c = 0 + for idx, hog in pairs(teamHogs[team]) do + if GetHealth(hog) ~= nil then + anyHog = hog + c = c + 1 + end + end + + -- Only one hog left, unfreeze the hog + if c == 1 then + if GetHealth(anyHog) ~= nil then + SetEffect(anyHog, heFrozen, 0) + end + end + end + + -- When we are on points mode count remaining weapon/helper points + if mode == 'points' and GetHealth(CurHog) ~= nil then + savePoints(CurHog) + end + + -- Run random turn events + RandomTurnEvents() +end + +function savePoints(hog) + local team = getHogInfo(hog, 'team') + local hogWepPoints = 0 + local hogHlpPoints = 0 + + for ammoType=0,amAirMine do + local ammoCount = GetAmmoCount(hog, ammoType) + + if pointsWeaponVal[ammoType] ~= nil then + hogWepPoints = hogWepPoints + (pointsWeaponVal[ammoType] * ammoCount) + elseif pointsHelperVal[ammoType] ~= nil then + hogHlpPoints = hogHlpPoints + (pointsHelperVal[ammoType] * ammoCount) + end + end + + local wepWoTax = pointsPerTeam[team]['weaponsFix'] + local hlpWoTax = pointsPerTeam[team]['helpersFix'] + local wepToTax = 0 + local hlpToTax = 0 + + if hogWepPoints <= wepWoTax then + wepWoTax = hogWepPoints + else + wepToTax = hogWepPoints - wepWoTax + end + + if hogHlpPoints <= hlpWoTax then + hlpWoTax = hogHlpPoints + else + hlpToTax = hogHlpPoints - hlpWoTax + end + + if suddenDeath == false then + pointsPerTeam[team]['weapons'] = pointsPerTeam[team]['weaponsRem'] + wepWoTax + div(wepToTax * pointsKeepPerc, 100) + pointsPerTeam[team]['helpers'] = pointsPerTeam[team]['helpersRem'] + hlpWoTax + div(hlpToTax * pointsKeepPerc, 100) + else + pointsPerTeam[team]['weapons'] = pointsPerTeam[team]['weaponsRem'] + wepWoTax + div(wepToTax * pointsKeepSDPerc, 100) + pointsPerTeam[team]['helpers'] = pointsPerTeam[team]['helpersRem'] + hlpWoTax + div(hlpToTax * pointsKeepSDPerc, 100) + end + + local effect = AddVisualGear(GetX(hog) - (cratePickupGap / 2), GetY(hog), vgtHealthTag, pointsPerTeam[team]['weapons'], false) + -- (vgUid, X, Y, dX, dY, Angle, Frame, FrameTicks, State, Timer, Tint) + SetVisualGearValues(effect, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0xFFFFFFFF) + + local effect = AddVisualGear(GetX(hog) + (cratePickupGap / 2), GetY(hog), vgtHealthTag, pointsPerTeam[team]['helpers'], false) + -- (vgUid, X, Y, dX, dY, Angle, Frame, FrameTicks, State, Timer, Tint) + SetVisualGearValues(effect, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0x444444FF) +end + +function onPointsTurn() + local hogWepPoints = 0 + local hogHlpPoints = 0 + + if suddenDeath == false then + pointsPerTeam[LastTeam]['weapons'] = pointsPerTeam[LastTeam]['weapons'] + pointsWepTurn + pointsPerTeam[LastTeam]['helpers'] = pointsPerTeam[LastTeam]['helpers'] + pointsHlpTurn + + if pointsPerTeam[LastTeam]['weapons'] > pointsWepMax then + pointsPerTeam[LastTeam]['weapons'] = pointsWepMax + end + + if pointsPerTeam[LastTeam]['helpers'] > pointsHlpMax then + pointsPerTeam[LastTeam]['helpers'] = pointsHlpMax + end + else + pointsPerTeam[LastTeam]['weapons'] = pointsPerTeam[LastTeam]['weapons'] + pointsWepSDTurn + pointsPerTeam[LastTeam]['helpers'] = pointsPerTeam[LastTeam]['helpers'] + pointsHlpSDTurn + + if pointsPerTeam[LastTeam]['weapons'] > pointsWepSDMax then + pointsPerTeam[LastTeam]['weapons'] = pointsWepSDMax + end + + if pointsPerTeam[LastTeam]['helpers'] > pointsHlpSDMax then + pointsPerTeam[LastTeam]['helpers'] = pointsHlpSDMax + end + end + + -- Take the first alive hog from LastTeam and setup new weapons and helpers + -- Since the weapons and helpers are shared the whole team, this is sufficent + for idx, teamHog in pairs(teamHogs[LastTeam]) do + if GetHealth(teamHog) ~= nil then + clearHogAmmo(teamHog) + addTurnAmmo(teamHog) + break + end + end +end + +function onNewTurn() + LastHog = CurHog + LastTeam = CurTeam + CurHog = CurrentHedgehog + CurTeam = getHogInfo(CurHog, 'team') + TurnEnded = false + + if suddenDeath == true then + onSuddenDeathTurn() + else + AddCaption(loc("Round #") .. (TotalRounds +1).. loc(" (SD on #") .. (SuddenDeathTurns +2) .. ")", getHogInfo(CurHog, 'clanColor'), capgrpGameState) + end + + -- Generate new weapons for last hog if it's still alive + if LastHog ~= nil and LastHog ~= CurHog then + if mode == 'points' then + onPointsTurn() + else + hogInfo[LastHog]['weapons'] = {} + hogInfo[LastHog]['helpers'] = {} + setupHogTurn(LastHog) + end + end + + -- Recalculate the kings hp if required + if mode == 'king' then + calcKingHP() + end + + if mode == 'highland' then + highHasBonusWeps = false + highHasBonusHelp = false + end + + -- Set LastWaterLine to the current water line + LastWaterLine = WaterLine +end + +function onGameTick20() + if TurnEnded == false and TurnTimeLeft <= 0 then + TurnEnded = true + onTurnEnd() + end +end + +--[[ + ############################################################################## + ### GAME START FUNCTIONS ### + ############################################################################## +]]-- + +function onAmmoStoreInit() + local lastNum = amAirMine + + for val=0,lastNum do + SetAmmo(val, 0, 0, 0, 0) + end +end + +function onParameters() + parseParams() + + if params['mode'] ~= nil then + mode = params['mode'] + end + + if params['mutate'] ~= nil then + mutate = params['mutate'] + end + + if params['strength'] ~= nil and tonumber(params['strength']) > 0 then + strength = tonumber(params['strength']) + -- Highland + if mode == 'highland' then + highPickupCount = highPickupCount * strength + highPickupSDCount = highPickupSDCount * strength + highHelperCount = highHelperCount * strength + highHelperSDCount = highHelperSDCount * strength + -- Points + elseif mode == 'points' then + pointsWepBase = pointsWepBase * strength + pointsHlpBase = pointsHlpBase * strength + pointsWepTurn = pointsWepTurn * strength + pointsHlpTurn = pointsHlpTurn * strength + pointsWepMax = pointsWepMax * strength + pointsHlpMax = pointsHlpMax * strength + pointsWepSDTurn = pointsWepSDTurn * strength + pointsHlpSDTurn = pointsHlpSDTurn * strength + pointsWepSDMax = pointsWepSDMax * strength + pointsHlpSDMax = pointsHlpSDMax * strength + -- Either king or normal mode, change variants + else + for name, data in pairs(variants) do + variants[name]["weaponLimit"] = variants[name]["weaponLimit"] * strength + variants[name]["helperLimit"] = variants[name]["helperLimit"] * strength + end + end + end + + if params['luck'] ~= nil and tonumber(params['luck']) > 0 then + luck = tonumber(params['luck']) + + healthCrateChance = div(healthCrateChance * luck, 100) + utilCrateChance = div(utilCrateChance * luck, 100) + weaponCrateChance = div(weaponCrateChance * luck, 100) + + healthCrateChanceSD = div(healthCrateChanceSD * luck, 100) + utilCrateChanceSD = div(utilCrateChanceSD * luck, 100) + weaponCrateChanceSD = div(weaponCrateChanceSD * luck, 100) + + emptyCrateChance = div(emptyCrateChance * 100, luck) + bonusCrateChance = div(bonusCrateChance * luck, 100) + end +end + +function onGameStart() + -- If we are not on points mode, we start randomizing everything + if mode ~= 'points' then + if GetGameFlag(gfBorder) or MapHasBorder() then + variants["Air-General"] = nil + variants['Athlete'] = nil + end + + if mode == 'king' then + variants['King']['chance'] = 0 + end + + for i=1,8 do + addRandomVariantToTeam("all") + end + + -- Translate randomized team to a flat group + group['all'] = {} + for key, val in pairs(counter["all"]) do + for i=1, counter["all"][key] do + table.insert(group['all'], key) + end + end + + -- Shuffle group for more randomness + shuffle(group['all']) + -- We are in points mode, setup other weapons + elseif mode == 'points' then + --variants['King']['chance'] = 0 + --if variants['Air-General'] ~= nil then + -- variants['Air-General']['chance'] = 0 + --end + + -- Translate [ammo] -> points to [points] -> {ammo1, ammo2} + for ammoType, ammoPoints in pairs(pointsWeaponVal) do + if pointsToWep[ammoPoints] == nil then + pointsToWep[ammoPoints] = {} + end + + table.insert(pointsToWep[ammoPoints], ammoType) + end + + for ammoType, ammoPoints in pairs(pointsHelperVal) do + if pointsToHlp[ammoPoints] == nil then + pointsToHlp[ammoPoints] = {} + end + + table.insert(pointsToHlp[ammoPoints], ammoType) + end + + for points, ammoList in pairs(pointsToWep) do + table.insert(wepPoints, points) + end + + for points, ammoList in pairs(pointsToHlp) do + table.insert(hlpPoints, points) + end + + table.sort(wepPoints) + table.sort(hlpPoints) + + -- All done, sort the table + --table.sort(pointsToWep) + --table.sort(pointsToHlp) + end + + -- Initial Hog Setup + runOnGears(countTeamHogs) + + for key, val in pairs(teamNames) do + if mode == 'points' then + pointsPerTeam[key] = {} + pointsPerTeam[key]['weapons'] = pointsWepBase + pointsPerTeam[key]['helpers'] = pointsHlpBase + else + setTeamHogs(key) + end + end + + runOnGears(setHogInfo) + + if mode ~= 'points' then + runOnGears(setHogVariant) + runOnGears(setupHogTurn) + if mutate ~= false and mutate ~= 'false' then + runOnGears(MutateHog) + end + end + + if mode == 'points' then + for key, val in pairs(teamNames) do + clearHogAmmo(teamHogs[key][1]) + addTurnAmmo(teamHogs[key][1]) + end + end + + if mode == 'king' then + calcKingHP() + end + + local txt = '' + local icon = 0 + + if mode ~= 'points' then + txt = txt .. loc("Variants: Hogs will be randomized from 12 different variants|") + txt = txt .. loc("Weapon: Hogs will get 1 out of 3 weapons randomly each turn|") + txt = txt .. loc("Helper: Hogs will get 1 out of 2 helpers randomly each turn|") + txt = txt .. loc("Crates: Crates spawn randomly with chance of being empty|") + txt = txt .. loc("Hogs: Less than 25% base hp gives +Kamikaze|") + txt = txt .. loc("Flags: Unlimited Ammo, Per Hog Ammo|") + else + txt = txt .. loc("Crates: Crates spawn randomly with chance of being empty|") + txt = txt .. loc("Flags: Unlimited Ammo, Shared Team Ammo|") + end + + if luck ~= 100 then + txt = txt .. loc("Luck: ") .. luck .. loc("% (modifier for crates)|") + end + + if strength > 1 then + txt = txt .. loc("Strength: ") .. strength .. loc(" (multiplier for ammo)|") + end + + if mode == 'highland' then + txt = txt .. loc(" |") + txt = txt .. loc("--- Highland --- |") + txt = txt .. loc("Enemy kills: Collect victims weapons and + ") .. highEnemyKillHPBonus .. loc(" % of its base health|") + txt = txt .. loc("Friendly kills: Clears killers pool and - ") .. highFriendlyKillHPBonus .. loc(" % of its base health|") + txt = txt .. loc("Turns: Hogs get ") .. highPickupCount .. loc(" random weapon(s) from their pool|") + txt = txt .. loc("Hint: Kills wont transfer a hogs pool to the killers pool|") + txt = txt .. loc("Specials: Kings and Air-General drop helpers, not weapons|") + icon = 1 -- Target + elseif mode == 'king' then + txt = txt .. loc(" |") + txt = txt .. loc("--- King --- |") + txt = txt .. loc("Variants: The last hog of each team will be a king|") + txt = txt .. loc("Turns: Kings health are set to ") .. kingLinkPerc .. loc("% of the team health|") + icon = 0 -- Golen Crown + elseif mode == 'points' then + txt = txt .. loc(" |") + txt = txt .. loc("--- Points --- |") + txt = txt .. loc("Variants: Disables King and Air-General|") + txt = txt .. loc("Weapons: Every team starts with ") .. pointsWepBase .. loc(" weapon points|") + txt = txt .. loc("Helpers: Every team starts with ") .. pointsHlpBase .. loc(" helper points|") + txt = txt .. loc("Turns: Refills ") .. pointsWepTurn .. loc(" weapon and ") .. pointsHlpTurn .. loc(" helper points|") + txt = txt .. loc(" and randomizes weapons and helpers based on team points|") + icon = 4 -- Golden Star + else + icon = -amGrenade -- Grenade + end + + --txt = txt .. "Switch: Max. 3 times a game per team, cooldown of 5 turns|" + txt = txt .. loc(" |") + txt = txt .. loc("--- Sudden Death --- |") + txt = txt .. loc("Weapons: +Kamikaze, +1 for nearly every hog variant|") + txt = txt .. loc("Crates: Crates spawn more frequently with higher chance of bonus|") + txt = txt .. loc("Water: Rises by 37 per Round|") + txt = txt .. loc("Hogs: Loose up to 7% base hp per turn|") + + if mode == 'default' then + txt = txt .. loc(' |') + txt = txt .. loc('--- Hint ---|') + txt = txt .. loc('Modes: Activate highland, king or points mode by putting mode=|') + txt = txt .. loc(' into the script params|') + end + + if mode == 'highland' then + txt = txt .. loc("Highland: Hogs get ") .. highPickupSDCount .. loc(" random weapons from their pool|") + end + + ShowMission(loc("Battalion v") .. version, loc("Less tools, more fun.") .. " (by Anachron)", txt, icon, 1000) + + -- Tell the user about the amount of rounds until sudden death + AddCaption(loc("SuddenDeathTurns set to ") .. (SuddenDeathTurns +2), 0x808080, capgrpGameState) +end + +function onGameInit() + --[[ CONFIGURATEABLE FOR PLAYERS ]]-- + --[[ ONCE IT HAS BEEN ADDED TO HW ]]-- + + --[[ REQUIRED CONFIGURATIONS ]]-- + + WaterRise = 37 -- Water rises by 37 + HealthDecrease = 0 -- No health decrease by game, script with 7% + CaseFreq = 0 -- don't spawn crates + + -- Removed gfResetWeps to see weapons next turn + EnableGameFlags(gfInfAttack) + DisableGameFlags(gfResetWeps) + + if mode ~= 'points' then + EnableGameFlags(gfPerHogAmmo) + else + DisableGameFlags(gfPerHogAmmo) + end +end