Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- CREATE OR REPLACE FUNCTION "move"(moving_ship_id integer, new_speed integer, new_direction integer, new_destination_x integer, new_destination_y
- integer)
- RETURNS boolean AS
- $BODY$
- DECLARE
- max_speed integer;
- current_speed integer;
- current_fuel integer;
- current_direction integer;
- fuel_cost integer;
- direction_fuel_cost integer := 0;
- final_speed integer;
- final_direction integer;
- final_fuel integer;
- distance bigint;
- distance_x bigint;
- distance_y bigint;
- range integer;
- location_x integer;
- location_y integer;
- ship_player_id integer;
- BEGIN
- -- Grab current stats of ship
- SELECT INTO max_speed, current_fuel, location_x, location_y, ship_player_id ship.max_speed, ship.current_fuel, ship.location_x, ship.location_y, player_id from ship WHERE id=moving_ship_id;
- SELECT INTO current_speed, current_direction speed, direction FROM ship_control WHERE ship_id = moving_ship_id;
- IF MOVE_PERMISSION_CHECK(moving_ship_id) THEN
- -- If they don't know what direction they're going, calculate it for them
- IF (final_direction IS NULL) THEN
- final_direction := getangle(location_x, location_y, new_destination_x, new_destination_y);
- ELSE
- final_direction := MOD(new_direction, 360);
- END IF;
- -- Make sure they don't travel faster than max_speed!
- SELECT INTO final_speed CASE WHEN new_speed < max_speed THEN new_speed ELSE max_speed END;
- -- Calculate the distance to target (if it exists)
- IF (new_destination_x IS NOT NULL AND new_destination_y IS NOT NULL) THEN
- distance_x := new_destination_x - location_x;
- distance_y := new_destination_y - location_y;
- distance := CAST(SQRT((distance_x * distance_x) + (distance_y * distance_y)) AS bigint);
- -- If their distance is less than their speed, override it
- IF (distance < final_speed) THEN
- IF (distance < 2147483647) THEN
- final_speed = CAST(distance AS integer);
- ELSE
- final_speed := 2147483647;
- END IF;
- END IF;
- END IF;
- -- If they're not currently travelling at this speed/direction...
- IF (current_speed <> final_speed OR current_direction <> final_direction) THEN
- fuel_cost := ABS(final_speed - current_speed); -- Calculate the fuel cost to change speed
- -- if they're already moving and aren't trying to stop...
- IF (current_speed <> 0 AND final_speed <> 0) THEN -- add 1 fuel cost per degree changed
- direction_fuel_cost := ABS(final_direction - current_direction);
- -- Pythagorus is inexact with integer-only datatypes, so sometimes we're off by 1 degree when calculating the direction.
- -- Don't let this eat up our fuel!
- IF (direction_fuel_cost = 1) THEN direction_fuel_cost := 0; END IF;
- fuel_cost := fuel_cost + direction_fuel_cost;
- END IF;
- ELSE
- fuel_cost := 0;
- END IF;
- -- Abort moving if they specified a destination and don't have enough fuel to get/stop there
- IF ((new_destination_x IS NOT NULL AND new_destination_y IS NOT NULL) AND (current_fuel < fuel_cost + direction_fuel_cost + final_speed)) THEN
- EXECUTE 'NOTIFY ' || get_player_error_channel(GET_PLAYER_USERNAME(ship_player_id)) || ', ''' || GET_SHIP_NAME(moving_ship_id) || ' does not have enough fuel to fly heading ' || final_direction || ', accelerate to ' || final_speed ||' and then stop! To override, specify a NULL destination x and y.'';';
- RETURN 'f';
- END IF;
- final_fuel := current_fuel - fuel_cost;
- --EXECUTE 'NOTIFY ' || get_player_error_channel(GET_PLAYER_USERNAME(ship_player_id)) || ', ''Ship:' || moving_ship_id || '. Fuel:' || current_fuel || '. Cost:' || fuel_cost || '. DirCost:' || direction_fuel_cost || '. finalspeed: ' || final_speed || ''';';
- -- Move the ship!
- UPDATE
- ship
- SET
- current_fuel = final_fuel,
- location_x = ship.location_x + CAST(COS(RADIANS(final_direction)) * final_speed AS integer),
- location_y = ship.location_y + CAST(SIN(RADIANS(final_direction)) * final_speed AS integer),
- last_move_tic = (SELECT last_value FROM tic_seq)
- WHERE
- id = moving_ship_id;
- -- Update ship_control so future ticks know how to move this ship
- UPDATE
- ship_control
- SET
- destination_x=new_destination_x,
- destination_y=new_destination_y,
- speed=new_speed,
- direction=final_direction
- WHERE
- ship_id = moving_ship_id;
- -- Re-retrieve the current ship stats
- SELECT INTO max_speed, current_fuel, location_x, location_y, range, ship_player_id ship.max_speed, ship.current_fuel, ship.location_x, ship.location_y, ship.range, player_id FROM ship WHERE id=moving_ship_id;
- SELECT INTO current_speed, current_direction speed, direction FROM ship_control WHERE ship_id = moving_ship_id;
- -- If the ship is in range of its target..
- IF (new_destination_x BETWEEN (location_x - range) AND (location_x + range) AND new_destination_y BETWEEN (location_y - range) AND (location_y + range)) THEN
- -- calculate how much fuel it would require to stop (or slow down as much as possible)
- IF (current_fuel >= current_speed) THEN
- final_fuel := current_fuel - current_speed;
- final_speed := 0;
- final_direction := 0;
- ELSE
- final_fuel := 0;
- final_speed := current_speed - current_fuel;
- final_direction := current_direction;
- END IF;
- -- Update the control and ship tables with the stopping results
- UPDATE ship_control
- SET speed = final_speed,
- direction = final_direction
- WHERE ship_id = moving_ship_id;
- UPDATE ship
- SET current_fuel = final_fuel
- WHERE id = moving_ship_id;
- END IF;
- RETURN 't';
- ELSE
- EXECUTE 'NOTIFY ' || get_player_error_channel(GET_PLAYER_USERNAME(ship_player_id)) ||', ''Ship '|| moving_ship_id || ' did not budge!'';';
- RETURN 'f';
- END IF;
- END
- $BODY$
- LANGUAGE plpgsql VOLATILE SECURITY DEFINER;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement