181 lines
6.3 KiB
PL/PgSQL
181 lines
6.3 KiB
PL/PgSQL
-- LegacyWorlds Beta 6
|
|
-- PostgreSQL database scripts
|
|
--
|
|
-- Game updates - battles (start, main computation, end)
|
|
--
|
|
-- Copyright(C) 2004-2010, DeepClone Development
|
|
-- --------------------------------------------------------
|
|
|
|
|
|
CREATE OR REPLACE FUNCTION sys.process_planet_battle_start_updates( c_tick BIGINT )
|
|
RETURNS VOID
|
|
STRICT VOLATILE
|
|
SECURITY INVOKER
|
|
AS $$
|
|
DECLARE
|
|
p_id INT;
|
|
BEGIN
|
|
FOR p_id IN SELECT p.name_id
|
|
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
|
|
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_BATTLE_START' AND b.location_id IS NULL
|
|
FOR UPDATE OF p
|
|
LOOP
|
|
IF battles.check_start( p_id ) THEN
|
|
PERFORM events.battle_start_event( battles.initialise( p_id , c_tick ) );
|
|
END IF;
|
|
END LOOP;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
|
|
|
|
|
|
CREATE OR REPLACE FUNCTION sys.process_planet_battle_main_updates( c_tick BIGINT )
|
|
RETURNS VOID
|
|
STRICT VOLATILE
|
|
SECURITY INVOKER
|
|
AS $$
|
|
DECLARE
|
|
ttfi INT;
|
|
initi DOUBLE PRECISION;
|
|
dbonus DOUBLE PRECISION;
|
|
dmg DOUBLE PRECISION;
|
|
rdmg DOUBLE PRECISION;
|
|
rec RECORD;
|
|
a_power BIGINT;
|
|
d_power BIGINT;
|
|
p_power BIGINT;
|
|
bmod DOUBLE PRECISION;
|
|
a_dmg DOUBLE PRECISION;
|
|
d_dmg DOUBLE PRECISION;
|
|
BEGIN
|
|
ttfi := floor( sys.get_constant( 'game.battle.timeToFullIntensity' ) )::INT;
|
|
initi := sys.get_constant( 'game.battle.initialIntensity' );
|
|
dbonus := sys.get_constant( 'game.battle.defenceBonus');
|
|
dmg := sys.get_constant( 'game.battle.damage' );
|
|
rdmg := sys.get_constant( 'game.battle.randomDamage' );
|
|
|
|
FOR rec IN SELECT b.id AS battle , b.first_tick AS first_tick ,
|
|
b.location_id AS location , ph.current / p.population AS happiness
|
|
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 verse.planet_happiness ph ON ph.planet_id = p.name_id
|
|
INNER 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_BATTLE_MAIN'
|
|
FOR UPDATE OF p , b
|
|
LOOP
|
|
PERFORM sys.write_log( 'BattleUpdate' , 'DEBUG'::log_level , 'Handling battle #' || rec.battle
|
|
|| ' at planet #' || rec.location );
|
|
|
|
-- Get stationary defence power
|
|
p_power := floor( verse.adjust_production( verse.get_raw_production( rec.location , 'DEF' ) , rec.happiness ) );
|
|
|
|
-- Get fleets power
|
|
a_power := battles.get_fleets_power( rec.battle , c_tick , TRUE );
|
|
d_power := battles.get_fleets_power( rec.battle , c_tick , FALSE );
|
|
IF a_power = 0 OR d_power + p_power = 0
|
|
THEN
|
|
PERFORM battles.set_defence_power( rec.battle , c_tick , p_power );
|
|
CONTINUE;
|
|
END IF;
|
|
|
|
PERFORM sys.write_log( 'BattleUpdate' , 'TRACE'::log_level , 'Attack: ' || a_power
|
|
|| '; planetary defences: ' || p_power || '; defence: ' || d_power );
|
|
|
|
-- Compute battle intensity
|
|
IF c_tick - rec.first_tick < ttfi THEN
|
|
bmod := initi + ( 1 - initi ) * ( c_tick - rec.first_tick ) / ttfi;
|
|
ELSE
|
|
bmod := 1.0;
|
|
END IF;
|
|
PERFORM sys.write_log( 'BattleUpdate' , 'TRACE'::log_level , 'Intensity modifier: ' || bmod );
|
|
|
|
-- Compute damage
|
|
d_dmg := bmod * ( d_power * ( 1 + dbonus ) + p_power ) * dmg * ( 1 - rdmg + 2.0 * rdmg * random() );
|
|
a_dmg := bmod * a_power * dmg * ( 1 - rdmg + 2.0 * rdmg * random() );
|
|
PERFORM sys.write_log( 'BattleUpdate' , 'TRACE'::log_level , 'Damage - to defence: ' || a_dmg
|
|
|| '; to attack: ' || d_dmg );
|
|
|
|
-- Inflict damage
|
|
PERFORM battles.inflict_damage( rec.battle , a_dmg , FALSE , c_tick );
|
|
PERFORM battles.inflict_damage( rec.battle , d_dmg , TRUE , c_tick );
|
|
|
|
-- Update defence power
|
|
p_power := floor( verse.adjust_production( verse.get_raw_production( rec.location , 'DEF' ) , rec.happiness ) );
|
|
PERFORM battles.set_defence_power( rec.battle , c_tick , p_power );
|
|
END LOOP;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
|
|
|
|
|
|
CREATE OR REPLACE FUNCTION sys.process_planet_battle_end_updates( c_tick BIGINT )
|
|
RETURNS VOID
|
|
STRICT VOLATILE
|
|
SECURITY INVOKER
|
|
AS $$
|
|
DECLARE
|
|
rec RECORD;
|
|
n_owner INT;
|
|
BEGIN
|
|
FOR rec IN SELECT b.id AS battle , b.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 vu.planet_id = p.name_id
|
|
INNER 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_BATTLE_END'
|
|
FOR UPDATE OF p , b
|
|
LOOP
|
|
IF battles.get_fleets_power( rec.battle , c_tick , TRUE ) = 0 THEN
|
|
-- Attack is dead/gone, end the battle
|
|
UPDATE battles.battles SET last_tick = c_tick
|
|
WHERE id = rec.battle;
|
|
PERFORM events.battle_end_event( rec.battle );
|
|
ELSEIF battles.get_fleets_power( rec.battle , c_tick , FALSE ) + battles.get_defence_power( rec.battle , c_tick ) = 0 THEN
|
|
-- Defence is dead/gone, transfer planet ownership to biggest fleet owner
|
|
n_owner := battles.get_biggest_fleet_owner( rec.battle , c_tick );
|
|
PERFORM events.planet_ochange_events( rec.location , n_owner );
|
|
PERFORM emp.leave_planet( rec.location );
|
|
INSERT INTO emp.planets( planet_id , empire_id )
|
|
VALUES( rec.location , n_owner );
|
|
|
|
-- End the battle
|
|
UPDATE battles.battles SET last_tick = c_tick
|
|
WHERE id = rec.battle;
|
|
PERFORM events.battle_end_event( rec.battle );
|
|
|
|
-- Set fleets in orbit to defence if they're not on the new owner's enemy list
|
|
UPDATE fleets.fleets f SET attacking = ( ele.empire IS NOT NULL )
|
|
FROM fleets.fleets f2
|
|
LEFT OUTER JOIN fleets.movements m ON m.fleet_id = f2.id
|
|
LEFT OUTER JOIN emp.enemies ele ON ele.enemy = f2.owner_id AND ele.empire = n_owner
|
|
WHERE f.id = f2.id AND f.location_id = rec.location AND m.fleet_id IS NULL;
|
|
|
|
-- Check if the battle needs to be restarted
|
|
IF battles.check_start( rec.location ) THEN
|
|
PERFORM events.battle_start_event( battles.initialise( rec.location , c_tick ) );
|
|
END IF;
|
|
ELSE
|
|
CONTINUE;
|
|
END IF;
|
|
|
|
-- Mark the end of the battle
|
|
INSERT INTO battles.finished_battles_list
|
|
SELECT empire, battle, planet, x, y, orbit, name, first_tick, last_tick, last_update
|
|
FROM battles.full_battles_list
|
|
WHERE battle = rec.battle;
|
|
END LOOP;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|