Merge branch 'lawAndOrder_to_lua', #3254
commit
ad4aa02c7f
|
@ -9,6 +9,7 @@ local f = Faction:new('Solar Federation')
|
|||
:expansionRate(1.0)
|
||||
:military_name('SolFed Military')
|
||||
:police_name('SolFed Police Force')
|
||||
:police_ship('kanara')
|
||||
:colour(0.4,0.4,1.0)
|
||||
|
||||
f:govtype_weight('EARTHDEMOC', 60)
|
||||
|
|
|
@ -9,6 +9,7 @@ local f = Faction:new('Commonwealth of Independent Worlds')
|
|||
:expansionRate(1.0)
|
||||
:military_name('Confederation Fleet')
|
||||
:police_name('Confederal Police')
|
||||
:police_ship('pumpkinseed_police')
|
||||
:colour(0.4,1.0,0.4)
|
||||
|
||||
f:govtype_weight('CISSOCDEM', 80)
|
||||
|
|
|
@ -907,18 +907,6 @@
|
|||
"description" : "",
|
||||
"message" : "Sep"
|
||||
},
|
||||
"MULTI_SCOOP" : {
|
||||
"description" : "A ship equipment: a cargo scoop and fuel scoop combined to one",
|
||||
"message" : "Multi Scoop"
|
||||
},
|
||||
"MULTI_SCOOP_DESCRIPTION" : {
|
||||
"description" : "",
|
||||
"message" : "Although less effective than a fuel scoop it permits scooping of both cargo and fuel"
|
||||
},
|
||||
"MURDER" : {
|
||||
"description" : "",
|
||||
"message" : "Murder"
|
||||
},
|
||||
"M_S_RELATIVE_TO" : {
|
||||
"description" : "",
|
||||
"message" : "%speed{f.0} m/s rel-to %frame"
|
||||
|
@ -1111,10 +1099,6 @@
|
|||
"description" : "",
|
||||
"message" : "PIONEER"
|
||||
},
|
||||
"PIRACY" : {
|
||||
"description" : "",
|
||||
"message" : "Piracy"
|
||||
},
|
||||
"PITCH" : {
|
||||
"description" : "",
|
||||
"message" : "Pitch"
|
||||
|
@ -1151,10 +1135,6 @@
|
|||
"description" : "",
|
||||
"message" : "Plutocratic dictatorship"
|
||||
},
|
||||
"POLICE_SHIP_REGISTRATION" : {
|
||||
"description" : "",
|
||||
"message" : "POLICE"
|
||||
},
|
||||
"POPULATION" : {
|
||||
"description" : "",
|
||||
"message" : "Population:"
|
||||
|
@ -1707,10 +1687,6 @@
|
|||
"description" : "",
|
||||
"message" : "<unknown>"
|
||||
},
|
||||
"UNLAWFUL_WEAPONS_DISCHARGE" : {
|
||||
"description" : "",
|
||||
"message" : "Unlawful weapons discharge"
|
||||
},
|
||||
"USE_LOW_THRUST" : {
|
||||
"description" : "",
|
||||
"message" : "Use low thrust"
|
||||
|
@ -1771,10 +1747,6 @@
|
|||
"description" : "keybinding: x axis",
|
||||
"message" : "X"
|
||||
},
|
||||
"X_CANNOT_BE_TOLERATED_HERE" : {
|
||||
"description" : "",
|
||||
"message" : "%crime cannot be tolerated here."
|
||||
},
|
||||
"Y" : {
|
||||
"description" : "keybinding: y axis",
|
||||
"message" : "Y"
|
||||
|
|
|
@ -196,7 +196,7 @@
|
|||
"message" : "Crew Roster"
|
||||
},
|
||||
"CRIMINAL_RECORD" : {
|
||||
"description" : "",
|
||||
"description" : "Past crimes / crime history of character",
|
||||
"message" : "Criminal record"
|
||||
},
|
||||
"DANGEROUS" : {
|
||||
|
@ -255,6 +255,10 @@
|
|||
"description" : "mission deadline date",
|
||||
"message" : "Due"
|
||||
},
|
||||
"DUMPING" : {
|
||||
"description" : "The illegal act of dumping waste",
|
||||
"message" : "Dumping"
|
||||
},
|
||||
"D_DAYS_LEFT" : {
|
||||
"description" : "",
|
||||
"message" : "Days left: %d"
|
||||
|
@ -771,6 +775,10 @@
|
|||
"description" : "Player owing money to crew members",
|
||||
"message" : "Owed"
|
||||
},
|
||||
"OUTSTANDING_FINES" : {
|
||||
"description" : "Unpaid fines for crimes committed",
|
||||
"message" : "Outstanding fines"
|
||||
},
|
||||
"PAY_FINE_OF_N" : {
|
||||
"description" : "",
|
||||
"message" : "Pay fine of {amount}"
|
||||
|
@ -1126,5 +1134,9 @@
|
|||
"YOU_NOT_ENOUGH_MONEY" : {
|
||||
"description" : "",
|
||||
"message" : "You do not have enough money"
|
||||
},
|
||||
"X_CANNOT_BE_TOLERATED_HERE" : {
|
||||
"description" : "Message to be sent over comms by police when crime is committed by player",
|
||||
"message" : "{crime} cannot be tolerated here!"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
-- Copyright © 2008-2015 Pioneer Developers. See AUTHORS.txt for details
|
||||
-- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
local Comms = import("Comms")
|
||||
local Game = import("Game")
|
||||
|
||||
local Lang = import("Lang")
|
||||
local l = Lang.GetResource("ui-core")
|
||||
|
||||
|
||||
--
|
||||
-- Namespace: Legal
|
||||
--
|
||||
|
||||
--
|
||||
-- Constants: CrimeType
|
||||
--
|
||||
-- Different types of crimes and law offences
|
||||
--
|
||||
-- DUMPING - jettison of hazardous rubble/waste
|
||||
-- MURDER - destruction of ship
|
||||
-- PIRACY - fired on ship
|
||||
-- TRADING_ILLEGAL_GOODS - attempted to sell illegal goods
|
||||
-- WEAPONS_DISCHARGE - weapons discharged too close to station
|
||||
--
|
||||
-- Availability:
|
||||
--
|
||||
-- 2015 July
|
||||
--
|
||||
-- Status:
|
||||
--
|
||||
-- experimental
|
||||
--
|
||||
|
||||
|
||||
local Legal = {}
|
||||
Legal.CrimeType = {}
|
||||
|
||||
Legal.CrimeType["DUMPING"] = {basefine = 1e4, name = l.DUMPING}
|
||||
Legal.CrimeType["MURDER"] = {basefine = 1.5e6, name = l.MURDER}
|
||||
Legal.CrimeType["PIRACY"] = {basefine = 1e5, name = l.PIRACY}
|
||||
Legal.CrimeType["TRADING_ILLEGAL_GOODS"] = {basefine = 5e3, name = l.TRADING_ILLEGAL_GOODS}
|
||||
Legal.CrimeType["WEAPONS_DISCHARGE"] = {basefine = 5e2, name = l.UNLAWFUL_WEAPONS_DISCHARGE}
|
||||
|
||||
|
||||
function Legal:notifyOfCrime (ship, crime)
|
||||
if not ship:IsPlayer() then return end
|
||||
-- TODO: can this be called in hyperpace?
|
||||
|
||||
-- find closest law enforcing station
|
||||
local station = Game.player:FindNearestTo("SPACESTATION")
|
||||
|
||||
-- too far away for crime to be noticed
|
||||
if station.lawEnforcedRange < station:DistanceTo(Game.player) then
|
||||
return
|
||||
end
|
||||
|
||||
Comms.ImportantMessage(string.interp(l.X_CANNOT_BE_TOLERATED_HERE, {crime=self.CrimeType[crime].name}),
|
||||
station.label)
|
||||
|
||||
local lawlessness = Game.system.lawlessness
|
||||
local _, outstandingfines = Game.player:GetCrimeOutstanding()
|
||||
local newFine = math.max(1, 1+math.floor(self.CrimeType[crime].basefine * (1.0-lawlessness)))
|
||||
|
||||
-- don't keep compounding fines, except for murder
|
||||
if crime ~= "MURDER" and newFine < outstandingfines then newFine = 0 end
|
||||
Game.player:AddCrime(crime, newFine)
|
||||
end
|
||||
|
||||
|
||||
return Legal
|
|
@ -5,6 +5,275 @@ local Player = import_core("Player")
|
|||
local Serializer = import("Serializer")
|
||||
local Event = import("Event")
|
||||
local Game = import("Game")
|
||||
local utils = import("utils")
|
||||
local Legal = import("Legal")
|
||||
|
||||
Player.record = {}
|
||||
Player.record_old = {}
|
||||
|
||||
-- container for crimes committed
|
||||
local CrimeRecord = utils.inherits(nil, "CrimeRecord")
|
||||
|
||||
function CrimeRecord.New(rec)
|
||||
rec = rec or {}
|
||||
setmetatable(rec, CrimeRecord.meta)
|
||||
rec.fine = 0
|
||||
rec.crimetype = {}
|
||||
return rec
|
||||
end
|
||||
|
||||
|
||||
function CrimeRecord:Add(crime, fine)
|
||||
|
||||
if not fine then
|
||||
fine = Legal.CrimeType[crime].basefine
|
||||
end
|
||||
|
||||
-- if first time for this crime type
|
||||
if not self.crimetype[crime] then
|
||||
self.crimetype[crime] = {}
|
||||
self.crimetype[crime].count = 0
|
||||
end
|
||||
|
||||
self.crimetype[crime].count = self.crimetype[crime].count +1
|
||||
self.fine = self.fine + fine
|
||||
return self.fine
|
||||
end
|
||||
|
||||
|
||||
function CrimeRecord:SetFine(fine)
|
||||
self.fine = fine
|
||||
return self.fine
|
||||
end
|
||||
|
||||
-- add two crime records together
|
||||
function CrimeRecord:Append(record)
|
||||
self.fine = self.fine + record.fine
|
||||
|
||||
for k,v in pairs(record.crimetype) do
|
||||
for i = 1, record.crimetype[k].count do
|
||||
self:Add(k, 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function CrimeRecord:Serialize()
|
||||
local tmp = CrimeRecord.Super().Serialize(self)
|
||||
local ret = {}
|
||||
for k,v in pairs(tmp) do
|
||||
ret[k] = v
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
|
||||
function CrimeRecord.Unserialize(data)
|
||||
obj = CrimeRecord.Super().Unserialize(data)
|
||||
setmetatable(obj, CrimeRecord.meta)
|
||||
return obj
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Method: AddCrime
|
||||
--
|
||||
-- Add a crime to the player's criminal record
|
||||
--
|
||||
-- > Game.player:AddCrime(crime, fine, faction)
|
||||
--
|
||||
-- Parameters:
|
||||
--
|
||||
-- crime - a string constant describing the crime
|
||||
--
|
||||
-- fine - an amount to add to the player's fine
|
||||
--
|
||||
-- faction - optional argument, defaults to the faction id of the system
|
||||
-- the player is currently in
|
||||
--
|
||||
--
|
||||
-- Availability:
|
||||
--
|
||||
-- 2015 August
|
||||
--
|
||||
-- Status:
|
||||
--
|
||||
-- experimental
|
||||
--
|
||||
function Player:AddCrime (crime, fine, faction)
|
||||
local forFaction = (faction and faction.id) or Game.system.faction.id
|
||||
|
||||
-- first time for this faction
|
||||
if not self.record[forFaction] then
|
||||
self.record[forFaction] = CrimeRecord.New()
|
||||
end
|
||||
|
||||
self.record[forFaction]:Add(crime, fine)
|
||||
end
|
||||
|
||||
|
||||
local function __GetCrime (record)
|
||||
|
||||
-- return crime record and total fine for faction
|
||||
local listOfCrime, fine
|
||||
|
||||
if Game.player.flightState == "HYPERSPACE" then
|
||||
-- no crime in hyperspace
|
||||
listOfCrime = {}
|
||||
fine = 0
|
||||
elseif not record then
|
||||
-- first time for this faction, clean record
|
||||
listOfCrime = {}
|
||||
fine = 0
|
||||
else
|
||||
listOfCrime = record.crimetype
|
||||
fine = record.fine
|
||||
end
|
||||
|
||||
return listOfCrime, fine
|
||||
end
|
||||
|
||||
--
|
||||
-- Method: GetCrimeRecord
|
||||
--
|
||||
-- Get players past criminal record of and total payed fine for faction
|
||||
--
|
||||
-- > criminalRecord, fine = Game.player:GetCrimeRecord()
|
||||
-- > criminalRecord, fine = Game.player:GetCrimeRecord(faction)
|
||||
--
|
||||
-- Parameters:
|
||||
--
|
||||
-- faction - optional argument, defaults to the faction id of the system
|
||||
-- the player is in
|
||||
--
|
||||
--
|
||||
-- Return:
|
||||
--
|
||||
-- criminalRecord - a table with key being "crime constant" and "count"
|
||||
-- for each crime committed
|
||||
--
|
||||
-- fine - the total fine of the player in faction
|
||||
--
|
||||
--
|
||||
-- Availability:
|
||||
--
|
||||
-- 2015 September
|
||||
--
|
||||
-- Status:
|
||||
--
|
||||
-- experimental
|
||||
--
|
||||
function Player:GetCrimeRecord (faction)
|
||||
local forFaction = (faction and faction.id) or Game.system.faction.id
|
||||
return __GetCrime(self.record_old[forFaction])
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Method: GetCrimeOutstanding
|
||||
--
|
||||
-- Get players current outstanding criminal record and total unpayed fine for faction
|
||||
--
|
||||
-- > criminalRecord, fine = Game.player:GetCrimeOutstanding()
|
||||
-- > criminalRecord, fine = Game.player:GetCrimeOutstanding(faction)
|
||||
--
|
||||
-- Parameters:
|
||||
--
|
||||
-- faction - optional argument, defaults to the faction id of the system
|
||||
-- the player is currently in
|
||||
--
|
||||
--
|
||||
-- Return:
|
||||
--
|
||||
-- criminalRecord - a table with key being "crime constant" and "count"
|
||||
-- for each crime committed
|
||||
--
|
||||
-- fine - the total fine of the player in faction
|
||||
--
|
||||
--
|
||||
-- Availability:
|
||||
--
|
||||
-- 2015 September
|
||||
--
|
||||
-- Status:
|
||||
--
|
||||
-- experimental
|
||||
--
|
||||
function Player:GetCrimeOutstanding (faction)
|
||||
local forFaction = (faction and faction.id) or Game.system.faction.id
|
||||
return __GetCrime(self.record[forFaction])
|
||||
end
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- Method: ClearCrimeFine
|
||||
--
|
||||
-- Clear the current record of outstanding fines and crimes for player
|
||||
--
|
||||
-- > Game.player:ClearCrimeFine()
|
||||
-- > Game.player:ClearCrimeFine(faction)
|
||||
-- > Game.player:ClearCrimeFine(faction, clean)
|
||||
--
|
||||
-- Parameters:
|
||||
--
|
||||
-- faction - optional argument, defaults to the faction id of the system
|
||||
-- the player is currently in
|
||||
--
|
||||
-- clean - optional Boolean argument, defaults to false, resulting in the
|
||||
-- cleared fines to still be moved to the player's crime record
|
||||
-- over past offences
|
||||
--
|
||||
--
|
||||
-- Availability:
|
||||
--
|
||||
-- 2015 September
|
||||
--
|
||||
-- Status:
|
||||
--
|
||||
-- experimental
|
||||
--
|
||||
function Player:ClearCrimeFine (faction, forget)
|
||||
local forFaction = (faction and faction.id) or Game.system.faction.id
|
||||
|
||||
self.record[forFaction].fine = 0 -- Clear fine
|
||||
|
||||
if not forget then
|
||||
if not self.record_old[forFaction] then
|
||||
self.record_old[forFaction] = CrimeRecord.New()
|
||||
end
|
||||
self.record_old[forFaction]:Append(self.record[forFaction], true)
|
||||
end
|
||||
|
||||
self.record[forFaction] = nil -- Clear record
|
||||
end
|
||||
|
||||
--
|
||||
-- Method: ClearCrimeRecordHistory
|
||||
--
|
||||
-- Clear the player's crime record history, excluding current unpayed offences
|
||||
--
|
||||
-- > Game.player:ClearCrimeRecordHistory()
|
||||
-- > Game.player:ClearCrimeRecordHistory(faction)
|
||||
--
|
||||
-- Parameters:
|
||||
--
|
||||
-- faction - optional argument, defaults to the faction if of the system
|
||||
-- the player is currently in
|
||||
--
|
||||
--
|
||||
-- Availability:
|
||||
--
|
||||
-- 2015 September
|
||||
--
|
||||
-- Status:
|
||||
--
|
||||
-- experimental
|
||||
--
|
||||
function Player:ClearCrimeRecordHistory (faction)
|
||||
local forFaction = (faction and faction.id) or Game.system.faction.id
|
||||
self.record_old[forFaction] = nil
|
||||
end
|
||||
|
||||
--
|
||||
-- Method: GetMoney
|
||||
|
@ -82,21 +351,51 @@ end
|
|||
|
||||
local loaded_data
|
||||
|
||||
Event.Register("onGameStart", function ()
|
||||
local onGameStart = function ()
|
||||
|
||||
-- Don't reset these in onGameEnd (where they belong), since that
|
||||
-- sometimes clears out the data before autosave-exit can get to it
|
||||
-- (call order for event triggers is arbitrary)...
|
||||
Player.record = {}
|
||||
Player.record_old = {}
|
||||
|
||||
if (loaded_data) then
|
||||
Game.player:setprop("cash", loaded_data)
|
||||
Game.player:setprop("cash", loaded_data.cash)
|
||||
|
||||
-- ...thus we need to manually unserialize them
|
||||
Player.record = loaded_data.record
|
||||
Player.record_old = loaded_data.record_old
|
||||
|
||||
loaded_data = nil
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
Serializer:Register("Player",
|
||||
function ()
|
||||
return Game.player.cash
|
||||
end,
|
||||
function (data)
|
||||
loaded_data = data
|
||||
end
|
||||
)
|
||||
local serialize = function ()
|
||||
|
||||
local data = {
|
||||
cash = Game.player.cash,
|
||||
record = Game.player.record,
|
||||
record_old = Game.player.record_old
|
||||
}
|
||||
|
||||
return data
|
||||
end
|
||||
|
||||
|
||||
local unserialize = function (data)
|
||||
loaded_data = data
|
||||
Player.cash = data.cash
|
||||
Player.record = data.record
|
||||
Player.record_old = data.record_old
|
||||
end
|
||||
|
||||
local onGameEnd = function ()
|
||||
-- clean up for next game:
|
||||
end
|
||||
|
||||
Event.Register("onGameEnd", onGameEnd)
|
||||
Event.Register("onGameStart", onGameStart)
|
||||
Serializer:RegisterClass("CrimeRecord", CrimeRecord)
|
||||
Serializer:Register("Player", serialize, unserialize)
|
||||
|
||||
return Player
|
||||
|
|
|
@ -15,6 +15,9 @@ local Model = import("SceneGraph.Model")
|
|||
local ModelSkin = import("SceneGraph.ModelSkin")
|
||||
local Serializer = import("Serializer")
|
||||
local Equipment = import("Equipment")
|
||||
local Faction = import("Faction")
|
||||
local Lang = import("Lang")
|
||||
local l = Lang.GetResource("ui-core")
|
||||
|
||||
--
|
||||
-- Class: SpaceStation
|
||||
|
@ -289,6 +292,117 @@ local function updateShipsOnSale (station)
|
|||
end
|
||||
|
||||
|
||||
--
|
||||
-- Attribute: lawEnforcedRange
|
||||
--
|
||||
-- The distance, in meters, at which a station upholds the law,
|
||||
-- (is 100 km for all at the moment)
|
||||
--
|
||||
-- Availability:
|
||||
--
|
||||
-- 2015 September
|
||||
--
|
||||
-- Status:
|
||||
--
|
||||
-- experimental
|
||||
--
|
||||
SpaceStation.lawEnforcedRange = 100000
|
||||
|
||||
|
||||
local police = {}
|
||||
|
||||
--
|
||||
-- Method: LaunchPolice
|
||||
--
|
||||
-- Launch station police
|
||||
--
|
||||
-- > station:LaunchPolice(targetShip)
|
||||
--
|
||||
-- Parameters:
|
||||
--
|
||||
-- targetShip - the ship to intercept
|
||||
--
|
||||
-- Availability:
|
||||
--
|
||||
-- 2015 September
|
||||
--
|
||||
-- Status:
|
||||
--
|
||||
-- experimental
|
||||
--
|
||||
function SpaceStation:LaunchPolice(targetShip)
|
||||
if not targetShip then error("Ship targeted invalid") end
|
||||
|
||||
-- if no police created for this station yet:
|
||||
if not police[self] then
|
||||
police[self] = {}
|
||||
-- decide how many to create
|
||||
local lawlessness = Game.system.lawlessness
|
||||
local maxPolice = math.min(9, self.numDocks)
|
||||
local numberPolice = math.ceil(Engine.rand:Integer(1,maxPolice)*lawlessness)
|
||||
local shiptype = ShipDef[Game.system.faction.policeShip]
|
||||
|
||||
-- create and equip them
|
||||
while numberPolice > 0 do
|
||||
local policeShip = Space.SpawnShipDocked(shiptype.id, self)
|
||||
if policeShip == nil then
|
||||
return
|
||||
else
|
||||
numberPolice = numberPolice - 1
|
||||
--policeShip:SetLabel(Game.system.faction.policeName) -- this is cool, but not translatable right now
|
||||
policeShip:SetLabel(l.POLICE)
|
||||
policeShip:AddEquip(Equipment.laser.pulsecannon_dual_1mw)
|
||||
policeShip:AddEquip(Equipment.misc.atmospheric_shielding)
|
||||
policeShip:AddEquip(Equipment.misc.laser_cooling_booster)
|
||||
policeShip:AddEquip(Equipment.cargo.hydrogen, 1)
|
||||
|
||||
table.insert(police[self], policeShip)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for _, policeShip in pairs(police[self]) do
|
||||
-- if docked
|
||||
if policeShip.flightState == "DOCKED" then
|
||||
policeShip:Undock()
|
||||
end
|
||||
-- if not shot down
|
||||
if policeShip:exists() then
|
||||
policeShip:AIKill(targetShip)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Method: LandPolice
|
||||
--
|
||||
-- Clear any target assigned and land flying station police.
|
||||
--
|
||||
-- > station:LandPolice()
|
||||
--
|
||||
--
|
||||
-- Availability:
|
||||
--
|
||||
-- 2015 September
|
||||
--
|
||||
-- Status:
|
||||
--
|
||||
-- experimental
|
||||
--
|
||||
function SpaceStation:LandPolice()
|
||||
-- land command issued before creation of police
|
||||
if not police[self] then return end
|
||||
|
||||
for _, policeShip in pairs(police[self]) do
|
||||
if not (policeShip.flightState == "DOCKED") and policeShip:exists() then
|
||||
policeShip:CancelAI()
|
||||
policeShip:AIDockWith(self)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Group: Methods
|
||||
--
|
||||
|
@ -532,6 +646,8 @@ local function destroySystem ()
|
|||
equipmentStock = {}
|
||||
equipmentPrice = {}
|
||||
|
||||
police = {}
|
||||
|
||||
shipsOnSale = {}
|
||||
|
||||
for station,ads in pairs(SpaceStation.adverts) do
|
||||
|
@ -549,6 +665,7 @@ Event.Register("onGameStart", function ()
|
|||
if (loaded_data) then
|
||||
equipmentStock = loaded_data.equipmentStock
|
||||
equipmentPrice = loaded_data.equipmentPrice or {} -- handle missing in old saves
|
||||
police = loaded_data.police
|
||||
for station,list in pairs(loaded_data.shipsOnSale) do
|
||||
shipsOnSale[station] = {}
|
||||
for i,entry in pairs(loaded_data.shipsOnSale[station]) do
|
||||
|
@ -587,6 +704,7 @@ Event.Register("onGameEnd", function ()
|
|||
nextRef = 0
|
||||
equipmentStock = {}
|
||||
equipmentPrice = {}
|
||||
police = {}
|
||||
shipsOnSale = {}
|
||||
end)
|
||||
|
||||
|
@ -596,6 +714,7 @@ Serializer:Register("SpaceStation",
|
|||
local data = {
|
||||
equipmentStock = equipmentStock,
|
||||
equipmentPrice = equipmentPrice,
|
||||
police = police, --todo fails if a police ship is killed
|
||||
shipsOnSale = {},
|
||||
}
|
||||
for station,list in pairs(shipsOnSale) do
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
material smallship_fuselage-material
|
||||
diffuse 1.0 1.0 1.0
|
||||
specular 0.9 0.9 0.9
|
||||
shininess 70
|
||||
tex_diff pumpkinseed_police_diff.dds
|
||||
tex_glow pumpkinseed_police_glow.dds
|
||||
tex_spec pumpkinseed_police_spec.dds
|
||||
|
||||
lod 50
|
||||
mesh pumpkinseed_3low.dae
|
||||
|
||||
lod 100
|
||||
mesh pumpkinseed_2med.dae
|
||||
|
||||
lod 300
|
||||
mesh pumpkinseed_1hi.dae
|
||||
mesh pumpkinseed_shield.dae
|
||||
|
||||
collision pumpkinseed_collision.dae
|
||||
|
||||
anim gear_down 0 100
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,16 @@
|
|||
material Material-material
|
||||
diffuse 1.0 1.0 1.0
|
||||
specular 0.8 0.8 0.8
|
||||
tex_diff sinonatrix_tex_police.dds
|
||||
tex_spec sinonatrix_spec.dds
|
||||
tex_glow sinonatrix_glow.dds
|
||||
mesh sinonatrix.dae
|
||||
|
||||
anim gear_down 1 100
|
||||
|
||||
|
||||
collision sinonatrix_col.obj
|
||||
|
||||
lod 75
|
||||
mesh sinonatrix_LOD.dae
|
||||
mesh sinonatrix_shield.dae
|
Binary file not shown.
|
@ -0,0 +1,124 @@
|
|||
-- Copyright © 2008-2015 Pioneer Developers. See AUTHORS.txt for details
|
||||
-- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
local Event = import("Event")
|
||||
local Game = import("Game")
|
||||
local Engine = import("Engine")
|
||||
local Timer = import("Timer")
|
||||
local Serializer = import("Serializer")
|
||||
local Legal = import("Legal")
|
||||
|
||||
-- Fine at which police will launch and hunt donwn outlaw player
|
||||
local maxFineTolerated = 300
|
||||
|
||||
-- store which station sent them out
|
||||
local policeDispatched = false
|
||||
|
||||
-- check if we should dispatch police, or call them back
|
||||
local function doLawAndOrder ()
|
||||
if Game.player.flightState == "HYPERSPACE" then return end
|
||||
|
||||
local crimes, fine = Game.player:GetCrimeOutstanding()
|
||||
if not policeDispatched then
|
||||
if fine > maxFineTolerated and
|
||||
Game.player.flightState == "FLYING" and
|
||||
Engine.rand:Integer(0,1) > Game.system.lawlessness then
|
||||
local station = Game.player:FindNearestTo("SPACESTATION")
|
||||
if station.lawEnforcedRange >= station:DistanceTo(Game.player) then
|
||||
station:LaunchPolice(Game.player)
|
||||
policeDispatched = station
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- if police are out flying about, check if they should land
|
||||
-- Note: If player docks police will land.
|
||||
if policeDispatched then
|
||||
if fine < maxFineTolerated or
|
||||
Game.player.flightState == "DOCKED" or Game.player.flightState == "DOCKING" then
|
||||
policeDispatched:LandPolice()
|
||||
policeDispatched = false
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
local loaded_data
|
||||
|
||||
local onGameStart = function ()
|
||||
if (loaded_data) then
|
||||
policeDispatched = loaded_data.policeDispatched
|
||||
end
|
||||
loaded_data = nil
|
||||
Timer:CallEvery(5, doLawAndOrder)
|
||||
end
|
||||
|
||||
|
||||
local serialize = function ()
|
||||
local data = {
|
||||
policeDispatched = policeDispatched,
|
||||
}
|
||||
return data
|
||||
end
|
||||
|
||||
|
||||
local unserialize = function (data)
|
||||
loaded_data = data
|
||||
end
|
||||
|
||||
|
||||
local onJettison = function(ship, cargo)
|
||||
if ship:IsPlayer() then
|
||||
if cargo.price <= 0 or not Game.system:IsCommodityLegal(cargo) then
|
||||
Legal:notifyOfCrime(ship,"DUMPING")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local onShipHit = function(ship, attacker)
|
||||
if attacker and attacker:IsPlayer() then
|
||||
Legal:notifyOfCrime(ship,"PIRACY")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local onShipDestroyed = function(ship, attacker)
|
||||
-- Note: crash issue #887, this _should_ no longer trigger crash.
|
||||
-- Also, attacker can be a body, which does not have an IsPlayer()
|
||||
if attacker and attacker:isa("Ship") and attacker:IsPlayer() then
|
||||
Legal:notifyOfCrime(ship,"MURDER")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local onShipFiring = function(ship)
|
||||
if ship:IsPlayer() then
|
||||
Legal:notifyOfCrime(ship,"WEAPONS_DISCHARGE")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local onLeaveSystem = function(ship)
|
||||
if not ship:IsPlayer() then return end
|
||||
-- if we leave the system, the space station object will be invalid
|
||||
policeDispatched = nil
|
||||
end
|
||||
|
||||
|
||||
local onGameEnd = function ()
|
||||
policeDispatched = nil
|
||||
end
|
||||
|
||||
|
||||
Event.Register("onShipHit", onShipHit)
|
||||
Event.Register("onShipDestroyed", onShipDestroyed)
|
||||
Event.Register("onShipFiring", onShipFiring)
|
||||
Event.Register("onJettison", onJettison)
|
||||
Event.Register("onGameStart", onGameStart)
|
||||
Event.Register("onGameEnd", onGameEnd)
|
||||
Event.Register("onLeaveSystem", onLeaveSystem)
|
||||
|
||||
Serializer:Register("CrimeTracking", serialize, unserialize)
|
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"angular_thrust" : 16500000.0,
|
||||
"capacity" : 17,
|
||||
"cockpit" : "",
|
||||
"down_thrust" : 350000.0,
|
||||
"effective_exhaust_velocity" : 29000000.0,
|
||||
"forward_thrust" : 3200000.0,
|
||||
"fuel_tank_mass" : 9,
|
||||
"hull_mass" : 8,
|
||||
"hyperdrive_class" : 1,
|
||||
"left_thrust" : 350000.0,
|
||||
"manufacturer" : "kaluri",
|
||||
"max_crew" : 1,
|
||||
"min_crew" : 1,
|
||||
"model" : "pumpkinseed_police",
|
||||
"name" : "Police Pumpkinseed",
|
||||
"price" : 0.0,
|
||||
"reverse_thrust" : 1200000.0,
|
||||
"right_thrust" : 350000.0,
|
||||
"ship_class" : "light_courier",
|
||||
"slots" : {
|
||||
"cargo" : 10,
|
||||
"scoop" : 0,
|
||||
"laser_front" : 1,
|
||||
"laser_rear" : 1,
|
||||
"missile" : 4,
|
||||
"sensor" : 8
|
||||
},
|
||||
"thruster_fuel_use" : -1.0,
|
||||
"up_thrust" : 550000.0
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"model" : "sinonatrix_police",
|
||||
"name" : "Police Sinonatrix",
|
||||
"cockpit" : "",
|
||||
"manufacturer" : "opli",
|
||||
"ship_class" : "light_fighter",
|
||||
"min_crew" : 1,
|
||||
"max_crew" : 2,
|
||||
"price" : 0.0,
|
||||
"hull_mass" : 22,
|
||||
"capacity" : 35,
|
||||
"slots" : {
|
||||
"cargo" : 35,
|
||||
"scoop" : 0,
|
||||
"laser_front" : 1,
|
||||
"missile" : 4,
|
||||
"sensor" : 8
|
||||
},
|
||||
"effective_exhaust_velocity" : 10000000.0,
|
||||
"thruster_fuel_use" : -1.0,
|
||||
"fuel_tank_mass" : 30,
|
||||
"hyperdrive_class" : 0,
|
||||
"forward_thrust" : 6150000.0,
|
||||
"reverse_thrust" : 1250000.0,
|
||||
"up_thrust" : 1600000.0,
|
||||
"down_thrust" : 1200000.0,
|
||||
"left_thrust" : 1200000.0,
|
||||
"right_thrust" : 1200000.0,
|
||||
"angular_thrust" : 27000000.0
|
||||
}
|
|
@ -9,6 +9,7 @@ local Lang = import("Lang")
|
|||
local Comms = import("Comms")
|
||||
|
||||
local InfoFace = import("ui/InfoFace")
|
||||
local MessageBox = import("ui/MessageBox")
|
||||
|
||||
local l = Lang.GetResource("ui-core")
|
||||
|
||||
|
@ -22,13 +23,16 @@ local lobby = function (tab)
|
|||
|
||||
local launchButton = ui:Button(l.REQUEST_LAUNCH):SetFont("HEADING_LARGE")
|
||||
launchButton.onClick:Connect(function ()
|
||||
local crimes, fine = Game.player:GetCrime()
|
||||
local crimes, fine = Game.player:GetCrimeOutstanding()
|
||||
|
||||
if not Game.player:HasCorrectCrew() then
|
||||
MessageBox.Message(l.LAUNCH_PERMISSION_DENIED_CREW)
|
||||
Comms.ImportantMessage(l.LAUNCH_PERMISSION_DENIED_CREW, station.label)
|
||||
elseif fine > 0 then
|
||||
MessageBox.Message(l.LAUNCH_PERMISSION_DENIED_FINED)
|
||||
Comms.ImportantMessage(l.LAUNCH_PERMISSION_DENIED_FINED, station.label)
|
||||
elseif not Game.player:Undock() then
|
||||
MessageBox.Message(l.LAUNCH_PERMISSION_DENIED_BUSY)
|
||||
Comms.ImportantMessage(l.LAUNCH_PERMISSION_DENIED_BUSY, station.label)
|
||||
else
|
||||
Game.SwitchView()
|
||||
|
|
|
@ -8,6 +8,7 @@ local Rand = import("Rand")
|
|||
local Character = import("Character")
|
||||
local Format = import("Format")
|
||||
local utils = import("utils")
|
||||
local Legal = import("Legal")
|
||||
|
||||
local InfoFace = import("ui/InfoFace")
|
||||
local SmallLabeledButton = import("ui/SmallLabeledButton")
|
||||
|
@ -16,14 +17,9 @@ local MessageBox = import("ui/MessageBox")
|
|||
local ui = Engine.ui
|
||||
local l = Lang.GetResource("ui-core")
|
||||
|
||||
local crimeStrings = {
|
||||
TRADING_ILLEGAL_GOODS = l.TRADING_ILLEGAL_GOODS,
|
||||
WEAPON_DISCHARGE = l.UNLAWFUL_WEAPONS_DISCHARGE,
|
||||
PIRACY = l.PIRACY,
|
||||
MURDER = l.MURDER,
|
||||
}
|
||||
|
||||
local police = function (tab)
|
||||
|
||||
local station = Game.player:GetDockedWith()
|
||||
|
||||
local rand = Rand.New(util.hash_random(station.seed .. '-police', 2^31-1) - 1)
|
||||
|
@ -32,26 +28,52 @@ local police = function (tab)
|
|||
armour = true,
|
||||
}, rand))
|
||||
|
||||
local crimes, fine = Game.player:GetCrime()
|
||||
local crimes, fine = Game.player:GetCrimeOutstanding()
|
||||
local tmp_table = {}
|
||||
for k,v in pairs(crimes) do
|
||||
table.insert(tmp_table,k)
|
||||
end
|
||||
|
||||
local infoBox = ui:VBox(10)
|
||||
if #crimes > 0 then
|
||||
if #utils.build_array(pairs(crimes)) > 0 then
|
||||
infoBox:PackEnd({
|
||||
ui:Label(l.CRIMINAL_RECORD):SetFont("HEADING_LARGE"),
|
||||
ui:Label(l.OUTSTANDING_FINES):SetFont("HEADING_LARGE"),
|
||||
ui:VBox():PackEnd(
|
||||
utils.build_table(utils.map(function (k,v) return k,crimeStrings[v] end, pairs(crimes)))
|
||||
),
|
||||
utils.build_table(utils.map(function (k,v)
|
||||
return k, ui:Label(crimes[v].count.."\t"..Legal.CrimeType[v].name)
|
||||
end, pairs(tmp_table)))),
|
||||
})
|
||||
end
|
||||
|
||||
local actionBox = ui:VBox()
|
||||
infoBox:PackEnd(actionBox)
|
||||
|
||||
local past_crimes, stump = Game.player:GetCrimeRecord()
|
||||
local tmp_table_old = {}
|
||||
for k,v in pairs(past_crimes) do
|
||||
table.insert(tmp_table_old, k)
|
||||
print(v.count.."\t"..Legal.CrimeType[k].name) -- todo xxx
|
||||
end
|
||||
|
||||
local grey = { r = 0.3, g = 0.3, b = 0.3}
|
||||
local past_crimes_infoBox = ui:VBox(10)
|
||||
if #utils.build_array(pairs(past_crimes)) > 0 then
|
||||
past_crimes_infoBox:PackEnd({
|
||||
ui:Label(l.CRIMINAL_RECORD):SetFont("HEADING_LARGE"):SetColor(grey),
|
||||
ui:VBox():PackEnd(
|
||||
utils.build_table(utils.map(function (k,v)
|
||||
return k, ui:Label(past_crimes[v].count.."\t"..Legal.CrimeType[v].name):SetColor(grey)
|
||||
end, pairs(tmp_table_old)))),
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
local function noBusiness ()
|
||||
actionBox:Clear()
|
||||
actionBox:PackEnd(l.WE_HAVE_NO_BUSINESS_WITH_YOU)
|
||||
end
|
||||
|
||||
|
||||
if fine == 0 then
|
||||
noBusiness()
|
||||
else
|
||||
|
@ -73,7 +95,7 @@ local police = function (tab)
|
|||
return
|
||||
ui:Grid({48,4,48},1)
|
||||
:SetColumn(0, {
|
||||
infoBox
|
||||
ui:VBox(50):PackEnd({infoBox, past_crimes_infoBox})
|
||||
})
|
||||
:SetColumn(2, {
|
||||
face.widget
|
||||
|
|
|
@ -174,6 +174,16 @@ static int l_fac_police_name(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
//preferred police ship model
|
||||
static int l_fac_police_ship(lua_State *L)
|
||||
{
|
||||
Faction *fac = l_fac_check(L, 1);
|
||||
std::string police_ship = luaL_checkstring(L, 2);
|
||||
fac->police_ship = police_ship;
|
||||
lua_settop(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
//commodity legality
|
||||
static int l_fac_illegal_goods_probability(lua_State *L)
|
||||
{
|
||||
|
@ -268,6 +278,7 @@ static luaL_Reg LuaFaction_meta[] = {
|
|||
{ "expansionRate", &l_fac_expansionRate },
|
||||
{ "military_name", &l_fac_military_name },
|
||||
{ "police_name", &l_fac_police_name },
|
||||
{ "police_ship", &l_fac_police_ship },
|
||||
{ "illegal_goods_probability", &l_fac_illegal_goods_probability },
|
||||
{ "colour", &l_fac_colour },
|
||||
{ "add_to_factions", &l_fac_add_to_factions },
|
||||
|
|
|
@ -46,7 +46,7 @@ public:
|
|||
std::string military_name; // "Space Defense Force", "Imperial Will Enforcement Division"...
|
||||
//military logo
|
||||
std::string police_name; // "Police", "Polizia Locale"...
|
||||
|
||||
std::string police_ship; // "kanara", "varada"...
|
||||
//police logo
|
||||
//goods/equipment availability (1-per-economy-type: aka agricultural, industrial, tourist, etc)
|
||||
|
||||
|
|
|
@ -77,7 +77,6 @@ Game::Game(const SystemPath &path, double time) :
|
|||
m_player->SetPosition(vector3d(0, 1.5*sbody->GetRadius(), 0));
|
||||
m_player->SetVelocity(vector3d(0,0,0));
|
||||
}
|
||||
Polit::Init(m_galaxy);
|
||||
|
||||
CreateViews();
|
||||
|
||||
|
@ -168,9 +167,6 @@ m_forceTimeAccel(false)
|
|||
for (Uint32 i = 0; i < hyperspaceCloudArray.size(); i++)
|
||||
m_hyperspaceClouds.push_back(static_cast<HyperspaceCloud*>(Body::FromJson(hyperspaceCloudArray[i], 0)));
|
||||
|
||||
// system political stuff
|
||||
Polit::FromJson(jsonObj, m_galaxy);
|
||||
|
||||
// views
|
||||
LoadViewsFromJson(jsonObj);
|
||||
|
||||
|
@ -225,9 +221,6 @@ void Game::ToJson(Json::Value &jsonObj)
|
|||
}
|
||||
jsonObj["hyperspace_clouds"] = hyperspaceCloudArray; // Add hyperspace cloud array to supplied object.
|
||||
|
||||
// system political data (crime etc)
|
||||
Polit::ToJson(jsonObj);
|
||||
|
||||
// views. must be saved in init order
|
||||
m_gameViews->m_cpan->SaveToJson(jsonObj);
|
||||
m_gameViews->m_sectorView->SaveToJson(jsonObj);
|
||||
|
|
|
@ -131,10 +131,6 @@ DECLARE_STRING(ALERT_CANCELLED)
|
|||
DECLARE_STRING(SHIP_DETECTED_NEARBY)
|
||||
DECLARE_STRING(DOWNGRADING_ALERT_STATUS)
|
||||
DECLARE_STRING(LASER_FIRE_DETECTED)
|
||||
DECLARE_STRING(TRADING_ILLEGAL_GOODS)
|
||||
DECLARE_STRING(UNLAWFUL_WEAPONS_DISCHARGE)
|
||||
DECLARE_STRING(PIRACY)
|
||||
DECLARE_STRING(MURDER)
|
||||
DECLARE_STRING(NO_ESTABLISHED_ORDER)
|
||||
DECLARE_STRING(HARD_CAPITALIST)
|
||||
DECLARE_STRING(CAPITALIST)
|
||||
|
@ -151,7 +147,6 @@ DECLARE_STRING(MILITARY_DICTATORSHIP)
|
|||
DECLARE_STRING(COMMUNIST)
|
||||
DECLARE_STRING(PLUTOCRATIC_DICTATORSHIP)
|
||||
DECLARE_STRING(VIOLENT_ANARCHY)
|
||||
DECLARE_STRING(X_CANNOT_BE_TOLERATED_HERE)
|
||||
DECLARE_STRING(SECTOR_X_Y_Z)
|
||||
DECLARE_STRING(CURRENT_SYSTEM)
|
||||
DECLARE_STRING(SELECTED_SYSTEM)
|
||||
|
@ -219,7 +214,6 @@ DECLARE_STRING(SHIP_NEARBY)
|
|||
DECLARE_STRING(DOCKING_CLEARANCE_EXPIRED)
|
||||
DECLARE_STRING(MESSAGE_FROM_X)
|
||||
DECLARE_STRING(SELECT_A_TARGET)
|
||||
DECLARE_STRING(POLICE_SHIP_REGISTRATION)
|
||||
DECLARE_STRING(CLEARANCE_ALREADY_GRANTED_BAY_N)
|
||||
DECLARE_STRING(CLEARANCE_GRANTED_BAY_N)
|
||||
DECLARE_STRING(CLEARANCE_DENIED_NO_BAYS)
|
||||
|
|
|
@ -204,25 +204,6 @@ void LuaConstants::Register(lua_State *l)
|
|||
* experimental
|
||||
*/
|
||||
|
||||
/*
|
||||
* Constants: PolitCrime
|
||||
*
|
||||
* Crimes
|
||||
*
|
||||
* TRADING_ILLEGAL_GOODS - .
|
||||
* WEAPON_DISCHARGE - .
|
||||
* PIRACY - .
|
||||
* MURDER - .
|
||||
*
|
||||
* Availability:
|
||||
*
|
||||
* alpha 10
|
||||
*
|
||||
* Status:
|
||||
*
|
||||
* experimental
|
||||
*/
|
||||
|
||||
/*
|
||||
* Constants: PolitEcon
|
||||
*
|
||||
|
|
|
@ -239,6 +239,30 @@ static int l_faction_attr_police_name(lua_State *l)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attribute: policeShip
|
||||
*
|
||||
* The ships used by the police
|
||||
*
|
||||
* Availability:
|
||||
*
|
||||
* 2015 September
|
||||
*
|
||||
* Status:
|
||||
*
|
||||
* experimental
|
||||
*/
|
||||
static int l_faction_attr_police_ship(lua_State *l)
|
||||
{
|
||||
Faction *faction = LuaObject<Faction>::CheckFromLua(1);
|
||||
|
||||
if(faction->police_ship.empty())
|
||||
faction->police_ship = "sinonatrix_police"; // set default ship
|
||||
|
||||
lua_pushlstring(l, faction->police_ship.c_str(), faction->police_ship.size());
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attribute: colour
|
||||
*
|
||||
|
@ -283,6 +307,7 @@ template <> void LuaObject<Faction>::RegisterClass()
|
|||
{ "radius", l_faction_attr_radius },
|
||||
{ "militaryName", l_faction_attr_military_name },
|
||||
{ "policeName", l_faction_attr_police_name },
|
||||
{ "policeShip", l_faction_attr_police_ship },
|
||||
{ "colour", l_faction_attr_colour },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include "LuaUtils.h"
|
||||
#include "LuaConstants.h"
|
||||
#include "Player.h"
|
||||
#include "Polit.h"
|
||||
#include "Pi.h"
|
||||
#include "Game.h"
|
||||
#include "SectorView.h"
|
||||
|
@ -24,66 +23,6 @@ static int l_player_is_player(lua_State *l)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Method: AddCrime
|
||||
*
|
||||
* Add a crime to the player's criminal record
|
||||
*
|
||||
* > player:AddCrime(crime, fine)
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* crime - a <Constants.PolitCrime> string describing the crime
|
||||
*
|
||||
* fine - an amount to add to the player's fine
|
||||
*
|
||||
* Availability:
|
||||
*
|
||||
* alpha 10
|
||||
*
|
||||
* Status:
|
||||
*
|
||||
* stable
|
||||
*/
|
||||
static int l_player_add_crime(lua_State *l)
|
||||
{
|
||||
LuaObject<Player>::CheckFromLua(1); // check that the method is being called on a Player object
|
||||
Sint64 crimeBitset = LuaConstants::GetConstantFromArg(l, "PolitCrime", 2);
|
||||
Sint64 fine = Sint64(luaL_checknumber(l, 3) * 100.0);
|
||||
Polit::AddCrime(crimeBitset, fine);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// XXX temporary until crime is moved out to Lua properly
|
||||
static int l_player_get_crime(lua_State *l)
|
||||
{
|
||||
LuaObject<Player>::CheckFromLua(1); // check that the method is being called on a Player object
|
||||
|
||||
Sint64 crimeBitset, fine;
|
||||
Polit::GetCrime(&crimeBitset, &fine);
|
||||
|
||||
lua_newtable(l);
|
||||
for (Sint64 i = 0; i < 4; i++) { // hardcoding 4 possible Polit::Crime flags
|
||||
if (crimeBitset & (Sint64(1)<<i)) {
|
||||
lua_pushstring(l, EnumStrings::GetString("PolitCrime", 1<<i));
|
||||
lua_rawseti(l, -2, lua_rawlen(l, -2)+1);
|
||||
}
|
||||
}
|
||||
|
||||
lua_pushnumber(l, double(fine) * 0.01);
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int l_player_clear_crime_fine(lua_State *l)
|
||||
{
|
||||
LuaObject<Player>::CheckFromLua(1); // check that the method is being called on a Player object
|
||||
Sint64 crimeBitset, fine;
|
||||
Polit::GetCrime(&crimeBitset, &fine);
|
||||
Polit::AddCrime(0, -fine);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Method: GetNavTarget
|
||||
*
|
||||
|
@ -278,10 +217,6 @@ template <> void LuaObject<Player>::RegisterClass()
|
|||
static const luaL_Reg l_methods[] = {
|
||||
{ "IsPlayer", l_player_is_player },
|
||||
|
||||
{ "AddCrime", l_player_add_crime },
|
||||
{ "GetCrime", l_player_get_crime },
|
||||
{ "ClearCrimeFine", l_player_clear_crime_fine },
|
||||
|
||||
{ "GetNavTarget", l_get_nav_target },
|
||||
{ "SetNavTarget", l_set_nav_target },
|
||||
{ "GetCombatTarget", l_get_combat_target },
|
||||
|
|
161
src/Polit.cpp
161
src/Polit.cpp
|
@ -13,7 +13,6 @@
|
|||
#include "Ship.h"
|
||||
#include "ShipCpanel.h"
|
||||
#include "SpaceStation.h"
|
||||
#include "PersistSystemData.h"
|
||||
#include "Lang.h"
|
||||
#include "StringF.h"
|
||||
#include "Game.h"
|
||||
|
@ -21,28 +20,6 @@
|
|||
namespace Polit {
|
||||
|
||||
|
||||
static PersistSystemData<Sint64> s_criminalRecord;
|
||||
static PersistSystemData<Sint64> s_outstandingFine;
|
||||
struct crime_t {
|
||||
crime_t() : record(0), fine(0) {}
|
||||
Sint64 record;
|
||||
Sint64 fine;
|
||||
};
|
||||
static std::vector<crime_t> s_playerPerBlocCrimeRecord;
|
||||
|
||||
const char *crimeNames[64] = {
|
||||
Lang::TRADING_ILLEGAL_GOODS,
|
||||
Lang::UNLAWFUL_WEAPONS_DISCHARGE,
|
||||
Lang::PIRACY,
|
||||
Lang::MURDER
|
||||
};
|
||||
// in 1/100th credits, as all money is
|
||||
static const Sint64 crimeBaseFine[64] = {
|
||||
50000,
|
||||
100000,
|
||||
1000000,
|
||||
1500000,
|
||||
};
|
||||
const char *s_econDesc[ECON_MAX] = {
|
||||
Lang::NO_ESTABLISHED_ORDER,
|
||||
Lang::HARD_CAPITALIST,
|
||||
|
@ -77,148 +54,10 @@ static politDesc_t s_govDesc[GOV_MAX] = {
|
|||
{ Lang::VIOLENT_ANARCHY, 2, ECON_NONE, fixed(90,100) },
|
||||
};
|
||||
|
||||
void Init(RefCountedPtr<Galaxy> galaxy)
|
||||
{
|
||||
s_criminalRecord.Clear();
|
||||
s_outstandingFine.Clear();
|
||||
|
||||
// setup the per faction criminal records
|
||||
const Uint32 numFactions = galaxy->GetFactions()->GetNumFactions();
|
||||
s_playerPerBlocCrimeRecord.clear();
|
||||
s_playerPerBlocCrimeRecord.resize( numFactions );
|
||||
}
|
||||
|
||||
void ToJson(Json::Value &jsonObj)
|
||||
{
|
||||
Json::Value politObj(Json::objectValue); // Create JSON object to contain polit data.
|
||||
|
||||
Json::Value criminalRecordObj(Json::objectValue); // Create JSON object to contain criminal record data.
|
||||
s_criminalRecord.ToJson(criminalRecordObj);
|
||||
politObj["criminal_record"] = criminalRecordObj; // Add criminal record object to polit object.
|
||||
|
||||
Json::Value outstandingFineObj(Json::objectValue); // Create JSON object to contain outstanding fine data.
|
||||
s_outstandingFine.ToJson(outstandingFineObj);
|
||||
politObj["outstanding_fine"] = outstandingFineObj; // Add outstanding fine object to polit object.
|
||||
|
||||
Json::Value crimeRecordArray(Json::arrayValue); // Create JSON array to contain crime record data.
|
||||
for (Uint32 i = 0; i < s_playerPerBlocCrimeRecord.size(); i++)
|
||||
{
|
||||
Json::Value crimeRecordArrayEl(Json::objectValue); // Create JSON object to contain crime record element.
|
||||
crimeRecordArrayEl["record"] = SInt64ToStr(s_playerPerBlocCrimeRecord[i].record);
|
||||
crimeRecordArrayEl["fine"] = SInt64ToStr(s_playerPerBlocCrimeRecord[i].fine);
|
||||
crimeRecordArray.append(crimeRecordArrayEl); // Append crime record object to array.
|
||||
}
|
||||
politObj["crime_record"] = crimeRecordArray; // Add crime record array to polit object.
|
||||
|
||||
jsonObj["polit"] = politObj; // Add polit object to supplied object.
|
||||
}
|
||||
|
||||
void FromJson(const Json::Value &jsonObj, RefCountedPtr<Galaxy> galaxy)
|
||||
{
|
||||
Init(galaxy);
|
||||
|
||||
if (!jsonObj.isMember("polit")) throw SavedGameCorruptException();
|
||||
Json::Value politObj = jsonObj["polit"];
|
||||
|
||||
if (!politObj.isMember("criminal_record")) throw SavedGameCorruptException();
|
||||
if (!politObj.isMember("outstanding_fine")) throw SavedGameCorruptException();
|
||||
if (!politObj.isMember("crime_record")) throw SavedGameCorruptException();
|
||||
|
||||
Json::Value criminalRecordObj = politObj["criminal_record"];
|
||||
PersistSystemData<Sint64>::FromJson(criminalRecordObj, &s_criminalRecord);
|
||||
|
||||
Json::Value outstandingFineObj = politObj["outstanding_fine"];
|
||||
PersistSystemData<Sint64>::FromJson(outstandingFineObj, &s_outstandingFine);
|
||||
|
||||
Json::Value crimeRecordArray = politObj["crime_record"];
|
||||
if (!crimeRecordArray.isArray()) throw SavedGameCorruptException();
|
||||
assert(s_playerPerBlocCrimeRecord.size() == crimeRecordArray.size());
|
||||
for (Uint32 i = 0; i < s_playerPerBlocCrimeRecord.size(); i++)
|
||||
{
|
||||
Json::Value crimeRecordArrayEl = crimeRecordArray[i];
|
||||
if (!crimeRecordArrayEl.isMember("record")) throw SavedGameCorruptException();
|
||||
if (!crimeRecordArrayEl.isMember("fine")) throw SavedGameCorruptException();
|
||||
s_playerPerBlocCrimeRecord[i].record = StrToSInt64(crimeRecordArrayEl["record"].asString());
|
||||
s_playerPerBlocCrimeRecord[i].fine = StrToSInt64(crimeRecordArrayEl["fine"].asString());
|
||||
}
|
||||
}
|
||||
|
||||
fixed GetBaseLawlessness(GovType gov) {
|
||||
return s_govDesc[gov].baseLawlessness;
|
||||
}
|
||||
|
||||
/* The drawbacks of stuffing stuff into integers */
|
||||
static int GetCrimeIdxFromEnum(enum Crime crime)
|
||||
{
|
||||
assert(crime);
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
if (crime & 1) return i;
|
||||
crime = Crime(crime >> 1); // cast needed because this gets promoted to 'int'
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void NotifyOfCrime(Ship *s, enum Crime crime)
|
||||
{
|
||||
// ignore crimes of NPCs for the time being
|
||||
if (!s->IsType(Object::PLAYER)) return;
|
||||
// find nearest starport to this evil criminal
|
||||
SpaceStation *station = static_cast<SpaceStation*>(Pi::game->GetSpace()->FindNearestTo(s, Object::SPACESTATION));
|
||||
if (station) {
|
||||
double dist = station->GetPositionRelTo(s).Length();
|
||||
// too far away for crime to be noticed :)
|
||||
if (dist > 100000.0) return;
|
||||
const int crimeIdx = GetCrimeIdxFromEnum(crime);
|
||||
Pi::game->log->Add(station->GetLabel(),
|
||||
stringf(Lang::X_CANNOT_BE_TOLERATED_HERE, formatarg("crime", crimeNames[crimeIdx])));
|
||||
|
||||
float lawlessness = Pi::game->GetSpace()->GetStarSystem()->GetSysPolit().lawlessness.ToFloat();
|
||||
Sint64 oldCrimes, oldFine;
|
||||
GetCrime(&oldCrimes, &oldFine);
|
||||
Sint64 newFine = std::max(1, 1 + int(crimeBaseFine[crimeIdx] * (1.0-lawlessness)));
|
||||
// don't keep compounding fines (maybe should for murder, etc...)
|
||||
if ( (!(crime & CRIME_MURDER)) && (newFine < oldFine) ) newFine = 0;
|
||||
AddCrime(crime, newFine);
|
||||
}
|
||||
}
|
||||
|
||||
void AddCrime(Sint64 crimeBitset, Sint64 addFine)
|
||||
{
|
||||
const Faction *faction = (Pi::game->GetSpace()->GetStarSystem()->GetFaction());
|
||||
|
||||
if (faction->IsValid()) {
|
||||
s_playerPerBlocCrimeRecord[faction->idx].record |= crimeBitset;
|
||||
s_playerPerBlocCrimeRecord[faction->idx].fine += addFine;
|
||||
} else {
|
||||
SystemPath path = Pi::game->GetSpace()->GetStarSystem()->GetPath();
|
||||
Sint64 record = s_criminalRecord.Get(path, 0);
|
||||
record |= crimeBitset;
|
||||
s_criminalRecord.Set(path, crimeBitset);
|
||||
s_outstandingFine.Set(path, s_outstandingFine.Get(path, 0) + addFine);
|
||||
}
|
||||
}
|
||||
|
||||
void GetCrime(Sint64 *crimeBitset, Sint64 *fine)
|
||||
{
|
||||
// no crime in hyperspace :)
|
||||
if (Pi::game->IsHyperspace()) {
|
||||
*crimeBitset = 0;
|
||||
*fine = 0;
|
||||
return ;
|
||||
}
|
||||
|
||||
const Faction *faction = Pi::game->GetSpace()->GetStarSystem()->GetFaction();
|
||||
|
||||
if (faction->IsValid()) {
|
||||
*crimeBitset = s_playerPerBlocCrimeRecord[faction->idx].record;
|
||||
*fine = s_playerPerBlocCrimeRecord[faction->idx].fine;
|
||||
} else {
|
||||
SystemPath path = Pi::game->GetSpace()->GetStarSystem()->GetPath();
|
||||
*crimeBitset = s_criminalRecord.Get(path, 0);
|
||||
*fine = s_outstandingFine.Get(path, 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const char *SysPolit::GetGovernmentDesc() const
|
||||
|
|
17
src/Polit.h
17
src/Polit.h
|
@ -5,8 +5,6 @@
|
|||
#define _POLIT_H
|
||||
|
||||
#include "galaxy/Economy.h"
|
||||
#include "Serializer.h"
|
||||
#include "json/json.h"
|
||||
|
||||
class Galaxy;
|
||||
class StarSystem;
|
||||
|
@ -14,13 +12,6 @@ class SysPolit;
|
|||
class Ship;
|
||||
|
||||
namespace Polit {
|
||||
enum Crime { // <enum scope='Polit' name=PolitCrime prefix=CRIME_ public>
|
||||
CRIME_TRADING_ILLEGAL_GOODS = (1<<0),
|
||||
CRIME_WEAPON_DISCHARGE = (1<<1),
|
||||
CRIME_PIRACY = (1<<2),
|
||||
CRIME_MURDER = (1<<3),
|
||||
};
|
||||
|
||||
enum PolitEcon { // <enum scope='Polit' name=PolitEcon prefix=ECON_ public>
|
||||
ECON_NONE,
|
||||
ECON_VERY_CAPITALIST,
|
||||
|
@ -53,15 +44,7 @@ namespace Polit {
|
|||
GOV_RAND_MAX = GOV_MAX-1, // <enum skip>
|
||||
};
|
||||
|
||||
void NotifyOfCrime(Ship *s, enum Crime c);
|
||||
void Init(RefCountedPtr<Galaxy> galaxy);
|
||||
void ToJson(Json::Value &jsonObj);
|
||||
void FromJson(const Json::Value &jsonObj, RefCountedPtr<Galaxy> galaxy);
|
||||
void AddCrime(Sint64 crimeBitset, Sint64 addFine);
|
||||
void GetCrime(Sint64 *crimeBitset, Sint64 *fine);
|
||||
fixed GetBaseLawlessness(GovType gov);
|
||||
|
||||
extern const char *crimeNames[64];
|
||||
}
|
||||
|
||||
class SysPolit {
|
||||
|
|
|
@ -434,16 +434,10 @@ bool Ship::OnDamage(Object *attacker, float kgDamage, const CollisionContact& co
|
|||
if (attacker) {
|
||||
if (attacker->IsType(Object::BODY))
|
||||
LuaEvent::Queue("onShipDestroyed", this, dynamic_cast<Body*>(attacker));
|
||||
|
||||
if (attacker->IsType(Object::SHIP))
|
||||
Polit::NotifyOfCrime(static_cast<Ship*>(attacker), Polit::CRIME_MURDER);
|
||||
}
|
||||
|
||||
Explode();
|
||||
} else {
|
||||
if (attacker && attacker->IsType(Object::SHIP))
|
||||
Polit::NotifyOfCrime(static_cast<Ship*>(attacker), Polit::CRIME_PIRACY);
|
||||
|
||||
if (Pi::rng.Double() < kgDamage)
|
||||
Sfx::Add(this, Sfx::TYPE_DAMAGE);
|
||||
|
||||
|
@ -931,7 +925,6 @@ void Ship::FireWeapon(int num)
|
|||
Projectile::Add(this, lifespan, damage, length, width, mining, c, pos, baseVel, dirVel);
|
||||
}
|
||||
|
||||
Polit::NotifyOfCrime(this, Polit::CRIME_WEAPON_DISCHARGE);
|
||||
Sound::BodyMakeNoise(this, "Pulse_Laser", 1.0f);
|
||||
lua_pop(prop.GetLua(), 1);
|
||||
LuaEvent::Queue("onShipFiring", this);
|
||||
|
|
|
@ -74,7 +74,6 @@ void SpaceStation::SaveToJson(Json::Value &jsonObj, Space *space)
|
|||
spaceStationObj["ports"] = portArray; // Add port array to space station object.
|
||||
|
||||
spaceStationObj["index_for_system_body"] = space->GetIndexForSystemBody(m_sbody);
|
||||
spaceStationObj["num_police_docked"] = m_numPoliceDocked;
|
||||
|
||||
spaceStationObj["door_animation_step"] = DoubleToStr(m_doorAnimationStep);
|
||||
spaceStationObj["door_animation_state"] = DoubleToStr(m_doorAnimationState);
|
||||
|
@ -95,7 +94,6 @@ void SpaceStation::LoadFromJson(const Json::Value &jsonObj, Space *space)
|
|||
if (!spaceStationObj.isMember("ship_docking")) throw SavedGameCorruptException();
|
||||
if (!spaceStationObj.isMember("ports")) throw SavedGameCorruptException();
|
||||
if (!spaceStationObj.isMember("index_for_system_body")) throw SavedGameCorruptException();
|
||||
if (!spaceStationObj.isMember("num_police_docked")) throw SavedGameCorruptException();
|
||||
if (!spaceStationObj.isMember("door_animation_step")) throw SavedGameCorruptException();
|
||||
if (!spaceStationObj.isMember("door_animation_state")) throw SavedGameCorruptException();
|
||||
|
||||
|
@ -156,7 +154,6 @@ void SpaceStation::LoadFromJson(const Json::Value &jsonObj, Space *space)
|
|||
}
|
||||
|
||||
m_sbody = space->GetSystemBodyByIndex(spaceStationObj["index_for_system_body"].asUInt());
|
||||
m_numPoliceDocked = spaceStationObj["num_police_docked"].asInt();
|
||||
|
||||
m_doorAnimationStep = StrToDouble(spaceStationObj["door_animation_step"].asString());
|
||||
m_doorAnimationState = StrToDouble(spaceStationObj["door_animation_state"].asString());
|
||||
|
@ -177,7 +174,6 @@ void SpaceStation::PostLoadFixup(Space *space)
|
|||
SpaceStation::SpaceStation(const SystemBody *sbody): ModelBody()
|
||||
{
|
||||
m_sbody = sbody;
|
||||
m_numPoliceDocked = Pi::rng.Int32(3,10);
|
||||
|
||||
m_oldAngDisplacement = 0.0;
|
||||
|
||||
|
@ -541,7 +537,6 @@ void SpaceStation::PositionDockedShip(Ship *ship, int port) const
|
|||
|
||||
void SpaceStation::StaticUpdate(const float timeStep)
|
||||
{
|
||||
DoLawAndOrder(timeStep);
|
||||
DockingUpdate(timeStep);
|
||||
m_navLights->Update(timeStep);
|
||||
}
|
||||
|
@ -681,47 +676,6 @@ vector3d SpaceStation::GetTargetIndicatorPosition(const Frame *relTo) const
|
|||
return GetInterpPositionRelTo(relTo);
|
||||
}
|
||||
|
||||
// XXX this whole thing should be done by Lua
|
||||
void SpaceStation::DoLawAndOrder(const double timeStep)
|
||||
{
|
||||
Sint64 fine, crimeBitset;
|
||||
Polit::GetCrime(&crimeBitset, &fine);
|
||||
if (Pi::player->GetFlightState() != Ship::DOCKED
|
||||
&& m_numPoliceDocked
|
||||
&& (fine > 1000)
|
||||
&& (GetPositionRelTo(Pi::player).Length() < 100000.0)) {
|
||||
Ship *ship = new Ship(ShipType::POLICE);
|
||||
int port = GetFreeDockingPort(ship);
|
||||
// at 60 Hz updates (ie, 1x time acceleration),
|
||||
// this spawns a police ship with probability ~0.83% each frame
|
||||
// This makes it unlikely (but not impossible) that police will spawn on top of each other
|
||||
// the expected number of game-time seconds between spawns: 120 (2*60 Hz)
|
||||
// variance is quite high though
|
||||
if (port != -1 && 2.0*Pi::rng.Double() < timeStep) {
|
||||
m_numPoliceDocked--;
|
||||
// Make police ship intent on killing the player
|
||||
ship->AIKill(Pi::player);
|
||||
ship->SetFrame(GetFrame());
|
||||
ship->SetDockedWith(this, port);
|
||||
Pi::game->GetSpace()->AddBody(ship);
|
||||
ship->SetLabel(Lang::POLICE_SHIP_REGISTRATION);
|
||||
lua_State *l = Lua::manager->GetLuaState();
|
||||
LUA_DEBUG_START(l);
|
||||
pi_lua_import(l, "Equipment");
|
||||
LuaTable equip(l, -1);
|
||||
LuaTable misc = equip.Sub("misc");
|
||||
LuaObject<Ship>::CallMethod(ship, "AddEquip", equip.Sub("laser").Sub("pulsecannon_dual_1mw"));
|
||||
LuaObject<Ship>::CallMethod(ship, "AddEquip", misc.Sub("laser_cooling_booster"));
|
||||
LuaObject<Ship>::CallMethod(ship, "AddEquip", misc.Sub("atmospheric_shielding"));
|
||||
lua_pop(l, 6);
|
||||
LUA_DEBUG_END(l, 0);
|
||||
ship->UpdateEquipStats();
|
||||
} else {
|
||||
delete ship;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SpaceStation::IsPortLocked(const int bay) const
|
||||
{
|
||||
for (auto &bayIter : m_ports ) {
|
||||
|
|
|
@ -110,7 +110,6 @@ private:
|
|||
const SpaceStationType *m_type;
|
||||
const SystemBody *m_sbody;
|
||||
CityOnPlanet *m_adjacentCity;
|
||||
int m_numPoliceDocked;
|
||||
enum { NUM_STATIC_SLOTS = 4 };
|
||||
bool m_staticSlot[NUM_STATIC_SLOTS];
|
||||
|
||||
|
|
|
@ -53,14 +53,6 @@ const struct EnumItem ENUM_PhysicsObjectType[] = {
|
|||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct EnumItem ENUM_PolitCrime[] = {
|
||||
{ "TRADING_ILLEGAL_GOODS", int(Polit::CRIME_TRADING_ILLEGAL_GOODS) },
|
||||
{ "WEAPON_DISCHARGE", int(Polit::CRIME_WEAPON_DISCHARGE) },
|
||||
{ "PIRACY", int(Polit::CRIME_PIRACY) },
|
||||
{ "MURDER", int(Polit::CRIME_MURDER) },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct EnumItem ENUM_PolitEcon[] = {
|
||||
{ "NONE", int(Polit::ECON_NONE) },
|
||||
{ "VERY_CAPITALIST", int(Polit::ECON_VERY_CAPITALIST) },
|
||||
|
@ -457,7 +449,6 @@ const struct EnumTable ENUM_TABLES[] = {
|
|||
{ "DetailLevel", ENUM_DetailLevel },
|
||||
{ "FileSystemRoot", ENUM_FileSystemRoot },
|
||||
{ "PhysicsObjectType", ENUM_PhysicsObjectType },
|
||||
{ "PolitCrime", ENUM_PolitCrime },
|
||||
{ "PolitEcon", ENUM_PolitEcon },
|
||||
{ "PolitGovType", ENUM_PolitGovType },
|
||||
{ "ShipFlightState", ENUM_ShipFlightState },
|
||||
|
@ -500,7 +491,6 @@ const struct EnumTable ENUM_TABLES_PUBLIC[] = {
|
|||
{ "DetailLevel", ENUM_DetailLevel },
|
||||
{ "FileSystemRoot", ENUM_FileSystemRoot },
|
||||
{ "PhysicsObjectType", ENUM_PhysicsObjectType },
|
||||
{ "PolitCrime", ENUM_PolitCrime },
|
||||
{ "PolitEcon", ENUM_PolitEcon },
|
||||
{ "PolitGovType", ENUM_PolitGovType },
|
||||
{ "ShipFlightState", ENUM_ShipFlightState },
|
||||
|
|
|
@ -13,7 +13,6 @@ struct EnumTable { const char *name; const EnumItem *first; };
|
|||
extern const struct EnumItem ENUM_DetailLevel[];
|
||||
extern const struct EnumItem ENUM_FileSystemRoot[];
|
||||
extern const struct EnumItem ENUM_PhysicsObjectType[];
|
||||
extern const struct EnumItem ENUM_PolitCrime[];
|
||||
extern const struct EnumItem ENUM_PolitEcon[];
|
||||
extern const struct EnumItem ENUM_PolitGovType[];
|
||||
extern const struct EnumItem ENUM_ShipFlightState[];
|
||||
|
|
Loading…
Reference in New Issue