1740 lines
54 KiB
Lua
1740 lines
54 KiB
Lua
local mod_gui = require("mod-gui")
|
|
|
|
require "util"
|
|
require "particles"
|
|
--local modsprites = require("prototypes.sprites")
|
|
local format_number = util.format_number
|
|
local stg_critical_interval = 1.5
|
|
--[[
|
|
** RPG SYSTEM **
|
|
by ProjectMakers (Fork from MFerrari)
|
|
]]
|
|
|
|
function shortnumberstring(number)
|
|
local steps = {
|
|
{1,""},
|
|
{1e3,"k"},
|
|
{1e6,"m"},
|
|
{1e9,"g"},
|
|
{1e12,"t"},
|
|
}
|
|
for _,b in ipairs(steps) do
|
|
if b[1] <= number+1 then
|
|
steps.use = _
|
|
end
|
|
end
|
|
local result = string.format("%.1f", number / steps[steps.use][1])
|
|
if tonumber(result) >= 1e3 and steps.use < #steps then
|
|
steps.use = steps.use + 1
|
|
result = string.format("%.1f", tonumber(result) / 1e3)
|
|
end
|
|
return result .. steps[steps.use][2]
|
|
end
|
|
|
|
function RPG_format_number(number)
|
|
local result
|
|
if number < 1000000000 then result=format_number(number)
|
|
else result=shortnumberstring(number) end
|
|
return result
|
|
end
|
|
|
|
|
|
|
|
function Log(what)
|
|
game.write_file("myrpg.log", serpent.block(what), true)
|
|
end
|
|
|
|
|
|
local colors = {
|
|
white = {r = 1, g = 1, b = 1},
|
|
black = {r = 0, g = 0, b = 0},
|
|
darkgrey = {r = 0.25, g = 0.25, b = 0.25},
|
|
grey = {r = 0.5, g = 0.5, b = 0.5},
|
|
lightgrey = {r = 0.75, g = 0.75, b = 0.75},
|
|
|
|
red = {r = 1, g = 0, b = 0},
|
|
darkred = {r = 0.5, g = 0, b = 0},
|
|
lightred = {r = 1, g = 0.5, b = 0.5},
|
|
green = {r = 0, g = 1, b = 0},
|
|
darkgreen = {r = 0, g = 0.5, b = 0},
|
|
lightgreen = {r = 0.5, g = 1, b = 0.5},
|
|
blue = {r = 0, g = 0, b = 1},
|
|
darkblue = {r = 0, g = 0, b = 0.5},
|
|
lightblue = {r = 0.5, g = 0.5, b = 1},
|
|
|
|
orange = {r = 1, g = 0.55, b = 0.1},
|
|
yellow = {r = 1, g = 1, b = 0},
|
|
pink = {r = 1, g = 0, b = 1},
|
|
purple = {r = 0.6, g = 0.1, b = 0.6},
|
|
brown = {r = 0.6, g = 0.4, b = 0.1},
|
|
}
|
|
|
|
--prototypes.sprites.charxpmod_space_suit.layers[2].tint = {1,0,0,0.5}
|
|
|
|
|
|
-- CUSTOM EVENT HANDLING --
|
|
--(remote interface is lower in the file, there I describe how to subscribe to my events)
|
|
-- if your mod alters the character bonus settings, then you should get_on_player_updated_status to make required adjusts to your mod, if necessary
|
|
local on_player_updated_status = script.generate_event_name() --uint
|
|
local on_player_level_up = script.generate_event_name() --uint
|
|
|
|
|
|
|
|
function printXP(player,XP)
|
|
if player and player.valid then
|
|
if settings.get_player_settings(player)["charxpmod_print_xp_user"].value then
|
|
player.surface.create_entity{name = "flying-text", position = player.position, text = "+" .. RPG_format_number(XP) ..' XP', color = colors.yellow}
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
function ResetXPTables()
|
|
local xp = 1500
|
|
global.xp_table = {[1] = xp}
|
|
local mp = 1.6
|
|
local red = 0.018
|
|
--local maxL = settings.startup["charxpmod_xp_maxlevel"].value
|
|
|
|
local maxi = global.setting_max_player_level
|
|
|
|
local m
|
|
for k=2,maxi do
|
|
m = mp - k*(red-red*k/ maxi) -- (Multiplier - Level * (reductor-reductor*Level/100))
|
|
xp = math.ceil(xp * m)
|
|
if (xp / global.xp_table[k-1]) < 1.02 then
|
|
xp = global.xp_table[k-1] * 1.02
|
|
end
|
|
xp= math.ceil(xp)
|
|
global.xp_table[k] = xp
|
|
end
|
|
global.max_xp = xp
|
|
end
|
|
|
|
|
|
function SetForceValues(name)
|
|
global.kills_spawner[name] = 0
|
|
global.kills_units[name] = 0
|
|
global.kills_worms[name] = 0
|
|
global.XP[name] = 0
|
|
global.XP_GANHO[name] = 0
|
|
global.XP_TECH[name] = 0
|
|
global.XP_LEVEL[name] = 1
|
|
global.XP_LEVEL_MIN[name] = 0
|
|
global.XP_KILL_HP[name] = 0
|
|
global.XP_MAX_PLAYTIME[name] = 0
|
|
global.XP_AVG_PLAYTIME[name] = 0
|
|
end
|
|
|
|
|
|
|
|
function CheckAddPlayerStatus(name)
|
|
global.personalxp[name] = global.personalxp[name] or {}
|
|
for _, player in pairs(game.players) do
|
|
global.personalxp[name][player.name] = global.personalxp[name][player.name] or 0
|
|
--game.print(name .. player.name .. global.personalxp[name][player.name])
|
|
end
|
|
end
|
|
|
|
|
|
function VersionChange()
|
|
|
|
if global.personalxp.opt_Pick_Extender == nil then
|
|
global.personalxp.opt_Pick_Extender = {}
|
|
for _, player in pairs(game.players) do
|
|
global.personalxp.opt_Pick_Extender[player.name] = false
|
|
end
|
|
end
|
|
|
|
if global.XP_MAX_PLAYTIME == nil then
|
|
global.XP_MAX_PLAYTIME={}
|
|
for name, force in pairs (game.forces) do
|
|
if name~='neutral' and name~='enemy' then
|
|
global.XP_MAX_PLAYTIME[name] = 0
|
|
end
|
|
end
|
|
end
|
|
|
|
if global.XP_AVG_PLAYTIME == nil then
|
|
global.XP_AVG_PLAYTIME={}
|
|
for name, force in pairs (game.forces) do
|
|
if name~='neutral' and name~='enemy' then
|
|
global.XP_AVG_PLAYTIME[name] = 0
|
|
end
|
|
end
|
|
end
|
|
|
|
CheckAddPlayerStatus('rocketsXP_count')
|
|
|
|
end
|
|
|
|
|
|
function SetupPlayer(player,ResetXP)
|
|
local name= player.name
|
|
|
|
if ResetXP then
|
|
global.personalxp.XP[name] = 0
|
|
global.personalxp.Death[name] = 0
|
|
global.personal_kill_units[name] = 0
|
|
global.personal_kill_spawner[name] = 0
|
|
global.personal_kill_turrets[name] = 0
|
|
end
|
|
|
|
global.personalxp.Level[name] = 1
|
|
Reset_Character_Bonuses(player.character)
|
|
|
|
for k=1,#global.Player_Attributes do
|
|
local attrib = global.Player_Attributes[k]
|
|
global.personalxp[attrib][name]= 0
|
|
end
|
|
|
|
global.personalxp.opt_Pick_Extender[name] = false
|
|
|
|
UpdatePlayerLvStats(player)
|
|
end
|
|
|
|
function CheckPlayers()
|
|
for _, player in pairs(game.players) do
|
|
if not (global.personalxp.Level[player.name]) then
|
|
SetupPlayer(player,true)
|
|
end
|
|
|
|
if not global.personal_kill_units[player.name] then
|
|
global.personal_kill_units[player.name] = 0
|
|
global.personal_kill_spawner[player.name] = 0
|
|
global.personal_kill_turrets[player.name] = 0
|
|
end
|
|
|
|
InitPlayerGui(player)
|
|
end
|
|
end
|
|
|
|
function CheckPlayer(player)
|
|
if not (global.personalxp.Level[player.name]) then
|
|
SetupPlayer(player,true)
|
|
end
|
|
end
|
|
|
|
|
|
|
|
|
|
function ReadRunTimeSettings(event)
|
|
global.setting_print_critical = false
|
|
global.setting_afk_time = 15
|
|
global.setting_time_ratio_xp = true
|
|
global.setting_death_penal = 30
|
|
|
|
if event and event.setting_type=='runtime-per-user' and event.setting=='charxpmod_hide_xp_panel' then
|
|
local player = game.players[event.player_index]
|
|
player.gui.top.chartopframe.visible = not settings.get_player_settings(player)["charxpmod_hide_xp_panel"].value
|
|
end
|
|
end
|
|
|
|
|
|
|
|
|
|
function XPModSetup()
|
|
global.handle_respawn = global.handle_respawn or {}
|
|
global.last_critical_effect_from = global.last_critical_effect_from or {}
|
|
|
|
global.Player_Attributes = {
|
|
"LV_Health_Bonus",
|
|
"LV_Armor_Bonus",
|
|
"LV_Damage_Bonus",
|
|
"LV_Damage_Critical",
|
|
"LV_Run_Speed",
|
|
"LV_Craft_Speed",
|
|
"LV_Mining_Speed",
|
|
"LV_Inv_Bonus",
|
|
"LV_InvTrash_Bonus",
|
|
"LV_Robot_Bonus",
|
|
"LV_Reach_Dist",
|
|
}
|
|
|
|
global.setting_allow_xp_by_tech = true
|
|
global.setting_allow_xp_by_kill = true
|
|
global.setting_allow_xp_by_rocket = true
|
|
global.setting_allow_xp_by_mining = true
|
|
global.XP_Mult = 1
|
|
global.setting_allow_damage_attribs = false
|
|
global.setting_max_player_level = 200
|
|
global.setting_max_level_ability = 50
|
|
|
|
|
|
|
|
ReadRunTimeSettings()
|
|
|
|
|
|
|
|
if global.CharXPMOD == nil then
|
|
global.CharXPMOD = 1
|
|
global.kills_spawner={}
|
|
global.kills_units={}
|
|
global.kills_worms={}
|
|
global.XP={}
|
|
global.XP_GANHO={}
|
|
global.XP_KILL_HP={}
|
|
global.XP_TECH={}
|
|
global.XP_LEVEL={}
|
|
global.XP_LEVEL_MIN={}
|
|
global.XP_MAX_PLAYTIME={}
|
|
global.XP_AVG_PLAYTIME={}
|
|
|
|
global.personalxp = {}
|
|
global.personalxp.Level = {}
|
|
global.personalxp.XP = {}
|
|
global.personalxp.Death = {}
|
|
|
|
|
|
|
|
for k=1,#global.Player_Attributes do
|
|
global.personalxp[global.Player_Attributes[k]]= {}
|
|
end
|
|
|
|
global.personalxp.opt_Pick_Extender = {}
|
|
|
|
for name, force in pairs (game.forces) do
|
|
if name~='neutral' and name~='enemy' then
|
|
SetForceValues(name)
|
|
end
|
|
end
|
|
end
|
|
|
|
ResetXPTables()
|
|
|
|
|
|
mySettingsrpg = {
|
|
charxpmod_LV_Health_Bonus = {
|
|
value = 10,
|
|
},
|
|
charxpmod_LV_Armor_Bonus = {
|
|
value = 1,
|
|
},
|
|
charxpmod_LV_Run_Speed = {
|
|
value = 3,
|
|
},
|
|
charxpmod_LV_Damage_Bonus = {
|
|
value = 2,
|
|
},
|
|
charxpmod_LV_Damage_Critical = {
|
|
value = 1,
|
|
},
|
|
charxpmod_LV_Craft_Speed = {
|
|
value = 5,
|
|
},
|
|
charxpmod_LV_Mining_Speed = {
|
|
value = 5,
|
|
},
|
|
charxpmod_LV_Reach_Dist = {
|
|
value = 1,
|
|
},
|
|
charxpmod_LV_Inv_Bonus = {
|
|
value = 1,
|
|
},
|
|
charxpmod_LV_InvTrash_Bonus = {
|
|
value = 1,
|
|
},
|
|
charxpmod_LV_Robot_Bonus = {
|
|
value = 1,
|
|
},
|
|
|
|
}
|
|
|
|
global.RPG_Bonus = {}
|
|
for k=1,#global.Player_Attributes do
|
|
local attrib = global.Player_Attributes[k]
|
|
global.RPG_Bonus[attrib]= mySettingsrpg ["charxpmod_"..attrib].value
|
|
CheckAddPlayerStatus(attrib)
|
|
end
|
|
|
|
global.personal_kill_units = global.personal_kill_units or {}
|
|
global.personal_kill_spawner = global.personal_kill_spawner or {}
|
|
global.personal_kill_turrets = global.personal_kill_turrets or {}
|
|
|
|
VersionChange()
|
|
CheckPlayers()
|
|
end
|
|
|
|
|
|
function ResetAll()
|
|
ResetXPTables()
|
|
for name, force in pairs (game.forces) do
|
|
if name~='neutral' and name~='enemy' then
|
|
SetForceValues(name)
|
|
end
|
|
end
|
|
for _, player in pairs(game.players) do
|
|
SetupPlayer(player,true)
|
|
UpdatePanel(player)
|
|
end
|
|
end
|
|
|
|
|
|
function ResetPointSpent()
|
|
ResetXPTables()
|
|
|
|
for _, player in pairs(game.players) do
|
|
SetupPlayer(player,false)
|
|
end
|
|
end
|
|
|
|
|
|
|
|
function InitPlayerGui(player)
|
|
|
|
local name = player.name
|
|
|
|
-- close main panel
|
|
local frame = player.gui.center["char-panel"] or player.gui.screen["char-panel"]
|
|
if frame then frame.destroy() end
|
|
|
|
-- remove previous versions
|
|
if player.gui.top.chartopframe then player.gui.top.chartopframe.destroy() end
|
|
if player.gui.top.btcharxp then player.gui.top.btcharxp.destroy() end
|
|
|
|
-- create new ones
|
|
local Topframe = player.gui.top.add{name="chartopframe", direction = "horizontal", type="frame", style=mod_gui.frame_style, visible = false}
|
|
Topframe.style.minimal_height = 30
|
|
-- Topframe.style.maximal_height = 37
|
|
Topframe.style.minimal_width = 150
|
|
-- Topframe.style.maximal_width = 250
|
|
--snouz
|
|
Topframe.style.margin = {0,10,5,10}
|
|
Topframe.style.padding = {0,9,0,0}
|
|
|
|
Topframe.add{name="btcharxp", type="sprite-button", sprite = "entity/character", tooltip = {"panel-title", player.name}, style = mod_gui.top_button_style, visible = false} -- "mod_gui_button"}
|
|
|
|
local tabFrame = Topframe.add{type = "table", name = "tabtopframexp", column_count = 1, visible = false}
|
|
Level = global.personalxp.Level[name]
|
|
local pnivel = tabFrame.add{type="label", name='chartoplvtxt', caption={'actual_lv',Level}, visible = false}
|
|
pnivel.style.font="charxpmod_font_17b"
|
|
local TopXPbar = tabFrame.add{type = "progressbar", name = "TopXPbar", visible = false}
|
|
TopXPbar.style.width=110
|
|
UpdatePanel(player)
|
|
end
|
|
|
|
|
|
----------------------------------------------------------------------------------------------------------
|
|
----------------------------------------------------------------------------------------------------------
|
|
----------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
function RatioXP(player)
|
|
local ratioXP = 1
|
|
if global.setting_time_ratio_xp and global.XP_AVG_PLAYTIME[player.force.name]>0 then
|
|
ratioXP = player.online_time/global.XP_AVG_PLAYTIME[player.force.name]
|
|
if ratioXP >= 1.10 then ratioXP = 1.10
|
|
elseif ratioXP < 0.05 then ratioXP = 0.05 end
|
|
end
|
|
return ratioXP
|
|
end
|
|
|
|
|
|
function XP_Player_upd()
|
|
|
|
for name, force in pairs (game.forces) do
|
|
if name~='neutral' and name~='enemy' then
|
|
|
|
local cp = #force.connected_players
|
|
local afk = global.setting_afk_time
|
|
if cp>0 then
|
|
local XP = global.XP[name] --math.ceil(global.XP[name] / cp)
|
|
|
|
if XP>0 then
|
|
for p, PL in pairs (force.connected_players) do
|
|
if afk==0 or PL.afk_time<afk*3600 then
|
|
local ratioXP = RatioXP(PL)
|
|
XP = math.ceil(XP*ratioXP)
|
|
global.personalxp.XP[PL.name] = global.personalxp.XP[PL.name] + XP
|
|
printXP(PL,XP)
|
|
UpdatePanel(PL)
|
|
end
|
|
end
|
|
end
|
|
global.XP[name]=0
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
function XP_PlayerLv_upd()
|
|
|
|
for _, player in pairs(game.players) do
|
|
if player.connected then
|
|
local name = player.name
|
|
local Lv = global.personalxp.Level[name]
|
|
if global.personalxp.XP[name]>global.max_xp then
|
|
global.personalxp.Level[name]=global.setting_max_player_level
|
|
else
|
|
|
|
for L=Lv, #global.xp_table do
|
|
if global.personalxp.XP[name]< global.xp_table[L] then
|
|
global.personalxp.Level[name]=L
|
|
break
|
|
end
|
|
end end
|
|
|
|
if global.personalxp.Level[name] > Lv then
|
|
--player.print({'player_lv_up',global.personalxp.Level[name]})
|
|
--mod_gui.get_button_flow(player).focus()
|
|
--player.gui.top.chartopframe.focus()
|
|
player.play_sound{path = 'player_level_up',volume_modifier=0.85}
|
|
script.raise_event(on_player_level_up, {player_index = player.index, player_level = global.personalxp.Level[name]})
|
|
end
|
|
UpdatePanel(player)
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
function XP_Time_upd()
|
|
for name, force in pairs (game.forces) do
|
|
if name~='neutral' and name~='enemy' then
|
|
local PT
|
|
local TT=0
|
|
local QP=0
|
|
|
|
for p, PL in pairs (force.players) do
|
|
PT = PL.online_time
|
|
if PT > global.XP_AVG_PLAYTIME[name]/20 then -- a player time count for avg if he has at least 5% of the avg time
|
|
TT = TT + PT
|
|
QP = QP + 1
|
|
end
|
|
|
|
if global.XP_MAX_PLAYTIME[name] < PT then
|
|
global.XP_MAX_PLAYTIME[name] = PT
|
|
end
|
|
end
|
|
if QP>0 then global.XP_AVG_PLAYTIME[name] = TT/QP end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
function XP_UPDATE_tick()
|
|
|
|
XP_Time_upd()
|
|
XP_Player_upd()
|
|
XP_PlayerLv_upd()
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function SumPointSpent(name)
|
|
local sum = 0
|
|
for k=1,#global.Player_Attributes do
|
|
local attrib = global.Player_Attributes[k]
|
|
sum = sum + global.personalxp[attrib][name]
|
|
end
|
|
return sum
|
|
end
|
|
|
|
|
|
-- MAIN RPG CHARACTER GUI
|
|
function update_char_panel(player)
|
|
XP_Time_upd()
|
|
|
|
local force = player.force.name
|
|
local painel = player.gui.center["char-panel"] or player.gui.screen["char-panel"]
|
|
local frame = painel.tabcharScroll
|
|
local name = player.name
|
|
local Level = global.personalxp.Level[name]
|
|
local HP = 0
|
|
--local playercolor = player.color
|
|
--modsprites.charxpmod_space_suit_mask.tint = playercolor
|
|
|
|
|
|
local ptime = player.online_time
|
|
local txtPTime = {"time-played", string.format("%d:%02d:%02d", math.floor(ptime / 216000), math.floor(ptime / 3600) % 60, math.floor(ptime / 60) % 60)}
|
|
|
|
local PontosXP = Level - 1 - SumPointSpent(name)
|
|
if PontosXP<0 then PontosXP=0 end
|
|
|
|
frame.add{type = "line"}
|
|
|
|
local tabChar = frame.add{type = "table", name = "tab_tbchar", column_count = 2}
|
|
|
|
local frametabChar = tabChar.add{name="frametabChar", type="frame", style=mod_gui.frame_style}
|
|
if player.character and player.character.valid then
|
|
HP = math.ceil(player.character.health)
|
|
|
|
local cam = frametabChar.add{type = "entity-preview", name='rpg_player_preview'}
|
|
|
|
--local cam = frametabChar.add({ type="camera", name="rpg_player_preview", position = player.position, zoom = 0.75 })
|
|
|
|
cam.style.width = 110 cam.style.height = 110
|
|
cam.entity=player.character
|
|
cam.style.padding = {0,-10,0,-10}
|
|
cam.style.margin = {5,0,-5,0}
|
|
else
|
|
|
|
local rpgportrait = frametabChar.add{type = "sprite", sprite = "charxpmod_space_suit"}
|
|
rpgportrait.style.padding = {0,-10,0,-10}
|
|
rpgportrait.style.margin = {5,0,-5,0}
|
|
--rpgportrait.style.width = 44.8
|
|
--rpgportrait.style.height = 84
|
|
--rpgportrait.style.margin = {2,25,4,20}
|
|
end
|
|
|
|
|
|
|
|
local tabScroll = tabChar.add{type = "scroll-pane", name = "tabScroll2", vertical_scroll_policy = "auto", horizontal_scroll_policy = "auto"}
|
|
|
|
--tabScroll.style.height = 120
|
|
tabScroll.style.padding = {-5,0,5,10}
|
|
|
|
local tabPName = tabScroll.add{type = "table", name = "tab_pname", column_count = 1}
|
|
|
|
local pnivel = tabPName.add{type="label", name='ocharlevel', caption={'actual_lv',Level}}
|
|
pnivel.style.font = "charxpmod_font_30"
|
|
--pnivel.style.font_color = player.color
|
|
pnivel.style.bottom_padding = -5
|
|
|
|
|
|
|
|
-- XP RATIO
|
|
local ratioXP = RatioXP(player)
|
|
ratioXP = math.floor(ratioXP*100)
|
|
|
|
|
|
local tabStats = tabScroll.add{type = "table", name = "tabStats", column_count = 1}
|
|
|
|
|
|
local wd = 160
|
|
tabStats.add{type="label", name='STT1', caption=txtPTime}.style.width = wd
|
|
tabStats.add{type="label", name='STT3', caption={'xp_ratio',ratioXP}} --.style.width = wd
|
|
tabStats.add{type="label", name='STT2', caption={'xp_deaths',global.personalxp.Death[name]}}.style.width = wd
|
|
tabStats.add{type="label", name='STT5', caption='HP: '.. format_number(HP)}.style.width = wd
|
|
|
|
|
|
|
|
|
|
local pbvalue = CalculateXP_PB(player.name)
|
|
local XP = global.personalxp.XP[name]
|
|
local NextLevel = global.xp_table[Level]
|
|
|
|
local NextLtxt = RPG_format_number(NextLevel)
|
|
if XP >= global.max_xp then NextLtxt = 'MAX' end
|
|
|
|
|
|
frame.add{type = "line"}
|
|
|
|
---------------XP NUMBERS
|
|
|
|
|
|
local flowXP = frame.add{type = "flow", direction="horizontal"}
|
|
flowXP.style.width = 450
|
|
local currXP = flowXP.add{type="label", name='lbxpatual', caption='XP: ' .. RPG_format_number( XP ) } --.style.font="charxpmod_font_17"
|
|
currXP.style.font='default-bold'
|
|
local stretchableFlow = flowXP.add{type = "flow", direction="horizontal"}
|
|
stretchableFlow.style.horizontally_stretchable = true
|
|
local flownextXP = flowXP.add{type = "flow", direction="horizontal"}
|
|
flownextXP.style.horizontal_align = "right"
|
|
flownextXP.style.width = 200
|
|
local nextXP = flownextXP.add{type="label", caption={'next_lv', NextLtxt}} --.style.font="charxpmod_font_17"
|
|
|
|
|
|
----------------XP BAR
|
|
|
|
local btAttribute2 = frame.add{type="sprite-button", sprite = "info11", name="info22", tooltip = { "xp_hint_global.personalxp.LV_Info" } }
|
|
|
|
btAttribute2.style.width = 70
|
|
btAttribute2.style.height = 70
|
|
btAttribute2.style.margin = {0,0,0,0}
|
|
btAttribute2.style.padding = {0,0,0,0}
|
|
|
|
local tabBar = frame.add{type = "table", column_count = 1}
|
|
|
|
local bar = tabBar.add{type = "progressbar", value = pbvalue, name = "tab_XPbar", style="achievement_progressbar"}
|
|
bar.style.width = 450
|
|
|
|
|
|
frame.add{type = "line"}
|
|
|
|
|
|
frame.add{type = "label", name = 'lbxPAGastar', caption={'xp_points',PontosXP}}.style.font="charxpmod_font_20"
|
|
|
|
-- LEVELS / UPGRADES
|
|
local tabUpgrades = frame.add{type = "table", name = "tabUpgrades", column_count = 6}
|
|
tabUpgrades.style.horizontal_spacing = 10
|
|
tabUpgrades.style.vertical_spacing = 10
|
|
|
|
|
|
local Max = global.setting_max_level_ability
|
|
local custo = 1
|
|
local vchar
|
|
local at_level
|
|
local attrib
|
|
local bonus, Tbonus
|
|
|
|
|
|
for A=1,#global.Player_Attributes do
|
|
attrib = global.Player_Attributes[A]
|
|
local enabled = true
|
|
if (attrib=="LV_Armor_Bonus" or attrib=="LV_Damage_Bonus" or attrib=="LV_Damage_Critical")
|
|
and (not global.setting_allow_damage_attribs) then enabled = false end
|
|
|
|
if global.RPG_Bonus[attrib]==0 then enabled = false end
|
|
|
|
if enabled then
|
|
|
|
vchar = 'global.personalxp.'..attrib
|
|
at_level = global.personalxp[attrib][name]
|
|
bonus = global.RPG_Bonus[attrib]
|
|
Tbonus = at_level * bonus
|
|
|
|
|
|
local tabAttrib = tabUpgrades.add{type = "table", column_count = 1}
|
|
tabAttrib.style.horizontal_align = "center"
|
|
|
|
local framebtAttributetext = tabAttrib.add{direction = "horizontal", type="frame"}
|
|
framebtAttributetext.style.width = 67 --67
|
|
framebtAttributetext.style.horizontal_align = "center"
|
|
framebtAttributetext.style.margin = {0,0,-5,0}
|
|
framebtAttributetext.style.padding = {0,0,-5,0}
|
|
local btAttributetext = framebtAttributetext.add{type="label", caption={vchar}}
|
|
btAttributetext.style.font = "charxpmod_font_12"
|
|
btAttributetext.style.width = 60 --57
|
|
btAttributetext.style.horizontal_align = "center"
|
|
btAttributetext.style.margin = {0,0,0,0}
|
|
btAttributetext.style.padding = {0,0,0,0}
|
|
local btAttribute = tabAttrib.add{type="sprite-button", sprite = attrib .. "_sprite", style = 'rounded_button', name='btLVU_'..vchar, tooltip={'xp_hint_'..vchar,format_number(bonus),format_number(Tbonus)}}
|
|
btAttribute.style.font = "charxpmod_font_icons"
|
|
btAttribute.style.width = 67
|
|
btAttribute.style.height = 67
|
|
btAttribute.style.margin = {0,0,0,0}
|
|
btAttribute.style.padding = {0,0,0,0}
|
|
btAttribute.style.horizontal_align = "center"
|
|
local frametxtAttLv = tabAttrib.add{direction = "horizontal", type="frame"}
|
|
frametxtAttLv.style.width = 67
|
|
frametxtAttLv.style.margin = {-5,0,0,0}
|
|
frametxtAttLv.style.padding = {-5,0,0,0}
|
|
frametxtAttLv.style.horizontal_align = "center"
|
|
local txtAttLv = frametxtAttLv.add{type="label", caption=at_level}
|
|
txtAttLv.style.font = "charxpmod_font_17"
|
|
txtAttLv.style.width = 57
|
|
txtAttLv.style.horizontal_align = "center"
|
|
txtAttLv.style.margin = {0,0,0,0}
|
|
txtAttLv.style.padding = {0,0,0,0}
|
|
|
|
btAttribute.enabled = PontosXP>=custo and at_level<Max
|
|
end
|
|
end
|
|
|
|
frame.add{type = "line"}
|
|
|
|
|
|
local pickbutton = frame.add{type = "checkbox", name = "cb_pick_extender", caption={'xp_opt_Pick_Extender'}, state = global.personalxp.opt_Pick_Extender[name]}
|
|
|
|
--frame.add{type="label", name='blankL4', caption=' '}
|
|
frame.add{type = "line"}
|
|
|
|
--[[TAG
|
|
local frametag = frame.add{type="flow", name="char_frametag", direction = "horizontal"}
|
|
|
|
local tabtag = frametag.add{type = "table", name = "tabchartag", column_count = 3}
|
|
tabtag.style.top_margin = 5
|
|
tabtag.add{type="label", name="lab_ctag", caption={'player_tag'}}
|
|
tabtag.add{type="textfield", name="ctag_field", text=player.tag}
|
|
|
|
|
|
local btTagOK = tabtag.add{name="btTagCharOK", type="button", style = 'rounded_button', caption='OK'}
|
|
btTagOK.style.width = 64
|
|
]]
|
|
--local btColors= tabtag.add{name="btColorsChar", type="button", style = 'confirm_double_arrow_button', caption={'panel-colors-title'}}
|
|
end
|
|
|
|
|
|
function create_gui_box(player, caption)
|
|
local frame = player.gui.left["rpg-list"]
|
|
if frame then frame.destroy() end
|
|
frame = player.gui.left.add{type="frame", name="rpg-list", direction = "vertical", style=mod_gui.frame_style, caption=caption}
|
|
local scroll = frame.add{type = "scroll-pane", name= "list-scroll", vertical_scroll_policy="auto", horizontal_scroll_policy="auto"}
|
|
local bt_destroy_my_parent = frame.add{type = "button", caption ={'close'}, name = "bt_destroy_my_parent", style = "back_button"}
|
|
return scroll
|
|
end
|
|
|
|
function ListAll(player)
|
|
local scroll = create_gui_box(player, {"players-list"})
|
|
local force = player.force
|
|
local tabpllst = scroll.add{type = "table", name = "tabpllst", column_count = 3}
|
|
for p,PL in pairs (force.players) do
|
|
local ptime = PL.online_time
|
|
local txtPTime = string.format("%d:%02d", math.floor(ptime / 216000), math.floor(ptime / 3600) % 60)
|
|
local ratioXP = math.floor(RatioXP(PL) * 100)
|
|
tabpllst.add{type="label", name='pllstname'..p, caption=PL.name .. ' '..global.personalxp.Level[PL.name] .. ' (' ..txtPTime.. ' '..ratioXP..'%)'}
|
|
end
|
|
end
|
|
|
|
|
|
function ListXPTable(player)
|
|
local scroll = create_gui_box(player, 'XP Level Table:')
|
|
for k=1,#global.xp_table do
|
|
local txt = 'Level '.. k .. ' - ' .. global.xp_table[k]
|
|
scroll.add{type="label", caption=txt}
|
|
end
|
|
end
|
|
|
|
|
|
function CalculateXP_PB(plname)
|
|
local Level = global.personalxp.Level[plname]
|
|
local XP = global.personalxp.XP[plname]
|
|
if XP > global.max_xp then XP = global.max_xp end
|
|
local NextLevel = global.xp_table[Level]
|
|
if not NextLevel then return end
|
|
local XP_ant
|
|
if Level==1 then XP_ant = 0 else XP_ant = global.xp_table[Level-1] end
|
|
local Interval_XP = NextLevel - XP_ant
|
|
local pbvalue = (XP-XP_ant)/Interval_XP
|
|
return pbvalue
|
|
end
|
|
|
|
|
|
function CalculateXP_GAIN_LV(playername)
|
|
|
|
local pbvalue = CalculateXP_PB(playername)
|
|
local Level = global.personalxp.Level[playername]
|
|
local NextLevel = global.xp_table[Level]
|
|
if not NextLevel then return end
|
|
local XP = global.personalxp.XP[playername]
|
|
|
|
local xp_to_next_level = NextLevel - XP
|
|
local next_partial = 0
|
|
|
|
if Level<global.setting_max_player_level then
|
|
next_partial = math.ceil((global.xp_table[Level+1] - NextLevel) * pbvalue)
|
|
end
|
|
|
|
return xp_to_next_level + next_partial
|
|
end
|
|
|
|
|
|
function CalculateXP_PERCENT_CURRENT_LV(playername,Perc)
|
|
|
|
local Level = global.personalxp.Level[playername]
|
|
local GainXP = 0
|
|
|
|
if Level<global.setting_max_player_level then
|
|
local NextLevel = global.xp_table[Level]
|
|
local PriorLVXP = 0
|
|
if Level>1 then PriorLVXP = global.xp_table[Level-1] end
|
|
GainXP = math.ceil((NextLevel - PriorLVXP) * Perc)
|
|
end
|
|
|
|
return GainXP
|
|
end
|
|
|
|
|
|
|
|
function UpdatePanel(player, focus)
|
|
-- BARRA DE XP tabtopframexp
|
|
local TopXPbar = player.gui.top.chartopframe.tabtopframexp.TopXPbar
|
|
local txtlv = player.gui.top.chartopframe.tabtopframexp.chartoplvtxt
|
|
|
|
local Level = global.personalxp.Level[player.name]
|
|
local pbvalue = CalculateXP_PB(player.name)
|
|
|
|
txtlv.caption={'actual_lv',Level}
|
|
TopXPbar.value=pbvalue
|
|
|
|
local frame = player.gui.center["char-panel"] or player.gui.screen["char-panel"]
|
|
if frame then expand_char_gui(player) end
|
|
|
|
end
|
|
|
|
|
|
function close_char_panel(player)
|
|
local frame = player.gui.center["char-panel"] or player.gui.screen["char-panel"]
|
|
if frame then frame.destroy() end
|
|
end
|
|
|
|
function reopen_char_panel(player)
|
|
close_char_panel(player)
|
|
expand_char_gui(player)
|
|
end
|
|
|
|
function open_close_char_gui(player)
|
|
local frame = player.gui.center["char-panel"] or player.gui.screen["char-panel"]
|
|
if frame then close_char_panel(player) else expand_char_gui(player) end
|
|
end
|
|
|
|
|
|
|
|
function expand_char_gui(player)
|
|
local wid = 470
|
|
local frame = player.gui.center["char-panel"] or player.gui.screen["char-panel"]
|
|
if not frame then
|
|
frame = player.gui.screen.add{type="frame", name="char-panel", direction = "vertical", style=mod_gui.frame_style}
|
|
frame.auto_center = true
|
|
frame.style.minimal_height = 430
|
|
--frame.style.maximal_height = 430
|
|
frame.style.minimal_width = wid
|
|
frame.style.maximal_width = 485
|
|
|
|
|
|
local title_table = frame.add{type="table", name="title_table", column_count=4, draw_horizontal_lines=false}
|
|
title_table.style.horizontally_stretchable = true
|
|
title_table.style.column_alignments[1] = "left"
|
|
title_table.style.column_alignments[2] = "right"
|
|
title_table.style.column_alignments[3] = "right"
|
|
title_table.style.column_alignments[4] = "right"
|
|
title_table.drag_target = frame
|
|
local title_frame = title_table.add{type="frame", name="title_frame", caption={"panel-title", player.name}, style="ic_title_frame"} --
|
|
title_frame.ignored_by_interaction = true
|
|
|
|
local tagfield = title_table.add{type="textfield", name="ctag_field", text=player.tag}
|
|
tagfield.style.width=200
|
|
tagfield.visible=false
|
|
|
|
local edittag = title_table.add{name="rpg_bt_edittag", type="sprite-button", sprite = "utility/rename_icon_normal", style = "shortcut_bar_button_small", tooltip={'player_tag'}}
|
|
local closeb = title_table.add{name="rpg_bt_close", type="sprite-button", sprite = "utility/close_black", style = "shortcut_bar_button_small"}
|
|
end
|
|
|
|
if frame.tabcharScroll then frame.tabcharScroll.destroy() end
|
|
local tabcharScroll = frame.add{type = "scroll-pane", name= "tabcharScroll", vertical_scroll_policy="auto", horizontal_scroll_policy="auto"}
|
|
tabcharScroll.style.minimal_height = 400
|
|
--tabcharScroll.style.maximal_height = 1000
|
|
tabcharScroll.style.minimal_width = wid - 15
|
|
tabcharScroll.style.maximal_width = wid - 15
|
|
|
|
update_char_panel(player)
|
|
end
|
|
|
|
|
|
|
|
function UpdatePlayerLvStats(player, skip_inv)
|
|
local name=player.name
|
|
|
|
if player.character then
|
|
|
|
player.character.character_crafting_speed_modifier = player.character.character_crafting_speed_modifier + global.personalxp.LV_Craft_Speed[name] * global.RPG_Bonus['LV_Craft_Speed']/100
|
|
player.character.character_mining_speed_modifier = player.character.character_mining_speed_modifier + global.personalxp.LV_Mining_Speed[name] * global.RPG_Bonus['LV_Mining_Speed']/100
|
|
player.character.character_running_speed_modifier = player.character.character_running_speed_modifier + global.personalxp.LV_Run_Speed[name] * global.RPG_Bonus['LV_Run_Speed']/100
|
|
|
|
player.character.character_build_distance_bonus = player.character.character_build_distance_bonus+ global.personalxp.LV_Reach_Dist[name] * global.RPG_Bonus['LV_Reach_Dist']
|
|
player.character.character_reach_distance_bonus = player.character.character_reach_distance_bonus+ global.personalxp.LV_Reach_Dist[name] * global.RPG_Bonus['LV_Reach_Dist']
|
|
player.character.character_item_drop_distance_bonus = player.character.character_item_drop_distance_bonus+ global.personalxp.LV_Reach_Dist[name] * global.RPG_Bonus['LV_Reach_Dist']
|
|
player.character.character_resource_reach_distance_bonus = player.character.character_resource_reach_distance_bonus+ global.personalxp.LV_Reach_Dist[name] * global.RPG_Bonus['LV_Reach_Dist']
|
|
|
|
if not skip_inv then
|
|
player.character.character_inventory_slots_bonus = player.character.character_inventory_slots_bonus + global.personalxp.LV_Inv_Bonus[name] * global.RPG_Bonus['LV_Inv_Bonus']
|
|
end
|
|
player.character.character_trash_slot_count_bonus = player.character.character_trash_slot_count_bonus + global.personalxp.LV_InvTrash_Bonus[name] * global.RPG_Bonus['LV_InvTrash_Bonus']
|
|
player.character.character_maximum_following_robot_count_bonus = player.character.character_maximum_following_robot_count_bonus + global.personalxp.LV_Robot_Bonus[name] * global.RPG_Bonus['LV_Robot_Bonus']
|
|
player.character.character_health_bonus = player.character.character_health_bonus+ global.personalxp.LV_Health_Bonus[name] * global.RPG_Bonus['LV_Health_Bonus']
|
|
|
|
if global.personalxp.opt_Pick_Extender[name] then
|
|
player.character.character_item_pickup_distance_bonus = player.character.character_reach_distance_bonus
|
|
player.character.character_loot_pickup_distance_bonus = player.character.character_reach_distance_bonus
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
|
|
local p_attribs = { 'character_crafting_speed_modifier',
|
|
'character_mining_speed_modifier',
|
|
'character_running_speed_modifier',
|
|
'character_reach_distance_bonus',
|
|
'character_item_drop_distance_bonus',
|
|
'character_resource_reach_distance_bonus',
|
|
'character_inventory_slots_bonus',
|
|
'character_trash_slot_count_bonus',
|
|
'character_maximum_following_robot_count_bonus',
|
|
'character_health_bonus',
|
|
'character_item_pickup_distance_bonus'}
|
|
|
|
function Reset_Character_Bonuses(character)
|
|
if character and character.valid then
|
|
for a=1,#p_attribs do character[p_attribs[a]]=0 end
|
|
end
|
|
end
|
|
|
|
|
|
function CopyPlayerStats(name)
|
|
local player = game.players[name]
|
|
if player and player.valid then
|
|
local character_attribs = {}
|
|
|
|
if player.character and player.character.valid then
|
|
for a=1,#p_attribs do
|
|
table.insert(character_attribs,player.character[p_attribs[a]]) end
|
|
end
|
|
|
|
local rpg_stats = {global.personalxp.Level[name],
|
|
global.personalxp.XP[name],
|
|
global.personalxp.Death[name],
|
|
global.personalxp.opt_Pick_Extender[name],
|
|
global.personal_kill_units[name],
|
|
global.personal_kill_spawner[name],
|
|
global.personal_kill_turrets[name],
|
|
}
|
|
for k=1,#global.Player_Attributes do
|
|
local attrib = global.Player_Attributes[k]
|
|
table.insert(rpg_stats, global.personalxp[attrib][name] )
|
|
end
|
|
return {character_attribs=character_attribs, rpg_stats=rpg_stats}
|
|
end
|
|
end
|
|
|
|
|
|
function PastePlayerStats(name,status)
|
|
local player = game.players[name]
|
|
if player and player.valid and status then
|
|
local character_attribs = status.character_attribs
|
|
|
|
if player.character and player.character.valid then
|
|
for a=1,#p_attribs do player.character[p_attribs[a]]=character_attribs[a] end
|
|
end
|
|
|
|
local rpg_stats = status.rpg_stats
|
|
global.personalxp.Level[name] = rpg_stats[1]
|
|
global.personalxp.XP[name] = rpg_stats[2]
|
|
global.personalxp.Death[name] = rpg_stats[3]
|
|
global.personalxp.opt_Pick_Extender[name] = rpg_stats[4]
|
|
global.personal_kill_units[name] = rpg_stats[5]
|
|
global.personal_kill_spawner[name] = rpg_stats[6]
|
|
global.personal_kill_turrets[name] = rpg_stats[7]
|
|
|
|
for k=1,#global.Player_Attributes do
|
|
local attrib = global.Player_Attributes[k]
|
|
global.personalxp[attrib][name] = rpg_stats[k+7]
|
|
end
|
|
UpdatePanel(player)
|
|
end
|
|
end
|
|
|
|
|
|
-- this will calculate the stat using sum, instead of replacing the value
|
|
-- used for compatibility with other mods
|
|
function AdjustPlayerStat(player,stat)
|
|
local name=player.name
|
|
|
|
if player.character ~= nil then
|
|
if stat=='character_crafting_speed_modifier' then
|
|
player.character[stat] = player.character[stat] + global.personalxp.LV_Craft_Speed[name] * global.RPG_Bonus['LV_Craft_Speed']/100
|
|
elseif stat=='character_mining_speed_modifier' then
|
|
player.character[stat] = player.character[stat] + global.personalxp.LV_Mining_Speed[name] * global.RPG_Bonus['LV_Mining_Speed']/100
|
|
elseif stat=='character_running_speed_modifier' then
|
|
player.character[stat] = player.character[stat] + global.personalxp.LV_Run_Speed[name] * global.RPG_Bonus['LV_Run_Speed']/100
|
|
elseif stat=='character_build_distance_bonus' then
|
|
player.character[stat] = player.character[stat] + global.personalxp.LV_Reach_Dist[name]* global.RPG_Bonus['LV_Reach_Dist']
|
|
elseif stat=='character_reach_distance_bonus' then
|
|
player.character[stat] = player.character[stat] + global.personalxp.LV_Reach_Dist[name]* global.RPG_Bonus['LV_Reach_Dist']
|
|
elseif stat=='character_item_drop_distance_bonus' then
|
|
player.character[stat] = player.character[stat] + global.personalxp.LV_Reach_Dist[name]* global.RPG_Bonus['LV_Reach_Dist']
|
|
elseif stat=='character_resource_reach_distance_bonus' then
|
|
player.character[stat] = player.character[stat] + global.personalxp.LV_Reach_Dist[name]* global.RPG_Bonus['LV_Reach_Dist']
|
|
elseif stat=='character_inventory_slots_bonus' then
|
|
player.character[stat] = player.character[stat] + global.personalxp.LV_Inv_Bonus[name] * global.RPG_Bonus['LV_Inv_Bonus']
|
|
elseif stat=='character_trash_slot_count_bonus' then
|
|
player.character[stat] = player.character[stat] + global.personalxp.LV_InvTrash_Bonus[name]* global.RPG_Bonus['LV_InvTrash_Bonus']
|
|
elseif stat=='character_maximum_following_robot_count_bonus' then
|
|
player.character[stat] = player.character[stat] + global.personalxp.LV_Robot_Bonus[name]* global.RPG_Bonus['LV_Robot_Bonus']
|
|
elseif stat=='character_health_bonus' then
|
|
player.character[stat] = player.character[stat] + global.personalxp.LV_Health_Bonus[name]* global.RPG_Bonus['LV_Health_Bonus']
|
|
elseif stat=='character_item_pickup_distance_bonus' then
|
|
if global.personalxp.opt_Pick_Extender[name] then
|
|
player.character[stat] = player.character[stat] + global.personalxp.LV_Reach_Dist[name]* global.RPG_Bonus['LV_Reach_Dist'] end
|
|
elseif stat=='character_loot_pickup_distance_bonus' then
|
|
if global.personalxp.opt_Pick_Extender[name] then
|
|
player.character[stat] = player.character[stat] + global.personalxp.LV_Reach_Dist[name]* global.RPG_Bonus['LV_Reach_Dist'] end
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function LevelUPPlayer(player,btname)
|
|
|
|
local name=player.name
|
|
|
|
for A=1,#global.Player_Attributes do
|
|
local attrib = global.Player_Attributes[A]
|
|
|
|
if btname=='btLVU_global.personalxp.'.. attrib then
|
|
global.personalxp[attrib][name] = global.personalxp[attrib][name] + 1
|
|
|
|
if btname=='btLVU_global.personalxp.LV_Craft_Speed' then
|
|
player.character.character_crafting_speed_modifier = player.character.character_crafting_speed_modifier + global.RPG_Bonus[attrib]/100 end
|
|
if btname=='btLVU_global.personalxp.LV_Mining_Speed' then
|
|
player.character.character_mining_speed_modifier = player.character.character_mining_speed_modifier + global.RPG_Bonus[attrib]/100 end
|
|
if btname=='btLVU_global.personalxp.LV_Run_Speed' then
|
|
player.character.character_running_speed_modifier = player.character.character_running_speed_modifier + global.RPG_Bonus[attrib]/100 end
|
|
|
|
if btname=='btLVU_global.personalxp.LV_Reach_Dist' then
|
|
player.character.character_build_distance_bonus = player.character.character_build_distance_bonus + global.RPG_Bonus[attrib]
|
|
player.character.character_reach_distance_bonus = player.character.character_reach_distance_bonus + global.RPG_Bonus[attrib]
|
|
player.character.character_item_drop_distance_bonus = player.character.character_item_drop_distance_bonus + global.RPG_Bonus[attrib]
|
|
player.character.character_resource_reach_distance_bonus = player.character.character_resource_reach_distance_bonus + global.RPG_Bonus[attrib] end
|
|
|
|
if btname=='btLVU_global.personalxp.LV_Inv_Bonus' then
|
|
player.character.character_inventory_slots_bonus = player.character.character_inventory_slots_bonus + global.RPG_Bonus[attrib] end
|
|
|
|
if btname=='btLVU_global.personalxp.LV_InvTrash_Bonus' then
|
|
player.character.character_trash_slot_count_bonus = player.character.character_trash_slot_count_bonus + global.RPG_Bonus[attrib] end
|
|
|
|
if btname=='btLVU_global.personalxp.LV_Robot_Bonus' then
|
|
player.character.character_maximum_following_robot_count_bonus = player.character.character_maximum_following_robot_count_bonus + global.RPG_Bonus[attrib] end
|
|
|
|
if btname=='btLVU_global.personalxp.LV_Health_Bonus' then
|
|
player.character.character_health_bonus = player.character.character_health_bonus + global.RPG_Bonus[attrib] end
|
|
|
|
script.raise_event(on_player_updated_status, {player_index = player.index, player_level = global.personalxp.Level[name], attribute=attrib})
|
|
|
|
break
|
|
end
|
|
end
|
|
|
|
|
|
|
|
if global.personalxp.opt_Pick_Extender[name] then
|
|
player.character.character_item_pickup_distance_bonus = math.min(player.character.character_reach_distance_bonus,320)
|
|
player.character.character_loot_pickup_distance_bonus = math.min(player.character.character_reach_distance_bonus,320)
|
|
else
|
|
player.character.character_item_pickup_distance_bonus = 0
|
|
player.character.character_loot_pickup_distance_bonus = 0
|
|
end
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
script.on_nth_tick(60 * 5,function (event)
|
|
XP_UPDATE_tick()
|
|
check_respawned_players()
|
|
end)
|
|
|
|
|
|
|
|
|
|
function check_respawned_players()
|
|
for name,died in pairs (global.handle_respawn) do
|
|
if died then
|
|
if game.players[name] and game.players[name].valid and game.players[name].character and game.players[name].character.valid then
|
|
global.handle_respawn[name]=false
|
|
UpdatePlayerLvStats(game.players[name])
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function Cria_Player(event)
|
|
local player = game.players[event.player_index]
|
|
SetupPlayer(player,true)
|
|
end
|
|
|
|
|
|
function on_force_created(event)
|
|
local name = event.force.name
|
|
SetForceValues(name)
|
|
end
|
|
|
|
|
|
function onPlayerJoin(event)
|
|
local player = game.players[event.player_index]
|
|
CheckPlayer(player)
|
|
InitPlayerGui(player)
|
|
end
|
|
|
|
|
|
function On_Init()
|
|
XPModSetup()
|
|
end
|
|
|
|
|
|
function on_configuration_changed(data)
|
|
XPModSetup()
|
|
end
|
|
|
|
script.on_event(defines.events.on_player_created, Cria_Player)
|
|
script.on_event(defines.events.on_player_joined_game, onPlayerJoin)
|
|
script.on_event(defines.events.on_runtime_mod_setting_changed, ReadRunTimeSettings)
|
|
|
|
--script.on_event(defines.events.on_tick, on_tick )
|
|
script.on_event(defines.events.on_force_created,on_force_created)
|
|
script.on_configuration_changed(on_configuration_changed)
|
|
script.on_init(On_Init)
|
|
script.on_event("key-I", function(event) open_close_char_gui(game.players[event.player_index]) end)
|
|
|
|
|
|
-- closes panel when player open inventory E
|
|
script.on_event(defines.events.on_gui_opened, function(event)
|
|
if event.gui_type and event.gui_type ==defines.gui_type.controller then
|
|
close_char_panel(game.players[event.player_index])
|
|
end
|
|
end)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local function on_gui_click(event)
|
|
local player = game.players[event.element.player_index]
|
|
local element = event.element
|
|
if element and element.valid then
|
|
local name = element.name
|
|
local frame = player.gui.center["char-panel"] or player.gui.screen["char-panel"]
|
|
|
|
if (name == "btcharxp") then open_close_char_gui(player)
|
|
elseif (name == "rpg_bt_edittag")then
|
|
|
|
local tagfield = element.parent.ctag_field
|
|
local text =tagfield.text
|
|
|
|
if tagfield.visible then
|
|
tagfield.visible = false
|
|
element.sprite = "utility/rename_icon_normal"
|
|
if player.tag~=text then
|
|
player.tag = text
|
|
player.print({"",{'player_tag'}, ': ', text})
|
|
end
|
|
else
|
|
tagfield.visible = true
|
|
element.sprite = "utility/check_mark_green"
|
|
end
|
|
|
|
elseif string.sub(name,1,6)=='btLVU_' then
|
|
if player.character and player.character.valid then
|
|
LevelUPPlayer(player,name)
|
|
expand_char_gui(player)
|
|
end
|
|
|
|
elseif name == "cb_pick_extender" then
|
|
if player.character == nil then
|
|
frame.tabcharScroll.cb_pick_extender.state = global.personalxp.opt_Pick_Extender[player.name]
|
|
return
|
|
end
|
|
local cb_pick_extender = frame.tabcharScroll.cb_pick_extender.state
|
|
global.personalxp.opt_Pick_Extender[player.name] = cb_pick_extender
|
|
|
|
if cb_pick_extender then
|
|
player.character.character_item_pickup_distance_bonus = player.character.character_reach_distance_bonus
|
|
player.character.character_loot_pickup_distance_bonus = player.character.character_reach_distance_bonus
|
|
else
|
|
player.character.character_item_pickup_distance_bonus = 0
|
|
player.character.character_loot_pickup_distance_bonus = 0
|
|
end
|
|
|
|
elseif name == "bt_destroy_my_parent" then if element and element.parent then element.parent.destroy() end
|
|
elseif name == "rpg_bt_close" then element.parent.parent.destroy()
|
|
|
|
end
|
|
end
|
|
end
|
|
script.on_event(defines.events.on_gui_click, on_gui_click)
|
|
|
|
|
|
|
|
script.on_event(defines.events.on_player_respawned, function(event)
|
|
local player = game.players[event.player_index]
|
|
global.handle_respawn[player.name]=false
|
|
UpdatePlayerLvStats(player)
|
|
end)
|
|
|
|
|
|
script.on_event(defines.events.on_pre_player_died, function(event)
|
|
local player = game.players[event.player_index]
|
|
local name = player.name
|
|
local XP = global.personalxp.XP[name]
|
|
local Level = global.personalxp.Level[name]
|
|
local NextLevel = global.xp_table[Level]
|
|
local XP_ant
|
|
if Level==1 then XP_ant = 0 else XP_ant = global.xp_table[Level-1] end
|
|
local Interval_XP = NextLevel - XP_ant
|
|
local Penal = math.floor((XP-XP_ant)*global.setting_death_penal/100)
|
|
global.personalxp.Death[name] = global.personalxp.Death[name]+1
|
|
global.handle_respawn[name]=true
|
|
if Penal>0 then
|
|
global.personalxp.XP[name] = global.personalxp.XP[name]-Penal
|
|
player.print({"", {'xp_lost'}, RPG_format_number(Penal)},colors.lightred)
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
|
|
function GetXPByKill(entity,killer,force)
|
|
if force then
|
|
if global.setting_allow_xp_by_kill then
|
|
if not global.last_overkill or (global.last_overkill and global.last_overkill~=entity) then
|
|
|
|
if entity and entity.valid then
|
|
local XP = entity.prototype.max_health
|
|
local player , plname
|
|
|
|
if killer and killer.valid then
|
|
if killer.is_player() then player=killer
|
|
else
|
|
if killer.type and killer.type == 'character' then
|
|
player=killer.player
|
|
force=killer.force
|
|
end
|
|
end
|
|
end
|
|
|
|
if player then plname=player.name end
|
|
|
|
local nforce=force.name
|
|
|
|
if force ~= entity.force and (not force.get_friend(entity.force)) then
|
|
|
|
if entity.type == 'character' then XP = XP * 4
|
|
elseif entity.type == 'unit' then
|
|
global.kills_units[nforce] = global.kills_units[nforce] + 1
|
|
if player then global.personal_kill_units[plname]=global.personal_kill_units[plname]+1 end
|
|
elseif entity.type == 'unit-spawner' then
|
|
XP = XP * 3
|
|
global.kills_spawner[nforce] = global.kills_spawner[nforce] +1
|
|
if player then global.personal_kill_spawner[plname]=global.personal_kill_spawner[plname]+1 end
|
|
elseif entity.type == 'turret' then
|
|
global.kills_worms[nforce] = global.kills_worms[nforce] +1
|
|
if player then global.personal_kill_turrets[plname]=global.personal_kill_turrets[plname]+1 end
|
|
XP = XP * 2
|
|
end
|
|
|
|
-- if XP > 999999 then XP=999999 end
|
|
XP = math.ceil((1+force.evolution_factor) * global.XP_Mult * XP/3)
|
|
if XP<1 then XP=1 end
|
|
|
|
local teamxp = true
|
|
if plname then
|
|
if global.personalxp.XP[plname] then
|
|
global.personalxp.XP[plname] = global.personalxp.XP[plname] + XP
|
|
printXP(player,XP)
|
|
teamxp = false
|
|
end
|
|
end
|
|
|
|
if teamxp and global.XP_KILL_HP[nforce] then
|
|
XP=math.ceil(XP/3)
|
|
global.XP_KILL_HP[nforce] = global.XP_KILL_HP[nforce] +XP
|
|
global.XP[nforce] = global.XP[nforce] + XP
|
|
end
|
|
|
|
end
|
|
end
|
|
end
|
|
end
|
|
global.last_overkill=nil
|
|
end
|
|
end
|
|
|
|
|
|
--- XP FOR KILL
|
|
script.on_event(defines.events.on_entity_died, function(event)
|
|
if not event.force then return end
|
|
|
|
|
|
local force=event.force -- force that kill
|
|
local killer=event.cause
|
|
|
|
|
|
--if event.entity.force.name == 'enemy' and force~='neutral' and force~='enemy' then --aliens
|
|
if killer and killer.valid and global.kills_units[force.name] and event.entity.force~=game.forces.neutral then
|
|
if event.entity.prototype and event.entity.prototype.max_health and (not force.get_friend(event.entity.force)) then
|
|
|
|
if killer.type=='car' then
|
|
if killer.get_driver() and killer.get_driver().valid then
|
|
killer = killer.get_driver()
|
|
elseif killer.get_passenger() and killer.get_passenger().valid then
|
|
killer = killer.get_passenger()
|
|
end
|
|
end
|
|
GetXPByKill(event.entity,killer,force)
|
|
end
|
|
end
|
|
|
|
if not killer then
|
|
if global.kills_units[force.name] and event.entity.force~=game.forces.neutral then
|
|
GetXPByKill(event.entity,killer,force)
|
|
end end
|
|
|
|
end,
|
|
{{filter = "type", type = "unit"}, {filter = "type", type = "unit-spawner"},
|
|
{filter = "type", type = "spider-vehicle"},
|
|
{filter = "type", type = "car"},{filter = "type", type = "electric-turret"},
|
|
{filter = "type", type = "artillery-turret"}, {filter = "type", type = "ammo-turret"},
|
|
{filter = "type", type = "fluid-turret"}, {filter = "type", type = "turret"},
|
|
{filter = "type", type = "character"}}
|
|
) -- event filters
|
|
|
|
|
|
|
|
function create_crithit_effect(entity,level,damage)
|
|
if string.find(entity.type, 'unit') or entity.type == 'character' or entity.type == 'turret' then
|
|
create_blood_particles(entity.surface, 300+level*10, entity.position,2+level/10)
|
|
create_guts_particles(entity.surface, 40 + level*2, entity.position,2+level/10)
|
|
else
|
|
create_remnants_particles(entity.surface, level, entity.position,1+level/10)
|
|
end
|
|
entity.surface.play_sound{path='utility/axe_fighting',position=entity.position,volume_modifier=1}
|
|
if global.setting_print_critical then
|
|
entity.surface.create_entity{name = "flying-text", position = entity.position, text = math.ceil(damage), color = colors.red}
|
|
end
|
|
end
|
|
|
|
local crit = false
|
|
if crit == true then
|
|
-- damage bonus, criticals , natural armor
|
|
script.on_event(defines.events.on_entity_damaged, function(event)
|
|
local entity = event.entity
|
|
local damage_type = event.damage_type
|
|
local original_damage_amount = event.original_damage_amount
|
|
local cause = event.cause
|
|
|
|
|
|
if cause and cause.valid and entity and entity.valid and entity.health>0 and damage_type and original_damage_amount then
|
|
|
|
-- NATURAL ARMOR
|
|
if event.final_damage_amount>0 and entity.type == 'character' then
|
|
local player = entity.player
|
|
if player and player.valid then
|
|
local armor_lv = global.personalxp.LV_Armor_Bonus[player.name]
|
|
if armor_lv>0 then
|
|
local bonus = (global.RPG_Bonus.LV_Armor_Bonus * armor_lv)
|
|
local recover = event.final_damage_amount*bonus/100
|
|
entity.health = entity.health + recover
|
|
end
|
|
end
|
|
end
|
|
|
|
-- DAMAGE BONUS
|
|
if cause.type == 'character' and damage_type.name~='poison' and damage_type.name~='cold' then
|
|
local player = cause.player
|
|
if player and player.valid then
|
|
local dmg_lv = global.personalxp.LV_Damage_Bonus[player.name]
|
|
local critical_lv = global.personalxp.LV_Damage_Critical[player.name]
|
|
local new_damage = original_damage_amount
|
|
if dmg_lv>0 then
|
|
local bonus = 1+ (global.RPG_Bonus.LV_Damage_Bonus * dmg_lv/100)
|
|
new_damage = original_damage_amount * bonus
|
|
end
|
|
|
|
-- CRITICAL HITS
|
|
if critical_lv>0 and (string.find(entity.type, 'unit') or string.find(entity.type, 'turret') or entity.type=='car'
|
|
or entity.type=='character' or entity.type=='spider-vehicle') then
|
|
local proba = 100
|
|
if damage_type.name=='fire' then proba=proba*60 end --because damage per tick
|
|
if math.random(proba)<=critical_lv * global.RPG_Bonus['LV_Damage_Critical'] then
|
|
new_damage = math.ceil(new_damage * (5 + critical_lv/2))
|
|
|
|
if (not global.last_critical_effect_from[player.name]) or global.last_critical_effect_from[player.name]+60*stg_critical_interval<game.tick then
|
|
global.last_critical_effect_from[player.name]=game.tick
|
|
create_crithit_effect(entity,critical_lv,new_damage)
|
|
end
|
|
end
|
|
end
|
|
|
|
if new_damage > original_damage_amount then
|
|
local dif = new_damage - original_damage_amount
|
|
if entity.health < dif then -- give kill xp to player because the extra damage will kill entity
|
|
GetXPByKill(entity,cause,cause.force)
|
|
global.last_overkill = event.entity
|
|
end
|
|
if entity.valid then
|
|
entity.health = entity.health + event.final_damage_amount
|
|
entity.damage(new_damage,player.force,damage_type.name) -- this fires the event again
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
|
|
end, {{filter = "type", type = "unit"}, {filter = "type", type = "unit-spawner"},
|
|
{filter = "type", type = "wall"}, {filter = "type", type = "gate"}, {filter = "type", type = "spider-vehicle"},
|
|
{filter = "type", type = "car"},{filter = "type", type = "electric-turret"},
|
|
{filter = "type", type = "artillery-turret"}, {filter = "type", type = "ammo-turret"},
|
|
{filter = "type", type = "fluid-turret"}, {filter = "type", type = "turret"},
|
|
{filter = "type", type = "character"}}) -- event filters
|
|
end
|
|
|
|
|
|
|
|
-- XP by research
|
|
script.on_event(defines.events.on_research_finished, function(event)
|
|
if global.setting_allow_xp_by_tech and game.tick > 3600 * 2 then
|
|
|
|
if event.research.force then
|
|
local force = event.research.force.name
|
|
if force~='neutral' and force~='enemy' then
|
|
if global.XP_TECH[force] then
|
|
local techXP = event.research.research_unit_count * #event.research.research_unit_ingredients
|
|
techXP = math.ceil(global.XP_Mult * techXP * (1+ (6*game.forces["enemy"].evolution_factor)))
|
|
global.XP_TECH[force] = global.XP_TECH[force] +techXP
|
|
global.XP[force] = global.XP[force] +techXP
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
|
|
|
|
|
|
-- XP by Rocket
|
|
script.on_event(defines.events.on_rocket_launched, function(event)
|
|
if global.setting_allow_xp_by_rocket then
|
|
local rocket = event.rocket
|
|
local force = rocket.force
|
|
local XP
|
|
|
|
for p, PL in pairs (force.connected_players) do
|
|
local r_count = global.personalxp.rocketsXP_count[PL.name]
|
|
if r_count == nil then r_count=0 end
|
|
XP = math.ceil(global.XP_Mult * global.personalxp.XP[PL.name]/(5+(r_count*2))) --20% inicial
|
|
global.personalxp.XP[PL.name] = global.personalxp.XP[PL.name] + XP
|
|
printXP(PL,XP)
|
|
global.personalxp.rocketsXP_count[PL.name] = r_count+1
|
|
end
|
|
end
|
|
end)
|
|
|
|
|
|
--- XP FOR Mining rocks, trees
|
|
function XPByMiningRT(player,ent)
|
|
local XP = 0
|
|
|
|
|
|
if ent.prototype.max_health then
|
|
XP=ent.prototype.max_health
|
|
if ent.type=='tree' then XP=XP/100 else XP=XP/400 end
|
|
end
|
|
|
|
|
|
if XP>0 then
|
|
local plname = player.name
|
|
XP = math.ceil(XP * global.personalxp.Level[plname] * global.XP_Mult)
|
|
global.personalxp.XP[plname] = global.personalxp.XP[plname] + XP
|
|
printXP(player,XP)
|
|
end
|
|
|
|
end
|
|
|
|
|
|
script.on_event(defines.events.on_player_mined_entity, function(event)
|
|
if global.setting_allow_xp_by_mining then
|
|
local player = game.players[event.player_index]
|
|
if not player.valid then return end
|
|
|
|
local ent = event.entity
|
|
local name= ent.name
|
|
|
|
if ent.type=='tree' or (ent.type=='simple-entity' and name:find('rock')) then
|
|
XPByMiningRT(player,ent)
|
|
end
|
|
end
|
|
end,
|
|
{{filter = "type", type = "tree"}, {filter = "type", type = "simple-entity"}}
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- INTERFACE --
|
|
--------------------------------------------------------------------------------------
|
|
-- /c remote.call("RPG","TeamXP","player",1150)
|
|
local interface = {}
|
|
|
|
-- Give XP to Team (may be negative)
|
|
function interface.TeamXP(forcename,XP)
|
|
global.XP[forcename] = global.XP[forcename] + XP
|
|
XP_UPDATE_tick()
|
|
end
|
|
|
|
-- Give XP to a player (may be negative)
|
|
function interface.PlayerXP(playername,XP)
|
|
global.personalxp.XP[playername] = global.personalxp.XP[playername] + XP
|
|
printXP(game.players[playername],XP)
|
|
XP_UPDATE_tick()
|
|
end
|
|
|
|
-- Give a fixed XP multiplyed by player level (may be negative)
|
|
function interface.PlayerXPPerLevel(playername,XP)
|
|
global.personalxp.XP[playername] = global.personalxp.XP[playername] + (XP * global.personalxp.Level[playername])
|
|
XP_UPDATE_tick()
|
|
end
|
|
|
|
-- Player gain one level
|
|
function interface.PlayerGainLevel(playername)
|
|
if global.personalxp.XP[playername] then
|
|
local XP = CalculateXP_GAIN_LV(playername)
|
|
global.personalxp.XP[playername] = global.personalxp.XP[playername] + XP
|
|
XP_UPDATE_tick()
|
|
end
|
|
end
|
|
|
|
|
|
-- Give player XP % of his current XP level bar - perc=0 to 1, eg 0.25
|
|
function interface.PlayerXPPercCurrentBar(playername,Perc)
|
|
if global.personalxp.XP[playername] then
|
|
local XP = CalculateXP_PERCENT_CURRENT_LV(playername,Perc)
|
|
global.personalxp.XP[playername] = global.personalxp.XP[playername] + XP
|
|
printXP(game.players[playername],XP)
|
|
XP_UPDATE_tick()
|
|
end
|
|
end
|
|
|
|
|
|
|
|
-- Give player XP % of his own XP
|
|
function interface.PlayerXPPerc(playername,Perc)
|
|
local XP = math.ceil(global.personalxp.XP[playername]*Perc/100)
|
|
global.personalxp.XP[playername] = global.personalxp.XP[playername] + XP
|
|
printXP(game.players[playername],XP)
|
|
XP_UPDATE_tick()
|
|
end
|
|
|
|
-- Penalty XP for a % of his own XP
|
|
function interface.PlayerXPPenalPerc(playername,Perc)
|
|
global.personalxp.XP[playername] = global.personalxp.XP[playername] - math.ceil(global.personalxp.XP[playername]*Perc/100)
|
|
XP_UPDATE_tick()
|
|
end
|
|
|
|
|
|
-- Give all force players a XP% of his own XP
|
|
function interface.TeamXPPerc(forcename,Perc)
|
|
local XP
|
|
for p, PL in pairs (game.forces[forcename].connected_players) do
|
|
XP = math.ceil(global.personalxp.XP[PL.name]*Perc/100)
|
|
global.personalxp.XP[PL.name] = global.personalxp.XP[PL.name] + XP
|
|
printXP(PL,XP)
|
|
end
|
|
XP_UPDATE_tick()
|
|
end
|
|
|
|
-- Used only for compatibility with other mods
|
|
function interface.OtherEventsByPlayer(player,event_name,parameter)
|
|
if event_name=='mine_rock' then
|
|
XPByMiningRT(player.name,parameter)
|
|
end
|
|
if event_name=='adjust_player_stats' then
|
|
AdjustPlayerStat(player,parameter)
|
|
end
|
|
end
|
|
|
|
|
|
function interface.ResetAll()
|
|
ResetAll()
|
|
end
|
|
|
|
|
|
interface.CopyPlayerStats = CopyPlayerStats
|
|
function interface.PastePlayerStats(playername,stats)
|
|
PastePlayerStats(playername,stats)
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
commands.add_command('rpg-reset-points', 'Reconstruct XP table and reset all habilities to zero. Players can spent all points again', function(event)
|
|
local player = game.players[event.player_index]
|
|
if player.admin then
|
|
ResetPointSpent()
|
|
game.print({'xp_reset_altert'})
|
|
end
|
|
end)
|
|
commands.add_command('rpg-reset-all', 'Reconstruct XP table and reset everything to zero, as a new game', function(event)
|
|
local player = game.players[event.player_index]
|
|
if player.admin then
|
|
ResetAll()
|
|
game.print({'xp_reset_altert'})
|
|
end
|
|
end)
|
|
commands.add_command('rpg-players-list', 'List all players', function(event)
|
|
local player = game.players[event.player_index]
|
|
ListAll(player)
|
|
end)
|
|
commands.add_command('rpg-listXPTable', 'List XP table', function(event)
|
|
local player = game.players[event.player_index]
|
|
ListXPTable(player)
|
|
end)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
--[[ HOW TO subscribe to my 2 events below:
|
|
script.on_event(remote.call("RPG", "get_on_player_updated_status"), function(event)
|
|
--do your stuff
|
|
end)
|
|
WARNING: this has to be done within on_init and on_load, otherwise the game will error about the remote.call
|
|
|
|
if your dependency on my mod is optional, remember to check if the remote interface exists before calling it:
|
|
if remote.interfaces["RPG"] then
|
|
--interface exists
|
|
end]]
|
|
|
|
function interface.get_on_player_updated_status()
|
|
return on_player_updated_status
|
|
end
|
|
-- Returns :
|
|
-- event.player_index = Index of the player that upgraded an attribute
|
|
-- event.level = Player current XP Level
|
|
-- event.attribute = The attribute that was upgraded
|
|
|
|
function interface.get_on_player_level_up()
|
|
return on_player_level_up
|
|
end
|
|
-- Returns :
|
|
-- event.player_index = Index of the player that has just leveled up
|
|
-- event.level = Player current XP Level
|
|
|
|
|
|
--other mods
|
|
--jetpack
|
|
function interface.on_character_swapped(event)
|
|
--local new_unit_number = event.new_unit_number
|
|
--local old_unit_number = event.old_unit_number
|
|
local new_character = event.new_character
|
|
local old_character = event.old_character
|
|
if new_character and new_character.valid then
|
|
local player = new_character.player
|
|
if player and player.valid then
|
|
|
|
UpdatePlayerLvStats(player, true)
|
|
|
|
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
|
|
remote.add_interface("RPG", interface )
|