[[http://www.siedler-games.de|{{:sg-link.jpg|}}]] ====== RPG Mod ====== Mit dem Code auf dieser Seite kann man mit seinen Helden wie in einem RPG Spiel Erfahrung sammeln und im Level aufsteigen. Durch einen Levelaufstieg bekommen die Helden mehr Gesundheitspunkte, mehr Angriff und mehr Verteidigung. Außerdem können sie schneller ihre Spezialfähigkeiten einsetzen. Diese Mod wurde für den MP Modus entwickelt, funktioniert aber durchaus auch im Singleplayer. ===== Beschreibung der Änderungen ===== ==== Heldenmenü ==== Wird ein Held markiert, öffnet sich über dem normalen Selektionsmenü ein weiteres Infofenster, in dem das aktuelle Level, die gesammelte Erfahrung (in Prozent bis zum nächsten Level), die Aktionspunkte sowie die vorhandenen Items zu sehen sind. ==== Erfahrung sammeln ==== Erfahrung sammelt ein Held, wenn in seiner Nähe eine feindliche Einheit durch die eigenen Einheiten vernichtet wird. Die Anzahl der Erfahrungspunkte richtet sich nach dem Typ des Gegners. Ein Hauptmann bringt z.B. mehr Erfahrung als ein einfacher Soldat. Gebäude bringen keine Erfahrung. Feindliche Helden geben je nach Level am meisten Erfahrungspunkte. Befindet sich mehr als ein eigener Held in Reichweite, so wird die gewonnene Erfahrung zu gleichen Teilen auf alle Helden aufgeteilt. Tipp: Man kann einen schwachen Helden also schneller Erfahrung sammeln, wenn man die starken Helden aus den Kämpfen heraushält. ==== Levelaufstieg ==== Wenn ein Held genug Erfahrung gesammelt hat, steigt er eine Stufe auf. Die Erfahrung die dafür benötigt wird, steigt von Level zu Level. Mit anderen Worten wird ein Held mit niedrigem Level schneller aufsteigen, als ein Held mit hohem Level. Pro Level erhöht sich die Gesundheit, der Angriff, die Verteidigung und die Aktionspunkte. ==== Spezialfähigkeiten und Aktionspunkte ==== Der Einsatz der Spezialfähigkeiten hat sich gegenüber dem Originalspiel geändert. Die Fähigkeiten haben keinen Cooldown mehr, sondern verbrauchen die sogenannten Aktionspunkte. Aktionspunkte regenerieren sich (ähnlich wie die Gesundheit) mit der Zeit von selbst. ==== Items ==== Helden können nun Gegenstände tragen, die in speziellen Schatzkisten zu finden sind. Das können z.B. Heiltränke oder Rüstungen sein. Im SP Modus könnten die Helden auch Schlüssel oder andere Questgegenstände tragen. Leider gibt es noch keine Möglichkeit Items beliebig einzusetzen oder wegzuwerfen. Ein Heiltrank müsste also automatisch eingesetzt werden, wenn die Gesundheit des Helden sehr schwach ist. ==== Eigene Namen für die Helden ==== Im Multiplayer können den Helden über die [[http://web21.server3.bluestarhosting.de/shr/S5Tools/|S5Tools]] eigene Namen gegeben werden, die dann bei Info-Messages bei allen Spielern angezeigt werden. ===== Lua-Code für die RPG Mod ===== --++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -- Hero Level System v1.2 --++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ function HeroLevelSystem_Init() gvHeroLevelSystem = {} gvHeroLevelSystem.Heroes = {} gvHeroLevelSystem.Entities = {} gvHeroLevelSystem.Config = {} -- -- Hier können die Einstellungen geändert werden! -- -- Maximal erreichbares Level gvHeroLevelSystem.Config.MaxLevel = 10 -- Berechnungsgrundlage für den Levelaufstieg gvHeroLevelSystem.Config.BaseLevelExperience = 100 -- Maximale Distanz zu einem Gegner, bei dem der Held die komplette -- Erfahrung bekommt. Ist er weiter weg, gibt es weniger Erfahrung, je -- größer die Entfernung zwischen Held und Feind ist gvHeroLevelSystem.Config.MaxDistance = 2200 -- Maximale Anzahl an Items die ein Held aufnehmen kann gvHeroLevelSystem.Config.MaxItems = 3 -- Funktion die die benötigte Erfahrung für das nächste Level berechnet -- Sollte polynomiell/exponentiell mit dem Level wachsen. -- Ein sehr nützliches Tool, um den asymptotischen Verlauf der Erfahrung -- abzuschätzen findet man unter: http://www.mathe-fa.de gvHeroLevelSystem.Config.NextLevel = function(_currentLevel) local neededExperience = gvHeroLevelSystem.Config.BaseLevelExperience -- Zum Beispiel: Polynom 2. Grades mit Base=100 -- f(x) = Base * (1+x)^2 / 4 -- f(1) = 100, f(9) = 2500, f(14) = 5000, f(19) = 10000 neededExperience = neededExperience * (1 + _currentLevel)^2 / 4 return neededExperience end -- Zusätliche Lebenspunkte pro Level (sparsam einsetzen!) gvHeroLevelSystem.Config.HealthPerLevel = 100 -- Zusätzliche Schadenpunkte pro Level -- Eine Lvl4 Kanone hat 75 Schaden, nur als Hinweis... gvHeroLevelSystem.Config.DamagePerLevel = 8 -- Zusätzliche Verteidigung pro Level -- Sollte auf keinen Fall zu hoch gewählt werden! gvHeroLevelSystem.Config.ArmorPerLevel = 2 -- Zusätzliche Aktionspunkte pro Level gvHeroLevelSystem.Config.ActionPointsPerLevel = 50 -- Dürfen Helden wiederbelebt werden? -- Im SP _muss_ das hier auf false gesetzt werden! gvHeroLevelSystem.Config.AllowRespawn = true -- Zeit in Sekunden nach der ein Hero automatisch respawned gvHeroLevelSystem.Config.RespawnTime = 45 -- Anzahl Gold mit der man seinen Helden sofort wiederbeleben kann gvHeroLevelSystem.Config.RespawnGold = 250 -- Werden die Helden normal im MP gekauft? -- Wenn nein hier false setzen und jeden Helden mit -- HeroLevelSystem_NewHero(_id) -- in der OnGameStart() initialisieren. Für den SP Modus gilt das Gleiche! -- z.B. HeroLevelSystem_NewHero(GetEntityId("HeldVonSpieler1")) gvHeroLevelSystem.Config.BuyHeroes = true -- -- Ab hier nichts mehr ändern! -- HeroLevelSystem_InitInterface() if gvHeroLevelSystem.Config.BuyHeroes then Trigger.RequestTrigger(Events.LOGIC_EVENT_ENTITY_CREATED, nil, "HeroLevelSystem_OnEntityCreated", 1) end Trigger.RequestTrigger(Events.LOGIC_EVENT_ENTITY_HURT_ENTITY, nil, "HeroLevelSystem_OnEntityHurtEntity", 1) Trigger.RequestTrigger(Events.LOGIC_EVENT_ENTITY_DESTROYED, nil, "HeroLevelSystem_OnEntityDestroyed", 1) Trigger.RequestTrigger(Events.LOGIC_EVENT_EVERY_SECOND, nil, "HeroLevelSystem_EverySecond", 1) -- Allow multiplayer tributes function GameCallback_FulfillTribute() return 1 end end -------------------------------------------------------------------------------- -- Creates a new hero table -------------------------------------------------------------------------------- function HeroLevelSystem_NewHero(_id, _level) local Hero = {} if not _level then _level = 1 end assert(_level > 0, "Hero level must be greater zero") ---------------------------------------------------------------------------- -- Set default hero values ---------------------------------------------------------------------------- function Hero:Hero(_id, _level) self.ID = _id self.Player = GetPlayer(_id) self.Level = 1 self.Experience = 0 self.IsDead = false self.Type = Logic.GetEntityType(self.ID) self.MaxHealth = 500 + (_level - 1) * gvHeroLevelSystem.Config.HealthPerLevel self.Health = self.MaxHealth self.MaxActionPoints = 200 + (_level - 1) * gvHeroLevelSystem.Config.ActionPointsPerLevel self.ActionPoints = self.MaxActionPoints self.BaseArmor = Logic.GetEntityArmor(_id) self.ExtraArmor = (_level - 1) * gvHeroLevelSystem.Config.ArmorPerLevel self.BaseDamage = Logic.GetEntityDamage(_id) self.ExtraDamage = (_level - 1) * gvHeroLevelSystem.Config.DamagePerLevel self.Items = {} self.FoundItemRemainingTime = 0 -- Get the hero name from the stringtable - can be also a custom name local HeroName = XGUIEng.GetStringTableText("Names/" .. Logic.GetEntityTypeName(self.Type)) -- Get the player color local R, G, B = GUI.GetPlayerColor(self.Player) -- Color the hero name :) self.Name = "@color:" .. R .. "," .. G .. "," .. B .. " " .. HeroName .. " @color:255,255,255 " -- Prevent the game from hurt our hero - we will do it self MakeInvulnerable(self.ID) return self end ---------------------------------------------------------------------------- -- The hero gains some experience; called when an enemy died ---------------------------------------------------------------------------- function Hero:TakeExperience(_xp) -- Hero is dead at the moment - sorry no xp! if self.IsDead then return end -- Maximum level reached - no xp anymore if self.Level >= gvHeroLevelSystem.Config.MaxLevel then return end -- Increase xp self.Experience = self.Experience + _xp -- Enough xp for the next level - level up! if self.Experience >= gvHeroLevelSystem.Config.NextLevel(self.Level) then self:LevelUp() end end ---------------------------------------------------------------------------- -- The hero gets a level up :) ---------------------------------------------------------------------------- function Hero:LevelUp() -- Decrease experience self.Experience = math.max(0, self.Experience - gvHeroLevelSystem.Config.NextLevel(self.Level)) -- Increase level self.Level = self.Level + 1 -- Increase (maximum) health values self.MaxHealth = self.MaxHealth + gvHeroLevelSystem.Config.HealthPerLevel self.Health = math.min(self.MaxHealth, self.Health + gvHeroLevelSystem.Config.HealthPerLevel) -- Increase maximum action points self.MaxActionPoints = self.MaxActionPoints + gvHeroLevelSystem.Config.ActionPointsPerLevel -- Increase damage and armor values self.ExtraDamage = self.ExtraDamage + gvHeroLevelSystem.Config.DamagePerLevel self.ExtraArmor = self.ExtraArmor + gvHeroLevelSystem.Config.ArmorPerLevel -- Inform the player(s) about this event HeroLevelSystem_Chat(self.Name .. " hat Stufe " .. self.Level .. " erreicht!", self.Player) -- Play a sound feedback if GUI.GetPlayerID() == self.Player then Sound.PlayGUISound(Sounds.OnKlick_Select_dario, 0) end end ---------------------------------------------------------------------------- -- This function is called when someone hurts the hero ---------------------------------------------------------------------------- function Hero:TakeDamage(_attackerDamage) -- Just decrease the internal health here local hitpointsToHurt = math.max(0, _attackerDamage - (self.BaseArmor + self.ExtraArmor)) + GetRandom(3) + 1 self.Health = self.Health - hitpointsToHurt end ---------------------------------------------------------------------------- -- This function is called when the hero hurts another entity ---------------------------------------------------------------------------- function Hero:HurtEntity(_entity) -- Target is already dead or a building (no extra damage against buildings - inba;)) if IsDead(_entity) and Logic.IsBuilding(_entity) == 1 then return end -- Target is a leader - hurt the soldiers first if Logic.IsLeader(_entity) == 1 then local soldiersList = {Logic.GetSoldiersAttachedToLeader(_entity)} if soldiersList[1] > 0 then _entity = soldiersList[2] end end local hitpointsToHurt = self.ExtraDamage local targetHitpoints = Logic.GetEntityHealth(_entity) -- Give full damage against soldiers, cause they never receive damage by the game if Logic.IsEntityInCategory(_entity, EntityCategories.Soldier) == 1 then hitpointsToHurt = hitpointsToHurt + self.BaseDamage + GetRandom(4) end -- Hurt the target Logic.HurtEntity(_entity, hitpointsToHurt) -- Remember the last attacker of the target gvHeroLevelSystem.Entities[_entity] = self.ID end ---------------------------------------------------------------------------- -- Update the entity health bar on the 3D gamearea ---------------------------------------------------------------------------- function Hero:Update3DHealthBar() local maxHealth = HeroLevelSystem_GetEntityMaxHealth(self.ID) local health = HeroLevelSystem_GetEntityHealth(self.ID) local delta = (maxHealth * self.Health / self.MaxHealth) - health MakeVulnerable(self.ID) if delta > 0 then Logic.HealEntity(self.ID, delta) else Logic.HurtEntity(self.ID, -delta) end MakeInvulnerable(self.ID) end ---------------------------------------------------------------------------- -- Update hero status values ---------------------------------------------------------------------------- function Hero:UpdateStatusValues() -- Every two seconds if Counter.Tick2("Hero" .. self.ID .. "_UpdateStatusValues", 2) then -- Heal self.Health = math.min(self.MaxHealth, self.Health + 5 + GetRandom(6)) -- Refresh action points self.ActionPoints = math.min(self.MaxActionPoints, self.ActionPoints + 4 + GetRandom(math.floor(self.Level / 2))) end -- Perform item effects for _, ItemID in self.Items do Item = HeroItems_GetByID(ItemID) if Item.EffectEverySecond ~= nil then Item.EffectEverySecond(self, ItemID) end end -- Check for performed abilities for _, Ability in Abilities do if Logic.HeroIsAbilitySupported(self.ID, Ability) == 1 then local RechargeTime = Logic.HeroGetAbilityRechargeTime(self.ID, Ability) -- Check if an ability was performed and decrease the action points if Logic.HeroGetAbiltityChargeSeconds(self.ID, Ability) < RechargeTime then self.ActionPoints = self.ActionPoints - RechargeTime end -- Set the ability charge seconds to the maximum Logic.HeroSetAbilityChargeSeconds(self.ID, Ability, RechargeTime) end end end ---------------------------------------------------------------------------- -- Create the respawn tribute and countdown when the hero died ---------------------------------------------------------------------------- function Hero:InitRespawn() if gvHeroLevelSystem.Config.AllowRespawn and self.IsDead then -- Pay Gold and resurrect the hero immediately self.TributeID = AddTribute{ playerId = self.Player, text = self.Name .. " fuer " .. gvHeroLevelSystem.Config.RespawnGold .. " Gold wiederbeleben.", cost = {Gold = gvHeroLevelSystem.Config.RespawnGold}, Callback = function() self:Respawn() end } -- The hero always respawns after a certain time self.RespawnCountdown = StartCountdown(gvHeroLevelSystem.Config.RespawnTime, function() self:Respawn() end) return true else return false end end ---------------------------------------------------------------------------- -- Destroy the respawn countdown/tribute ---------------------------------------------------------------------------- function Hero:StopRespawn() if gvHeroLevelSystem.Config.AllowRespawn and not self.IsDead then -- Tribute Logic.RemoveTribute(self.Player, self.TributeID) -- Countdown StopCountdown(self.RespawnCountdown) end end ---------------------------------------------------------------------------- -- This function is called every second ---------------------------------------------------------------------------- function Hero:EverySecond() if not self.IsDead then self.IsDead = IsDead(self.ID) -- The hero died if self.IsDead then -- Show a message HeroLevelSystem_Chat(self.Name .. " (Stufe " .. self.Level .. ") ist gefallen.", self.Player) -- Callback HeroLevelSystem_OnEntityDestroyed(self.ID) -- Init respawn self:InitRespawn() -- Hero is still alive else -- Update status values self:UpdateStatusValues() -- Update helathbar self:Update3DHealthBar() end else self.IsDead = IsDead(self.ID) -- Hero was resurrected by friendly units if not self.IsDead then -- Update all status values once before we set the default values after resurrection self:UpdateStatusValues() -- Give him back some health... self.Health = math.floor(self.MaxHealth / 2) -- ...and action points self.ActionPoints = math.floor(self.MaxActionPoints / 3) -- Stop respawn self:StopRespawn() end end end ---------------------------------------------------------------------------- -- Resurrect the hero by the system ---------------------------------------------------------------------------- function Hero:Respawn() -- This might happen, when the hero drowned. No solution yet :( if not IsExisting(self.ID) then return end -- Drop an item self:DropItem() -- Respawn in front of the HQ or, if non exists, at the last position local position = GetPosition(self.ID) for i = 3, 1, -1 do local count, id = Logic.GetPlayerEntities(self.Player, Entities["PB_Headquarters"..i], 1) if count > 0 then position = KreisPosition(id, 1000, 0) end end -- Remove the dead body local oldID = self.ID DestroyEntity(self.ID) -- Create a new hero of the same type self.ID = CreateEntity(self.Player, self.Type, position) -- Full health now self.Health = self.MaxHealth -- Update hero table gvHeroLevelSystem.Heroes[self.ID] = gvHeroLevelSystem.Heroes[oldID] gvHeroLevelSystem.Heroes[oldID] = nil end ---------------------------------------------------------------------------- -- Give an item to the hero ---------------------------------------------------------------------------- function Hero:GiveItem(_ItemID) -- The hero can't carry one more item, maximum reached if table.getn(self.Items) >= gvHeroLevelSystem.Config.MaxItems then Message(self.Name .. " kann nicht noch mehr Items mehr tragen!") return false end local Item = HeroItems_GetByID(_ItemID) -- Check if the item can be carried if Item.Unique then for _, ItemID in self.Items do if ItemID == _ItemID then -- Hero has this item already Message(self.Name .. " hat dieses Item bereits!") return false end end end -- Perform item effect if Item.EffectOnReceipt ~= nil then Item.EffectOnReceipt(self, _ItemID) end -- Add the item to the list table.insert(self.Items, _ItemID) return true end ---------------------------------------------------------------------------- -- Remove an item from the hero ---------------------------------------------------------------------------- function Hero:RemoveItem(_ItemID) for i, ItemID in self.Items do if ItemID == _ItemID then Item = HeroItems_GetByID(_ItemID) -- Perform item effect if Item.EffectOnDrop ~= nil then Item.EffectOnDrop(self, _ItemID) end table.remove(self.Items, i) return end end end ---------------------------------------------------------------------------- -- Drops an item on the gamearea ---------------------------------------------------------------------------- function Hero:DropItem(_ItemID) local NumberOfItems = table.getn(self.Items) -- Hero has no items if NumberOfItems == 0 then return end -- Drop a random item if no ID given if not _ItemID then local i = GetRandom(NumberOfItems) + 1 _ItemID = self.Items[i].ID end -- Drop the item near the hero local Position = GetPosition(self.ID) HeroItems_CreateChest(Position, _ItemID) self:RemoveItem(_ItemID) end gvHeroLevelSystem.Heroes[_id] = Hero:Hero(_id, _level) end -------------------------------------------------------------------------------- -- Returns the hero table of the given id or false if the id was not found -------------------------------------------------------------------------------- function HeroLevelSystem_GetHero(_HeroID) return gvHeroLevelSystem.Heroes[_HeroID] or false end -------------------------------------------------------------------------------- -- Returns the number of heroes of a player and a table with all his heroes -------------------------------------------------------------------------------- function HeroLevelSystem_GetHeroesOfPlayer(_Player) local Heroes = {} for HeroID, Hero in pairs(gvHeroLevelSystem.Heroes) do if Hero.Player == _Player then table.insert(Heroes, Hero) end end return table.getn(Heroes), Heroes end -------------------------------------------------------------------------------- -- Will be called when an entity was created -------------------------------------------------------------------------------- function HeroLevelSystem_OnEntityCreated() local EntityID = Event.GetEntityID() if Logic.IsHero(EntityID) == 1 then HeroLevelSystem_NewHero(EntityID) end end -------------------------------------------------------------------------------- -- This function is called when an entity hits another entity -------------------------------------------------------------------------------- function HeroLevelSystem_DelayOneTurn(_Attacker, _Target) local Hero = HeroLevelSystem_GetHero(_Attacker) if Hero then Hero:HurtEntity(_Target) end Hero = HeroLevelSystem_GetHero(_Target) if Hero then Hero:TakeDamage(Logic.GetEntityDamage(_Attacker)) end return true end function HeroLevelSystem_OnEntityHurtEntity() local Attacker, Target = Event.GetEntityID1(), Event.GetEntityID2() if Logic.IsLeader(Target) == 1 then local soldiersList = {Logic.GetSoldiersAttachedToLeader(Target)} for i = 2, soldiersList[1] + 1 do gvHeroLevelSystem.Entities[soldiersList[i]] = Attacker end end gvHeroLevelSystem.Entities[Target] = Attacker Trigger.RequestTrigger(Events.LOGIC_EVENT_EVERY_TURN, nil, "HeroLevelSystem_DelayOneTurn", 1, nil, {Attacker, Target}) end -------------------------------------------------------------------------------- -- This function is called when an entity was destroyed or a hero died -------------------------------------------------------------------------------- function HeroLevelSystem_OnEntityDestroyed(_entity) if not _entity then _entity = Event.GetEntityID() if Logic.IsHero(_entity) == 1 then return end end local attacker = gvHeroLevelSystem.Entities[_entity] if not IsValid(attacker) then return end local xp = 0 if Logic.IsSerf(_entity) == 1 then xp = 5 elseif Logic.IsBuilding(entity) == 1 then return elseif Logic.IsEntityInCategory(_entity, EntityCategories.Military) == 0 then return elseif Logic.IsEntityInCategory(_entity, EntityCategories.Hero) == 1 then local Hero = HeroLevelSystem_GetHero(_entity) if Hero then xp = Hero.Level * 50 else xp = 100 end elseif Logic.IsEntityInCategory(_entity, EntityCategories.Cannon) == 1 then xp = 20 elseif Logic.IsEntityInCategory(_entity, EntityCategories.Leader) == 1 then xp = 30 elseif Logic.IsEntityInCategory(_entity, EntityCategories.Soldier) == 1 then xp = 15 end local Player = GetPlayer(attacker) local Position = GetPosition(_entity) -- Get all near heroes in range local NearHeroes = {} for p = 1, gvMission.HumanPlayers do -- Must be an enemy, of course if Logic.GetDiplomacyState(Player, p) == Diplomacy.Hostile then -- Is a hero of this player in range? if Logic.IsPlayerEntityOfCategoryInArea(p, Position.X, Position.Y, gvHeroLevelSystem.Config.MaxDistance, "Hero") == 1 then -- Yes, get all heroes and find out which heroes are near the target local Count, Heroes = HeroLevelSystem_GetHeroesOfPlayer(p) for _, Hero in Heroes do if IsNear(_entity, Hero.ID, gvHeroLevelSystem.Config.MaxDistance) then table.insert(NearHeroes, Hero) end end end end end -- For all near heroes: XP and gold, shared with all other near heroes NumberOfNearHeroes = table.getn(NearHeroes) for _, Hero in NearHeroes do -- Give experience Hero:TakeExperience(math.floor(xp / NumberOfNearHeroes + 0.5)) end gvHeroLevelSystem.Entities[_entity] = nil end -------------------------------------------------------------------------------- -- This function is called every second -------------------------------------------------------------------------------- function HeroLevelSystem_EverySecond() for id, hero in pairs(gvHeroLevelSystem.Heroes) do hero:EverySecond() end -- Item chest quest if HeroItems_EverySecond ~= nil then HeroItems_EverySecond() end end -------------------------------------------------------------------------------- -- Initialise the user interface -------------------------------------------------------------------------------- function HeroLevelSystem_InitInterface() ---------------------------------------------------------------------------- -- This shows the real maximum of health of a hero ---------------------------------------------------------------------------- HeroLevelSystem_GetEntityMaxHealth = Logic.GetEntityMaxHealth Logic.GetEntityMaxHealth = function(_EntityID) local Hero = HeroLevelSystem_GetHero(_EntityID) if Hero then -- Additional hero information HeroLevelSystem_DetailsHero(_EntityID) return Hero.MaxHealth else return HeroLevelSystem_GetEntityMaxHealth(_EntityID) end end ---------------------------------------------------------------------------- -- This shows the real current health of a hero ---------------------------------------------------------------------------- HeroLevelSystem_GetEntityHealth = Logic.GetEntityHealth Logic.GetEntityHealth = function(_EntityID) local Hero = HeroLevelSystem_GetHero(_EntityID) if Hero then return Hero.Health else return HeroLevelSystem_GetEntityHealth(_EntityID) end end ---------------------------------------------------------------------------- -- This shows the real damage amount of a hero ---------------------------------------------------------------------------- HeroLevelSystem_GetEntityDamage = Logic.GetEntityDamage Logic.GetEntityDamage = function(_EntityID) local Hero = HeroLevelSystem_GetHero(_EntityID) if Hero then return Hero.BaseDamage + Hero.ExtraDamage else return HeroLevelSystem_GetEntityDamage(_EntityID) end end ---------------------------------------------------------------------------- -- This shows the real armor amount of a hero ---------------------------------------------------------------------------- HeroLevelSystem_GetEntityArmor = Logic.GetEntityArmor Logic.GetEntityArmor = function(_EntityID) local Hero = HeroLevelSystem_GetHero(_EntityID) if Hero then return Hero.BaseArmor + Hero.ExtraArmor else return HeroLevelSystem_GetEntityArmor(_EntityID) end end ---------------------------------------------------------------------------- -- Update the hero details widget ---------------------------------------------------------------------------- HeroLevelSystem_DetailsHero = function(_EntityID) local Hero = HeroLevelSystem_GetHero(_EntityID) if not Hero then XGUIEng.ShowWidget(XGUIEng.GetWidgetID("TooltipBottom"), 0) return end -- Hero name and level local Text = Hero.Name .. " (Stufe " .. Hero.Level -- Experience if Hero.Level < gvHeroLevelSystem.Config.MaxLevel then local Experience = math.floor(Hero.Experience / gvHeroLevelSystem.Config.NextLevel(Hero.Level) * 100) Text = Text .. " => Stufe " .. (Hero.Level + 1) .. ": " .. Experience .. "%" end Text = Text .. ")" -- ActionPoints Text = Text .. " @cr Aktionspunkte: " .. Hero.ActionPoints .. "/" .. Hero.MaxActionPoints -- Items local NumberOfItems = table.getn(Hero.Items) if NumberOfItems > 0 then Text = Text .. " @cr Items: " local i = 1 for _, ItemID in Hero.Items do local Item = HeroItems_GetByID(ItemID) Text = Text .. Item.Name if i ~= NumberOfItems then Text = Text .. ", " end i = i + 1 end end -- Open item chest if Hero.FoundItemRemainingTime ~= 0 then Text = Text .. " @cr Kiste mit " .. Hero.FoundItem.Name .. " wird geoeffnet..." .. Hero.FoundItemRemainingTime end -- Update Tooltip text XGUIEng.ShowWidget(XGUIEng.GetWidgetID("TooltipBottom"), 1) XGUIEng.SetText(gvGUI_WidgetID.TooltipBottomCosts, "") XGUIEng.SetText(gvGUI_WidgetID.TooltipBottomText, Text) XGUIEng.SetText(gvGUI_WidgetID.TooltipBottomShortCut, "") end ---------------------------------------------------------------------------- -- Show or hide the tooltip widget with the hero details when the selection changed ---------------------------------------------------------------------------- HeroLevelSystem_SelectionChanged = GameCallback_GUI_SelectionChanged GameCallback_GUI_SelectionChanged = function() HeroLevelSystem_SelectionChanged() HeroLevelSystem_DetailsHero(GUI.GetSelectedEntity()) end ---------------------------------------------------------------------------- -- Enable or disable the ability buttons in subject to the available action points ---------------------------------------------------------------------------- HeroLevelSystem_HeroAbility = GUIUpdate_HeroAbility GUIUpdate_HeroAbility = function(_ability, _button) local HeroID = HeroSelection_GetCurrentSelectedHeroID() local Hero = HeroLevelSystem_GetHero(HeroID) if Hero then local CurrentWidgetID = XGUIEng.GetCurrentWidgetID() XGUIEng.SetMaterialColor(CurrentWidgetID, 1, 0, 0, 0, 0) local NeededActionPoints = Logic.HeroGetAbilityRechargeTime(HeroID, _ability) if Hero.ActionPoints >= NeededActionPoints then XGUIEng.DisableButton(_button, 0) end if Hero.ActionPoints < NeededActionPoints then XGUIEng.DisableButton(_button, 1) end else HeroLevelSystem_HeroAbility(_ability, _button) end end ---------------------------------------------------------------------------- -- Use the chatsystem when network exists. So everyone will see the custom hero name :) ---------------------------------------------------------------------------- if XNetwork and XNetwork.Manager_DoesExist() == 1 then HeroLevelSystem_Chat = function(_message, _player) if _player == GUI.GetPlayerID() then XNetwork.Chat_SendMessageToAll(_message) end end else HeroLevelSystem_Chat = Message end end ===== Code für Items ===== --++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -- HeroItems.lua -- Functions to create items and to control the item-chests. -- Defines also some basic items. -- -- Item table description: -- .ID Internal name of the item -- .Name The displayed name of the item -- .Unique Set to true if the hero can carray only one item of -- this type (optional) -- .Probability The chance of the apperance of this item. -- Value must be in range [0; 1] -- .EffectOnReceipt A callback function that defines the behaviour of -- the item after receipt (optional) -- .EffectEverySecond A callback function that defines the behaviour of -- the item every second -- .EffectOnDrop A callback function that defines the behaviour of -- the item when it is dropped --++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ HeroItems = {} gvHeroItems_List = {} gvHeroItems_Chests = {} function HeroItems_GetByID(_ItemID) return gvHeroItems_List[_ItemID] end -------------------------------------------------------------------------------- -- Create a new item -------------------------------------------------------------------------------- function HeroItems_Create(_ItemDescription) table.insert(gvHeroItems_List, _ItemDescription) HeroItems[_ItemDescription.ID] = table.getn(gvHeroItems_List) end -------------------------------------------------------------------------------- -- Create a chest with an item -------------------------------------------------------------------------------- function HeroItems_CreateChest(_Position, _ItemID) local ChestID = CreateEntity(0, Entities.XD_ChestClose, _Position) gvHeroItems_Chests[ChestID] = _ItemID return ChestID end -------------------------------------------------------------------------------- -- Remove an item chest from the map -------------------------------------------------------------------------------- function HeroItems_RemoveChest(_ChestID) DestroyEntity(_ChestID) table.remove(gvHeroItems_Chests, _ChestID) end -------------------------------------------------------------------------------- -- Return a random item -------------------------------------------------------------------------------- function HeroItems_GetRandom() local n = table.getn(gvHeroItems_List) local ItemID, Item, p repeat ItemID = 1 + GetRandom(n) Item = HeroItems_GetByID(ItemID) p = GetRandom(101) / 100.0 until p <= Item.Probability return ItemID end -------------------------------------------------------------------------------- -- This function handles the opening of the item chests and is called every second -------------------------------------------------------------------------------- function HeroItems_EverySecond() -- For all heroes... for _, Hero in gvHeroLevelSystem.Heroes do -- ...and all chest for ChestID, ItemID in gvHeroItems_Chests do local Item = HeroItems_GetByID(ItemID) local NeededTime = 6 local CounterName = "Hero" .. Hero.ID .. "Chest" .. ChestID -- Create a counter if not Counter.IsValid(CounterName) then Counter.SetLimit(CounterName, NeededTime) end -- Check if a hero is near this chest if IsNear(Hero.ID, ChestID, 250) and not Hero.IsDead then -- Need five seconds to open the chest if Counter.Tick(CounterName) then -- Hero has taken this item, remove the chest and give a sound feedback if Hero:GiveItem(ItemID) then Hero.FoundItemRemainingTime = 0 -- Remove the chest HeroItems_RemoveChest(ChestID) Message(Item.Name .. " @color:255,255,255 gefunden!") Sound.PlayGUISound(Sounds.OnKlick_Select_erec, 0) end -- Show item description and the remaining time that is needed to open the chest else Hero.FoundItemRemainingTime = NeededTime - Counter.GetTick(CounterName) Hero.FoundItem = Item end -- Ignore all other chests; a hero can only open one chest at the same time break -- The hero is not near this chest else Counter.Reset(CounterName) Hero.FoundItemRemainingTime = 0 end end end end ===== Beispiele für Items ===== -------------------------------------------------------------------------------- -- Define some basic items -------------------------------------------------------------------------------- -- Ring of regeneration HeroItems_Create{ ID = "RingOfRegeneration", Name = "Ring der Regeneration", Unique = true, Probability = 0.05, EffectEverySecond = function(_Hero) _Hero.Heath = math.min(_Hero.MaxHealth, _Hero.Health + 1 + GetRandom(3)) end, } -- Heavy Armor HeroItems_Create{ ID = "HeavyArmor", Name = "Schwere Ruestung", Unique = true, Probability = 0.10, EffectOnReceipt = function(_Hero, _ItemID) _Hero.ExtraArmor = _Hero.ExtraArmor + 2 end, EffectOnDrop = function(_Hero, _ItemID) _Hero.ExtraArmor = _Hero.ExtraArmor - 2 end, } -- Small Heal Potion HeroItems_Create{ ID = "SmallHealPotion", Name = "Schwacher Heiltrank", Probability = 0.75, EffectEverySecond = function(_Hero, _ItemID) if _Hero.Health <= 25 then _Hero.Health = math.min(_Hero.MaxHealth, _Hero.Health + 100) _Hero:RemoveItem(_ItemID) end end, }