prevent qtmain from not being linked in on windows
--[[------------------------------------------------------- CONSTRUCTION MODE -----------------------------------------------------------A Hedgewars gameplay mode by mikade.Special thanks to all who helped test and offered suggestions.Additional thanks to sheepluva/nemo for adding some extra hooks.----------------------- STRUCTURES LIST -----------------------* Healing Station: Heals hogs to 150 health* Teleportation Node: Allows teleporting to any other teleporter nodes* Bio-filter: Explodes enemy hogs* Respawner: If you have one of these, any slain hogs are resurrected here* Generator: Generates power (used to buy stuff)* Support Station: Allows purchasing crates* Construction Station: Allows purchasing girders, rubber, mines, sticky mines, barrels* Reflector Shield: Reflect projectiles* Weapon Filter: Removes all equipement of enemy hogs passing through this area----------------------------------------------------------- SCRIPT PARAMETER---------------------------------------------------------The script parameter can be used to configure the energyof the game. It is a comma-seperated list of key=value pairs, where eachkey is a word and each value is an integer between 0 and 4294967295.Possible keys:* initialenergy: Amount of energy that each team starts with (default: 550) Note: Must be smaller than or equal to maxenergy* energyperround: Amount of energy that each team gets per round (default: 50)* maxenergy: Maximum amount of energy each team can hold (default: 1000)* cratesperround: Maximum number of crates you can place per round (default: 5)For the previous 2 keys, you can use the value “inf” for an unlimited amount.Example: “initialenergy=750, maxenergy=2000” starts thee game with 750 energy and sets the maximum energy to 2000.Example: “craterperround=inf” disables the crate placement limit.----------------------------------------------------------- Ideas list -----------------------------------------------------------* To make the weapon filter more attractive, make it vaporize flying saucers and also rope, and maybe incoming gears* Make healing thing also cure poison?* Maybe make poison more virulent and dangerous]]HedgewarsScriptLoad("/Scripts/Locale.lua")HedgewarsScriptLoad("/Scripts/Tracker.lua")HedgewarsScriptLoad("/Scripts/Params.lua")-- Structures stufflocal strucID = {}local strucGear = {}local strucClan = {}local strucType = {}local strucCost = {}local strucHealth = {}local strucCirc = {}local strucCircCol = {}local strucCircRadius = {}local strucAltDisplay = {}-- Clan stufflocal clanPower = {} -- current power for each clan. Used to build stufflocal clanPowerTag = nil -- visual gear ID of displayed clan powerlocal clanUsedExtraTime = {} -- has used extra time in this round?local clanCratesSpawned = {} -- number of crates spawned in this roundlocal clanFirstTurn = {}local clanBoundsSX = {}local clanBoundsSY = {}local clanBoundsEX = {}local clanBoundsEY = {}-- For tracking previous mode selection per-teamlocal teamLStructIndex = {}local teamLObjectMode = {}local teamLCrateMode = {}local teamLMineIndex = {}local teamLWeapIndex = {}local teamLUtilIndex = {}-- Wall stufflocal wallsVisible = falselocal wX = {}local wY = {}local wWidth = {}local wHeight = {}local wCol = {}local wMargin = 20local borderEffectTimer = 0 -- timer for border clan sparkles-- Other stufflocal placedExpense = 0 -- Cost of current selected thinglocal curWep = amNothing -- current weapon, used to reduce # of calls to GetCurAmmoType()local fortMode = false -- is using a fort map?local tempID_CheckProximity = nil -- temporary structure variable for CheckProximitylocal cGear = nil -- detects placement of girders and objects (using airattack)local uniqueStructureID = 0 -- Counter and ID for structures. Is incremented each time a structure spawns-- Colorslocal colorSupportStation = 0xFFFF00FFlocal colorConstructionStation = 0xFFFFFFFFlocal colorTeleportationNode = 0x0000FFFFlocal colorHealingStation = 0xFF808040 -- Just a slight glowlocal colorBioFilter = 0xFF0000FFlocal colorReflectorShield = 0xFFAE00FFlocal colorWeaponFilter = 0xA800FFFFlocal colorHealingStationParticle = 0x00FF0080local colorGeneratorParticle = 0xFFFF00FFlocal colorMessageError = capcolDefault-- Fake ammo types, for the overwritten weapons in Construction Modelocal amCMStructurePlacer = amAirAttacklocal amCMCratePlacer = amMineStrikelocal amCMObjectPlacer = amNapalm-- Config variables (script parameter)-- NOTE: If you change this, also change the default game scheme “Construction Mode”local conf_initialEnergy = 550local conf_energyPerRound = 50local conf_maxEnergy = 1000local conf_cratesPerRound = 5------------------------- CRATE DEFINITIONS --------------------------- format:-- { ammoType, cost }local costFactor = 20-- WEAPON CRATES-- Weapons which shouldn't be aded:-- Air attack, napalm, drillstrike: Overwritten weapons for the Construction Mode tools-- Mine strike: Is currently broken-- Piano strike: Hog is resurrected by respawner. Not strictly prohibited, however.local atkArray = { {amBazooka, 2*costFactor}, --{amBee, 4*costFactor}, {amMortar, 1*costFactor}, {amDrill, 3*costFactor}, {amSnowball, 3*costFactor}, {amGrenade, 2*costFactor}, {amClusterBomb, 3*costFactor}, {amWatermelon, 25*costFactor}, {amHellishBomb, 25*costFactor}, {amMolotov, 3*costFactor}, {amGasBomb, 3*costFactor}, {amShotgun, 2*costFactor}, {amDEagle, 2*costFactor}, {amSniperRifle, 3*costFactor}, --{amSineGun, 6*costFactor}, {amFlamethrower, 4*costFactor}, {amIceGun, 15*costFactor}, {amMinigun, 13*costFactor}, {amFirePunch, 3*costFactor}, {amWhip, 1*costFactor}, {amBaseballBat, 7*costFactor}, --{amKamikaze, 1*costFactor}, {amSeduction, 1*costFactor}, {amHammer, 1*costFactor}, {amMine, 1*costFactor}, {amDynamite, 9*costFactor}, {amCake, 25*costFactor}, {amBallgun, 40*costFactor}, --{amRCPlane, 25*costFactor}, {amSMine, 5*costFactor}, --{amPiano, 40*costFactor}, {amPickHammer, 2*costFactor}, {amBlowTorch, 4*costFactor}, {amKnife, 2*costFactor}, {amBirdy, 7*costFactor},}-- UTILITY CRATES ---- Utilities which shouldn't be added:-- * Teleport: We have teleportation node-- * Switch: Infinite in default Construction Mode weapons scheme-- * Girder, rubber: Requires construction station-- * Resurrector: We have the resurrector structure for this-- Utilities which might be weird for this mode:-- * Tardis: Randomly teleports hog, maybe even into enemy clan's arealocal utilArray = { {amLandGun, 5*costFactor}, {amRope, 7*costFactor}, {amParachute, 2*costFactor}, {amJetpack, 8*costFactor}, {amPortalGun, 15*costFactor}, {amInvulnerable, 5*costFactor}, {amLaserSight, 2*costFactor}, {amVampiric, 6*costFactor}, {amLowGravity, 4*costFactor}, {amExtraDamage, 6*costFactor}, {amExtraTime, 8*costFactor}}------------------------------ Placement stuff------------------------------ primary placement categorieslocal cIndex = 1 -- category indexlocal cat = { loc_noop("Girder Placement Mode"), loc_noop("Rubber Placement Mode"), loc_noop("Mine Placement Mode"), loc_noop("Sticky Mine Placement Mode"), loc_noop("Barrel Placement Mode"), loc_noop("Weapon Crate Placement Mode"), loc_noop("Utility Crate Placement Mode"), loc_noop("Health Crate Placement Mode"), loc_noop("Structure Placement Mode"),}-- Frames in sprTarget for the structure imageslocal catFrames = { ["Respawner"] = 1, ["Generator"] = 2, ["Healing Station"] = 3, ["Support Station"] = 4, ["Weapon Filter"] = 5, ["Teleportation Node"] = 6, ["Bio-Filter"] = 7, ["Construction Station"] = 8, ["Reflector Shield"] = 9,}local catReverse = {}for c=1, #cat do catReverse[cat[c]] = cend-- Track girders in proximity of CurrentHedgehoglocal sProx = { ["Girder Placement Mode"] = false, ["Rubber Placement Mode"] = false, ["Mine Placement Mode"] = false, ["Sticky Mine Placement Mode"] = false, ["Barrel Placement Mode"] = false, ["Weapon Crate Placement Mode"] = false, ["Utility Crate Placement Mode"] = false, ["Health Crate Placement Mode"] = false, ["Structure Placement Mode"] = false, ["Teleportation Mode"] = false,}local pMode = {} -- pMode contains custom subsets of the main categorieslocal pIndex = 1local currentGirderRotation = 1 -- current girder rotation, we actually need this as HW remembers what rotation you last used-- Returns true if ammoType is an ammo type with a special meaning-- in Construction Mode.function IsConstructionModeAmmo(ammoType) return ammoType == amCMStructurePlacer or ammoType == amCMObjectPlacer or ammoType == amCMCratePlacer or ammoType == amGirder or ammoType == amRubber or ammoType == amTeleportendfunction RenderClanPower() for i=0, TeamsCount-1 do local name = GetTeamName(i) SetTeamLabel(name, clanPower[GetTeamClan(name)]) end DrawClanPowerTag()endfunction DrawClanPowerTag() local zoomL = 1.1 local xOffset = 45 local yOffset = 70 local tValue = clanPower[GetHogClan(CurrentHedgehog)] local tCol = GetClanColor(GetHogClan(CurrentHedgehog)) DeleteVisualGear(clanPowerTag) clanPowerTag = AddVisualGear(-div(ScreenWidth, 2) + xOffset, ScreenHeight - yOffset, vgtHealthTag, tValue, false) SetVisualGearValues( clanPowerTag, -- id nil, -- x offset (set above) nil, -- y offset (set above) 0, -- dx 0, -- dy zoomL, -- zoom 1, -- ~= 0 means align to screen nil, -- frameticks nil, -- value (set above) 240000, -- timer tCol -- color )endfunction DeleteClanPowerTag() DeleteVisualGear(clanPowerTag) clanPowerTag = nilendfunction XYisInRect(px, py, psx, psy, pex, pey) if (px > psx) and (px < pex) and (py > psy) and (py < pey) then return(true) else return(false) endendfunction AddWall(zXMin, zYMin, zWidth, zHeight, zCol) table.insert(wX, zXMin) table.insert(wY, zYMin) table.insert(wWidth, zWidth) table.insert(wHeight, zHeight) table.insert(wCol, zCol)endfunction BorderSpark(zXMin,zYMin, zWidth, zHeight, bCol) local eX = zXMin + GetRandom(zWidth+10) local eY = zYMin + GetRandom(zHeight+10) local tempE = AddVisualGear(eX, eY, vgtDust, 0, false) if tempE ~= 0 then SetVisualGearValues(tempE, eX, eY, nil, nil, nil, nil, nil, 1, nil, bCol) endendfunction HandleBorderEffects() borderEffectTimer = borderEffectTimer + 1 if borderEffectTimer > 15 then borderEffectTimer = 1 for i = 1, #wX do BorderSpark(wX[i],wY[i],wWidth[i],wHeight[i], wCol[i]) end endend------ old reflecting stuff from like 3 years ago lol---function gearCanBeDeflected(gear) if (GetGearType(gear) == gtShell) or (GetGearType(gear) == gtGrenade) or (GetGearType(gear) == gtAirBomb) or (GetGearType(gear) == gtClusterBomb) or (GetGearType(gear) == gtCluster) or (GetGearType(gear) == gtGasBomb) or (GetGearType(gear) == gtMine) or (GetGearType(gear) == gtMortar) or (GetGearType(gear) == gtHellishBomb) or (GetGearType(gear) == gtWatermelon) or (GetGearType(gear) == gtMelonPiece) or (GetGearType(gear) == gtEgg) or (GetGearType(gear) == gtDrill) or (GetGearType(gear) == gtBall) or (GetGearType(gear) == gtExplosives) or (GetGearType(gear) == gtFlame) or (GetGearType(gear) == gtPortal) or (GetGearType(gear) == gtDynamite) or (GetGearType(gear) == gtSMine) or (GetGearType(gear) == gtKnife) or (GetGearType(gear) == gtJetpack) or (GetGearType(gear) == gtBirdy) or (GetGearType(gear) == gtSnowball) or (GetGearType(gear) == gtMolotov) then return(true) else return(false) endendfunction getThreatDamage(gear) local dmg --- damage amounts for weapons if (GetGearType(gear) == gtGrenade) or (GetGearType(gear) == gtClusterBomb) or (GetGearType(gear) == gtGasBomb) or (GetGearType(gear) == gtKnife) or (GetGearType(gear) == gtEgg) or (GetGearType(gear) == gtMolotov) or (GetGearType(gear) == gtHellishBomb) or (GetGearType(gear) == gtWatermelon) or (GetGearType(gear) == gtSMine) then dmg = 30 elseif (GetGearType(gear) == gtMelonPiece) then dmg = 40 elseif (GetGearType(gear) == gtAirBomb) or (GetGearType(gear) == gtDrill) or (GetGearType(gear) == gtMine) or (GetGearType(gear) == gtCluster) then dmg = 20 elseif (GetGearType(gear) == gtFlame) or (GetGearType(gear) == gtPortal) or (GetGearType(gear) == gtDynamite) then dmg = 0 elseif (GetGearType(gear) == gtBall) then dmg = 1 else -- normal shell, snowball etc dmg = 65 end return(dmg)endfunction setGearReflectionValues(gear) local dmg = getThreatDamage(gear) setGearValue(gear,"damage",dmg) setGearValue(gear,"deflects",0) if (CurrentHedgehog ~= nil) then setGearValue(gear,"owner",GetHogClan(CurrentHedgehog)) -- NEW NEEDS CHANGE? else setGearValue(gear,"owner",10) endendfunction isATrackedGear(gear) if (GetGearType(gear) == gtHedgehog) or (GetGearType(gear) == gtTarget) or (GetGearType(gear) == gtCase) then return(true) else return(false) endendfunction AddStruc(pX,pY, pType, pClan) uniqueStructureID = uniqueStructureID + 1 local tempG = AddGear(0, 0, gtTarget, 0, 0, 0, 0) SetGearPosition(tempG, pX, pY) setGearValue(tempG, "uniqueStructureID", uniqueStructureID) local tempCirc = AddVisualGear(0,0,vgtCircle,0,true) if pType ~= "Respawner" and pType ~= "Generator" then SetVisualGearValues(tempCirc, 0, 0, 100, 255, 1, 100, 0, 500, 1, 0xFFFFFF00) table.insert(strucCirc, tempCirc) else table.insert(strucCirc, false) end table.insert(strucID, uniqueStructureID) table.insert(strucType, pType) table.insert(strucGear,tempG) table.insert(strucClan,pClan) table.insert(strucCost,2) local frameID = 0 local visualSprite = sprTarget local madness = AddVisualGear(GetX(tempG), GetY(tempG), vgtStraightShot, 1, true,1) if pType == "Reflector Shield" then table.insert(strucHealth,255) else table.insert(strucHealth,1) end if pType == "Bio-Filter" then table.insert(strucCircCol, colorBioFilter) table.insert(strucCircRadius,1000) elseif pType == "Healing Station" then table.insert(strucCircCol, colorHealingStation) table.insert(strucCircRadius,500) elseif pType == "Respawner" then table.insert(strucCircCol, 0) table.insert(strucCircRadius,0) runOnHogs(EnableHogResurrectionForThisClan) elseif pType == "Teleportation Node" then table.insert(strucCircCol, colorTeleportationNode) table.insert(strucCircRadius,350) elseif pType == "Generator" then table.insert(strucCircCol, 0) table.insert(strucCircRadius,0) setGearValue(tempG, "power", 0) elseif pType == "Support Station" then table.insert(strucCircCol, colorSupportStation) table.insert(strucCircRadius,500) elseif pType == "Construction Station" then table.insert(strucCircCol, colorConstructionStation) table.insert(strucCircRadius,500) elseif pType == "Reflector Shield" then table.insert(strucCircCol, colorReflectorShield) table.insert(strucCircRadius,750) elseif pType == "Weapon Filter" then table.insert(strucCircCol, colorWeaponFilter) table.insert(strucCircRadius,750) end if catFrames[pType] then frameID = catFrames[pType] end SetVisualGearValues(madness, nil, nil, 0, 0, nil, frameID, nil, visualSprite, nil, nil) SetState(tempG, bor(GetState(tempG),gstInvisible) ) table.insert(strucAltDisplay, madness)end-- this is basically onStructureDelete-- we may need to expand it for non-gear structures laterfunction CheckGearForStructureLink(gear) local respawnerDestroyed = false for i = 1, #strucID do if strucID[i] == getGearValue(gear,"uniqueStructureID") then if strucType[i] == "Respawner" then respawnerDestroyed = true end table.remove(strucID,i) table.remove(strucGear,i) table.remove(strucClan,i) table.remove(strucType,i) table.remove(strucCost,i) table.remove(strucHealth,i) DeleteVisualGear(strucCirc[i]) table.remove(strucCirc,i) table.remove(strucCircCol,i) table.remove(strucCircRadius,i) if strucAltDisplay[i] ~= 1 then DeleteVisualGear(strucAltDisplay[i]) end table.remove(strucAltDisplay,i) end end if respawnerDestroyed == true then runOnHogs(RecalibrateRespawn) endend-- called when we add a new respawnerfunction EnableHogResurrectionForThisClan(gear) if GetHogClan(gear) == GetHogClan(CurrentHedgehog) then SetEffect(gear, heResurrectable, 1) endend-- this is called when a respawner blows upfunction RecalibrateRespawn(gear) local respawnerList = {} for i = 1, #strucID do if (strucType[i] == "Respawner") and (strucClan[i] == GetHogClan(gear)) then table.insert(respawnerList, i) end end if #respawnerList >= 1 then SetEffect(gear, heResurrectable, 1) else SetEffect(gear, heResurrectable, 0) endend--resposition dead hogs at a respawner if they own onefunction FindRespawner(gear) local respawnerList = {} for i = 1, #strucID do if (strucType[i] == "Respawner") and (strucClan[i] == GetHogClan(gear)) then table.insert(respawnerList, i) end end if #respawnerList >= 1 then local i = GetRandom(#respawnerList)+1 SetGearPosition(gear,GetX(strucGear[respawnerList[i]]),GetY(strucGear[respawnerList[i]])-25) AddVisualGear(GetX(gear), GetY(gear), vgtExplosion, 0, false) local msgs = { loc("The respawner respawns %s"), loc("%s died … and lives again!"), loc("%s gets an extra life"), loc("%s is now a zombie hedgehog"), loc("%s has been rescued from death"), } local r = math.random(1, #msgs) AddCaption(string.format(msgs[r], GetHogName(gear))) else -- (this should never happen, but just in case) SetEffect(gear, heResurrectable, 0) DeleteGear(gear) endendfunction CheckTeleport(gear, tX, tY) local teleportOriginSuccessful = false local teleportDestinationSuccessful = false for i = 1, #strucID do if (strucType[i] == "Teleportation Node") and (strucClan[i] == GetHogClan(CurrentHedgehog)) then local dist = GetDistFromGearToXY(CurrentHedgehog,GetX(strucGear[i]), GetY(strucGear[i])) local NR NR = (48/100*strucCircRadius[i])/2 if dist <= NR*NR then teleportOriginSuccessful = true end dist = GetDistFromXYtoXY(tX,tY,GetX(strucGear[i]), GetY(strucGear[i])) NR = (48/100*strucCircRadius[i])/2 if dist <= NR*NR then teleportDestinationSuccessful = true end end end if ((teleportDestinationSuccessful == false) or (teleportOriginSuccessful == false)) then if IsHogLocal(CurrentHedgehog) then AddCaption(loc("Teleport unsuccessful. Please teleport within a clan teleporter's sphere of influence."), colorMessageError, capgrpMessage) end SetGearTarget(gear, GetX(CurrentHedgehog), GetY(CurrentHedgehog)) endend--Check for proximity of gears to structures, and make structures behave accordinglyfunction CheckProximity(gear) local sID = tempID_CheckProximity local dist = GetDistFromGearToXY(gear, GetX(strucGear[sID]), GetY(strucGear[sID])) if not dist then return end -- calculate my real radius if I am an aura local NR NR = (48/100*strucCircRadius[sID])/2 -- we're in business if dist <= NR*NR then -- heal clan hogs if strucType[sID] == "Healing Station" then if GetGearType(gear) == gtHedgehog then if GetHogClan(gear) == strucClan[sID] then local hogLife = GetHealth(gear) -- Heal hog by 1 HP, up to 150 HP total if hogLife < 150 then if ((hogLife + 1) % 5) == 0 then -- Health anim every 5 HP HealHog(gear, 1, false) else SetHealth(gear, hogLife+1) end end -- Maybe find better animation? local tempE = AddVisualGear(GetX(strucGear[sID]), GetY(strucGear[sID]), vgtSmoke, 0, false) SetVisualGearValues(tempE, nil, nil, nil, nil, nil, nil, nil, nil, nil, colorHealingStationParticle) end end -- explode enemy clan hogs elseif strucType[sID] == "Bio-Filter" then if GetGearType(gear) == gtHedgehog then if (GetHogClan(gear) ~= strucClan[sID]) and (GetHealth(gear) > 0) then AddGear(GetX(gear), GetY(gear), gtGrenade, 0, 0, 0, 1) end end -- were those weapons in your pocket, or were you just happy to see me? elseif strucType[sID] == "Weapon Filter" then if GetGearType(gear) == gtHedgehog then if (GetHogClan(gear) ~= strucClan[sID]) then -- Vaporize (almost) all of the hog's ammo local ammosDestroyed = 0 for wpnIndex = 0, AmmoTypeMax do if (not IsConstructionModeAmmo(wpnIndex)) and wpnIndex ~= amSkip and wpnIndex ~= amNothing then local count = GetAmmoCount(gear, wpnIndex) -- Infinite ammos are spared if count ~= 100 then ammosDestroyed = ammosDestroyed + count AddAmmo(gear, wpnIndex, 0) end end end if ammosDestroyed > 0 then -- Vaporize effects if gear == CurrentHedgehog then local r = math.random(1, 2) if r == 1 then PlaySound(sndNutter, gear) else PlaySound(sndOops, gear) end end PlaySound(sndVaporize) for i=1, 5 do AddVisualGear(GetX(gear), GetY(gear), vgtSmoke, 0, false) end local msgs = { loc("%s lost all the weapons"), loc("The ammo of %s has been vaporized"), loc("%s fell victim to a weapon filter"), loc("%s is suddenly low on ammo"), loc("%s is now as poor as a church mouse"), } local r = math.random(1, #msgs) AddCaption(string.format(msgs[r], GetHogName(gear)), capcolDefault, capgrpAmmoinfo) end end end -- BOUNCE! POGO! POGO! POGO! POGO! elseif strucType[sID] == "Reflector Shield" then -- add check for whose projectile it is if gearCanBeDeflected(gear) == true then local gOwner = getGearValue(gear,"owner") local gDeflects = getGearValue(gear,"deflects") local gDmg = getGearValue(gear,"damage") if gDeflects >= 3 then DeleteGear(gear) AddVisualGear(GetX(gear), GetY(gear), vgtSmoke, 0, false) PlaySound(sndVaporize) elseif gOwner ~= strucClan[sID] then --whether to vaporize gears or bounce them if gDmg ~= 0 then local dx, dy = GetGearVelocity(gear) if (dx == 0) and (dy == 0) then -- static mine, explosive, etc encountered -- do nothing else --let's bounce something! dx = dx*(-1) dy = dy*(-1) SetGearVelocity(gear,dx,dy) setGearValue(gear,"deflects",(gDeflects+1)) AddVisualGear(GetX(gear), GetY(gear), vgtExplosion, 0, false) PlaySound(sndExplosion) strucHealth[sID] = strucHealth[sID] - gDmg if strucCirc[sID] then strucCircCol[sID] = strucCircCol[sID] - gDmg end if strucHealth[sID] <= 0 then AddVisualGear(GetX(strucGear[sID]), GetY(strucGear[sID]), vgtExplosion, 0, false) DeleteGear(strucGear[sID]) PlaySound(sndExplosion) end end else DeleteGear(gear) AddVisualGear(GetX(gear), GetY(gear), vgtSmoke, 0, false) PlaySound(sndVaporize) end end end --mark as within range of a teleporter node elseif strucType[sID] == "Teleportation Node" then if GetGearType(gear) == gtHedgehog then if GetHogClan(gear) == strucClan[sID] then sProx["Teleportation Mode"] = true end end -- mark as within range of construction station -- and thus allow menu access to placement modes -- for girders, mines, sticky mines and barrels elseif strucType[sID] == "Construction Station" then if GetGearType(gear) == gtHedgehog then if GetHogClan(gear) == strucClan[sID] then AddVisualGear(GetX(strucGear[sID]), GetY(strucGear[sID]), vgtSmoke, 0, false) sProx["Girder Placement Mode"] = true sProx["Rubber Placement Mode"] = true sProx["Mine Placement Mode"] = true sProx["Sticky Mine Placement Mode"] = true sProx["Barrel Placement Mode"] = true end end -- mark as within stupport station range -- and thus allow menu access to placement modes -- for weapon, utility, and med crates elseif strucType[sID] == "Support Station" then if GetGearType(gear) == gtHedgehog then if GetHogClan(gear) == strucClan[sID] then AddVisualGear(GetX(strucGear[sID]), GetY(strucGear[sID]), vgtSmoke, 0, false) sProx["Health Crate Placement Mode"] = true sProx["Weapon Crate Placement Mode"] = true sProx["Utility Crate Placement Mode"] = true end end end endend-- used to check if we need to run through all hogs or just currenthedgehogfunction isAStructureThatAppliesToMultipleGears(pID) if strucType[pID] == "Healing Station" or strucType[pID] == "Reflector Shield" or strucType[pID] == "Weapon Filter" or strucType[pID] == "Bio-Filter" then return(true) else return(false) endendfunction HandleStructures() if GameTime % 100 == 0 then for k, _ in pairs(sProx) do if k ~= "Structure Placement Mode" then sProx[k] = false end end end for i = 1, #strucID do if strucCirc[i] then SetVisualGearValues(strucCirc[i], GetX(strucGear[i]), GetY(strucGear[i]), nil, nil, nil, nil, nil, strucCircRadius[i], nil, strucCircCol[i]) end tempID_CheckProximity = i SetVisualGearValues(strucAltDisplay[i], GetX(strucGear[i]), GetY(strucGear[i]), 0, 0, nil, nil, 800000, sprTarget) if GameTime % 100 == 0 then -- Check For proximity of stuff to our structures if isAStructureThatAppliesToMultipleGears(i) then runOnGears(CheckProximity) else -- only check prox on CurrentHedgehog if CurrentHedgehog ~= nil then CheckProximity(CurrentHedgehog) end end if strucType[i] == "Generator" then for z = 0, ClansCount-1 do if z == strucClan[i] then increaseGearValue(strucGear[i],"power") if getGearValue(strucGear[i],"power") == 10 then setGearValue(strucGear[i],"power",0) -- Add 1 energy (if not at max. already) if not (conf_maxEnergy ~= "inf" and clanPower[z] + 1 > conf_maxEnergy) then clanPower[z] = clanPower[z] + 1 -- Spawn one particle per energy added local particle = AddVisualGear(GetX(strucGear[i]), GetY(strucGear[i])-16, vgtStraightShot, sprStar, false) SetVisualGearValues(particle, nil, nil, math.random(-100, 100)*0.00005, 0.02, math.random(360), 0, 900, nil, 0, colorGeneratorParticle) else SetVisualGearValues(strucAltDisplay[i], GetX(strucGear[i]), GetY(strucGear[i]), 0, 0, nil, nil, 800000, sprTarget) end end end end end end end -- Add and remove ammo based on structure proximity if GameTime % 100 == 0 and CurrentHedgehog ~= nil then if sProx["Girder Placement Mode"] then AddAmmo(CurrentHedgehog, amGirder, 100) else AddAmmo(CurrentHedgehog, amGirder, 0) end if sProx["Rubber Placement Mode"] then AddAmmo(CurrentHedgehog, amRubber, 100) else AddAmmo(CurrentHedgehog, amRubber, 0) end if sProx["Mine Placement Mode"] or sProx["Sticky Mine Placement Mode"] or sProx["Barrel Placement Mode"] then AddAmmo(CurrentHedgehog, amCMObjectPlacer, 100) else AddAmmo(CurrentHedgehog, amCMObjectPlacer, 0) end if sProx["Teleportation Mode"] then AddAmmo(CurrentHedgehog, amTeleport, 100) else AddAmmo(CurrentHedgehog, amTeleport, 0) end if sProx["Weapon Crate Placement Mode"] or sProx["Utility Crate Placement Mode"] or sProx["Health Crate Placement Mode"] then AddAmmo(CurrentHedgehog, amCMCratePlacer, 100) else AddAmmo(CurrentHedgehog, amCMCratePlacer, 0) end endend-------------------------- SOME GENERAL METHODS------------------------function GetDistFromGearToXY(gear, g2X, g2Y) local g1X, g1Y = GetGearPosition(gear) if not g1X then return nil end local q = g1X - g2X local w = g1Y - g2Y return ( (q*q) + (w*w) )endfunction GetDistFromXYtoXY(a, b, c, d) local q = a - c local w = b - d return ( (q*q) + (w*w) )end-- essentially called when user clicks the mouse-- with girders or an airattackfunction PlaceObject(x,y) if (clanUsedExtraTime[GetHogClan(CurrentHedgehog)] == true) and (cat[cIndex] == "Utility Crate Placement Mode") and (utilArray[pIndex][1] == amExtraTime) then if IsHogLocal(CurrentHedgehog) then AddCaption(loc("You may only place 1 Extra Time crate per turn."), colorMessageError, capgrpVolume) end PlaySound(sndDenied) elseif (conf_cratesPerRound ~= "inf" and clanCratesSpawned[GetHogClan(CurrentHedgehog)] >= conf_cratesPerRound) and ( (cat[cIndex] == "Health Crate Placement Mode") or (cat[cIndex] == "Utility Crate Placement Mode") or (cat[cIndex] == "Weapon Crate Placement Mode") ) then if IsHogLocal(CurrentHedgehog) then AddCaption(string.format(loc("You may only place %d crates per round."), conf_cratesPerRound), colorMessageError, capgrpVolume) end PlaySound(sndDenied) elseif (XYisInRect(x,y, clanBoundsSX[GetHogClan(CurrentHedgehog)],clanBoundsSY[GetHogClan(CurrentHedgehog)],clanBoundsEX[GetHogClan(CurrentHedgehog)],clanBoundsEY[GetHogClan(CurrentHedgehog)]) == true) and (clanPower[GetHogClan(CurrentHedgehog)] >= placedExpense) then -- For checking if the actual placement succeeded local placed = false local gear if cat[cIndex] == "Girder Placement Mode" then placed = PlaceGirder(x, y, currentGirderRotation) elseif cat[cIndex] == "Rubber Placement Mode" then placed = PlaceRubber(x, y, currentGirderRotation) elseif cat[cIndex] == "Health Crate Placement Mode" then gear = SpawnHealthCrate(x,y) if gear ~= nil then placed = true SetHealth(gear, pMode[pIndex]) clanCratesSpawned[GetHogClan(CurrentHedgehog)] = clanCratesSpawned[GetHogClan(CurrentHedgehog)] +1 end elseif cat[cIndex] == "Weapon Crate Placement Mode" then gear = SpawnAmmoCrate(x, y, atkArray[pIndex][1]) if gear ~= nil then placed = true clanCratesSpawned[GetHogClan(CurrentHedgehog)] = clanCratesSpawned[GetHogClan(CurrentHedgehog)] +1 end elseif cat[cIndex] == "Utility Crate Placement Mode" then gear = SpawnUtilityCrate(x, y, utilArray[pIndex][1]) if gear ~= nil then placed = true if utilArray[pIndex][1] == amExtraTime then clanUsedExtraTime[GetHogClan(CurrentHedgehog)] = true end clanCratesSpawned[GetHogClan(CurrentHedgehog)] = clanCratesSpawned[GetHogClan(CurrentHedgehog)] +1 end elseif cat[cIndex] == "Barrel Placement Mode" then gear = AddGear(x, y, gtExplosives, 0, 0, 0, 0) if gear ~= nil then placed = true SetHealth(gear, pMode[pIndex]) end elseif cat[cIndex] == "Mine Placement Mode" then gear = AddGear(x, y, gtMine, 0, 0, 0, 0) if gear ~= nil then placed = true SetTimer(gear, pMode[pIndex]) end elseif cat[cIndex] == "Sticky Mine Placement Mode" then gear = AddGear(x, y, gtSMine, 0, 0, 0, 0) placed = gear ~= nil elseif cat[cIndex] == "Structure Placement Mode" then AddStruc(x,y, pMode[pIndex],GetHogClan(CurrentHedgehog)) placed = true end if placed then -- Pay the price clanPower[GetHogClan(CurrentHedgehog)] = clanPower[GetHogClan(CurrentHedgehog)] - placedExpense RenderClanPower() if cat[cIndex] == "Girder Placement Mode" or cat[cIndex] == "Rubber Placement Mode" then PlaySound(sndPlaced) end else if IsHogLocal(CurrentHedgehog) then AddCaption(loc("Invalid Placement"), colorMessageError, capgrpVolume) end PlaySound(sndDenied) end else if (clanPower[GetHogClan(CurrentHedgehog)] >= placedExpense) then if IsHogLocal(CurrentHedgehog) then AddCaption(loc("Invalid Placement"), colorMessageError, capgrpVolume) end else if IsHogLocal(CurrentHedgehog) then AddCaption(loc("Insufficient Power"), colorMessageError, capgrpVolume) end end PlaySound(sndDenied) endend-- called when user changes primary selection-- either via up/down keys-- or selecting girder/airattackfunction RedefineSubset() pIndex = 1 pMode = {} if (CurrentHedgehog == nil or band(GetState(CurrentHedgehog), gstHHDriven) == 0) then return false end local team = GetHogTeamName(CurrentHedgehog) if cat[cIndex] == "Girder Placement Mode" then pIndex = currentGirderRotation pMode = {amGirder} elseif cat[cIndex] == "Rubber Placement Mode" then pIndex = currentGirderRotation pMode = {amRubber} elseif cat[cIndex] == "Barrel Placement Mode" then pMode = {60} teamLObjectMode[team] = cat[cIndex] elseif cat[cIndex] == "Health Crate Placement Mode" then pMode = {HealthCaseAmount} teamLCrateMode[team] = cat[cIndex] elseif cat[cIndex] == "Weapon Crate Placement Mode" then for i = 1, #atkArray do pMode[i] = atkArray[i][1] end teamLCrateMode[team] = cat[cIndex] pIndex = teamLWeapIndex[team] elseif cat[cIndex] == "Utility Crate Placement Mode" then for i = 1, #utilArray do pMode[i] = utilArray[i][1] end teamLCrateMode[team] = cat[cIndex] pIndex = teamLUtilIndex[team] elseif cat[cIndex] == "Mine Placement Mode" then pMode = {0,1000,2000,3000,4000,5000} teamLObjectMode[team] = cat[cIndex] pIndex = teamLMineIndex[team] elseif cat[cIndex] == "Sticky Mine Placement Mode" then pMode = {amSMine} teamLObjectMode[team] = cat[cIndex] elseif cat[cIndex] == "Structure Placement Mode" then pMode = { loc_noop("Support Station"), loc_noop("Construction Station"), loc_noop("Healing Station"), loc_noop("Teleportation Node"), loc_noop("Weapon Filter"), loc_noop("Bio-Filter"), loc_noop("Reflector Shield"), loc_noop("Respawner"), loc_noop("Generator"), } pIndex = teamLStructIndex[team] end return trueend-- Updates the handling of the main construction mode tools:-- Structure Placer, Crate Placer, Object Placer.-- This handles the internal category state,-- the HUD display and the clans outline.function HandleConstructionModeTools() -- Update display selection criteria if (CurrentHedgehog ~= nil and band(GetState(CurrentHedgehog), gstHHDriven) ~= 0) then curWep = GetCurAmmoType() local updated = false local team = GetHogTeamName(CurrentHedgehog) if (curWep == amGirder) then cIndex = 1 RedefineSubset() updated = true elseif (curWep == amRubber) then cIndex = 2 RedefineSubset() updated = true elseif (curWep == amCMStructurePlacer) then cIndex = 9 RedefineSubset() updateCost() updated = true elseif (curWep == amCMCratePlacer) then cIndex = catReverse[teamLCrateMode[team]] RedefineSubset() updateCost() updated = true elseif (curWep == amCMObjectPlacer) then cIndex = catReverse[teamLObjectMode[team]] RedefineSubset() updateCost() updated = true end if curWep == amCMStructurePlacer or curWep == amCMCratePlacer or curWep == amCMObjectPlacer then SetSoundMask(sndIncoming, true) else SetSoundMask(sndIncoming, false) end if curWep == amGirder or curWep == amRubber then SetSoundMask(sndDenied, true) else SetSoundMask(sndDenied, false) end if updated then AddCaption(loc(cat[cIndex]), GetClanColor(GetHogClan(CurrentHedgehog)), capgrpMessage) showModeMessage() wallsVisible = true else wallsVisible = false end else curWep = amNothing wallsVisible = false endendlocal cursorIcon = nillocal ammoIcon = nillocal ammoIconBorder = nil-- Handle cursor stuff. This displays a sprite under the cursor so you can see what you're going to place.function HandleCursor() if curWep == amCMStructurePlacer or curWep == amCMObjectPlacer or curWep == amCMCratePlacer then local dFrame = 0 local dSprite local yOffset = 0 if (cat[cIndex] == "Structure Placement Mode") then dSprite = sprTarget dFrame = catFrames[pMode[pIndex]] elseif (cat[cIndex] == "Mine Placement Mode") then dSprite = sprCustom2 -- sprMineOff elseif (cat[cIndex] == "Sticky Mine Placement Mode") then dSprite = sprCustom3 -- sprSMineOff elseif (cat[cIndex] == "Barrel Placement Mode") then dSprite = sprExplosives elseif (cat[cIndex] == "Health Crate Placement Mode") then dSprite = sprFAid elseif (cat[cIndex] == "Weapon Crate Placement Mode") then dSprite = sprCase elseif (cat[cIndex] == "Utility Crate Placement Mode") then dSprite = sprUtility else dSprite = sprArrow end -- Display the gear to be spawned under the cursor if not cursorIcon then cursorIcon = AddVisualGear(CursorX, CursorY, vgtStraightShot, dSprite, true, 3) end SetVisualGearValues(cursorIcon, CursorX, CursorY, 0, 0, 0, dFrame, 1000, dSprite, 1000) -- Render ammo icon for weapon and utility crate. -- But hide this from prying eyes of your enemies online! if IsHogLocal(CurrentHedgehog) then local ammoFrame if (cat[cIndex] == "Weapon Crate Placement Mode") or (cat[cIndex] == "Utility Crate Placement Mode") then local tArr if (cat[cIndex] == "Weapon Crate Placement Mode") then tArr = atkArray else tArr = utilArray end -- Get ammo icon ammoFrame = tArr[pIndex][1] - 1 end if ammoFrame then local xDisplacement = 42 local yDisplacement = 42 local x = CursorX + yDisplacement local y = CursorY + yDisplacement -- Border around ammo icon if not ammoIconBorder then ammoIconBorder = AddVisualGear(x, y, vgtStraightShot, sprCustom1, true, 3) end SetVisualGearValues(ammoIconBorder, x, y, 0, 0, 0, 0, 1000, nil, 1000) -- Ammo icon if not ammoIcon then ammoIcon = AddVisualGear(x, y, vgtStraightShot, sprAMAmmos, true, 3) end SetVisualGearValues(ammoIcon, x, y, 0, 0, 0, ammoFrame, 1000, nil, 1000) else -- Cleanup vgears if not placing ammo crates if ammoIcon then DeleteVisualGear(ammoIcon) end if ammoIconBorder then DeleteVisualGear(ammoIconBorder) end end end else -- Cleanup vgears if cursorIcon then DeleteVisualGear(cursorIcon) end if ammoIcon then DeleteVisualGear(ammoIcon) end if ammoIconBorder then DeleteVisualGear(ammoIconBorder) end endendfunction onVisualGearDelete(vg) if vg ~= nil then if vg == cursorIcon then cursorIcon = nil elseif vg == ammoIcon then ammoIcon = nil elseif vg == ammoIconBorder then ammoIconBorder = nil end endend-- called in onGameTick()function HandleConstructionMode() HandleStructures() if CurrentHedgehog ~= nil then if wallsVisible == true then HandleBorderEffects() end HandleCursor() if GameTime % 100 == 0 then -- Force-update the construction mode tools every 100ms. -- This makes sure the announcer messages don't disappear -- while the tool is selected. if (band(GetState(CurrentHedgehog), gstHHDriven) ~= 0) then RenderClanPower() curWep = GetCurAmmoType() HandleConstructionModeTools() else DeleteClanPowerTag() curWep = amNothing end end end -- some kind of target detected, tell me your story if cGear ~= nil then local x,y = GetGearTarget(cGear) if GetGearType(cGear) == gtAirAttack then DeleteGear(cGear) PlaceObject(x, y) elseif GetGearType(cGear) == gtTeleport then CheckTeleport(cGear, x, y) cGear = nil elseif GetGearType(cGear) == gtGirder then currentGirderRotation = GetState(cGear) PlaceObject(x, y) end endend----------------------------------------------------------------- Cycle through selection subsets (by changing pIndex, pMode)-- i.e health of barrels, medikits,-- timer of mines-- contents of crates-- gears to reposition etc.---------------------------------------------------------------function updateCost() if CurrentHedgehog == nil or band(GetState(CurrentHedgehog), gstHHDriven) == 0 then return end -- Fallback cost placedExpense = 1 if pMode[pIndex] == "Healing Station" then placedExpense = 50 elseif pMode[pIndex] == "Weapon Filter" then placedExpense = 50 elseif pMode[pIndex] == "Bio-Filter" then placedExpense = 100 elseif pMode[pIndex] == "Respawner" then placedExpense = 300 elseif pMode[pIndex] == "Teleportation Node" then placedExpense = 30 elseif pMode[pIndex] == "Support Station" then placedExpense = 50 elseif pMode[pIndex] == "Construction Station" then placedExpense = 50 elseif pMode[pIndex] == "Generator" then placedExpense = 300 elseif pMode[pIndex] == "Reflector Shield" then placedExpense = 200 elseif cat[cIndex] == "Weapon Crate Placement Mode" then placedExpense = atkArray[pIndex][2] elseif cat[cIndex] == "Utility Crate Placement Mode" then placedExpense = utilArray[pIndex][2] elseif cat[cIndex] == "Health Crate Placement Mode" then placedExpense = 5 elseif cat[cIndex] == "Mine Placement Mode" then placedExpense = 15 elseif cat[cIndex] == "Sticky Mine Placement Mode" then placedExpense = 20 elseif cat[cIndex] == "Barrel Placement Mode" then placedExpense = 10 elseif cat[cIndex] == "Girder Placement Mode" then placedExpense = 1 elseif cat[cIndex] == "Rubber Placement Mode" then placedExpense = 3 end -- Hide cost from spectators. -- Also, this information is hidden cuz it could be used to infer e.g. crate contents. if IsHogLocal(CurrentHedgehog) then AddCaption(string.format(loc("Cost: %d"), placedExpense), GetClanColor(GetHogClan(CurrentHedgehog)), capgrpAmmostate) endend-- Should be called when the index of the mode was changed by the player.-- E.g. new weapon crate contents or structure typefunction updateIndex() if (curWep == amGirder) or (curWep == amRubber) or (curWep == amCMStructurePlacer) or (curWep == amCMCratePlacer) or (curWep == amCMObjectPlacer) then showModeMessage() updateCost() end -- Update team variables so the previous state can be restored later if CurrentHedgehog == nil or band(GetState(CurrentHedgehog), gstHHDriven) == 0 then return end local val = pMode[pIndex] local team = GetHogTeamName(CurrentHedgehog) if cat[cIndex] == "Structure Placement Mode" then teamLStructIndex[team] = pIndex elseif cat[cIndex] == "Mine Placement Mode" then teamLMineIndex[team] = pIndex elseif cat[cIndex] == "Weapon Crate Placement Mode" then teamLWeapIndex[team] = pIndex elseif cat[cIndex] == "Utility Crate Placement Mode" then teamLUtilIndex[team] = pIndex endendfunction showModeMessage() if CurrentHedgehog == nil or band(GetState(CurrentHedgehog), gstHHDriven) == 0 then return end local val = pMode[pIndex] local str if cat[cIndex] == "Mine Placement Mode" then -- timer in seconds str = string.format(loc("%d sec"), div(val, 1000)) elseif cat[cIndex] == "Structure Placement Mode" then str = loc(val) elseif cat[cIndex] == "Girder Placement Mode" then str = GetAmmoName(amGirder) elseif cat[cIndex] == "Rubber Placement Mode" then str = GetAmmoName(amRubber) elseif cat[cIndex] == "Sticky Mine Placement Mode" then str = GetAmmoName(amSMine) elseif cat[cIndex] == "Weapon Crate Placement Mode" or cat[cIndex] == "Utility Crate Placement Mode" then str = GetAmmoName(val) elseif cat[cIndex] == "Health Crate Placement Mode" then str = tostring(val) else str = tostring(val) end -- Hide the mode message from prying enemy eyes except for the structure placer. -- So stuff like crate contents or mine timers are secret. if cat[cIndex] == "Structure Placement Mode" or IsHogLocal(CurrentHedgehog) then AddCaption(str, GetClanColor(GetHogClan(CurrentHedgehog)), capgrpMessage2) endendfunction rotateMode(pDir) curWep = GetCurAmmoType() local foundMatch = false while(foundMatch == false) do cIndex = cIndex + pDir if (cIndex == 1) or (cIndex == 2) then -- we no longer hit girder by normal means cIndex = #cat elseif cIndex > #cat then cIndex = 3 -- we no longer hit girder by normal means end if (GetCurAmmoType() == amCMCratePlacer) then if (cat[cIndex] == "Health Crate Placement Mode") or (cat[cIndex] == "Weapon Crate Placement Mode") or (cat[cIndex] == "Utility Crate Placement Mode") then foundMatch = true end elseif (GetCurAmmoType() == amCMObjectPlacer) then if (cat[cIndex] == "Mine Placement Mode") or (cat[cIndex] == "Sticky Mine Placement Mode") or (cat[cIndex] == "Barrel Placement Mode") then foundMatch = true end elseif (GetCurAmmoType() == amCMStructurePlacer) then if cat[cIndex] == "Structure Placement Mode" then foundMatch = true end end end if foundMatch == true then RedefineSubset() --updateCost() HandleConstructionModeTools() endend----------------------- PLAYER CONTROLS ------------------------- [Timer X]: Used as shortcut key for faster selection of stufffunction onTimer(key) curWep = GetCurAmmoType() if (curWep == amCMStructurePlacer) then -- Select structure directly in structure placer -- [Timer X] selects structures 1-5 -- [Precise]+[Timer X] selects structures 6-10 local structureID = key local precise = band(GetGearMessage(CurrentHedgehog), gmPrecise) ~= 0 if precise then structureID = structureID + 5 end -- Check for valid pIndex if structureID <= #pMode then pIndex = structureID updateIndex() end elseif (curWep == amCMObjectPlacer) then -- [Timer X]: Set mine time 1-5 if cat[cIndex] == "Mine Placement Mode" then local index = key + 1 if key <= #pMode then pIndex = index updateIndex() end end endend-- [Switch]: Set mine time to 0 (only in mine placement mode)function onSwitch() curWep = GetCurAmmoType() if (curWep == amCMObjectPlacer) then pIndex = 1 updateIndex() endend-- [Left]/[Right]: Change submode (e.g. structure type) of any Construction Mode tool or rotate girder/rubberfunction onLeft() curWep = GetCurAmmoType() if (curWep == amGirder) or (curWep == amRubber) or (curWep == amCMStructurePlacer) or (curWep == amCMCratePlacer) or (curWep == amCMObjectPlacer) then pIndex = pIndex - 1 if pIndex == 0 then pIndex = #pMode end updateIndex() endendfunction onRight() curWep = GetCurAmmoType() if (curWep == amGirder) or (curWep == amRubber) or (curWep == amCMStructurePlacer) or (curWep == amCMCratePlacer) or (curWep == amCMObjectPlacer) then pIndex = pIndex + 1 if pIndex > #pMode then pIndex = 1 end updateIndex() endend-- [Up]/[Down]-- Cycle through the primary categories-- (by changing cIndex) i.e. mine, sticky mine,-- barrels, health/weapon/utility crate.function onUp() curWep = GetCurAmmoType() if ( (curWep == amCMCratePlacer) or (curWep == amCMObjectPlacer) ) then if CurrentHedgehog ~= nil and band(GetState(CurrentHedgehog), gstHHDriven) ~= 0 then rotateMode(-1) end endendfunction onDown() curWep = GetCurAmmoType() if ( (curWep == amCMCratePlacer) or (curWep == amCMObjectPlacer) ) then if CurrentHedgehog ~= nil and band(GetState(CurrentHedgehog), gstHHDriven) ~= 0 then rotateMode(1) end endend-- [Set weapon]/[Slot X]: Just update internal stuffonSetWeapon = HandleConstructionModeTools()onSlot = onSetWeapon------------------------------ standard event handlers------------------------------ Parses a positive integerfunction parseInt(str, default, infinityPermitted) if str == "inf" and infinityPermitted then return "inf" end if str == nil then return default end local s = string.match(str, "(%d*)") if s ~= nil then return math.min(4294967295, math.max(0, tonumber(s))) else return nil endend-- Parse parametersfunction onParameters() parseParams() conf_initialEnergy = parseInt(params["initialenergy"], conf_initialEnergy) conf_energyPerRound = parseInt(params["energyperround"], conf_energyPerRound) conf_maxEnergy = parseInt(params["maxenergy"], conf_maxEnergy, true) conf_cratesPerRound = parseInt(params["cratesperround"], conf_cratesPerRound, true)endfunction onGameInit() Explosives = 0 MinesNum = 0 EnableGameFlags(gfInfAttack) -- This is a hack to make sure all girder/rubber placement is handled by Construction Mode to overwrite the default behaviour SetMaxBuildDistance(1) fortMode = MapGen == mgForts -- if there are forts, let engine place the hogs on them if fortMode then EnableGameFlags(gfDivideTeams) end RedefineSubset()endfunction initialSetup(gear) -- Engine already placed hogs in fort mode if not fortMode then FindPlace(gear, false, clanBoundsSX[GetHogClan(gear)], clanBoundsEX[GetHogClan(gear)],true) end -- Add core ammo AddAmmo(gear, amCMStructurePlacer, 100) AddAmmo(gear, amSkip, 100) -- Remove special Construction Mode stuff. -- This stuff is added and removed dynamically based on -- proximity to structures. AddAmmo(gear, amCMObjectPlacer, 0) AddAmmo(gear, amCMCratePlacer, 0) AddAmmo(gear, amGirder, 0) AddAmmo(gear, amRubber, 0) AddAmmo(gear, amTeleport, 0) -- Drill strike is broken, so we force-remove it AddAmmo(gear, amDrillStrike, 0) -- Everything else is set by the weapon scheme. -- Infinite switch is recommended.endfunction onGameStart() trackTeams() ShowMission ( loc("CONSTRUCTION MODE"), loc("A Hedgewars mini-game"), loc("Build a fortress and destroy your enemy.") .. "|" .. loc("There are a variety of structures available to aid you.") .. "|" .. loc("Use the structure placer to place structures.") , -amCMStructurePlacer, 5000 ) SetAmmoTexts(amCMStructurePlacer, loc("Structure Placer"), loc("Construction Mode tool"), loc("Build one of multiple different structures|to aid you in victory, at the cost of energy.") .. "| |" .. loc("Support Station: Allows placement of crates.") .. "|".. loc("Construction Station: Allows placement of| girders, rubber, mines, sticky mines| and barrels.") .. "|" .. loc("Healing Station: Heals nearby hogs.") .. "|" .. loc("Teleportation Node: Allows teleportation| between other nodes.") .. "|" .. loc("Weapon Filter: Dematerializes all ammo| carried by enemies entering it.") .. "|" .. loc("Bio-Filter: Aggressively removes enemies.") .. "|" .. loc("Reflector Shield: Reflects enemy projectiles.") .. "|" .. loc("Respawner: Resurrects dead hogs.") .. "|" .. loc("Generator: Generates energy.") .. "|" .. " |" .. loc("Left/right: Choose structure type").."|".. loc("1-5, Precise + 1-4: Choose structure type").."|".. loc("Cursor: Build structure")) local txt_crateLimit = "" if conf_cratesPerRound ~= "inf" then txt_crateLimit = string.format(loc("You may only place %d crates per round."), conf_cratesPerRound) .. "|" end SetAmmoTexts(amCMCratePlacer, loc("Crate Placer"), loc("Construction Mode tool"), loc("This allows you to create a crate anywhere|within your clan's area of influence,|at the cost of energy.") .. "|" .. txt_crateLimit .. loc("Up/down: Choose crate type") .. "|" .. loc("Left/right: Choose crate contents") .. "|" .. loc("|Cursor: Place crate")) SetAmmoTexts(amCMObjectPlacer, loc("Object Placer"), loc("Construction Mode tool"), loc("This allows you to create and place mines,|sticky mines and barrels anywhere within your|clan's area of influence at the cost of energy.").."|".. loc("Up/down: Choose object type|1-5/Switch/Left/Right: Choose mine timer|Cursor: Place object") ) SetAmmoDescriptionAppendix(amTeleport, loc("It only works in teleportation nodes of your own clan.")) local sCirc = AddVisualGear(0,0,vgtCircle,0,true) SetVisualGearValues(sCirc, 0, 0, 100, 255, 1, 10, 0, 40, 3, 0x00000000) for i = 0, ClansCount-1 do clanPower[i] = math.min(conf_initialEnergy, conf_maxEnergy) clanUsedExtraTime[i] = false clanCratesSpawned[i] = 0 clanFirstTurn[i] = true end for i = 0, TeamsCount-1 do local team = GetTeamName(i) teamLStructIndex[team] = 1 teamLObjectMode[team] = "Mine Placement Mode" teamLCrateMode[team] = "Weapon Crate Placement Mode" teamLMineIndex[team] = 1 teamLWeapIndex[team] = 1 teamLUtilIndex[team] = 1 SetTeamLabel(team, tostring(clanPower[GetTeamClan(team)])) end local tMapWidth = RightX - LeftX local tMapHeight = WaterLine - TopY local clanInterval = div(tMapWidth,ClansCount) -- define construction areas for each clan -- if there are forts-based spawn locations, adjust areas around them for i = 0, ClansCount-1 do local slot if fortMode then slot = div(GetX(getFirstHogOfClan(i))-LeftX,clanInterval) else slot = i end local color = GetClanColor(i) clanBoundsSX[i] = LeftX+(clanInterval*slot)+20 clanBoundsSY[i] = TopY clanBoundsEX[i] = LeftX+(clanInterval*slot)+clanInterval-20 clanBoundsEY[i] = WaterLine --top and bottom AddWall(LeftX+(clanInterval*slot),TopY,clanInterval,wMargin,color) AddWall(LeftX+(clanInterval*slot),WaterLine-25,clanInterval,wMargin,color) --add a wall to the left and right AddWall(LeftX+(clanInterval*slot)+20,TopY,wMargin,WaterLine,color) AddWall(LeftX+(clanInterval*slot)+clanInterval-20,TopY,wMargin,WaterLine,color) end runOnHogs(initialSetup)endfunction onNewTurn() curWep = GetCurAmmoType() HandleConstructionModeTools() local clan = GetHogClan(CurrentHedgehog) if clanFirstTurn[clan] then clanFirstTurn[clan] = false else clanPower[clan] = clanPower[clan] + conf_energyPerRound if conf_maxEnergy ~= "inf" and clanPower[clan] > conf_maxEnergy then clanPower[clan] = conf_maxEnergy end end clanUsedExtraTime[clan] = false clanCratesSpawned[clan] = 0 RenderClanPower()endfunction onEndTurn() curWep = amNothing HandleConstructionModeTools() DeleteClanPowerTag()endfunction onGameTick() HandleConstructionMode()endfunction onScreenResize() -- redraw Tags so that their screen locations are updated if (CurrentHedgehog ~= nil) then RenderClanPower() endendfunction onGearResurrect(gear, vGear) if GetGearType(gear) == gtHedgehog then FindRespawner(gear) if vGear then SetVisualGearValues(vGear, GetX(gear), GetY(gear)) end endend-- track hedgehogs and placement gearsfunction onGearAdd(gear) local gt = GetGearType(gear) if (gt == gtAirAttack) or (gt == gtTeleport) or (gt == gtGirder) then cGear = gear end if isATrackedGear(gear) then trackGear(gear) elseif gearCanBeDeflected(gear) then trackGear(gear) setGearReflectionValues(gear) endendfunction onGearDelete(gear) if GetGearType(gear) == gtTarget then CheckGearForStructureLink(gear) end if (GetGearType(gear) == gtAirAttack) or (GetGearType(gear) == gtTeleport) or (GetGearType(gear) == gtGirder) then cGear = nil end if (isATrackedGear(gear) or gearCanBeDeflected(gear)) then trackDeletion(gear) endend