====== Heldenfähigkeit: "Charge" ====== "Charge" fügt Kerberos' "Aura der Furcht" eine weitere Komponente hinzu: 20 Sekunden lang kann bis zu 5x ein Nahkämpfer aus dem Umkreis von Kerberos (max. Abstand 1500) einen gegnerischen Fernkämpfer anstürmen - der Nahkämpfer wird dabei sofort an die Position des Fernkämpfers versetzt. Dieser Sturmangriff wird ausgelöst, wenn der feindliche Fernkämpfer den betreffenden eigenen Nahkämpfer aus einer Distanz von 400-2200 angreift. Pro Einsatz der Aura kann ein einzelner Trupp höchstens 1x "stürmen". Als Bonus wird die Erfahrung eines Trupps beim Stürmen auf 3 Sterne angehoben. Truppen, die vorher schon mehr Sterne hatten, behalten den alten Wert. **Anmerkungen:** * Das Skript kann für einen Spieler nicht unter mehreren Kerberossen auf der Karte unterscheiden - es sollte pro Spieler nur einen geben! * Die Aura wirkt zZt nicht auf Verbündete, nur für eigene Truppen. function Heromods_ActivateCharge() Heromods_Charge = { -- ### Konstanten AURA_RANGE = 1500, MIN_RANGE = 400, MAX_RANGE = 2200, MAX_DURATION = 20, MAX_CHARGES = 5, MELEE_ENTITY_TYPES = { [Entities.PU_BattleSerf] = true, [Entities.PU_Hero5_Outlaw] = true, [Entities.CU_Barbarian_Hero_wolf] = true, [Entities.PU_LeaderHeavyCavalry1] = true, [Entities.PU_LeaderHeavyCavalry2] = true, [Entities.PU_LeaderPoleArm1] = true, [Entities.PU_LeaderPoleArm2] = true, [Entities.PU_LeaderPoleArm3] = true, [Entities.PU_LeaderPoleArm4] = true, [Entities.PU_LeaderSword1] = true, [Entities.PU_LeaderSword2] = true, [Entities.PU_LeaderSword3] = true, [Entities.PU_LeaderSword4] = true, [Entities.CU_VeteranCaptain] = true, [Entities.CU_VeteranLieutenant] = true, [Entities.CU_VeteranMajor] = true, [Entities.CU_Evil_LeaderBearman1] = true, [Entities.CU_BlackKnight_LeaderMace1] = true, [Entities.CU_Barbarian_LeaderClub1] = true, [Entities.CU_BanditLeaderSword1] = true, [Entities.CU_AggressiveWolf] = true, }, -- ### Verwaltung activeForPlayer = {false, false, false, false, false, false, false, false}, effectCounter = {0,0,0,0,0,0,0,0}, chargesUsed = {0,0,0,0,0,0,0,0}, chargedEntities = {{},{},{},{},{},{},{},{}}, entityHurtTriggerID = 0, }; GUIAction_Hero7Madness_OrigHeroMod = GUIAction_Hero7Madness; GUIAction_Hero7Madness = function() GUIAction_Hero7Madness_OrigHeroMod(); local pID = GUI.GetPlayerID(); GUI.PayTribute( 8, Heromods_Charge.tribut[pID] ); end GUITooltip_NormalButton_OrigHeroMod = GUITooltip_NormalButton; GUITooltip_NormalButton = function( _wID, _keyBind ) GUITooltip_NormalButton_OrigHeroMod( _wID, _keyBind ); if _wID == "MenuHero7/command_madness" then XGUIEng.SetText( gvGUI_WidgetID.TooltipBottomText, "@color:220,10,30 Aura des Krieges @cr @color:255,255,255 Kerberos senkt die Widerstandskraft aller Feinde in seiner Umgebung und ermöglicht es verbündeten Nahkämpfern 20 Sek. lang, feindliche Fernkämpfer anzustürmen." ); end end -- ############################### -- ### Tribute Heromods_Charge.tributCallback = { [1] = function() Heromods_Charge_ActivateForPlayer(1); Heromods_Charge.tribut[1] = AddTribute( CreateATribute( 8, "", {Gold=0}, Heromods_Charge.tributCallback[1] ) ); end, [2] = function() Heromods_Charge_ActivateForPlayer(2); Heromods_Charge.tribut[1] = AddTribute( CreateATribute( 8, "", {Gold=0}, Heromods_Charge.tributCallback[2] ) ); end, [3] = function() Heromods_Charge_ActivateForPlayer(3); Heromods_Charge.tribut[1] = AddTribute( CreateATribute( 8, "", {Gold=0}, Heromods_Charge.tributCallback[3] ) ); end, [4] = function() Heromods_Charge_ActivateForPlayer(4); Heromods_Charge.tribut[1] = AddTribute( CreateATribute( 8, "", {Gold=0}, Heromods_Charge.tributCallback[4] ) ); end, [5] = function() Heromods_Charge_ActivateForPlayer(5); Heromods_Charge.tribut[1] = AddTribute( CreateATribute( 8, "", {Gold=0}, Heromods_Charge.tributCallback[5] ) ); end, [6] = function() Heromods_Charge_ActivateForPlayer(6); Heromods_Charge.tribut[1] = AddTribute( CreateATribute( 8, "", {Gold=0}, Heromods_Charge.tributCallback[6] ) ); end, [7] = function() Heromods_Charge_ActivateForPlayer(7); Heromods_Charge.tribut[1] = AddTribute( CreateATribute( 8, "", {Gold=0}, Heromods_Charge.tributCallback[7] ) ); end, [8] = function() Heromods_Charge_ActivateForPlayer(8); Heromods_Charge.tribut[1] = AddTribute( CreateATribute( 8, "", {Gold=0}, Heromods_Charge.tributCallback[8] ) ); end, }; Heromods_Charge.tribut = { [1] = AddTribute( CreateATribute( 8, "", {Gold=0}, Heromods_Charge.tributCallback[1] ) ), [2] = AddTribute( CreateATribute( 8, "", {Gold=0}, Heromods_Charge.tributCallback[2] ) ), [3] = AddTribute( CreateATribute( 8, "", {Gold=0}, Heromods_Charge.tributCallback[3] ) ), [4] = AddTribute( CreateATribute( 8, "", {Gold=0}, Heromods_Charge.tributCallback[4] ) ), [5] = AddTribute( CreateATribute( 8, "", {Gold=0}, Heromods_Charge.tributCallback[5] ) ), [6] = AddTribute( CreateATribute( 8, "", {Gold=0}, Heromods_Charge.tributCallback[6] ) ), [7] = AddTribute( CreateATribute( 8, "", {Gold=0}, Heromods_Charge.tributCallback[7] ) ), [8] = AddTribute( CreateATribute( 8, "", {Gold=0}, Heromods_Charge.tributCallback[8] ) ), }; -- ############################### -- ### Comforts Heromods_Charge_GetHero = function(_pID) local found,heroID = Logic.GetPlayerEntities( _pID, Entities.CU_BlackKnight, 1 ); if found == 0 then Message("DEBUG: Kein Kerberos fuer Spieler ".._pID.." gefunden!"); return 0; else return heroID; end end Heromods_ChargeAbility = function( _charger, _target ) if SoldierTypes[Logic.GetEntityType(_charger)] then _charger = SoldierGetLeaderEntityID(_charger); end assert(IsExisting(_charger)); local eType = Logic.GetEntityType(_charger); local eName = GetEntityName(_charger); local pID = GetPlayer(_charger); assert(IsValidPlayerID[pID]); local oldPos = GetPosition(_charger); assert(IsValidPosition(oldPos)); local newPos = GetPosition(_target); assert(IsValidPosition(newPos)); local nSol = Logic.LeaderGetNumberOfSoldiers(_charger); assert(type(nSol) == "number"); local ep = Logic.GetLeaderExperienceLevel(_charger); assert(type(ep) == "number"); local hurt = Logic.GetEntityMaxHealth(_charger) - Logic.GetEntityHealth(_charger); assert(type(hurt) == "number"); local selected = false; if pID == GUI.GetPlayerID() then local sels = {GUI.GetSelectedEntities()}; for i,sel in ipairs(sels) do if sel == _charger then selected = true; break; end end end Logic.CreateEffect( GGL_Effects.FXCrushBuilding, oldPos.X, oldPos.Y ); Logic.CreateEffect( GGL_Effects.FXCrushBuilding, newPos.X, newPos.Y ); Effektlinie( oldPos.X, oldPos.Y, newPos.X, newPos.Y, GGL_Effects.FXDestroyTree, 150 ); Logic.DestroyGroupByLeader(_charger); local newID = CreateArmyTroops( pID, newPos, eType, nSol, 1, math.max(ep-1, 1) ); if selected then GUI.SelectEntity(newID); end if hurt>0 then Logic.HurtEntity( newID, hurt ); end if type(eName) == "string" then SetEntityName(newID,eName); end Logic.GroupAttack( newID, _target ); return newID; end Heromods_Charge_ActivateForPlayer = function(_pID) -- ### Einstellungen Heromods_Charge.activeForPlayer[_pID] = true; Heromods_Charge.effectCounter[_pID] = 0; Heromods_Charge.chargesUsed[_pID] = 0; Heromods_Charge.chargedEntities[_pID] = {}; -- ### Jobs if JobIsRunning(Heromods_Charge.entityHurtTriggerID) == 0 then Heromods_Charge.entityHurtTriggerID = Trigger.RequestTrigger( Events.LOGIC_EVENT_ENTITY_HURT_ENTITY, "", "Heromods_Charge_EntityHurt", 1); Message("SPIELER ".._pID..": EFFEKT BEGINNT -> Trigger inaktiv, starten!"); else Message("SPIELER ".._pID..": EFFEKT BEGINNT -> Trigger bereits aktiv!"); end StartSimpleJob("Heromods_Charge_Job1"); end Heromods_Charge_DeactivateForPlayer = function(_pID) -- ### Einstellungen Heromods_Charge.activeForPlayer[_pID] = false; -- ### Jobs local t = Heromods_Charge.activeForPlayer; if not (t[1] or t[2] or t[3] or t[4] or t[5] or t[6] or t[7] or t[8]) then EndJob( Heromods_Charge.entityHurtTriggerID ); -- solange kein Effekt laeuft, braucht der Hurt-Callback nicht aktiv zu sein Message("SPIELER ".._pID..": EFFEKT KLINGT AUS -> Trigger wird deaktiviert!"); else Message("SPIELER ".._pID..": EFFEKT KLINGT AUS -> Trigger bleibt aktiv..."); end end Heromods_Charge_JobTick = function(_pID) if not Heromods_Charge.activeForPlayer[1] then return true; else local count = Heromods_Charge.effectCounter[_pID]; if (count < Heromods_Charge.MAX_DURATION) then local heroID = Heromods_Charge_GetHero(_pID); if IsAlive( heroID ) then Message("Job Tick "..count.." fuer Spieler ".._pID); Heromods_Charge.effectCounter[_pID] = count+1; local pos = GetPosition( heroID ); -- Logic.CreateEffect( GGL_Effects.FXKerberosFear, pos.X, pos.Y ); -- Logic.CreateEffect( GGL_Effects.FXMaryDemoralize, pos.X, pos.Y ); Logic.CreateEffect( GGL_Effects.FXBuildingSmokeLarge, pos.X, pos.Y ); Logic.CreateEffect( GGL_Effects.FXCannonFire, pos.X, pos.Y ); else Heromods_Charge_DeactivateForPlayer(_pID); end else Heromods_Charge_DeactivateForPlayer(_pID); end return false; end end -- ############################### -- ### Jobs Heromods_Charge_Job1 = function() return Heromods_Charge_JobTick(1); end Heromods_Charge_Job2 = function() return Heromods_Charge_JobTick(2); end Heromods_Charge_Job3 = function() return Heromods_Charge_JobTick(3); end Heromods_Charge_Job4 = function() return Heromods_Charge_JobTick(4); end Heromods_Charge_Job5 = function() return Heromods_Charge_JobTick(5); end Heromods_Charge_Job6 = function() return Heromods_Charge_JobTick(6); end Heromods_Charge_Job7 = function() return Heromods_Charge_JobTick(7); end Heromods_Charge_Job8 = function() return Heromods_Charge_JobTick(8); end Heromods_Charge_EntityHurt = function() local attID = Event.GetEntityID1(); local tarID = TroopGetLeaderEntityID( Event.GetEntityID2() ); local eType = Logic.GetEntityType(tarID); if Heromods_Charge.MELEE_ENTITY_TYPES[eType] then local pID = GetPlayer(tarID); if Heromods_Charge.activeForPlayer[pID] then -- TODO: auch Verbündete ermöglichen if not Heromods_Charge.chargedEntities[pID][tarID] then local nChargesUsed = Heromods_Charge.chargesUsed[pID]; if (nChargesUsed < Heromods_Charge.MAX_CHARGES) then local heroID = Heromods_Charge_GetHero(pID); if (GetDistance(tarID, heroID) <= Heromods_Charge.AURA_RANGE) then local dist = GetDistance(attID, tarID); if (dist >= Heromods_Charge.MIN_RANGE) and (dist <= Heromods_Charge.MAX_RANGE) then local newID = Heromods_ChargeAbility( tarID, attID ); Heromods_Charge.chargesUsed[pID] = nChargesUsed+1; Heromods_Charge.chargedEntities[pID][newID] = true; end else -- Message("zu weit vom Helden weg."); end else Heromods_Charge_DeactivateForPlayer(pID); -- Message("charges verbraucht"); end else -- Message("bereits gecharged: "..tarID); end else -- Message("nicht aktiv fuer Spieler: "..pID); end else -- Message("ungueltiger Typ: "..eType); end end end -- ################################## -- ### Comforts -- ################################## function IsValidPosition( _position ) if ( type(_position) == "table" ) then if ( type(_position.X) == "number" ) and ( type(_position.Y) == "number" ) then local x,y = Logic.WorldGetSize(); if ( (_position.X <= x+100) and (_position.X >= 0) ) and ( (_position.Y <= y+100) and (_position.Y >= 0) ) then return true; end end end return false; end IsValidPlayerID = {1,2,3,4,5,6,7,8} function GetDistance(_pos1,_pos2) if (type(_pos1) == "string") or (type(_pos1) == "number") then _pos1 = GetPosition(_pos1); end assert(type(_pos1) == "table"); if (type(_pos2) == "string") or (type(_pos2) == "number") then _pos2 = GetPosition(_pos2); end assert(type(_pos2) == "table"); local xDistance = (_pos1.X - _pos2.X); local yDistance = (_pos1.Y - _pos2.Y); return math.sqrt((xDistance^2) + (yDistance^2)); end SoldierTypes = { -- Alle Soldaten-EntityTypes mit zugehörigem Leader-Typ [Entities.CU_BanditSoldierBow1] = Entities.CU_BanditLeaderBow1, [Entities.CU_BanditSoldierSword1] = Entities.CU_BanditLeaderSword1, [Entities.CU_BanditSoldierSword2] = Entities.CU_BanditLeaderSword2, [Entities.CU_Barbarian_SoldierClub1] = Entities.CU_Barbarian_LeaderClub1, [Entities.CU_Barbarian_SoldierClub2] = Entities.CU_Barbarian_LeaderClub2, [Entities.CU_BlackKnight_SoldierMace1] = Entities.CU_BlackKnight_LeaderMace1, [Entities.CU_BlackKnight_SoldierMace2] = Entities.CU_BlackKnight_LeaderMace2, [Entities.CU_Evil_SoldierBearman1] = Entities.CU_Evil_LeaderBearman1, [Entities.CU_Evil_SoldierSkirmisher1] = Entities.CU_Evil_LeaderSkirmisher1, [Entities.PU_SoldierBow1] = Entities.PU_LeaderBow1, [Entities.PU_SoldierBow2] = Entities.PU_LeaderBow2, [Entities.PU_SoldierBow3] = Entities.PU_LeaderBow3, [Entities.PU_SoldierBow4] = Entities.PU_LeaderBow4, [Entities.PU_SoldierCavalry1] = Entities.PU_LeaderCavalry1, [Entities.PU_SoldierCavalry2] = Entities.PU_LeaderCavalry2, [Entities.PU_SoldierHeavyCavalry1] = Entities.PU_LeaderHeavyCavalry1, [Entities.PU_SoldierHeavyCavalry2] = Entities.PU_LeaderHeavyCavalry2, [Entities.PU_SoldierPoleArm1] = Entities.PU_LeaderPoleArm1, [Entities.PU_SoldierPoleArm2] = Entities.PU_LeaderPoleArm2, [Entities.PU_SoldierPoleArm3] = Entities.PU_LeaderPoleArm3, [Entities.PU_SoldierPoleArm4] = Entities.PU_LeaderPoleArm4, [Entities.PU_SoldierRifle1] = Entities.PU_LeaderRifle1, [Entities.PU_SoldierRifle2] = Entities.PU_LeaderRifle2, [Entities.PU_SoldierSword1] = Entities.PU_LeaderSword1, [Entities.PU_SoldierSword2] = Entities.PU_LeaderSword2, [Entities.PU_SoldierSword3] = Entities.PU_LeaderSword3, [Entities.PU_SoldierSword4] = Entities.PU_LeaderSword4, }; function SoldierGetLeaderEntityID(_solID) local leadType = SoldierTypes[Logic.GetEntityType(_solID)] if leadType then local pID = GetPlayer(_solID) local pos = GetPosition(_solID) local t = {Logic.GetPlayerEntitiesInArea( pID, leadType, pos.X, pos.Y, 2000, 48 )} for i = 2,t[1]+1 do local leader = t[i]; local soldiers = {Logic.GetSoldiersAttachedToLeader(leader)} if soldiers[1] then for j = 2,soldiers[1]+1 do if soldiers[j] == _solID then return leader,soldiers[2]; end end end end end return 0; end function TroopGetLeaderEntityID( _eID ) if Logic.IsLeader(_eID) == 1 then return _eID; end return SoldierGetLeaderEntityID(_eID); end function Effektlinie( _Ax, _Ay, _Bx, _By, _effekt, _periode) assert(type(_Ax) == "number") assert(type(_Ay) == "number") assert(type(_Bx) == "number") assert(type(_By) == "number") local startX = _Bx local startY = _By local _Cx = (_Ax - _Bx) local _Cy = (_Ay - _By) if (_Cx < 0) and (_Cy < 0) then local loX = -_Cx local loY = -_Cy if (loX > loY) then Anzahl = math.floor ((loX / _periode) + 0.5) else Anzahl = math.floor ((loY / _periode) + 0.5) end elseif (_Cx < 0) then local loX = -_Cx local loY = _Cy if (loX > loY) then Anzahl = math.floor ((loX / _periode) + 0.5) else Anzahl = math.floor ((loY / _periode) + 0.5) end elseif (_Cy < 0) then local loX = _Cx local loY = -_Cy if (loX > loY) then Anzahl = math.floor ((loX / _periode) + 0.5) else Anzahl = math.floor ((loY / _periode) + 0.5) end else local loX = _Cx local loY = _Cy if (loX > loY) then Anzahl = math.floor ((loX / _periode) + 0.5) else Anzahl = math.floor ((loY / _periode) + 0.5) end end _Cx = _Cx / Anzahl _Cy = _Cy / Anzahl if (_Cx >= 0) and (_Cy >= 0) then while (_Bx <= _Ax) and (_By <= _Ay) do _Ax = _Ax - _Cx _Ay = _Ay - _Cy Logic.CreateEffect( _effekt, _Ax, _Ay, 1 ) end elseif (_Cx >= 0) and (_Cy <= 0) then _Cy = -_Cy while (_Bx <= _Ax) and (_By >= _Ay) do _Ax = _Ax - _Cx _Ay = _Ay + _Cy Logic.CreateEffect( _effekt, _Ax, _Ay, 1 ) end elseif (_Cx <= 0) and (_Cy >= 0) then _Cx = -_Cx while (_Bx >= _Ax) and (_By <= _Ay) do _Ax = _Ax + _Cx _Ay = _Ay - _Cy Logic.CreateEffect( _effekt, _Ax, _Ay, 1 ) end elseif (_Cx <= 0) and (_Cy <= 0) then _Cx = -_Cx _Cy = -_Cy while (_Bx >= _Ax) and (_By >= _Ay) do _Ax = _Ax + _Cx _Ay = _Ay + _Cy Logic.CreateEffect( _effekt, _Ax, _Ay, 1 ) end end end function CreateArmyTroops( _player, _position, _leaderType, _numberOfSoldiers, _troops, _experience, _move ) local army = { player = _player, } local tD = { maxNumberOfSoldiers = _numberOfSoldiers, minNumberOfSoldiers = 0, experiencePoints = _experience, leaderType = _leaderType, position = _position, } for i = 1,_troops do army[i] = CreateTroop( army , tD ) end if _move ~= nil then for i = 1,_troops do Move( army[i], _move ) end end return unpack(army); end