-- LegacyWorlds Beta 6 -- PostgreSQL database scripts -- -- Game updates - fleet arrivals -- -- Copyright(C) 2004-2010, DeepClone Development -- -------------------------------------------------------- CREATE OR REPLACE FUNCTION sys.process_planet_fleet_arrivals_updates( c_tick BIGINT ) RETURNS VOID STRICT VOLATILE SECURITY INVOKER AS $$ DECLARE rec RECORD; lstat BOOLEAN; f_ids BIGINT[]; BEGIN -- Lock all records PERFORM f.id FROM sys.updates su INNER JOIN verse.updates vu ON vu.update_id = su.id INNER JOIN verse.planets p ON p.name_id = vu.planet_id INNER JOIN fleets.fleets f ON f.location_id = p.name_id INNER JOIN fleets.movements fm ON fm.fleet_id = f.id INNER JOIN emp.empires e ON e.name_id = f.owner_id WHERE su.last_tick = c_tick AND su.status = 'PROCESSING' AND su.gu_type = 'PLANET_FLEET_ARRIVALS' AND f.status = 'AVAILABLE' AND fm.time_left = 1 FOR UPDATE; -- Update attack status according to planet owners and enemy lists FOR rec IN SELECT ep.empire_id AS planet_owner , p.name_id AS planet , f.owner_id AS fleet_owner , ( v.status = 'PROCESSED' AND b.id IS NULL ) AS on_vacation , bool_or( f.attacking ) AS attacking FROM sys.updates su INNER JOIN verse.updates vu ON vu.update_id = su.id INNER JOIN verse.planets p ON p.name_id = vu.planet_id INNER JOIN fleets.fleets f ON f.location_id = p.name_id INNER JOIN fleets.movements fm ON fm.fleet_id = f.id LEFT OUTER JOIN emp.planets ep ON ep.planet_id = p.name_id LEFT OUTER JOIN naming.empire_names en ON en.id = ep.empire_id LEFT OUTER JOIN users.vacations v ON v.account_id = en.owner_id LEFT OUTER JOIN battles.battles b ON b.location_id = p.name_id AND b.last_tick IS NULL WHERE su.last_tick = c_tick AND su.status = 'PROCESSING' AND su.gu_type = 'PLANET_FLEET_ARRIVALS' AND f.status = 'AVAILABLE' AND fm.time_left = 1 GROUP BY p.name_id , ep.empire_id , f.owner_id , v.status , b.id LOOP -- Fleets owned by the planet's owner are never attacking, same for fleets arriving on -- planets that are on vacation IF rec.fleet_owner = rec.planet_owner OR rec.on_vacation THEN UPDATE fleets.fleets f SET attacking = FALSE FROM fleets.movements m WHERE f.status = 'AVAILABLE' AND f.owner_id = rec.fleet_owner AND f.location_id = rec.planet AND m.fleet_id = f.id AND m.time_left = 1; CONTINUE; END IF; -- Check enemy lists PERFORM * FROM emp.enemies WHERE empire = rec.planet_owner AND enemy = rec.fleet_owner; IF FOUND THEN -- Fleet owner in the planet owner's EL UPDATE fleets.fleets f SET attacking = TRUE FROM fleets.movements m WHERE f.status = 'AVAILABLE' AND f.owner_id = rec.fleet_owner AND f.location_id = rec.planet AND m.fleet_id = f.id AND m.time_left = 1; CONTINUE; END IF; -- If one of the arriving fleets is attacking, or if the local fleets are already attacking, -- then switch all local or arriving fleets to attack SELECT INTO lstat f.attacking FROM fleets.fleets f LEFT OUTER JOIN fleets.movements fm ON fm.fleet_id = f.id WHERE f.owner_id = rec.fleet_owner AND f.location_id = rec.planet AND fm IS NULL GROUP BY f.attacking; IF ( FOUND AND lstat ) OR rec.attacking THEN SELECT INTO f_ids array_agg( f.id ) FROM fleets.fleets f WHERE f.owner_id = rec.fleet_owner AND f.location_id = rec.planet; PERFORM fleets.set_mode( rec.fleet_owner , f_ids , TRUE ); CONTINUE; END IF; END LOOP; -- Prepare fleet arrival events CREATE TEMPORARY TABLE fleet_arrivals( loc_id INT , loc_name VARCHAR(20) , own_id INT , own_name VARCHAR(20) , name VARCHAR(64) , power BIGINT , mode BOOLEAN , src_id INT , src_name VARCHAR(20) ); INSERT INTO fleet_arrivals SELECT f.location_id , ln.name , f.owner_id , fon.name , f.name , fs.power , f.attacking , fm.source_id , sn.name FROM sys.updates su INNER JOIN verse.updates vu ON vu.update_id = su.id INNER JOIN verse.planets p ON p.name_id = vu.planet_id INNER JOIN fleets.fleets f ON f.location_id = p.name_id INNER JOIN fleets.movements fm ON fm.fleet_id = f.id INNER JOIN fleets.stats_view fs ON fs.id = f.id INNER JOIN naming.empire_names fon ON fon.id = f.owner_id INNER JOIN naming.map_names ln ON ln.id = f.location_id INNER JOIN naming.map_names sn ON sn.id = fm.source_id WHERE su.last_tick = c_tick AND su.status = 'PROCESSING' AND su.gu_type = 'PLANET_FLEET_ARRIVALS' AND f.status = 'AVAILABLE' AND fm.time_left = 1; -- Delete movement records, set redeployment penalties, update battles FOR rec IN SELECT f.id AS fleet , fs.flight_time AS flight_time , f.attacking AS attacking , b.id AS battle , f.location_id AS location FROM sys.updates su INNER JOIN verse.updates vu ON vu.update_id = su.id INNER JOIN verse.planets p ON p.name_id = vu.planet_id INNER JOIN fleets.fleets f ON f.location_id = p.name_id INNER JOIN fleets.movements fm ON fm.fleet_id = f.id INNER JOIN fleets.stats_view fs ON fs.id = f.id LEFT OUTER JOIN battles.battles b ON b.location_id = p.name_id AND b.last_tick IS NULL WHERE su.last_tick = c_tick AND su.status = 'PROCESSING' AND su.gu_type = 'PLANET_FLEET_ARRIVALS' AND f.status = 'AVAILABLE' AND fm.time_left = 1 LOOP DELETE FROM fleets.movements WHERE fleet_id = rec.fleet; UPDATE fleets.fleets SET status = 'REDEPLOYING' , penalty = 1 + rec.flight_time * ( CASE WHEN rec.attacking THEN 40 ELSE 10 END ) WHERE id = rec.fleet; -- Add fleets to battle (will not be executed if battle is NULL) PERFORM battles.add_fleet( rec.battle , rec.fleet , FALSE , c_tick ); END LOOP; -- Send fleet arrival events PERFORM events.commit_fleet_arrivals( c_tick ); END; $$ LANGUAGE plpgsql;