You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
133 lines
6.4 KiB
133 lines
6.4 KiB
--! Previous: sha1:f03c81c8d0ca3976d4b6fe4792ee7558d1c2c2f1
|
|
--! Hash: sha1:c8b959244b460096124e37cb9014d1a1b3faf7d3
|
|
--! Message: pull command gets units
|
|
|
|
--- Runs the full /pull command.
|
|
--- Error codes:
|
|
--- VGBCG: Bad channel (game). This is not a valid channel to send game commands in.
|
|
--- VGBGG: Bad guild (game). This is not a valid guild to send game commands in.
|
|
--- VGNYJ: Not yet joined. The Discord user using has not joined the game yet.
|
|
--- VGNEC: Not enough currency.
|
|
--- VGNUT: No units in tier. The randomly selected tier has no units and it's impossible to summon a unit.
|
|
--- VGUNF: Unit not found. The randomly selected unit was not found.
|
|
--- VGTNF: Tier not found. The randomly selected tier was not found.
|
|
CREATE OR REPLACE FUNCTION Command_Pull(
|
|
IN requestedChannel DiscordChannel.discordId%TYPE,
|
|
IN requestedGuild DiscordChannel.guildId%TYPE,
|
|
IN forId DiscordUser.discordId%TYPE,
|
|
IN newUsername DiscordUser.username%TYPE,
|
|
IN newDiscriminator DiscordUser.discriminator%TYPE,
|
|
IN count INT
|
|
)
|
|
RETURNS TABLE
|
|
(
|
|
summonedUnitInstanceId SummonedUnit.instanceId%TYPE,
|
|
summonedUnitId Unit.id%TYPE,
|
|
summonedUnitName Unit.name%TYPE,
|
|
summonedUnitSubtitle Unit.subtitle%TYPE,
|
|
summonedUnitTierId UnitTier.id%TYPE,
|
|
summonedUnitTierName UnitTier.name%TYPE,
|
|
summonCost Player.currency%TYPE,
|
|
resultingCurrency Player.currency%TYPE,
|
|
firstTimePull BOOLEAN,
|
|
wasAlreadySummoned BOOLEAN
|
|
)
|
|
STRICT
|
|
VOLATILE
|
|
ROWS 10
|
|
AS
|
|
$$
|
|
DECLARE
|
|
costPerSummon CONSTANT INT := 10;
|
|
playerId Player.id%TYPE;
|
|
cost Player.currency%TYPE;
|
|
oldCurrency Player.currency%TYPE;
|
|
playerLastDaily Player.lastDaily%TYPE;
|
|
tierRandom FLOAT;
|
|
validUnits INTEGER[] := ARRAY []::INTEGER[];
|
|
unitRandom FLOAT;
|
|
BEGIN
|
|
CALL CheckGameCommandIn(requestedChannel, requestedGuild);
|
|
SELECT InvokingPlayer.id, InvokingPlayer.currency, InvokingPlayer.lastDaily
|
|
INTO playerId, oldCurrency, playerLastDaily
|
|
FROM GetInvokingPlayer(forId, newUsername, newDiscriminator) AS InvokingPlayer;
|
|
IF playerId IS NULL THEN
|
|
RAISE EXCEPTION USING
|
|
ERRCODE = 'VGNYJ',
|
|
MESSAGE = 'Not yet joined',
|
|
DETAIL = 'You haven''t joined the game yet, and can''t use this command until you do.',
|
|
HINT = 'Use the /join command to join the game!';
|
|
END IF;
|
|
cost = costPerSummon * count;
|
|
UPDATE Player SET currency = currency - cost WHERE id = playerId AND currency >= cost;
|
|
IF NOT FOUND THEN
|
|
RAISE EXCEPTION USING
|
|
ERRCODE = 'VGNEC',
|
|
MESSAGE = 'Not enough currency',
|
|
DETAIL = format('Pulling %s heroines would cost %s currency, but you only have %s currency.',
|
|
count, cost, oldCurrency),
|
|
HINT = CASE NextDailyCommand(playerLastDaily) > NOW()
|
|
WHEN FALSE THEN 'You can use the /daily command to get some more currency for today!'
|
|
ELSE format('You can use the /daily command again <t:%s:R> to get some more currency!',
|
|
extract(EPOCH FROM NextDailyCommand(playerLastDaily))::INT)
|
|
END;
|
|
END IF;
|
|
FOR summonIdx IN 1..count
|
|
LOOP
|
|
tierRandom = random();
|
|
unitRandom = random();
|
|
summonedUnitTierId = id
|
|
FROM UnitTier
|
|
WHERE (UnitTier.pullWeightLower <= tierRandom AND
|
|
UnitTier.pullWeightUpper > tierRandom);
|
|
validUnits = ARRAY(SELECT id FROM Unit WHERE (Unit.tierId = summonedUnitTierId));
|
|
IF validUnits = ARRAY []::INTEGER[] THEN
|
|
RAISE EXCEPTION USING
|
|
ERRCODE = 'VGNUT',
|
|
MESSAGE = 'No units of tier',
|
|
DETAIL = format(
|
|
'The dice selected the tier with ID ''%s'', but there are no units of that tier!',
|
|
summonedUnitTierId),
|
|
HINT = 'This indicates a problem in the database. '
|
|
|| 'Contact an admin to fix this problem and get your justly deserved pull.';
|
|
END IF;
|
|
summonedUnitId = validUnits[
|
|
floor(unitRandom::DOUBLE PRECISION * array_length(validUnits, 1)::DOUBLE PRECISION)::INTEGER + 1];
|
|
SELECT Unit.id, Unit.name, Unit.subtitle, Unit.tierId
|
|
INTO summonedUnitId, summonedUnitName, summonedUnitSubtitle, summonedUnitTierId
|
|
FROM Unit
|
|
WHERE Unit.id = summonedUnitId;
|
|
IF NOT FOUND THEN
|
|
RAISE EXCEPTION USING
|
|
ERRCODE = 'VGUNF',
|
|
MESSAGE = 'Unit not found',
|
|
DETAIL = format(
|
|
'The dice selected the unit with ID ''%s'' of tier ID ''%s'', but the unit wasn''t found!',
|
|
summonedUnitId, summonedUnitTierId),
|
|
HINT = 'This indicates a problem in the database.'
|
|
|| ' Contact an admin to fix this problem and get your justly deserved pull.';
|
|
END IF;
|
|
SELECT UnitTier.id, UnitTier.name
|
|
INTO summonedUnitTierId, summonedUnitTierName
|
|
FROM UnitTier
|
|
WHERE UnitTier.id = summonedUnitTierId;
|
|
IF NOT FOUND THEN
|
|
RAISE EXCEPTION USING
|
|
ERRCODE = 'VGTNF',
|
|
MESSAGE = 'Tier not found',
|
|
DETAIL = format(
|
|
'The dice selected the unit with ID ''%s'' of tier ID ''%s'', but the tier wasn''t found!',
|
|
summonedUnitId, summonedUnitTierId),
|
|
HINT = 'This indicates a problem in the database.'
|
|
|| ' Contact an admin to fix this problem and get your justly deserved pull.';
|
|
END IF;
|
|
summonedUnitInstanceId = NULL::INTEGER;
|
|
summonCost = costPerSummon;
|
|
resultingCurrency = oldCurrency - (costPerSummon * summonIdx);
|
|
firstTimePull = NULL::BOOLEAN;
|
|
wasAlreadySummoned = NULL::BOOLEAN;
|
|
RETURN NEXT;
|
|
END LOOP;
|
|
END;
|
|
|
|
$$ LANGUAGE 'plpgsql';
|
|
|