227 lines
6.4 KiB
PL/PgSQL
227 lines
6.4 KiB
PL/PgSQL
-- LegacyWorlds Beta 6
|
|
-- PostgreSQL database scripts
|
|
--
|
|
-- Game updates - ship construction
|
|
--
|
|
-- Copyright(C) 2004-2010, DeepClone Development
|
|
-- --------------------------------------------------------
|
|
|
|
|
|
CREATE OR REPLACE FUNCTION sys.process_planet_military_updates( c_tick BIGINT )
|
|
RETURNS VOID
|
|
STRICT VOLATILE
|
|
SECURITY INVOKER
|
|
AS $$
|
|
DECLARE
|
|
rec RECORD;
|
|
cur_empire INT;
|
|
cur_cash DOUBLE PRECISION;
|
|
cur_planet INT;
|
|
p_finished BOOLEAN;
|
|
cur_wus DOUBLE PRECISION;
|
|
cur_acc_c DOUBLE PRECISION;
|
|
n_found INT;
|
|
n_removed INT;
|
|
can_do DOUBLE PRECISION;
|
|
must_do INT;
|
|
fl_id BIGINT;
|
|
BEGIN
|
|
-- Create temporary table for built ships
|
|
CREATE TEMPORARY TABLE blt_ships(
|
|
location INT ,
|
|
owner INT ,
|
|
ship INT ,
|
|
amount INT
|
|
);
|
|
|
|
-- Enter update loop
|
|
cur_empire := NULL;
|
|
cur_planet := NULL;
|
|
FOR rec IN SELECT p.name_id AS id ,
|
|
ph.current / p.population AS happiness ,
|
|
e.name_id AS owner , e.cash AS cash ,
|
|
q.money AS acc_cash , q.work AS acc_work ,
|
|
qi.queue_order AS qorder , qi.amount AS amount ,
|
|
qi.ship_id AS ship , s.work AS req_work , s.cost AS req_cost
|
|
FROM sys.updates su
|
|
INNER JOIN verse.updates vu ON vu.update_id = su.id
|
|
INNER JOIN verse.planets p ON vu.planet_id = p.name_id
|
|
INNER JOIN emp.planets ep ON ep.planet_id = p.name_id
|
|
INNER JOIN emp.empires e ON e.name_id = ep.empire_id
|
|
INNER JOIN verse.planet_happiness ph ON ph.planet_id = p.name_id
|
|
INNER JOIN verse.mil_queues q ON q.planet_id = p.name_id
|
|
INNER JOIN verse.mil_items qi ON qi.queue_id = q.planet_id
|
|
INNER JOIN tech.buildables s ON s.name_id = qi.ship_id
|
|
INNER JOIN naming.empire_names en ON en.id = e.name_id
|
|
LEFT OUTER JOIN users.vacations v ON v.account_id = en.owner_id
|
|
WHERE su.last_tick = c_tick AND su.status = 'PROCESSING'
|
|
AND su.gu_type = 'PLANET_MILITARY'
|
|
AND ( v.account_id IS NULL OR v.status <> 'PROCESSED' )
|
|
ORDER BY e.name_id , p.name_id , qi.queue_order
|
|
FOR UPDATE OF p , e , q , qi
|
|
LOOP
|
|
-- Update accumulated work and money for the previous planet
|
|
IF cur_planet IS NOT NULL AND cur_planet <> rec.id THEN
|
|
IF n_found = n_removed THEN
|
|
cur_wus := 0;
|
|
cur_acc_c := 0;
|
|
PERFORM events.empty_queue_events( cur_empire , cur_planet , TRUE , c_tick );
|
|
END IF;
|
|
|
|
UPDATE verse.mil_queues
|
|
SET money = cur_acc_c , work = cur_wus
|
|
WHERE planet_id = cur_planet;
|
|
cur_cash := cur_cash - cur_acc_c;
|
|
|
|
IF cur_cash < 0 THEN
|
|
cur_cash := 0;
|
|
END IF;
|
|
|
|
cur_planet := NULL;
|
|
END IF;
|
|
|
|
-- Update cash of the previous empire
|
|
IF cur_empire IS NOT NULL AND cur_empire <> rec.owner
|
|
THEN
|
|
UPDATE emp.empires SET cash = cur_cash
|
|
WHERE name_id = cur_empire;
|
|
cur_empire := NULL;
|
|
END IF;
|
|
|
|
-- If this is the first record or if the empire changed...
|
|
IF cur_empire IS NULL THEN
|
|
cur_empire := rec.owner;
|
|
cur_cash := rec.cash;
|
|
END IF;
|
|
|
|
-- If this is the first record or if the planet changed...
|
|
IF cur_planet IS NULL THEN
|
|
cur_planet := rec.id;
|
|
cur_cash := cur_cash + rec.acc_cash;
|
|
cur_wus := rec.acc_work + verse.adjust_production(
|
|
verse.get_raw_production( rec.id , 'WORK' ) ,
|
|
rec.happiness
|
|
);
|
|
n_found := 1;
|
|
n_removed := 0;
|
|
cur_acc_c := 0;
|
|
p_finished := FALSE;
|
|
ELSE
|
|
n_found := n_found + 1;
|
|
END IF;
|
|
|
|
-- If we're done updating this planet but there were more items...
|
|
IF p_finished THEN
|
|
IF n_removed > 0 THEN
|
|
UPDATE verse.mil_items
|
|
SET queue_order = rec.qorder - n_removed
|
|
WHERE queue_order = rec.qorder AND queue_id = rec.id;
|
|
END IF;
|
|
CONTINUE;
|
|
END IF;
|
|
|
|
-- Compute how many items can be completed
|
|
can_do := cur_wus / rec.req_work;
|
|
IF cur_cash / rec.req_cost < can_do THEN
|
|
can_do := cur_cash / rec.req_cost;
|
|
cur_wus := rec.req_work * can_do;
|
|
END IF;
|
|
|
|
-- If we can't build anything at this point...
|
|
IF can_do < 1 THEN
|
|
-- Set accumulated cash
|
|
cur_acc_c := can_do * rec.req_cost;
|
|
|
|
-- Still update queue item if some items were removed
|
|
IF n_removed > 0 THEN
|
|
UPDATE verse.mil_items
|
|
SET queue_order = rec.qorder - n_removed
|
|
WHERE queue_order = rec.qorder AND queue_id = rec.id;
|
|
END IF;
|
|
|
|
-- Done with this planet
|
|
p_finished := TRUE;
|
|
CONTINUE;
|
|
END IF;
|
|
|
|
-- Compute how many actual items can be built
|
|
must_do := floor( can_do );
|
|
IF must_do >= rec.amount THEN
|
|
must_do := rec.amount;
|
|
can_do := 0;
|
|
n_removed := n_removed + 1;
|
|
END IF;
|
|
|
|
-- Handle construction
|
|
INSERT INTO blt_ships( location , owner , ship , amount)
|
|
VALUES ( rec.id , rec.owner , rec.ship , must_do );
|
|
cur_cash := cur_cash - must_do * rec.req_cost;
|
|
cur_wus := cur_wus - must_do * rec.req_work;
|
|
|
|
-- Check whether we're done with this queue
|
|
IF rec.qorder < n_removed THEN
|
|
-- Delete queue item
|
|
DELETE FROM verse.mil_items
|
|
WHERE queue_order = rec.qorder AND queue_id = rec.id;
|
|
ELSE
|
|
-- Update queue item
|
|
UPDATE verse.mil_items
|
|
SET queue_order = queue_order - n_removed ,
|
|
amount = amount - must_do
|
|
WHERE queue_order = rec.qorder AND queue_id = rec.id;
|
|
|
|
-- Set accumulated cash
|
|
cur_acc_c := ( can_do - floor( can_do ) ) * rec.req_cost;
|
|
|
|
p_finished := TRUE;
|
|
END IF;
|
|
END LOOP;
|
|
|
|
-- If a planet was being procesed, update it and the empire
|
|
IF cur_planet IS NOT NULL THEN
|
|
IF n_found = n_removed THEN
|
|
cur_wus := 0;
|
|
cur_acc_c := 0;
|
|
PERFORM events.empty_queue_events( cur_empire , cur_planet , TRUE , c_tick );
|
|
END IF;
|
|
|
|
UPDATE verse.mil_queues
|
|
SET money = cur_acc_c , work = cur_wus
|
|
WHERE planet_id = cur_planet;
|
|
cur_cash := cur_cash - cur_acc_c;
|
|
|
|
IF cur_cash < 0 THEN
|
|
cur_cash := 0;
|
|
END IF;
|
|
|
|
UPDATE emp.empires SET cash = cur_cash
|
|
WHERE name_id = cur_empire;
|
|
cur_empire := NULL;
|
|
END IF;
|
|
|
|
-- Spawn fleets
|
|
FOR cur_planet , cur_empire IN SELECT DISTINCT location , owner FROM blt_ships
|
|
LOOP
|
|
-- Get fleet's flight time
|
|
SELECT INTO must_do MAX( s.flight_time )
|
|
FROM blt_ships b
|
|
INNER JOIN tech.ships s ON s.buildable_id = b.ship
|
|
WHERE b.location = cur_planet AND b.owner = cur_empire;
|
|
|
|
-- Insert the fleet
|
|
INSERT INTO fleets.fleets (owner_id, location_id , attacking , status , penalty )
|
|
VALUES ( cur_empire , cur_planet , FALSE , 'DEPLOYING' , must_do * 2 )
|
|
RETURNING id INTO fl_id;
|
|
|
|
-- Insert ships
|
|
INSERT INTO fleets.ships ( fleet_id , ship_id , amount , damage )
|
|
SELECT fl_id , b.ship , sum( b.amount ) , 0
|
|
FROM blt_ships b
|
|
WHERE b.location = cur_planet AND b.owner = cur_empire
|
|
GROUP BY b.ship;
|
|
END LOOP;
|
|
|
|
-- Destroy temporary table
|
|
DROP TABLE blt_ships;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|