[[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,
}