added .rakeback to get a part of the house edge back. Rakeback is accumulated by betting (not winning or losing in particular). All games have manually specified rakeback values
slot now has 1 more icon (wheat!), and multipliers have been modified to even out the gains betroll is improved (around 2% better payout), as 66 is now a winning number, not a losing one
This commit is contained in:
parent
14ac3c92bb
commit
66870f6859
21 changed files with 7282 additions and 55 deletions
|
@ -74,6 +74,13 @@ public abstract class EllieContext : DbContext
|
|||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
#region Rakeback
|
||||
|
||||
modelBuilder.Entity<Rakeback>()
|
||||
.HasKey(x => x.UserId);
|
||||
|
||||
#endregion
|
||||
|
||||
#region UserBetStats
|
||||
|
||||
modelBuilder.Entity<UserBetStats>()
|
||||
|
|
3919
src/EllieBot/Migrations/PostgreSql/20241107051622_rakeback.Designer.cs
generated
Normal file
3919
src/EllieBot/Migrations/PostgreSql/20241107051622_rakeback.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,33 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace EllieBot.Migrations.PostgreSql
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class rakeback : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "rakeback",
|
||||
columns: table => new
|
||||
{
|
||||
userid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
||||
amount = table.Column<decimal>(type: "numeric", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_rakeback", x => x.userid);
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "rakeback");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3227,6 +3227,23 @@ namespace EllieBot.Migrations.PostgreSql
|
|||
b.ToTable("greetsettings", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Services.Rakeback", b =>
|
||||
{
|
||||
b.Property<decimal>("UserId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("numeric(20,0)")
|
||||
.HasColumnName("userid");
|
||||
|
||||
b.Property<decimal>("Amount")
|
||||
.HasColumnType("numeric")
|
||||
.HasColumnName("amount");
|
||||
|
||||
b.HasKey("UserId")
|
||||
.HasName("pk_rakeback");
|
||||
|
||||
b.ToTable("rakeback", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Services.UserBetStats", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
|
|
3025
src/EllieBot/Migrations/Sqlite/20241107051525_rakeback.Designer.cs
generated
Normal file
3025
src/EllieBot/Migrations/Sqlite/20241107051525_rakeback.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
34
src/EllieBot/Migrations/Sqlite/20241107051525_rakeback.cs
Normal file
34
src/EllieBot/Migrations/Sqlite/20241107051525_rakeback.cs
Normal file
|
@ -0,0 +1,34 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace EllieBot.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class rakeback : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Rakeback",
|
||||
columns: table => new
|
||||
{
|
||||
UserId = table.Column<ulong>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Amount = table.Column<decimal>(type: "TEXT", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Rakeback", x => x.UserId);
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "Rakeback");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2399,6 +2399,20 @@ namespace EllieBot.Migrations
|
|||
b.ToTable("GreetSettings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Services.Rakeback", b =>
|
||||
{
|
||||
b.Property<ulong>("UserId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<decimal>("Amount")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("UserId");
|
||||
|
||||
b.ToTable("Rakeback");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Services.UserBetStats", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
|
|
|
@ -38,6 +38,7 @@ public partial class Gambling : GamblingModule<GamblingService>
|
|||
private readonly IRemindService _remind;
|
||||
private readonly GamblingTxTracker _gamblingTxTracker;
|
||||
private readonly IPatronageService _ps;
|
||||
private readonly RakebackService _rb;
|
||||
|
||||
public Gambling(
|
||||
IGamblingService gs,
|
||||
|
@ -50,7 +51,8 @@ public partial class Gambling : GamblingModule<GamblingService>
|
|||
IBankService bank,
|
||||
IRemindService remind,
|
||||
IPatronageService patronage,
|
||||
GamblingTxTracker gamblingTxTracker)
|
||||
GamblingTxTracker gamblingTxTracker,
|
||||
RakebackService rb)
|
||||
: base(configService)
|
||||
{
|
||||
_gs = gs;
|
||||
|
@ -60,6 +62,7 @@ public partial class Gambling : GamblingModule<GamblingService>
|
|||
_bank = bank;
|
||||
_remind = remind;
|
||||
_gamblingTxTracker = gamblingTxTracker;
|
||||
_rb = rb;
|
||||
_ps = patronage;
|
||||
_rng = new EllieRandom();
|
||||
|
||||
|
@ -318,7 +321,6 @@ public partial class Gambling : GamblingModule<GamblingService>
|
|||
|
||||
|
||||
var val = Config.Timely.Amount;
|
||||
|
||||
var boostGuilds = Config.BoostBonus.GuildIds ?? new();
|
||||
var guildUsers = await boostGuilds
|
||||
.Select(async gid =>
|
||||
|
@ -1089,4 +1091,45 @@ public partial class Gambling : GamblingModule<GamblingService>
|
|||
footer: $"Total Bet: {tests} | Payout: {payout:F0} | {payout * 1.0M / tests * 100}%")
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
private EllieInteractionBase CreateRakebackInteraction()
|
||||
=> _inter.Create(ctx.User.Id,
|
||||
new ButtonBuilder(
|
||||
customId: "cash:rakeback",
|
||||
emote: new Emoji("💸")),
|
||||
RakebackAction);
|
||||
|
||||
private async Task RakebackAction(SocketMessageComponent arg)
|
||||
{
|
||||
var rb = await _rb.ClaimRakebackAsync(ctx.User.Id);
|
||||
|
||||
if (rb == 0)
|
||||
{
|
||||
await arg.DeferAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
await arg.RespondAsync(_sender, GetText(strs.rakeback_claimed(N(rb))), MsgType.Ok);
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
public async Task Rakeback()
|
||||
{
|
||||
var rb = await _rb.GetRakebackAsync(ctx.User.Id);
|
||||
|
||||
if (rb < 1)
|
||||
{
|
||||
await Response()
|
||||
.Error(strs.rakeback_none)
|
||||
.SendAsync();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var inter = CreateRakebackInteraction();
|
||||
await Response()
|
||||
.Pending(strs.rakeback_available(N(rb)))
|
||||
.Interaction(inter)
|
||||
.SendAsync();
|
||||
}
|
||||
}
|
|
@ -11,7 +11,7 @@ namespace EllieBot.Modules.Gambling.Common;
|
|||
public sealed partial class GamblingConfig : ICloneable<GamblingConfig>
|
||||
{
|
||||
[Comment("""DO NOT CHANGE""")]
|
||||
public int Version { get; set; } = 11;
|
||||
public int Version { get; set; } = 12;
|
||||
|
||||
[Comment("""Currency settings""")]
|
||||
public CurrencyConfig Currency { get; set; }
|
||||
|
@ -164,7 +164,7 @@ public partial class BetRollConfig
|
|||
},
|
||||
new()
|
||||
{
|
||||
WhenAbove = 66,
|
||||
WhenAbove = 65,
|
||||
MultiplyBy = 2
|
||||
}
|
||||
];
|
||||
|
@ -226,7 +226,7 @@ public partial class LuckyLadderSettings
|
|||
public decimal[] Multipliers { get; set; }
|
||||
|
||||
public LuckyLadderSettings()
|
||||
=> Multipliers = [2.4M, 1.7M, 1.5M, 1.2M, 0.5M, 0.3M, 0.2M, 0.1M];
|
||||
=> Multipliers = [2.4M, 1.7M, 1.5M, 1.1M, 0.5M, 0.3M, 0.2M, 0.1M];
|
||||
}
|
||||
|
||||
[Cloneable]
|
||||
|
|
|
@ -189,11 +189,16 @@ public sealed class GamblingConfigService : ConfigServiceBase<GamblingConfig>
|
|||
});
|
||||
}
|
||||
|
||||
if (data.Version < 11)
|
||||
if (data.Version < 12)
|
||||
{
|
||||
ModifyConfig(c =>
|
||||
{
|
||||
c.Version = 11;
|
||||
c.Version = 12;
|
||||
|
||||
if (c.BetRoll.Pairs.Length == 3 && c.BetRoll.Pairs[2].WhenAbove == 66)
|
||||
{
|
||||
c.BetRoll.Pairs[2].WhenAbove = 65;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,5 +13,10 @@ public interface IGamblingService
|
|||
Task<OneOf<SlotResult, GamblingError>> SlotAsync(ulong userId, long amount);
|
||||
Task<FlipResult[]> FlipAsync(int count);
|
||||
Task<OneOf<RpsResult, GamblingError>> RpsAsync(ulong userId, long amount, byte pick);
|
||||
Task<OneOf<BetdrawResult, GamblingError>> BetDrawAsync(ulong userId, long amount, byte? maybeGuessValue, byte? maybeGuessColor);
|
||||
|
||||
Task<OneOf<BetdrawResult, GamblingError>> BetDrawAsync(
|
||||
ulong userId,
|
||||
long amount,
|
||||
byte? maybeGuessValue,
|
||||
byte? maybeGuessColor);
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
#nullable disable
|
||||
using LinqToDB;
|
||||
using LinqToDB.EntityFrameworkCore;
|
||||
using EllieBot.Modules.Gambling.Betdraw;
|
||||
using EllieBot.Modules.Gambling.Rps;
|
||||
using EllieBot.Modules.Gambling.Services;
|
||||
|
@ -8,15 +10,15 @@ namespace EllieBot.Modules.Gambling;
|
|||
|
||||
public sealed class NewGamblingService : IGamblingService, IEService
|
||||
{
|
||||
private readonly GamblingConfigService _bcs;
|
||||
private readonly GamblingConfigService _gcs;
|
||||
private readonly ICurrencyService _cs;
|
||||
|
||||
public NewGamblingService(GamblingConfigService bcs, ICurrencyService cs)
|
||||
public NewGamblingService(GamblingConfigService gcs, ICurrencyService cs)
|
||||
{
|
||||
_bcs = bcs;
|
||||
_gcs = gcs;
|
||||
_cs = cs;
|
||||
}
|
||||
|
||||
|
||||
public async Task<OneOf<LuLaResult, GamblingError>> LulaAsync(ulong userId, long amount)
|
||||
{
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(amount);
|
||||
|
@ -31,9 +33,9 @@ public sealed class NewGamblingService : IGamblingService, IEService
|
|||
}
|
||||
}
|
||||
|
||||
var game = new LulaGame(_bcs.Data.LuckyLadder.Multipliers);
|
||||
var game = new LulaGame(_gcs.Data.LuckyLadder.Multipliers);
|
||||
var result = game.Spin(amount);
|
||||
|
||||
|
||||
var won = (long)result.Won;
|
||||
if (won > 0)
|
||||
{
|
||||
|
@ -57,9 +59,9 @@ public sealed class NewGamblingService : IGamblingService, IEService
|
|||
}
|
||||
}
|
||||
|
||||
var game = new BetrollGame(_bcs.Data.BetRoll.Pairs
|
||||
.Select(x => (x.WhenAbove, (decimal)x.MultiplyBy))
|
||||
.ToList());
|
||||
var game = new BetrollGame(_gcs.Data.BetRoll.Pairs
|
||||
.Select(x => (x.WhenAbove, (decimal)x.MultiplyBy))
|
||||
.ToList());
|
||||
|
||||
var result = game.Roll(amount);
|
||||
|
||||
|
@ -88,19 +90,23 @@ public sealed class NewGamblingService : IGamblingService, IEService
|
|||
}
|
||||
}
|
||||
|
||||
var game = new BetflipGame(_bcs.Data.BetFlip.Multiplier);
|
||||
var game = new BetflipGame(_gcs.Data.BetFlip.Multiplier);
|
||||
var result = game.Flip(guess, amount);
|
||||
|
||||
|
||||
var won = (long)result.Won;
|
||||
if (won > 0)
|
||||
{
|
||||
await _cs.AddAsync(userId, won, new("betflip", "win"));
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<OneOf<BetdrawResult, GamblingError>> BetDrawAsync(ulong userId, long amount, byte? maybeGuessValue, byte? maybeGuessColor)
|
||||
|
||||
public async Task<OneOf<BetdrawResult, GamblingError>> BetDrawAsync(
|
||||
ulong userId,
|
||||
long amount,
|
||||
byte? maybeGuessValue,
|
||||
byte? maybeGuessColor)
|
||||
{
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(amount);
|
||||
|
||||
|
@ -109,7 +115,7 @@ public sealed class NewGamblingService : IGamblingService, IEService
|
|||
|
||||
if (maybeGuessColor > 1)
|
||||
throw new ArgumentOutOfRangeException(nameof(maybeGuessColor));
|
||||
|
||||
|
||||
if (maybeGuessValue > 1)
|
||||
throw new ArgumentOutOfRangeException(nameof(maybeGuessValue));
|
||||
|
||||
|
@ -125,13 +131,13 @@ public sealed class NewGamblingService : IGamblingService, IEService
|
|||
|
||||
var game = new BetdrawGame();
|
||||
var result = game.Draw((BetdrawValueGuess?)maybeGuessValue, (BetdrawColorGuess?)maybeGuessColor, amount);
|
||||
|
||||
|
||||
var won = (long)result.Won;
|
||||
if (won > 0)
|
||||
{
|
||||
await _cs.AddAsync(userId, won, new("betdraw", "win"));
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -178,7 +184,7 @@ public sealed class NewGamblingService : IGamblingService, IEService
|
|||
|
||||
return Task.FromResult(results);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
// private readonly ConcurrentDictionary<ulong, Deck> _decks = new ConcurrentDictionary<ulong, Deck>();
|
||||
|
@ -236,7 +242,7 @@ public sealed class NewGamblingService : IGamblingService, IEService
|
|||
{
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(amount);
|
||||
ArgumentOutOfRangeException.ThrowIfGreaterThan(pick, 2);
|
||||
|
||||
|
||||
if (amount > 0)
|
||||
{
|
||||
var isTakeSuccess = await _cs.RemoveAsync(userId, amount, new("rps", "bet"));
|
||||
|
@ -249,7 +255,7 @@ public sealed class NewGamblingService : IGamblingService, IEService
|
|||
|
||||
var rps = new RpsGame();
|
||||
var result = rps.Play((RpsPick)pick, amount);
|
||||
|
||||
|
||||
var won = (long)result.Won;
|
||||
if (won > 0)
|
||||
{
|
||||
|
@ -265,4 +271,46 @@ public sealed class NewGamblingService : IGamblingService, IEService
|
|||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class RakebackService : IEService
|
||||
{
|
||||
private readonly DbService _db;
|
||||
private readonly ICurrencyService _cs;
|
||||
|
||||
public RakebackService(DbService db, ICurrencyService cs)
|
||||
{
|
||||
_db = db;
|
||||
_cs = cs;
|
||||
}
|
||||
|
||||
public async Task<long> GetRakebackAsync(ulong userId)
|
||||
{
|
||||
await using var uow = _db.GetDbContext();
|
||||
|
||||
var rb = uow.GetTable<Rakeback>()
|
||||
.Where(x => x.UserId == userId)
|
||||
.Select(x => x.Amount)
|
||||
.FirstOrDefault();
|
||||
|
||||
return (long)rb;
|
||||
}
|
||||
|
||||
public async Task<long> ClaimRakebackAsync(ulong userId)
|
||||
{
|
||||
await using var uow = _db.GetDbContext();
|
||||
|
||||
var rbs = await uow.GetTable<Rakeback>()
|
||||
.Where(x => x.UserId == userId)
|
||||
.DeleteWithOutputAsync((x) => x.Amount);
|
||||
|
||||
if (rbs.Length == 0)
|
||||
return 0;
|
||||
|
||||
var rb = (long)rbs[0];
|
||||
|
||||
await _cs.AddAsync(userId, rb, new("rakeback", "claim"));
|
||||
|
||||
return rb;
|
||||
}
|
||||
}
|
|
@ -11,9 +11,9 @@ public class SlotGame
|
|||
{
|
||||
var rolls = new[]
|
||||
{
|
||||
(byte)_rng.Next(0, 6),
|
||||
(byte)_rng.Next(0, 6),
|
||||
(byte)_rng.Next(0, 6)
|
||||
(byte)_rng.Next(0, 7),
|
||||
(byte)_rng.Next(0, 7),
|
||||
(byte)_rng.Next(0, 7)
|
||||
};
|
||||
|
||||
ref var a = ref rolls[0];
|
||||
|
@ -24,24 +24,24 @@ public class SlotGame
|
|||
var winType = SlotWinType.None;
|
||||
if (a == b && b == c)
|
||||
{
|
||||
if (a == 5)
|
||||
if (a == 6)
|
||||
{
|
||||
winType = SlotWinType.TrippleJoker;
|
||||
multi = 30;
|
||||
multi = 25;
|
||||
}
|
||||
else
|
||||
{
|
||||
winType = SlotWinType.TrippleNormal;
|
||||
multi = 10;
|
||||
multi = 15;
|
||||
}
|
||||
}
|
||||
else if (a == 5 && (b == 5 || c == 5)
|
||||
|| (b == 5 && c == 5))
|
||||
else if (a == 6 && (b == 6 || c == 6)
|
||||
|| (b == 6 && c == 6))
|
||||
{
|
||||
winType = SlotWinType.DoubleJoker;
|
||||
multi = 4;
|
||||
multi = 6;
|
||||
}
|
||||
else if (a == 5 || b == 5 || c == 5)
|
||||
else if (a == 6 || b == 6 || c == 6)
|
||||
{
|
||||
winType = SlotWinType.SingleJoker;
|
||||
multi = 1;
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace EllieBot.Common;
|
|||
public partial class ImageUrls : ICloneable<ImageUrls>
|
||||
{
|
||||
[Comment("DO NOT CHANGE")]
|
||||
public int Version { get; set; } = 5;
|
||||
public int Version { get; set; } = 6;
|
||||
|
||||
public CoinData Coins { get; set; }
|
||||
public Uri[] Currency { get; set; }
|
||||
|
|
|
@ -88,6 +88,10 @@ public sealed class GamblingTxTracker : ITxTracker, IEService, IReadyExecutor
|
|||
if (users.Count == 0)
|
||||
continue;
|
||||
|
||||
// rakeback
|
||||
var rakebacks = new Dictionary<ulong, decimal>();
|
||||
|
||||
// update userstats
|
||||
foreach (var (k, x) in users.GroupBy(x => (x.UserId, x.Game))
|
||||
.ToDictionary(x => x.Key,
|
||||
x => x.Aggregate((a, b) => new()
|
||||
|
@ -100,6 +104,10 @@ public sealed class GamblingTxTracker : ITxTracker, IEService, IReadyExecutor
|
|||
MaxWin = Math.Max(a.MaxWin, b.MaxWin),
|
||||
})))
|
||||
{
|
||||
rakebacks.TryAdd(k.UserId, 0m);
|
||||
rakebacks[k.UserId] += x.TotalBet * GetHouseEdge(k.Game) * BASE_RAKEBACK;
|
||||
|
||||
|
||||
// bulk upsert in the future
|
||||
await using var uow = _db.GetDbContext();
|
||||
await uow.GetTable<UserBetStats>()
|
||||
|
@ -129,6 +137,25 @@ public sealed class GamblingTxTracker : ITxTracker, IEService, IReadyExecutor
|
|||
Game = k.Game
|
||||
});
|
||||
}
|
||||
|
||||
foreach (var (k, v) in rakebacks)
|
||||
{
|
||||
await _db.GetDbContext()
|
||||
.GetTable<Rakeback>()
|
||||
.InsertOrUpdateAsync(() => new()
|
||||
{
|
||||
UserId = k,
|
||||
Amount = v
|
||||
},
|
||||
(old) => new()
|
||||
{
|
||||
Amount = old.Amount + v
|
||||
},
|
||||
() => new()
|
||||
{
|
||||
UserId = k
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -137,6 +164,8 @@ public sealed class GamblingTxTracker : ITxTracker, IEService, IReadyExecutor
|
|||
}
|
||||
}
|
||||
|
||||
private const decimal BASE_RAKEBACK = 0.05m;
|
||||
|
||||
public Task TrackAdd(ulong userId, long amount, TxData? txData)
|
||||
{
|
||||
if (txData is null)
|
||||
|
@ -275,6 +304,19 @@ public sealed class GamblingTxTracker : ITxTracker, IEService, IReadyExecutor
|
|||
.Where(x => x.UserId == userId && x.Game == game)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
public decimal GetHouseEdge(GamblingGame game)
|
||||
=> game switch
|
||||
{
|
||||
GamblingGame.Betflip => 0.025m,
|
||||
GamblingGame.Betroll => 0.04m,
|
||||
GamblingGame.Betdraw => 0.04m,
|
||||
GamblingGame.Slots => 0.034m,
|
||||
GamblingGame.Blackjack => 0.02m,
|
||||
GamblingGame.Lula => 0.025m,
|
||||
GamblingGame.Race => 0.06m,
|
||||
_ => 0
|
||||
};
|
||||
}
|
||||
|
||||
public sealed class UserBetStats
|
||||
|
@ -305,4 +347,10 @@ public enum GamblingGame
|
|||
Lula = 5,
|
||||
Race = 6,
|
||||
AnimalRace = 6
|
||||
}
|
||||
|
||||
public sealed class Rakeback
|
||||
{
|
||||
public ulong UserId { get; set; }
|
||||
public decimal Amount { get; set; }
|
||||
}
|
|
@ -27,5 +27,22 @@ public sealed class ImagesConfig : ConfigServiceBase<ImageUrls>
|
|||
c.Version = 5;
|
||||
});
|
||||
}
|
||||
|
||||
if (data.Version < 6)
|
||||
{
|
||||
ModifyConfig(c =>
|
||||
{
|
||||
if (c.Slots.Emojis?.Length == 6)
|
||||
{
|
||||
c.Slots.Emojis =
|
||||
[
|
||||
new("https://cdn.nadeko.bot/slots/15.png"),
|
||||
..c.Slots.Emojis
|
||||
];
|
||||
}
|
||||
|
||||
c.Version = 6;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1453,4 +1453,7 @@ translateflags:
|
|||
- translateflags
|
||||
- trfl
|
||||
- fltr
|
||||
- transflags
|
||||
- transflags
|
||||
rakeback:
|
||||
- rakeback
|
||||
- rb
|
|
@ -1,5 +1,5 @@
|
|||
# DO NOT CHANGE
|
||||
version: 11
|
||||
version: 12
|
||||
# Currency settings
|
||||
currency:
|
||||
# What is the emoji/character which represents the currency
|
||||
|
@ -28,7 +28,7 @@ betRoll:
|
|||
multiplyBy: 10
|
||||
- whenAbove: 90
|
||||
multiplyBy: 4
|
||||
- whenAbove: 66
|
||||
- whenAbove: 65
|
||||
multiplyBy: 2
|
||||
# Automatic currency generation settings.
|
||||
generation:
|
||||
|
@ -85,7 +85,7 @@ luckyLadder:
|
|||
- 2.4
|
||||
- 1.7
|
||||
- 1.5
|
||||
- 1.2
|
||||
- 1.1
|
||||
- 0.5
|
||||
- 0.3
|
||||
- 0.2
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# DO NOT CHANGE
|
||||
version: 5
|
||||
version: 6
|
||||
coins:
|
||||
heads:
|
||||
- https://cdn.nadeko.bot/coins/heads3.png
|
||||
|
@ -22,15 +22,13 @@ dice:
|
|||
- https://cdn.nadeko.bot/other/dice/9.png
|
||||
xp:
|
||||
bg: https://cdn.nadeko.bot/other/xp/bg_k.png
|
||||
rip:
|
||||
bg: https://cdn.nadeko.bot/other/rip/rip.png
|
||||
overlay: https://cdn.nadeko.bot/other/rip/overlay.png
|
||||
slots:
|
||||
emojis:
|
||||
- https://cdn.nadeko.bot/slots/0.png
|
||||
- https://cdn.nadeko.bot/slots/1.png
|
||||
- https://cdn.nadeko.bot/slots/2.png
|
||||
- https://cdn.nadeko.bot/slots/3.png
|
||||
- https://cdn.nadeko.bot/slots/4.png
|
||||
- https://cdn.nadeko.bot/slots/5.png
|
||||
- https://cdn.nadeko.bot/slots/10.png
|
||||
- https://cdn.nadeko.bot/slots/11.png
|
||||
- https://cdn.nadeko.bot/slots/12.png
|
||||
- https://cdn.nadeko.bot/slots/13.png
|
||||
- https://cdn.nadeko.bot/slots/14.png
|
||||
- https://cdn.nadeko.bot/slots/15.png
|
||||
- https://cdn.nadeko.bot/slots/16.png
|
||||
bg: https://cdn.nadeko.bot/slots/slots_bg.png
|
||||
|
|
|
@ -4661,4 +4661,12 @@ betstats:
|
|||
game:
|
||||
desc: 'The game to show betstats for. Omit to show betstats for all games combined'
|
||||
- game:
|
||||
desc: 'The game to show betstats for. Omit to show betstats for all games combined'
|
||||
desc: 'The game to show betstats for. Omit to show betstats for all games combined'
|
||||
rakeback:
|
||||
desc: |-
|
||||
Try to claim any rakeback that you have avaialable.
|
||||
Rakeback is accumulated by betting (not by winning or losing).
|
||||
Default rakeback is 0.05 * house edge
|
||||
House edge is defined per game
|
||||
params:
|
||||
- {}
|
|
@ -1114,5 +1114,8 @@
|
|||
"invalid_img_size": "Image must to be {0}x{1} pixels.",
|
||||
"no_attach_found": "No attachment found. Please send the image along with this command.",
|
||||
"trfl_enabled": "Flag translation enabled on this channel. Reacting to a message with a flag will translate it to that language.",
|
||||
"trfl_disabled": "Flag translation disabled."
|
||||
"trfl_disabled": "Flag translation disabled.",
|
||||
"rakeback_claimed": "You've claimed {0} as rakeback!",
|
||||
"rakeback_none": "You don't have any rakeback to claim yet.",
|
||||
"rakeback_available": "You have {0} rakeback available. Click the button to claim."
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue