mirror of
https://github.com/ComfyFactory/ComfyFactorio.git
synced 2025-01-08 00:39:30 +02:00
5a8fe50216
Fixed that worms and spawners did not accurately reduce threat, scaling with their current health bonus. Fixed that worms and spawners did not accurately give the correct amount of xp, scaling with their current health bonus. Value tweaks.
857 lines
29 KiB
Lua
857 lines
29 KiB
Lua
--[[
|
|
Character Experience Gain RPG by MewMew
|
|
|
|
STRENGTH > character_inventory_slots_bonus , character_mining_speed_modifier
|
|
|
|
MAGIC > character_build_distance_bonus, character_item_drop_distance_bonus, character_reach_distance_bonus,
|
|
character_item_pickup_distance_bonus, character_loot_pickup_distance_bonus,
|
|
|
|
DEXTERITY > character_running_speed_modifier, character_crafting_speed_modifier
|
|
|
|
VITALITY > character_health_bonus
|
|
|
|
Modified by Gerkiz *-*
|
|
]]
|
|
|
|
require "player_modifiers"
|
|
|
|
local math_random = math.random
|
|
local math_sqrt = math.sqrt
|
|
local math_floor = math.floor
|
|
local Global = require 'utils.global'
|
|
local Tabs = require "comfy_panel.main"
|
|
local P = require "player_modifiers"
|
|
local visuals_delay = 1800
|
|
local level_up_floating_text_color = {0, 205, 0}
|
|
local xp_floating_text_color = {157, 157, 157}
|
|
local experience_levels = {0}
|
|
for a = 1, 9999, 1 do
|
|
experience_levels[#experience_levels + 1] = experience_levels[#experience_levels] + a * 8
|
|
end
|
|
local gain_info_tooltip = "XP gain from mining, moving, crafting, repairing and combat."
|
|
|
|
local rpg_t = {}
|
|
local rpg_frame_icons = {
|
|
"entity/small-worm-turret", "entity/medium-worm-turret", "entity/big-worm-turret", "entity/behemoth-worm-turret",
|
|
"entity/small-biter", "entity/small-biter", "entity/small-spitter", "entity/medium-biter", "entity/medium-biter",
|
|
"entity/medium-spitter", "entity/big-biter", "entity/big-biter", "entity/big-spitter", "entity/behemoth-biter", "entity/behemoth-biter",
|
|
"entity/behemoth-spitter"
|
|
}
|
|
|
|
Global.register(
|
|
{rpg_t=rpg_t, rpg_frame_icons=rpg_frame_icons},
|
|
function(tbl)
|
|
rpg_t = tbl.rpg_t
|
|
rpg_frame_icons = tbl.rpg_frame_icons
|
|
end
|
|
)
|
|
|
|
local Public = {}
|
|
|
|
function Public.get_table()
|
|
return rpg_t
|
|
end
|
|
|
|
local classes = {
|
|
["engineer"] = "ENGINEER",
|
|
["strength"] = "MINER",
|
|
["magic"] = "SORCERER",
|
|
["dexterity"] = "ROGUE",
|
|
["vitality"] = "TANK",
|
|
}
|
|
|
|
local xp_yield = {
|
|
["behemoth-biter"] = 16,
|
|
["behemoth-spitter"] = 16,
|
|
["behemoth-worm-turret"] = 64,
|
|
["big-biter"] = 8,
|
|
["big-spitter"] = 8,
|
|
["big-worm-turret"] = 48,
|
|
["biter-spawner"] = 64,
|
|
["character"] = 16,
|
|
["gun-turret"] = 8,
|
|
["laser-turret"] = 16,
|
|
["medium-biter"] = 4,
|
|
["medium-spitter"] = 4,
|
|
["medium-worm-turret"] = 32,
|
|
["small-biter"] = 1,
|
|
["small-spitter"] = 1,
|
|
["small-worm-turret"] = 16,
|
|
["spitter-spawner"] = 64,
|
|
}
|
|
|
|
local enemy_types = {
|
|
["unit"] = true,
|
|
["unit-spawner"] = true,
|
|
["turret"] = true,
|
|
}
|
|
|
|
local function level_up_effects(player)
|
|
local position = {x = player.position.x - 0.75, y = player.position.y - 1}
|
|
player.surface.create_entity({name = "flying-text", position = position, text = "+LVL ", color = level_up_floating_text_color})
|
|
local b = 0.75
|
|
for a = 1, 5, 1 do
|
|
local p = {(position.x + 0.4) + (b * -1 + math_random(0, b * 20) * 0.1), position.y + (b * -1 + math_random(0, b * 20) * 0.1)}
|
|
player.surface.create_entity({name = "flying-text", position = p, text = "✚", color = {255, math_random(0, 100), 0}})
|
|
end
|
|
player.play_sound{path="utility/achievement_unlocked", volume_modifier=0.40}
|
|
end
|
|
|
|
local function get_melee_modifier(player) return (rpg_t[player.index].strength - 10) * 0.10 end
|
|
|
|
local function get_life_on_hit(player) return (rpg_t[player.index].vitality - 10) * 0.4 end
|
|
|
|
local function get_one_punch_chance(player)
|
|
if rpg_t[player.index].strength < 100 then return 0 end
|
|
local chance = math.round(rpg_t[player.index].strength * 0.01, 1)
|
|
if chance > 100 then chance = 100 end
|
|
return chance
|
|
end
|
|
|
|
local function draw_gui_char_button(player)
|
|
if player.gui.top.rpg then return end
|
|
local b = player.gui.top.add({type = "sprite-button", name = "rpg", caption = "CHAR"})
|
|
b.style.font_color = {165,165,165}
|
|
b.style.font = "heading-1"
|
|
b.style.minimal_height = 38
|
|
b.style.minimal_width = 60
|
|
b.style.padding = 0
|
|
b.style.margin = 0
|
|
end
|
|
|
|
local function update_char_button(player)
|
|
if not player.gui.top.rpg then draw_gui_char_button(player) end
|
|
if rpg_t[player.index].points_to_distribute > 0 then
|
|
player.gui.top.rpg.style.font_color = {245, 0, 0}
|
|
else
|
|
player.gui.top.rpg.style.font_color = {175,175,175}
|
|
end
|
|
end
|
|
|
|
local function update_player_stats(player)
|
|
local player_modifiers = P.get_table()
|
|
local strength = rpg_t[player.index].strength - 10
|
|
player_modifiers[player.index].character_inventory_slots_bonus["rpg"] = math.round(strength * 0.2, 3)
|
|
player_modifiers[player.index].character_mining_speed_modifier["rpg"] = math.round(strength * 0.008, 3)
|
|
|
|
local magic = rpg_t[player.index].magic - 10
|
|
local v = magic * 0.15
|
|
player_modifiers[player.index].character_build_distance_bonus["rpg"] = math.round(v, 3)
|
|
player_modifiers[player.index].character_item_drop_distance_bonus["rpg"] = math.round(v, 3)
|
|
player_modifiers[player.index].character_reach_distance_bonus["rpg"] = math.round(v, 3)
|
|
player_modifiers[player.index].character_loot_pickup_distance_bonus["rpg"] = math.round(v * 0.5, 3)
|
|
player_modifiers[player.index].character_item_pickup_distance_bonus["rpg"] = math.round(v * 0.25, 3)
|
|
player_modifiers[player.index].character_resource_reach_distance_bonus["rpg"] = math.round(v * 0.15, 3)
|
|
|
|
local dexterity = rpg_t[player.index].dexterity - 10
|
|
player_modifiers[player.index].character_running_speed_modifier["rpg"] = math.round(dexterity * 0.002, 3)
|
|
player_modifiers[player.index].character_crafting_speed_modifier["rpg"] = math.round(dexterity * 0.015, 3)
|
|
|
|
player_modifiers[player.index].character_health_bonus["rpg"] = math.round((rpg_t[player.index].vitality - 10) * 6, 3)
|
|
|
|
P.update_player_modifiers(player)
|
|
end
|
|
|
|
local function get_class(player)
|
|
local average = (rpg_t[player.index].strength + rpg_t[player.index].magic + rpg_t[player.index].dexterity + rpg_t[player.index].vitality) / 4
|
|
local high_attribute = 0
|
|
local high_attribute_name = ""
|
|
for _, attribute in pairs({"strength", "magic", "dexterity", "vitality"}) do
|
|
if rpg_t[player.index][attribute] > high_attribute then
|
|
high_attribute = rpg_t[player.index][attribute]
|
|
high_attribute_name = attribute
|
|
end
|
|
end
|
|
if high_attribute < average + average * 0.25 then high_attribute_name = "engineer" end
|
|
return classes[high_attribute_name]
|
|
end
|
|
|
|
local function add_gui_description(element, value, width)
|
|
local e = element.add({type = "label", caption = value})
|
|
e.style.single_line = false
|
|
e.style.maximal_width = width
|
|
e.style.minimal_width = width
|
|
e.style.maximal_height = 40
|
|
e.style.minimal_height = 38
|
|
e.style.font = "default-bold"
|
|
e.style.font_color = {175, 175, 200}
|
|
e.style.horizontal_align = "right"
|
|
e.style.vertical_align = "center"
|
|
return e
|
|
end
|
|
|
|
local function add_gui_stat(element, value, width)
|
|
local e = element.add({type = "sprite-button", caption = value})
|
|
e.style.maximal_width = width
|
|
e.style.minimal_width = width
|
|
e.style.maximal_height = 38
|
|
e.style.minimal_height = 38
|
|
e.style.font = "default-bold"
|
|
e.style.font_color = {222, 222, 222}
|
|
e.style.horizontal_align = "center"
|
|
e.style.vertical_align = "center"
|
|
return e
|
|
end
|
|
|
|
local function add_gui_increase_stat(element, name, player, width)
|
|
local sprite = "virtual-signal/signal-red"
|
|
local symbol = "✚"
|
|
if rpg_t[player.index].points_to_distribute <= 0 then sprite = "virtual-signal/signal-black" end
|
|
local e = element.add({type = "sprite-button", name = name, caption = symbol, sprite = sprite})
|
|
e.style.maximal_height = 38
|
|
e.style.minimal_height = 38
|
|
e.style.maximal_width = 38
|
|
e.style.minimal_width = 38
|
|
e.style.font = "default-large-semibold"
|
|
e.style.font_color = {0,0,0}
|
|
e.style.horizontal_align = "center"
|
|
e.style.vertical_align = "center"
|
|
e.style.padding = 0
|
|
e.style.margin = 0
|
|
e.tooltip = "Rightclick to allocate 5 points."
|
|
|
|
return e
|
|
end
|
|
|
|
local function add_separator(element, width)
|
|
local e = element.add({type = "line"})
|
|
e.style.maximal_width = width
|
|
e.style.minimal_width = width
|
|
e.style.minimal_height = 12
|
|
return e
|
|
end
|
|
|
|
local function draw_gui(player, forced)
|
|
if not forced then
|
|
if rpg_t[player.index].gui_refresh_delay > game.tick then return end
|
|
end
|
|
|
|
Tabs.comfy_panel_clear_left_gui(player)
|
|
|
|
if player.gui.left.rpg then player.gui.left.rpg.destroy() end
|
|
if not player.character then return end
|
|
|
|
local frame = player.gui.left.add({type = "frame", name = "rpg", direction = "vertical"})
|
|
frame.style.maximal_width = 425
|
|
frame.style.minimal_width = 425
|
|
frame.style.margin = 6
|
|
|
|
add_separator(frame, 400)
|
|
|
|
local t = frame.add({type = "table", column_count = 2})
|
|
local e = add_gui_stat(t, player.name, 200)
|
|
e.style.font_color = player.chat_color
|
|
e.style.font = "default-large-bold"
|
|
local e = add_gui_stat(t, get_class(player), 200)
|
|
e.style.font = "default-large-bold"
|
|
|
|
add_separator(frame, 400)
|
|
|
|
local t = frame.add({type = "table", column_count = 4})
|
|
t.style.cell_padding = 1
|
|
|
|
add_gui_description(t, "LEVEL", 80)
|
|
add_gui_stat(t, rpg_t[player.index].level, 80)
|
|
|
|
add_gui_description(t, "EXPERIENCE", 100)
|
|
local e = add_gui_stat(t, math.floor(rpg_t[player.index].xp), 125)
|
|
e.tooltip = gain_info_tooltip
|
|
|
|
add_gui_description(t, " ", 75)
|
|
add_gui_description(t, " ", 75)
|
|
|
|
add_gui_description(t, "NEXT LEVEL", 100)
|
|
local e = add_gui_stat(t, experience_levels[rpg_t[player.index].level + 1], 125)
|
|
e.tooltip = gain_info_tooltip
|
|
|
|
add_separator(frame, 400)
|
|
|
|
local t = frame.add({type = "table", column_count = 2})
|
|
local tt = t.add({type = "table", column_count = 3})
|
|
tt.style.cell_padding = 1
|
|
local w1 = 85
|
|
local w2 = 63
|
|
|
|
local tip = "Increases inventory slots and mining speed.\nIncreases melee damage."
|
|
local e = add_gui_description(tt, "STRENGTH", w1)
|
|
e.tooltip = tip
|
|
local e = add_gui_stat(tt, rpg_t[player.index].strength, w2)
|
|
e.tooltip = tip
|
|
add_gui_increase_stat(tt, "strength", player)
|
|
|
|
local tip = "Increases reach distance."
|
|
local e = add_gui_description(tt, "MAGIC", w1)
|
|
e.tooltip = tip
|
|
local e = add_gui_stat(tt, rpg_t[player.index].magic, w2)
|
|
e.tooltip = tip
|
|
add_gui_increase_stat(tt, "magic", player)
|
|
|
|
local tip = "Increases running and crafting speed."
|
|
local e = add_gui_description(tt, "DEXTERITY", w1)
|
|
e.tooltip = tip
|
|
local e = add_gui_stat(tt, rpg_t[player.index].dexterity, w2)
|
|
e.tooltip = tip
|
|
add_gui_increase_stat(tt, "dexterity", player)
|
|
|
|
local tip = "Increases health.\nIncreases melee life on-hit."
|
|
local e = add_gui_description(tt, "VITALITY", w1)
|
|
e.tooltip = tip
|
|
local e = add_gui_stat(tt, rpg_t[player.index].vitality, w2)
|
|
e.tooltip = tip
|
|
add_gui_increase_stat(tt, "vitality", player)
|
|
|
|
add_gui_description(tt, "POINTS TO\nDISTRIBUTE", w1)
|
|
local e = add_gui_stat(tt, rpg_t[player.index].points_to_distribute, w2)
|
|
e.style.font_color = {200, 0, 0}
|
|
add_gui_description(tt, " ", w2)
|
|
|
|
add_gui_description(tt, " ", w1)
|
|
add_gui_description(tt, " ", w2)
|
|
add_gui_description(tt, " ", w2)
|
|
|
|
add_gui_description(tt, "LIFE", w1)
|
|
add_gui_stat(tt, math.floor(player.character.health), w2)
|
|
add_gui_stat(tt, math.floor(player.character.prototype.max_health + player.character_health_bonus + player.force.character_health_bonus), w2)
|
|
|
|
local shield = 0
|
|
local shield_max = 0
|
|
local i = player.character.get_inventory(defines.inventory.character_armor)
|
|
if not i.is_empty() then
|
|
if i[1].grid then
|
|
shield = math.floor(i[1].grid.shield)
|
|
shield_max = math.floor(i[1].grid.max_shield)
|
|
end
|
|
end
|
|
add_gui_description(tt, "SHIELD", w1)
|
|
add_gui_stat(tt, shield, w2)
|
|
add_gui_stat(tt, shield_max, w2)
|
|
|
|
|
|
local tt = t.add({type = "table", column_count = 3})
|
|
tt.style.cell_padding = 1
|
|
local w0 = 2
|
|
local w1 = 80
|
|
local w2 = 80
|
|
|
|
add_gui_description(tt, " ", w0)
|
|
add_gui_description(tt, "MINING\nSPEED", w1)
|
|
local value = (player.force.manual_mining_speed_modifier + player.character_mining_speed_modifier + 1) * 100 .. "%"
|
|
add_gui_stat(tt, value, w2)
|
|
|
|
add_gui_description(tt, " ", w0)
|
|
add_gui_description(tt, "SLOT\nBONUS", w1)
|
|
local value = "+ " .. player.force.character_inventory_slots_bonus + player.character_inventory_slots_bonus
|
|
add_gui_stat(tt, value, w2)
|
|
|
|
add_gui_description(tt, " ", w0)
|
|
add_gui_description(tt, "MELEE\nDAMAGE", w1)
|
|
local value = 100 * (1 + get_melee_modifier(player)) .. "%"
|
|
local e = add_gui_stat(tt, value, w2)
|
|
e.tooltip = "Life on-hit: " .. get_life_on_hit(player) .. "\nOne punch chance: " .. get_one_punch_chance(player) .. "%"
|
|
|
|
local e = add_gui_description(tt, "", w0)
|
|
e.style.maximal_height = 10
|
|
local e = add_gui_description(tt, "", w0)
|
|
e.style.maximal_height = 10
|
|
local e = add_gui_description(tt, "", w0)
|
|
e.style.maximal_height = 10
|
|
|
|
local value = "+ " .. (player.force.character_reach_distance_bonus + player.character_reach_distance_bonus)
|
|
local tooltip = ""
|
|
tooltip = tooltip .. "Reach distance bonus: " .. player.character_reach_distance_bonus
|
|
tooltip = tooltip .. "\nBuild distance bonus: " .. player.character_build_distance_bonus
|
|
tooltip = tooltip .. "\nItem drop distance bonus: " .. player.character_item_drop_distance_bonus
|
|
tooltip = tooltip .. "\nLoot pickup distance bonus: " .. player.character_loot_pickup_distance_bonus
|
|
tooltip = tooltip .. "\nItem pickup distance bonus: " .. player.character_item_pickup_distance_bonus
|
|
tooltip = tooltip .. "\nResource reach distance bonus: " .. player.character_resource_reach_distance_bonus
|
|
add_gui_description(tt, " ", w0)
|
|
local e = add_gui_description(tt, "REACH\nDISTANCE", w1)
|
|
e.tooltip = tooltip
|
|
local e = add_gui_stat(tt, value, w2)
|
|
e.tooltip = tooltip
|
|
|
|
local e = add_gui_description(tt, "", w0)
|
|
e.style.maximal_height = 10
|
|
local e = add_gui_description(tt, "", w0)
|
|
e.style.maximal_height = 10
|
|
local e = add_gui_description(tt, "", w0)
|
|
e.style.maximal_height = 10
|
|
|
|
add_gui_description(tt, " ", w0)
|
|
add_gui_description(tt, "CRAFTING\nSPEED", w1)
|
|
local value = (player.force.manual_crafting_speed_modifier + player.character_crafting_speed_modifier + 1) * 100 .. "%"
|
|
add_gui_stat(tt, value, w2)
|
|
|
|
add_gui_description(tt, " ", w0)
|
|
add_gui_description(tt, "RUNNING\nSPEED", w1)
|
|
local value = (player.force.character_running_speed_modifier + player.character_running_speed_modifier + 1) * 100 .. "%"
|
|
add_gui_stat(tt, value, w2)
|
|
|
|
local e = add_gui_description(tt, "", w0)
|
|
e.style.maximal_height = 10
|
|
local e = add_gui_description(tt, "", w0)
|
|
e.style.maximal_height = 10
|
|
local e = add_gui_description(tt, "", w0)
|
|
e.style.maximal_height = 10
|
|
|
|
add_gui_description(tt, " ", w0)
|
|
add_gui_description(tt, "HEALTH\nBONUS", w1)
|
|
local value = "+ " .. (player.force.character_health_bonus + player.character_health_bonus)
|
|
add_gui_stat(tt, value, w2)
|
|
|
|
add_separator(frame, 400)
|
|
local t = frame.add({type = "table", column_count = 14})
|
|
for i = 1, 14, 1 do
|
|
local e = t.add({type = "sprite", sprite = rpg_frame_icons[i]})
|
|
e.style.maximal_width = 24
|
|
e.style.maximal_height = 24
|
|
e.style.padding = 0
|
|
end
|
|
add_separator(frame, 400)
|
|
|
|
rpg_t[player.index].gui_refresh_delay = game.tick + 60
|
|
update_char_button(player)
|
|
end
|
|
|
|
local function draw_level_text(player)
|
|
if not player.character then return end
|
|
|
|
if rpg_t[player.index].text then
|
|
rendering.destroy(rpg_t[player.index].text)
|
|
rpg_t[player.index].text = nil
|
|
end
|
|
|
|
local players = {}
|
|
for _, p in pairs(game.players) do
|
|
if p.index ~= player.index then
|
|
players[#players + 1] = p.index
|
|
end
|
|
end
|
|
if #players == 0 then return end
|
|
|
|
rpg_t[player.index].text = rendering.draw_text{
|
|
text = "lvl " .. rpg_t[player.index].level,
|
|
surface = player.surface,
|
|
target = player.character,
|
|
target_offset = {0, -3.25},
|
|
color = {
|
|
r = player.color.r * 0.6 + 0.25,
|
|
g = player.color.g * 0.6 + 0.25,
|
|
b = player.color.b * 0.6 + 0.25,
|
|
a = 1
|
|
},
|
|
players = players,
|
|
scale = 1.00,
|
|
font = "default-large-semibold",
|
|
alignment = "center",
|
|
scale_with_zoom = false
|
|
}
|
|
end
|
|
|
|
local function level_up(player)
|
|
local distribute_points_gain = 0
|
|
for i = rpg_t[player.index].level + 1, #experience_levels, 1 do
|
|
if rpg_t[player.index].xp > experience_levels[i] then
|
|
rpg_t[player.index].level = i
|
|
distribute_points_gain = distribute_points_gain + 5
|
|
else
|
|
break
|
|
end
|
|
end
|
|
if distribute_points_gain == 0 then return end
|
|
draw_level_text(player)
|
|
rpg_t[player.index].points_to_distribute = rpg_t[player.index].points_to_distribute + distribute_points_gain
|
|
update_char_button(player)
|
|
table.shuffle_table(rpg_frame_icons)
|
|
if player.gui.left.rpg then draw_gui(player, true) end
|
|
level_up_effects(player)
|
|
end
|
|
|
|
local function gain_xp(player, amount)
|
|
amount = math.round(amount, 2)
|
|
rpg_t[player.index].xp = rpg_t[player.index].xp + amount
|
|
rpg_t[player.index].xp_since_last_floaty_text = rpg_t[player.index].xp_since_last_floaty_text + amount
|
|
if player.gui.left.rpg then draw_gui(player, false) end
|
|
if not experience_levels[rpg_t[player.index].level + 1] then return end
|
|
if rpg_t[player.index].xp >= experience_levels[rpg_t[player.index].level + 1] then
|
|
level_up(player)
|
|
return
|
|
end
|
|
if rpg_t[player.index].last_floaty_text > game.tick then return end
|
|
player.create_local_flying_text{text="+" .. rpg_t[player.index].xp_since_last_floaty_text .. " xp", position=player.position, color=xp_floating_text_color, time_to_live=120, speed=2}
|
|
rpg_t[player.index].xp_since_last_floaty_text = 0
|
|
rpg_t[player.index].last_floaty_text = game.tick + visuals_delay
|
|
end
|
|
|
|
function Public.rpg_reset_player(player)
|
|
if player.gui.left.rpg then player.gui.left.rpg.destroy() end
|
|
if not player.character then
|
|
player.set_controller({type=defines.controllers.god})
|
|
player.create_character()
|
|
end
|
|
rpg_t[player.index] = {
|
|
level = 1, xp = 0, strength = 10, magic = 10, dexterity = 10, vitality = 10, points_to_distribute = 0,
|
|
last_floaty_text = visuals_delay, xp_since_last_floaty_text = 0,
|
|
rotated_entity_delay = 0, gui_refresh_delay = 0, last_mined_entity_position = {x = 0, y = 0},
|
|
}
|
|
draw_gui_char_button(player)
|
|
draw_level_text(player)
|
|
update_char_button(player)
|
|
update_player_stats(player)
|
|
end
|
|
|
|
function Public.rpg_reset_all_players()
|
|
for _, p in pairs(game.players) do
|
|
rpg_t[p.index] = nil
|
|
end
|
|
for _, p in pairs(game.connected_players) do
|
|
Public.rpg_reset_player(p)
|
|
end
|
|
end
|
|
|
|
local function on_gui_click(event)
|
|
if not event.element then return end
|
|
if not event.element.valid then return end
|
|
local element = event.element
|
|
|
|
if element.type ~= "sprite-button" then return end
|
|
|
|
if element.caption == "CHAR" then
|
|
if element.name == "rpg" then
|
|
local player = game.players[event.player_index]
|
|
if player.gui.left.rpg then
|
|
player.gui.left.rpg.destroy()
|
|
return
|
|
end
|
|
draw_gui(player, true)
|
|
end
|
|
end
|
|
|
|
if element.caption ~= "✚" then return end
|
|
if element.sprite ~= "virtual-signal/signal-red" then return end
|
|
|
|
local index = element.name
|
|
local player = game.players[event.player_index]
|
|
if not rpg_t[player.index][index] then return end
|
|
if not player.character then return end
|
|
|
|
if event.button == defines.mouse_button_type.right then
|
|
for a = 1, 5, 1 do
|
|
if rpg_t[player.index].points_to_distribute <= 0 then draw_gui(player, true) return end
|
|
rpg_t[player.index].points_to_distribute = rpg_t[player.index].points_to_distribute - 1
|
|
rpg_t[player.index][index] = rpg_t[player.index][index] + 1
|
|
update_player_stats(player)
|
|
end
|
|
draw_gui(player, true)
|
|
return
|
|
end
|
|
|
|
if rpg_t[player.index].points_to_distribute <= 0 then draw_gui(player, true) return end
|
|
rpg_t[player.index].points_to_distribute = rpg_t[player.index].points_to_distribute - 1
|
|
rpg_t[player.index][index] = rpg_t[player.index][index] + 1
|
|
update_player_stats(player)
|
|
draw_gui(player, true)
|
|
end
|
|
|
|
local function train_type_cause(cause)
|
|
local players = {}
|
|
if cause.train.passengers then
|
|
for _, player in pairs(cause.train.passengers) do
|
|
players[#players + 1] = player
|
|
end
|
|
end
|
|
return players
|
|
end
|
|
|
|
local get_cause_player = {
|
|
["character"] = function(cause)
|
|
if not cause.player then return end
|
|
return {cause.player}
|
|
end,
|
|
["combat-robot"] = function(cause)
|
|
if not cause.last_user then return end
|
|
if not game.players[cause.last_user.index] then return end
|
|
return {game.players[cause.last_user.index]}
|
|
end,
|
|
["car"] = function(cause)
|
|
local players = {}
|
|
local driver = cause.get_driver()
|
|
if driver then
|
|
if driver.player then players[#players + 1] = driver.player end
|
|
end
|
|
local passenger = cause.get_passenger()
|
|
if passenger then
|
|
if passenger.player then players[#players + 1] = passenger.player end
|
|
end
|
|
return players
|
|
end,
|
|
["locomotive"] = train_type_cause,
|
|
["cargo-wagon"] = train_type_cause,
|
|
["artillery-wagon"] = train_type_cause,
|
|
["fluid-wagon"] = train_type_cause,
|
|
}
|
|
|
|
local function on_entity_died(event)
|
|
if not event.entity.valid then return end
|
|
|
|
--Grant XP for hand placed land mines
|
|
if event.entity.last_user then
|
|
if event.entity.type == "land-mine" then
|
|
if event.cause then
|
|
if event.cause.valid then
|
|
if event.cause.force.index == event.entity.force.index then return end
|
|
end
|
|
end
|
|
gain_xp(event.entity.last_user, 1)
|
|
return
|
|
end
|
|
end
|
|
|
|
if not event.cause then return end
|
|
if not event.cause.valid then return end
|
|
if event.cause.force.index == event.entity.force.index then return end
|
|
if not get_cause_player[event.cause.type] then return end
|
|
|
|
local players = get_cause_player[event.cause.type](event.cause)
|
|
if not players then return end
|
|
if not players[1] then return end
|
|
|
|
--Grant modified XP for health boosted units
|
|
if global.biter_health_boost then
|
|
if enemy_types[event.entity.type] then
|
|
for _, player in pairs(players) do
|
|
if xp_yield[event.entity.name] then
|
|
gain_xp(player, xp_yield[event.entity.name] * global.biter_health_boost)
|
|
else
|
|
gain_xp(player, 0.5 * global.biter_health_boost)
|
|
end
|
|
end
|
|
return
|
|
end
|
|
end
|
|
|
|
--Grant normal XP
|
|
for _, player in pairs(players) do
|
|
if xp_yield[event.entity.name] then
|
|
gain_xp(player, xp_yield[event.entity.name])
|
|
else
|
|
gain_xp(player, 0.5)
|
|
end
|
|
end
|
|
end
|
|
|
|
--Melee damage modifier
|
|
local function one_punch(character, target, damage)
|
|
local base_vector = {target.position.x - character.position.x, target.position.y - character.position.y}
|
|
|
|
local vector = {base_vector[1], base_vector[2]}
|
|
vector[1] = vector[1] * 1000
|
|
vector[2] = vector[2] * 1000
|
|
|
|
character.surface.create_entity({name = "flying-text", position = {character.position.x + base_vector[1] * 0.5, character.position.y + base_vector[2] * 0.5}, text = "ONE PUNCH", color = {255, 0, 0}})
|
|
character.surface.create_entity({name = "blood-explosion-huge", position = target.position})
|
|
character.surface.create_entity({name = "big-artillery-explosion", position = {target.position.x + vector[1] * 0.5, target.position.y + vector[2] * 0.5}})
|
|
|
|
if math.abs(vector[1]) > math.abs(vector[2]) then
|
|
local d = math.abs(vector[1])
|
|
if math.abs(vector[1]) > 0 then vector[1] = vector[1] / d end
|
|
if math.abs(vector[2]) > 0 then vector[2] = vector[2] / d end
|
|
else
|
|
local d = math.abs(vector[2])
|
|
if math.abs(vector[2]) > 0 then vector[2] = vector[2] / d end
|
|
if math.abs(vector[1]) > 0 and d > 0 then vector[1] = vector[1] / d end
|
|
end
|
|
|
|
vector[1] = vector[1] * 1.5
|
|
vector[2] = vector[2] * 1.5
|
|
|
|
local a = 0.25
|
|
|
|
for i = 1, 16, 1 do
|
|
for x = i * -1 * a, i * a, 1 do
|
|
for y = i * -1 * a, i * a, 1 do
|
|
local p = {character.position.x + x + vector[1] * i, character.position.y + y + vector[2] * i}
|
|
character.surface.create_trivial_smoke({name="train-smoke", position=p})
|
|
for _, e in pairs(character.surface.find_entities({{p[1] - a, p[2] - a},{p[1] + a, p[2] + a}})) do
|
|
if e.valid then
|
|
if e.health then
|
|
if e.destructible and e.minable and e.force.index ~= 3 then
|
|
if e.force.index ~= character.force.index then
|
|
e.health = e.health - damage * 0.05
|
|
if e.health <= 0 then
|
|
e.die(e.force.name, character)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function on_entity_damaged(event)
|
|
if not event.cause then return end
|
|
if not event.cause.valid then return end
|
|
if event.cause.force.index == 2 then return end
|
|
if event.cause.name ~= "character" then return end
|
|
if event.damage_type.name ~= "physical" then return end
|
|
if not event.entity.valid then return end
|
|
if event.cause.get_inventory(defines.inventory.character_ammo)[event.cause.selected_gun_index].valid_for_read
|
|
and event.cause.get_inventory(defines.inventory.character_guns)[event.cause.selected_gun_index].valid_for_read then return end
|
|
if not event.cause.player then return end
|
|
|
|
--Grant the player life-on-hit.
|
|
event.cause.health = event.cause.health + get_life_on_hit(event.cause.player)
|
|
|
|
--Calculate modified damage.
|
|
local damage = event.original_damage_amount + event.original_damage_amount * get_melee_modifier(event.cause.player)
|
|
if event.entity.prototype.resistances then
|
|
if event.entity.prototype.resistances.physical then
|
|
damage = damage - event.entity.prototype.resistances.physical.decrease
|
|
damage = damage - damage * event.entity.prototype.resistances.physical.percent
|
|
end
|
|
end
|
|
damage = math.round(damage, 3)
|
|
if damage < 1 then damage = 1 end
|
|
|
|
--Cause a one punch.
|
|
if math_random(0,999) < get_one_punch_chance(event.cause.player) * 10 then
|
|
one_punch(event.cause, event.entity, damage)
|
|
if event.entity.valid then
|
|
event.entity.die(event.entity.force.name, event.cause)
|
|
end
|
|
return
|
|
end
|
|
|
|
--Floating messages and particle effects.
|
|
if math_random(1,7) == 1 then
|
|
damage = damage * math_random(250, 350) * 0.01
|
|
event.cause.surface.create_entity({name = "flying-text", position = event.entity.position, text = "‼" .. math.floor(damage), color = {255, 0, 0}})
|
|
event.cause.surface.create_entity({name = "blood-explosion-huge", position = event.entity.position})
|
|
else
|
|
damage = damage * math_random(100, 125) * 0.01
|
|
event.cause.player.create_local_flying_text({text = math.floor(damage), position = event.entity.position, color = {150, 150, 150}, time_to_live = 90, speed = 2})
|
|
end
|
|
|
|
--Handle the custom health pool of the biter health booster, if it is used in the map.
|
|
if global.biter_health_boost then
|
|
local health_pool = global.biter_health_boost_units[event.entity.unit_number]
|
|
if health_pool then
|
|
health_pool[1] = health_pool[1] + event.final_damage_amount
|
|
health_pool[1] = health_pool[1] - damage
|
|
|
|
--Set entity health relative to health pool
|
|
event.entity.health = health_pool[1] * health_pool[2]
|
|
|
|
if health_pool[1] <= 0 then
|
|
global.biter_health_boost_units[event.entity.unit_number] = nil
|
|
event.entity.die(event.entity.force.name, event.cause)
|
|
end
|
|
return
|
|
end
|
|
end
|
|
|
|
--Handle vanilla damage.
|
|
event.entity.health = event.entity.health + event.final_damage_amount
|
|
event.entity.health = event.entity.health - damage
|
|
if event.entity.health <= 0 then
|
|
event.entity.die(event.entity.force.name, event.cause)
|
|
end
|
|
end
|
|
|
|
local function on_player_repaired_entity(event)
|
|
if math_random(1, 4) ~= 1 then return end
|
|
local player = game.players[event.player_index]
|
|
if not player.character then return end
|
|
gain_xp(player, 0.40)
|
|
end
|
|
|
|
local function on_player_rotated_entity(event)
|
|
local player = game.players[event.player_index]
|
|
if not player.character then return end
|
|
if rpg_t[player.index].rotated_entity_delay > game.tick then return end
|
|
rpg_t[player.index].rotated_entity_delay = game.tick + 20
|
|
gain_xp(player, 0.20)
|
|
end
|
|
|
|
local function on_player_changed_position(event)
|
|
if math_random(1, 64) ~= 1 then return end
|
|
local player = game.players[event.player_index]
|
|
if not player.character then return end
|
|
if player.character.driving then return end
|
|
gain_xp(player, 1.0)
|
|
end
|
|
|
|
local building_and_mining_blacklist = {
|
|
["tile-ghost"] = true,
|
|
["entity-ghost"] = true,
|
|
["item-entity"] = true,
|
|
}
|
|
|
|
local function on_pre_player_mined_item(event)
|
|
local entity = event.entity
|
|
if not entity.valid then return end
|
|
if building_and_mining_blacklist[entity.type] then return end
|
|
if entity.force.index ~= 3 then return end
|
|
local player = game.players[event.player_index]
|
|
|
|
if rpg_t[player.index].last_mined_entity_position.x == event.entity.position.x and rpg_t[player.index].last_mined_entity_position.y == event.entity.position.y then return end
|
|
rpg_t[player.index].last_mined_entity_position.x = entity.position.x
|
|
rpg_t[player.index].last_mined_entity_position.y = entity.position.y
|
|
|
|
local distance_multiplier = math_floor(math_sqrt(entity.position.x ^ 2 + entity.position.y ^ 2)) * 0.0005 + 1
|
|
|
|
local xp_amount
|
|
if entity.type == "resource" then
|
|
xp_amount = 0.5 * distance_multiplier
|
|
else
|
|
xp_amount = (1.5 + event.entity.prototype.max_health * 0.0035) * distance_multiplier
|
|
end
|
|
|
|
gain_xp(player, xp_amount)
|
|
end
|
|
|
|
local function on_player_crafted_item(event)
|
|
if not event.recipe.energy then return end
|
|
local player = game.players[event.player_index]
|
|
gain_xp(player, event.recipe.energy * 0.20)
|
|
end
|
|
|
|
local function on_player_respawned(event)
|
|
local player = game.players[event.player_index]
|
|
if not rpg_t[player.index] then Public.rpg_reset_player(player) return end
|
|
update_player_stats(player)
|
|
draw_level_text(player)
|
|
end
|
|
|
|
local function on_player_joined_game(event)
|
|
local player = game.players[event.player_index]
|
|
if not rpg_t[player.index] then Public.rpg_reset_player(player) end
|
|
for _, p in pairs(game.connected_players) do
|
|
draw_level_text(p)
|
|
end
|
|
draw_gui_char_button(player)
|
|
if not player.character then return end
|
|
update_player_stats(player)
|
|
end
|
|
|
|
local function on_init(event)
|
|
table.shuffle_table(rpg_frame_icons)
|
|
end
|
|
|
|
local event = require 'utils.event'
|
|
event.on_init(on_init)
|
|
event.add(defines.events.on_entity_damaged, on_entity_damaged)
|
|
event.add(defines.events.on_entity_died, on_entity_died)
|
|
event.add(defines.events.on_gui_click, on_gui_click)
|
|
event.add(defines.events.on_player_changed_position, on_player_changed_position)
|
|
event.add(defines.events.on_player_crafted_item, on_player_crafted_item)
|
|
event.add(defines.events.on_player_joined_game, on_player_joined_game)
|
|
event.add(defines.events.on_player_repaired_entity, on_player_repaired_entity)
|
|
event.add(defines.events.on_player_respawned, on_player_respawned)
|
|
event.add(defines.events.on_player_rotated_entity, on_player_rotated_entity)
|
|
event.add(defines.events.on_pre_player_mined_item, on_pre_player_mined_item)
|
|
|
|
return Public |