1
0
mirror of https://github.com/ComfyFactory/ComfyFactorio.git synced 2025-01-26 03:52:22 +02:00

346 lines
15 KiB
Lua
Raw Normal View History

-- This file is part of thesixthroc's Pirate Ship softmod, licensed under GPLv3 and stored at https://github.com/danielmartin0/ComfyFactorio-Pirates.
2021-10-13 09:21:53 +01:00
local Memory = require 'maps.pirates.memory'
2022-03-19 21:20:55 +00:00
-- local Roles = require 'maps.pirates.roles.roles'
2021-10-13 09:21:53 +01:00
local Classes = require 'maps.pirates.roles.classes'
local Crew = require 'maps.pirates.crew'
2022-03-19 21:20:55 +00:00
-- local Boats = require 'maps.pirates.structures.boats.boats'
-- local Dock = require 'maps.pirates.surfaces.dock'
2021-10-13 09:21:53 +01:00
local Balance = require 'maps.pirates.balance'
local Common = require 'maps.pirates.common'
local Utils = require 'maps.pirates.utils_local'
local Roles = require 'maps.pirates.roles.roles'
2021-10-13 09:21:53 +01:00
local Math = require 'maps.pirates.math'
2022-03-19 21:20:55 +00:00
local _inspect = require 'utils.inspect'.inspect
2022-02-26 23:33:19 +00:00
local SurfacesCommon = require 'maps.pirates.surfaces.common'
local Upgrades = require 'maps.pirates.boat_upgrades'
2022-03-19 21:20:55 +00:00
-- local Upgrades = require 'maps.pirates.boat_upgrades'
2021-10-13 09:21:53 +01:00
local Public = {}
2022-03-07 18:41:42 +00:00
Public.Captains = require 'maps.pirates.shop.captains'
Public.Covered = require 'maps.pirates.shop.covered'
Public.Merchants = require 'maps.pirates.shop.merchants'
Public.Minimarket = require 'maps.pirates.shop.dock'
2021-10-13 09:21:53 +01:00
2022-05-22 23:39:25 +01:00
function Public.print_transaction(player, offer_itemname, offer_itemcount, price)
local type = 'traded away'
local s2 = {''}
2022-05-22 23:39:25 +01:00
local s3 = offer_itemcount .. ' ' .. offer_itemname
if offer_itemname == 'coin' then type = 'sold' end
2022-05-06 16:16:15 +01:00
for i, p in pairs(price) do
local p2 = {name = p.name, amount = p.amount}
if p2.name == 'raw-fish' then p2.name = 'fish' end
if p2.name == 'coin' then
type = 'bought'
2022-05-06 16:16:15 +01:00
p2.name = 'doubloons'
end
if i > 1 then
if i == #price then
s2[#s2+1] = {'pirates.separator_2'}
2022-05-06 16:16:15 +01:00
else
s2[#s2+1] = {'pirates.separator_1'}
2022-05-06 16:16:15 +01:00
end
end
s2[#s2+1] = p2.amount
s2[#s2+1] = ' '
s2[#s2+1] = p2.name
2022-05-06 16:16:15 +01:00
end
if type == 'sold' then
Common.notify_force_light(player.force, {'pirates.market_event_sell', player.name, s2, s3})
elseif type == 'traded away' then
Common.notify_force_light(player.force, {'pirates.market_event_trade', player.name, s2, s3})
elseif type == 'bought' then
Common.notify_force_light(player.force, {'pirates.market_event_buy', player.name, s3, s2})
2022-05-06 16:16:15 +01:00
end
end
2022-05-07 21:56:16 +01:00
local function purchaseData(market, player, offer_index)
--a proper rewriting of this function would directly check market entities against saved references to them in memory, but we haven't had time to rewrite it yet
2022-05-06 16:16:15 +01:00
2022-02-26 23:33:19 +00:00
local destination = Common.current_destination()
2021-10-13 09:21:53 +01:00
local alloffers = market.get_market_items()
local this_offer = alloffers[offer_index]
local price = this_offer.price
2022-02-26 18:25:48 +00:00
local offer_type = this_offer.offer.type
local offer_giveitem_name, offer_giveitem_count
if offer_type == 'give-item' then
offer_giveitem_name = this_offer.offer.item
offer_giveitem_count = this_offer.offer.count
end
2022-03-07 18:41:42 +00:00
-- check for BARTER vs STATIC vs ONE-OFF
2022-02-26 23:33:19 +00:00
-- One-off becomes unavailable after purchase, such as class purchase
-- Static doesn't decay
-- Barter decays
local decay_type
2022-03-03 00:19:20 +00:00
local dock_bool = destination.type == SurfacesCommon.enum.DOCK
2022-03-07 18:41:42 +00:00
local island_bool = destination.type == SurfacesCommon.enum.ISLAND
2022-03-03 00:19:20 +00:00
local purchase_bool = (price and price[1] and price[1].name and (price[1].name == 'coin'))
local simple_efficiency_trade_bool = (price and price[1] and price[1].name and (price[1].name == 'pistol' or price[1].name == 'burner-mining-drill'))
2022-03-09 21:39:47 +00:00
local special_purchase_bool = (offer_giveitem_name == 'rocket-launcher')
-- local special_purchase_bool = (offer_giveitem_name and (offer_giveitem_name == 'loader' or offer_giveitem_name == 'fast-loader' or offer_giveitem_name == 'express-loader' or offer_giveitem_name == 'rocket-launcher'))
2022-03-03 00:19:20 +00:00
local surface_name_decoded = SurfacesCommon.decode_surface_name(player.surface.name)
local type = surface_name_decoded.type
local in_captains_cabin = type and type == SurfacesCommon.enum.CABIN
local dock_upgrades_market = destination.dynamic_data.dock_captains_market and (destination.dynamic_data.dock_captains_market == market)
local permission_level_fail = (in_captains_cabin and Roles.player_privilege_level(player) < Roles.privilege_levels.OFFICER) or (dock_upgrades_market and Roles.player_privilege_level(player) < Roles.privilege_levels.OFFICER)
if in_captains_cabin then
decay_type = 'static'
2022-05-06 16:16:15 +01:00
elseif offer_type == 'nothing' or dock_upgrades_market then
2022-02-26 23:33:19 +00:00
decay_type = 'one-off'
2022-04-29 17:43:46 +01:00
elseif simple_efficiency_trade_bool or special_purchase_bool then
decay_type = 'static'
2022-03-03 00:19:20 +00:00
elseif dock_bool and purchase_bool and (offer_giveitem_name) and (offer_giveitem_name == 'stone' or offer_giveitem_name == 'iron-ore' or offer_giveitem_name == 'copper-ore' or offer_giveitem_name == 'crude-oil-barrel') then
2022-03-14 17:37:18 +00:00
decay_type = 'fast_decay'
2022-03-05 19:56:41 +00:00
elseif dock_bool and purchase_bool and (offer_giveitem_name) then
decay_type = 'one-off'
2022-03-08 23:36:03 +00:00
elseif island_bool and (not (offer_giveitem_name and offer_giveitem_name == 'rocket')) then
2022-03-07 18:41:42 +00:00
decay_type = 'one-off'
2022-02-26 23:33:19 +00:00
else
decay_type = 'decay'
end
2022-05-07 21:56:16 +01:00
return {
2022-05-22 23:20:30 +01:00
alloffers = alloffers,
2022-05-07 21:56:16 +01:00
decay_type = decay_type,
price = price,
offer_type = offer_type,
offer_giveitem_name = offer_giveitem_name,
offer_giveitem_count = offer_giveitem_count,
dock_bool = dock_bool,
island_bool = island_bool,
purchase_bool = purchase_bool,
simple_efficiency_trade_bool = simple_efficiency_trade_bool,
special_purchase_bool = special_purchase_bool,
in_captains_cabin = in_captains_cabin,
dock_upgrades_market = dock_upgrades_market,
permission_level_fail = permission_level_fail,
}
end
function Public.event_on_market_item_purchased(event)
local player_index, market, offer_index, trade_count = event.player_index, event.market, event.offer_index, event.count
local player = game.players[player_index]
if not (market and market.valid and offer_index and Common.validate_player(player)) then return end
local crew_id = tonumber(string.sub(player.force.name, -3, -1)) or nil
Memory.set_working_id(crew_id)
local memory = Memory.get_crew_memory()
local destination = Common.current_destination()
local inv = player.get_inventory(defines.inventory.character_main)
local thisPurchaseData = purchaseData(market, player, offer_index)
local refunds = 0
-- Normally we want to disallow multi-purchases in this game (with the exception of static trades for items), so refund any additional purchases:
2022-05-07 21:56:16 +01:00
if (thisPurchaseData.decay_type ~= 'static' or thisPurchaseData.offer_type == 'nothing') and player and trade_count and trade_count > 1 then
2022-03-05 14:09:35 +00:00
inv = player.get_inventory(defines.inventory.character_main)
if not inv then return end
2022-05-07 21:56:16 +01:00
for _, p in pairs(thisPurchaseData.price) do
2022-03-05 14:09:35 +00:00
inv.insert{name = p.name, count = p.amount * (trade_count - 1)}
end
2022-05-07 21:56:16 +01:00
if thisPurchaseData.offer_type == 'give-item' then
inv.remove{name = thisPurchaseData.offer_giveitem_name, count = thisPurchaseData.offer_giveitem_count * (trade_count - 1)}
2022-03-05 14:09:35 +00:00
end
refunds = refunds + (trade_count - 1)
2022-03-05 14:09:35 +00:00
end
2022-05-07 21:56:16 +01:00
if thisPurchaseData.decay_type == 'one-off' then
2021-10-13 09:21:53 +01:00
local force = player.force
2022-05-07 21:56:16 +01:00
if thisPurchaseData.dock_upgrades_market then
if thisPurchaseData.offer_type == 'give-item' then
-- this is the dummy artillery purchase
2022-05-07 21:56:16 +01:00
inv.remove{name = thisPurchaseData.offer_giveitem_name, count = thisPurchaseData.offer_giveitem_count}
2022-02-26 23:33:19 +00:00
end
2022-03-04 17:57:58 +00:00
2022-05-07 21:56:16 +01:00
if thisPurchaseData.permission_level_fail then
Common.notify_player_error(player, {'pirates.market_error_not_captain'})
-- refund:
inv = player.get_inventory(defines.inventory.character_main)
if not inv then return end
2022-05-07 21:56:16 +01:00
for _, p in pairs(thisPurchaseData.price) do
inv.insert{name = p.name, count = p.amount}
end
refunds = refunds + 1
else
2022-05-07 21:56:16 +01:00
if thisPurchaseData.offer_type == 'give-item' then
-- heal all cannons:
local cannons = game.surfaces[destination.surface_name].find_entities_filtered({type = 'artillery-turret'})
for _, c in pairs(cannons) do
local unit_number = c.unit_number
2022-05-07 21:56:16 +01:00
2022-05-07 21:41:45 +01:00
local healthbar = memory.boat.healthbars[unit_number]
if healthbar then
healthbar.health = healthbar.max_health
Common.update_healthbar_rendering(healthbar, healthbar.max_health)
2022-05-07 21:41:45 +01:00
else
log('error: healthbar ' .. unit_number .. ' not found')
end
2022-03-04 17:57:58 +00:00
end
Common.notify_force(force,{'pirates.repaired_cannons', player.name})
market.remove_market_item(offer_index)
2022-03-04 17:57:58 +00:00
else
local upgrade_type = Common.current_destination().static_params.upgrade_for_sale
if upgrade_type then
Upgrades.execute_upgade(upgrade_type, player)
2022-03-04 17:57:58 +00:00
end
market.remove_market_item(offer_index)
2022-03-04 17:57:58 +00:00
end
end
2022-03-04 17:57:58 +00:00
else
2022-03-19 21:20:55 +00:00
2022-05-07 21:56:16 +01:00
if thisPurchaseData.offer_type == 'nothing' and destination.static_params.class_for_sale then
local class_for_sale = destination.static_params.class_for_sale
-- if not class_for_sale then return end
local required_class = Classes.class_purchase_requirement[class_for_sale]
2022-05-07 21:56:16 +01:00
local ok = true
-- check if they have the required class to buy it
if required_class then
if not (memory.classes_table and memory.classes_table[player.index] and memory.classes_table[player.index] == required_class) then
ok = false
Common.notify_force_error(force, {'pirates.class_purchase_error_prerequisite_class',Classes.display_form(required_class)})
end
2022-03-04 17:57:58 +00:00
end
2022-05-07 21:56:16 +01:00
if ok then
if required_class then
if force and force.valid then
local message = {'pirates.class_upgrade', player.name, Classes.display_form(required_class), Classes.display_form(class_for_sale), Classes.explanation(class_for_sale)}
Common.notify_force_light(force,message)
end
else
-- check if they have a role already - renounce it if so
if memory.classes_table and memory.classes_table[player.index] then
Classes.try_renounce_class(player, false)
end
2022-05-07 21:56:16 +01:00
if force and force.valid then
local message = {'pirates.class_purchase', player.name, Classes.display_form(class_for_sale), Classes.explanation(class_for_sale)}
Common.notify_force_light(force, message)
end
end
2022-05-07 21:56:16 +01:00
memory.classes_table[player.index] = class_for_sale
2022-05-07 21:56:16 +01:00
memory.available_classes_pool = Utils.ordered_table_with_single_value_removed(memory.available_classes_pool, class_for_sale)
2022-05-07 21:56:16 +01:00
-- if destination.dynamic_data and destination.dynamic_data.market_class_offer_rendering then
-- rendering.destroy(destination.dynamic_data.market_class_offer_rendering)
-- end
2022-05-07 21:56:16 +01:00
market.remove_market_item(offer_index)
2022-05-07 21:56:16 +01:00
if Classes.class_unlocks[class_for_sale] then
for _, upgrade in pairs(Classes.class_unlocks[class_for_sale]) do
memory.available_classes_pool[#memory.available_classes_pool + 1] = upgrade
end
end
else
--refund
inv = player.get_inventory(defines.inventory.character_main)
if not inv then return end
2022-05-07 21:56:16 +01:00
for _, p in pairs(thisPurchaseData.price) do
inv.insert{name = p.name, count = p.amount}
2022-03-04 17:57:58 +00:00
end
refunds = refunds + 1
2022-03-04 17:57:58 +00:00
end
else
Common.notify_force_light(player.force, {'pirates.market_event_buy', player.name, thisPurchaseData.offer_giveitem_count .. ' ' .. thisPurchaseData.offer_giveitem_name, thisPurchaseData.price[1].amount .. ' ' .. thisPurchaseData.price[1].name})
2022-05-07 21:56:16 +01:00
market.remove_market_item(offer_index)
2022-02-26 23:33:19 +00:00
end
2021-10-13 09:21:53 +01:00
end
else
2022-05-07 21:56:16 +01:00
if thisPurchaseData.in_captains_cabin and thisPurchaseData.permission_level_fail then
Common.notify_player_error(player, {'pirates.market_error_not_captain_or_officer'})
-- refund:
inv = player.get_inventory(defines.inventory.character_main)
if not inv then return end
2022-05-07 21:56:16 +01:00
for _, p in pairs(thisPurchaseData.price) do
inv.insert{name = p.name, count = p.amount}
end
2022-05-07 21:56:16 +01:00
if thisPurchaseData.offer_type == 'give-item' then
inv.remove{name = thisPurchaseData.offer_giveitem_name, count = thisPurchaseData.offer_giveitem_count}
end
refunds = refunds + 1
else
-- print:
2022-05-07 21:56:16 +01:00
if (thisPurchaseData.price and thisPurchaseData.price[1]) then
if not (thisPurchaseData.price[1].name and thisPurchaseData.price[1].name == 'burner-mining-drill') then --this one is too boring to announce
if thisPurchaseData.in_captains_cabin and thisPurchaseData.offer_type == 'nothing' then
Common.notify_force_light(player.force, {'pirates.market_event_buy', player.name, {'pirates.extra_time_at_sea'}, thisPurchaseData.price[1].amount .. ' ' .. thisPurchaseData.price[1].name})
2022-02-28 16:36:46 +00:00
else
2022-05-22 23:11:52 +01:00
Public.print_transaction(player, thisPurchaseData.offer_giveitem_name, thisPurchaseData.offer_giveitem_count, thisPurchaseData.price)
2022-02-28 16:36:46 +00:00
end
2022-02-27 16:42:25 +00:00
end
2022-02-26 13:55:36 +00:00
end
2022-05-07 21:56:16 +01:00
if thisPurchaseData.in_captains_cabin and thisPurchaseData.offer_type == 'nothing' then
local success = Crew.try_add_extra_time_at_sea(60 * 60)
if not success then
Common.notify_player_error(player, {'pirates.market_error_maximum_loading_time'})
-- refund:
inv = player.get_inventory(defines.inventory.character_main)
if not inv then return end
2022-05-07 21:56:16 +01:00
for _, p in pairs(thisPurchaseData.price) do
inv.insert{name = p.name, count = p.amount}
end
refunds = refunds + 1
end
else
2022-05-07 21:56:16 +01:00
if thisPurchaseData.decay_type == 'static' then
if not inv then return end
local flying_text_color = {r = 255, g = 255, b = 255}
2022-05-22 23:20:30 +01:00
local text1 = '[color=1,1,1]+' .. thisPurchaseData.offer_giveitem_count .. '[/color] [item=' .. thisPurchaseData.offer_giveitem_name .. ']'
local text2 = '[color=' .. flying_text_color.r .. ',' .. flying_text_color.g .. ',' .. flying_text_color.b .. '](' .. inv.get_item_count(thisPurchaseData.offer_giveitem_name) .. ')[/color]'
2022-05-07 21:56:16 +01:00
Common.flying_text(player.surface, player.position, text1 .. ' [font=count-font]' .. text2 .. '[/font]')
else
local decay_param = Balance.barter_decay_parameter()
2022-05-07 21:56:16 +01:00
if thisPurchaseData.decay_type == 'fast_decay' then decay_param = Balance.barter_decay_parameter()^3 end
if not inv then return end
local flying_text_color = {r = 255, g = 255, b = 255}
2022-05-22 23:20:30 +01:00
local text1 = '[color=1,1,1]+' .. thisPurchaseData.offer_giveitem_count .. '[/color] [item=' .. thisPurchaseData.offer_giveitem_name .. ']'
2022-05-22 23:11:52 +01:00
local text2 = '[color=' .. flying_text_color.r .. ',' .. flying_text_color.g .. ',' .. flying_text_color.b .. '](' .. inv.get_item_count(thisPurchaseData.offer_giveitem_name) .. ')[/color]'
2022-05-07 21:56:16 +01:00
Common.flying_text(player.surface, player.position, text1 .. ' [font=count-font]' .. text2 .. '[/font]')
2022-05-07 21:56:16 +01:00
--update market trades:
2022-05-07 21:56:16 +01:00
thisPurchaseData.alloffers[offer_index].offer.count = Math.max(Math.floor(thisPurchaseData.alloffers[offer_index].offer.count * decay_param),1)
market.clear_market_items()
2022-05-07 21:56:16 +01:00
for _, offer in pairs(thisPurchaseData.alloffers) do
market.add_market_item(offer)
end
end
2021-10-13 09:21:53 +01:00
end
end
end
2022-05-22 23:11:52 +01:00
if thisPurchaseData.offer_giveitem_name and thisPurchaseData.offer_giveitem_name == 'coin' and refunds < trade_count then
memory.playtesting_stats.coins_gained_by_markets = memory.playtesting_stats.coins_gained_by_markets + thisPurchaseData.offer_giveitem_count
end
2021-10-13 09:21:53 +01:00
end
return Public