implement upgrades

This commit is contained in:
Rokas Puzonas 2026-07-19 10:48:36 +03:00
parent 3c61d2164d
commit e4307fb543
2 changed files with 306 additions and 80 deletions

View File

@ -53,6 +53,10 @@ terrain_tiles: []Tile,
show_minion_state: bool = false, show_minion_state: bool = false,
visual_progress: f32 = 0,
show_multiplier: bool = false,
show_heat: bool = false,
const terrain_origin_x: i32 = -80; const terrain_origin_x: i32 = -80;
const terrain_origin_y: i32 = -60; const terrain_origin_y: i32 = -60;
const terrain_width = 160; const terrain_width = 160;
@ -251,12 +255,15 @@ const Entity = struct {
const Upgrades = struct { const Upgrades = struct {
minion_count: u32 = 1, minion_count: u32 = 1,
minion_chop_damage: u32 = 2, minion_chop_level: u32 = 1,
minion_chop_rate: f32 = 1, minion_chop_damage: u32 = chop_levels[0].damage,
minion_throw_cooldown: Nanoseconds = std.time.ns_per_s, minion_chop_rate: f32 = chop_levels[0].rate,
minion_throw_strength: u32 = 1, minion_throw_level: u32 = 1,
minion_throw_cooldown: Nanoseconds = throw_levels[0].cooldown,
minion_throw_strength: u32 = throw_levels[0].strength,
minion_carry_capacity: u32 = 1, minion_carry_capacity: u32 = 1,
minion_walk: MinionWalkStats = .{}, minion_walk_level: u32 = 1,
minion_walk: MinionWalkStats = walk_levels[0],
tree_station_count: u32 = 1, tree_station_count: u32 = 1,
tree_level: u32 = 1, tree_level: u32 = 1,
@ -265,27 +272,106 @@ const Upgrades = struct {
tree_wood_amount: u32 = tree_levels[0].wood_amount, tree_wood_amount: u32 = tree_levels[0].wood_amount,
tree_wood_health: f32 = tree_levels[0].wood_health, tree_wood_health: f32 = tree_levels[0].wood_health,
burn_speed: f32 = 10, burn_speed: u32 = 10,
burn_heat_per_wood: u32 = 1, burn_heat_per_wood: u32 = 1,
burn_max_stack_size: u32 = 10, burn_max_stack_size: u32 = 10,
burn_levels: [2]BurnLevel = .{ burn_levels: [2]BurnLevel = .{
.{ .threshold = 10, .multiplier = 2 }, .{ .threshold = 5 , .multiplier = 2 },
.{ .threshold = 20, .multiplier = 3 }, .{ .threshold = 15, .multiplier = 3 },
}, },
const tree_levels = [_]TreeLevel{ const tree_levels = [_]TreeLevel{
TreeLevel{ TreeLevel{
.health = 10, .health = 10,
.respawn_duration = std.time.ns_per_s, .respawn_duration = std.time.ns_per_s * 5,
.wood_amount = 1, .wood_amount = 1,
.wood_health = 20, .wood_health = 20,
},
TreeLevel{
.health = 30,
.respawn_duration = std.time.ns_per_s * 3,
.wood_amount = 3,
.wood_health = 30,
},
TreeLevel{
.health = 60,
.respawn_duration = std.time.ns_per_s * 1,
.wood_amount = 6,
.wood_health = 50,
},
TreeLevel{
.health = 120,
.respawn_duration = std.time.ns_per_s * 0.5,
.wood_amount = 20,
.wood_health = 80,
}
};
const chop_levels = [_]ChopLevel{
ChopLevel{
.damage = 2,
.rate = 1
},
ChopLevel{
.damage = 5,
.rate = 2,
},
ChopLevel{
.damage = 10,
.rate = 4,
},
ChopLevel{
.damage = 40,
.rate = 8
},
};
const walk_levels = [_]MinionWalkStats{
MinionWalkStats{
.friction = 0.998,
.max_velocity = 50,
.max_speed = 300,
},
MinionWalkStats{
.friction = 0.998,
.max_velocity = 200,
.max_speed = 800,
},
MinionWalkStats{
.friction = 0.996,
.max_velocity = 400,
.max_speed = 1600,
},
MinionWalkStats{
.friction = 0.996,
.max_velocity = 1000,
.max_speed = 2800,
}
};
const throw_levels = [_]ThrowLevel{
ThrowLevel{
.cooldown = std.time.ns_per_s,
.strength = 1,
},
ThrowLevel{
.cooldown = std.time.ns_per_s*0.5,
.strength = 2,
},
ThrowLevel{
.cooldown = std.time.ns_per_s*0.25,
.strength = 4,
},
ThrowLevel{
.cooldown = std.time.ns_per_s*0.1,
.strength = 8,
} }
}; };
const MinionWalkStats = struct { const MinionWalkStats = struct {
friction: f32 = 0.998, friction: f32,
max_velocity: f32 = 50, max_velocity: f32,
max_speed: f32 = 300, max_speed: f32,
}; };
const BurnLevel = struct { const BurnLevel = struct {
@ -299,11 +385,24 @@ const Upgrades = struct {
wood_amount: u32, wood_amount: u32,
wood_health: f32, wood_health: f32,
}; };
const ChopLevel = struct {
damage: u32,
rate: f32,
};
const ThrowLevel = struct {
cooldown: Nanoseconds,
strength: u32,
};
}; };
const Shop = struct { const Shop = struct {
minion_count: Shop.Item, minion_count: Shop.Item,
minion_carry_capacity: Shop.Item, minion_carry_capacity: Shop.Item,
minion_chop_level: Shop.Item,
minion_walk_level: Shop.Item,
minion_throw_level: Shop.Item,
tree_count: Shop.Item, tree_count: Shop.Item,
tree_level: Shop.Item, tree_level: Shop.Item,
@ -572,11 +671,12 @@ pub fn init(self: *App, plt: Platform.Init) !?u8 {
self.spawnBurnStation(100); self.spawnBurnStation(100);
self.spawnBurnStation(150); self.spawnBurnStation(150);
self.spawnBurnStation(200);
self.eternal_flame_id = self.spawnEntity(Entity{ self.eternal_flame_id = self.spawnEntity(Entity{
.type = .eternal_flame, .type = .eternal_flame,
.pos = .init(250, 0), .pos = .init(300, 0),
.eternal_flame_size = .large, .eternal_flame_size = .small,
}).?; }).?;
return null; return null;
@ -586,33 +686,64 @@ fn initShop(self: *App, arena: Allocator) !void {
self.shop = .{ self.shop = .{
.minion_count = Shop.Item{ .minion_count = Shop.Item{
.label = "Minion count", .label = "Minion count",
.limit = 50, .limit = 30,
.unlocked = true,
.value_ref = .initU32(&self.upgrades.minion_count), .value_ref = .initU32(&self.upgrades.minion_count),
.value_scaling = .initFixed(1), .value_scaling = .initFixed(1),
.cost = 1, .cost = 1,
.cost_scaling = .initFixed(1), .cost_scaling = .initLinear(2, 1.25),
}, },
.minion_carry_capacity = Shop.Item{ .minion_carry_capacity = Shop.Item{
.label = "Carry capacity", .label = "Carry capacity",
.limit = 8,
.value_ref = .initU32(&self.upgrades.minion_carry_capacity), .value_ref = .initU32(&self.upgrades.minion_carry_capacity),
.value_scaling = .initFixed(1), .value_scaling = .initFixed(1),
.cost = 1, .cost = 2,
.cost_scaling = .initFixed(1), .cost_scaling = .initLinear(10, 2),
},
.minion_chop_level = Shop.Item{
.label = "Chop level",
.limit = Upgrades.chop_levels.len,
.value_ref = .initU32(&self.upgrades. minion_chop_level),
.value_scaling = .initFixed(1),
.cost = 2,
.cost_scaling = .initLinear(20, 2),
},
.minion_walk_level = Shop.Item{
.label = "Walk speed",
.limit = Upgrades.walk_levels.len,
.value_ref = .initU32(&self.upgrades.minion_walk_level),
.value_scaling = .initFixed(1),
.cost = 3,
.cost_scaling = .initLinear(10, 2),
},
.minion_throw_level = Shop.Item{
.label = "Throw wood level",
.limit = Upgrades.throw_levels.len,
.value_ref = .initU32(&self.upgrades.minion_throw_level),
.value_scaling = .initFixed(1),
.cost = 8,
.cost_scaling = .initLinear(20, 3.0),
}, },
.tree_count = Shop.Item{ .tree_count = Shop.Item{
.label = "Tree count", .label = "Tree count",
.limit = 15,
.value_ref = .initU32(&self.upgrades.tree_station_count), .value_ref = .initU32(&self.upgrades.tree_station_count),
.value_scaling = .initFixed(1), .value_scaling = .initFixed(1),
.cost = 1, .cost = 3,
.cost_scaling = .initFixed(1), .cost_scaling = .initLinear(1, 1.5),
}, },
.tree_level = Shop.Item{ .tree_level = Shop.Item{
.label = "Tree level", .label = "Tree level",
@ -621,50 +752,56 @@ fn initShop(self: *App, arena: Allocator) !void {
.value_ref = .initU32(&self.upgrades.tree_level), .value_ref = .initU32(&self.upgrades.tree_level),
.value_scaling = .initFixed(1), .value_scaling = .initFixed(1),
.cost = 1, .cost = 10,
.cost_scaling = .initFixed(1), .cost_scaling = .initLinear(2, 1.3),
}, },
.fire_speed = Shop.Item{ .fire_speed = Shop.Item{
.label = "Burn speed", .label = "Burn wood speed",
.limit = 50,
.value_ref = .initF32(&self.upgrades.burn_speed), .value_ref = .initU32(&self.upgrades.burn_speed),
.value_scaling = .initFixed(1), .value_scaling = .initLinear(0, 1.5),
.cost = 1, .cost = 10,
.cost_scaling = .initFixed(1), .cost_scaling = .initLinear(5, 1.5),
}, },
.fire_heat_per_wood = Shop.Item{ .fire_heat_per_wood = Shop.Item{
.label = "Heat per wood", .label = "Heat per wood",
.limit = 5,
.value_ref = .initU32(&self.upgrades.burn_heat_per_wood), .value_ref = .initU32(&self.upgrades.burn_heat_per_wood),
.value_scaling = .initFixed(1), .value_scaling = .initFixed(1),
.cost = 1, .cost = 30,
.cost_scaling = .initFixed(1), .cost_scaling = .initLinear(1, 2),
}, },
.fire_stack_size = Shop.Item{ .fire_stack_size = Shop.Item{
.label = "Stack size", .label = "Stack size",
.limit = 25,
.value_ref = .initU32(&self.upgrades.burn_max_stack_size), .value_ref = .initU32(&self.upgrades.burn_max_stack_size),
.value_scaling = .initFixed(1), .value_scaling = .initFixed(10),
.cost = 1, .cost = 20,
.cost_scaling = .initFixed(1), .cost_scaling = .initLinear(2, 2.5),
}, },
.minion_upgrades = try arena.dupe(*Shop.Item, &.{ .minion_upgrades = try arena.dupe(*Shop.Item, &.{
&self.shop.minion_count, &self.shop.minion_count,
&self.shop.minion_carry_capacity &self.shop.minion_carry_capacity,
&self.shop.minion_chop_level,
&self.shop.minion_walk_level,
&self.shop.minion_throw_level
}), }),
.tree_upgrades = try arena.dupe(*Shop.Item, &.{ .tree_upgrades = try arena.dupe(*Shop.Item, &.{
&self.shop.tree_count, &self.shop.tree_count,
&self.shop.tree_level &self.shop.tree_level
}), }),
.fire_upgrades = try arena.dupe(*Shop.Item, &.{ .fire_upgrades = try arena.dupe(*Shop.Item, &.{
&self.shop.fire_stack_size,
&self.shop.fire_speed, &self.shop.fire_speed,
&self.shop.fire_heat_per_wood, &self.shop.fire_heat_per_wood,
&self.shop.fire_stack_size,
}), }),
}; };
} }
@ -1207,16 +1344,25 @@ fn removeWoodStation(self: *App, id: EntityId) void {
self.entities.removeAssumeExists(id); self.entities.removeAssumeExists(id);
} }
fn getBurnMultiplier(self: *App) u32 { fn getBurnLevelIndex(self: *App) ?usize {
const stack_size = self.countEternalFlameStackSize(); const stack_size = self.countEternalFlameStackSize();
for (0..self.upgrades.burn_levels.len) |i| { for (0..self.upgrades.burn_levels.len) |oi| {
const level = self.upgrades.burn_levels[self.upgrades.burn_levels.len - i - 1]; const i = self.upgrades.burn_levels.len - oi - 1;
const level = self.upgrades.burn_levels[i];
if (stack_size >= level.threshold) { if (stack_size >= level.threshold) {
return level.multiplier; return i;
} }
} }
return null;
}
fn getBurnMultiplier(self: *App) u32 {
if (self.getBurnLevelIndex()) |index| {
return self.upgrades.burn_levels[index].multiplier;
}
return 1; return 1;
} }
@ -1252,7 +1398,7 @@ fn showShopPanel(
return; return;
} }
const panel_size = Vec2.init(400, unlocked_count * 32 + 10); const panel_size = Vec2.init(420, unlocked_count * 32 + 10);
const border_width = 5; const border_width = 5;
const border_color = Color.rgb(180, 180, 180); const border_color = Color.rgb(180, 180, 180);
@ -1353,8 +1499,8 @@ fn showShopPanel(
const allocPrint = std.fmt.allocPrint; const allocPrint = std.fmt.allocPrint;
Gfx.drawText(self.font, .{ Gfx.drawText(self.font, .{
.text = try allocPrint(plt.arena, "{f}", .{shop_item.value_ref.deref()}), .text = try allocPrint(plt.frame, "{f}", .{shop_item.value_ref.deref()}),
.pos = .init(180, 0), .pos = .init(200, 0),
.height = 24, .height = 24,
.color = text_color .color = text_color
}); });
@ -1362,7 +1508,7 @@ fn showShopPanel(
if (is_mouse_hovering) { if (is_mouse_hovering) {
const new_value = shop_item.value_scaling.apply(shop_item.value_ref.deref()); const new_value = shop_item.value_scaling.apply(shop_item.value_ref.deref());
Gfx.drawText(self.font, .{ Gfx.drawText(self.font, .{
.text = try allocPrint(plt.arena, "> {f}", .{new_value}), .text = try allocPrint(plt.frame, "> {f}", .{new_value}),
.pos = .init(250, 0), .pos = .init(250, 0),
.height = 24, .height = 24,
.color = text_color .color = text_color
@ -1370,7 +1516,7 @@ fn showShopPanel(
} }
Gfx.drawText(self.font, .{ Gfx.drawText(self.font, .{
.text = if (limit_reached) "MAX" else try std.fmt.allocPrint(plt.arena, "{}H", .{cost}), .text = if (limit_reached) "MAX" else try std.fmt.allocPrint(plt.frame, "{}H", .{cost}),
.pos = .init(panel_size.x - 20, 0), .pos = .init(panel_size.x - 20, 0),
.height = 24, .height = 24,
.color = text_color, .color = text_color,
@ -1382,12 +1528,12 @@ fn showShopPanel(
fn showUI(self: *App, plt: Platform.Frame) !void { fn showUI(self: *App, plt: Platform.Frame) !void {
var heat_pos = Vec2.init(50, -200); var heat_pos = Vec2.init(50, -200);
{ // Draw heat counter if (self.show_heat) { // Draw heat counter
var builder = Gfx.TextBuilder.init(plt.arena); var builder = Gfx.TextBuilder.init(plt.frame);
builder.font(self.font, 64); builder.font(self.font, 64);
builder.color = .rgb(200, 20, 20); builder.color = .rgb(200, 20, 20);
try builder.put(try std.fmt.allocPrint(plt.arena, "{}", .{self.heat})); try builder.put(try std.fmt.allocPrint(plt.frame, "{}", .{self.heat}));
builder.font(self.font, 32); builder.font(self.font, 32);
builder.color = .rgb(240, 100, 100); builder.color = .rgb(240, 100, 100);
@ -1395,6 +1541,61 @@ fn showUI(self: *App, plt: Platform.Frame) !void {
try builder.put("Heat"); try builder.put("Heat");
builder.draw(heat_pos.sub(builder.bounds.size.divideScalar(2))); builder.draw(heat_pos.sub(builder.bounds.size.divideScalar(2)));
} else {
self.show_heat = self.heat > 0;
}
if (self.show_multiplier) {
Gfx.transformPush();
defer Gfx.transformPop();
Gfx.transformTranslate(heat_pos);
Gfx.transformTranslate(.init(-10, 56));
var lower_threshold: u32 = 0;
var upper_threshold: u32 = 0;
if (self.getBurnLevelIndex()) |index| {
lower_threshold = self.upgrades.burn_levels[index].threshold;
if (index+1 < self.upgrades.burn_levels.len) {
upper_threshold = self.upgrades.burn_levels[index+1].threshold;
} else {
upper_threshold = lower_threshold;
}
} else {
upper_threshold = self.upgrades.burn_levels[0].threshold;
}
const stack_size = self.countEternalFlameStackSize();
var progress: f32 = 1;
if (lower_threshold < upper_threshold ) {
progress = @as(f32, @floatFromInt(stack_size-lower_threshold)) / @as(f32, @floatFromInt(upper_threshold-lower_threshold));
}
self.visual_progress = std.math.lerp(self.visual_progress, progress, 0.03);
const progress_bar_size = Vec2.init(80, 10);
drawProgressBar(1, .init(0, 0), progress_bar_size, .rgb(30, 30, 30));
drawProgressBar(self.visual_progress, .init(0, 0), progress_bar_size, .rgb(255, 255, 255));
Gfx.drawText(self.font, .{
.height = 18,
.pos = .init(progress_bar_size.x/2 + 10, -9),
.text = try std.fmt.allocPrint(plt.frame, "{}x", .{self.getBurnMultiplier()})
});
} else {
self.show_multiplier = self.heat > 2;
}
inline for (&.{ self.shop.minion_upgrades, self.shop.tree_upgrades, self.shop.fire_upgrades }) |upgrades| {
for (upgrades) |upgrade| {
if (!upgrade.unlocked) {
upgrade.unlocked = self.heat >= upgrade.cost;
}
}
}
if (!self.shop.minion_chop_level.unlocked) {
self.shop.minion_chop_level.unlocked = self.upgrades.tree_level > 1;
} }
try self.showShopPanel(plt, "Minion", Vec2.init(0, -600), self.shop.minion_upgrades); try self.showShopPanel(plt, "Minion", Vec2.init(0, -600), self.shop.minion_upgrades);
@ -1502,10 +1703,7 @@ fn showDebug(self: *App, plt: Platform.Frame) !void {
ImGUI.separator(); ImGUI.separator();
_ = ImGUI.text("Burn upgrades", .{}); _ = ImGUI.text("Burn upgrades", .{});
_ = ImGUI.inputF32Drag(.{ _ = ImGUI.inputU32("speed", &self.upgrades.burn_speed);
.label = "speed",
.value = &self.upgrades.burn_speed
});
_ = ImGUI.inputU32("heat_per_wood", &self.upgrades.burn_heat_per_wood); _ = ImGUI.inputU32("heat_per_wood", &self.upgrades.burn_heat_per_wood);
_ = ImGUI.inputU32("max_stack_size", &self.upgrades.burn_max_stack_size); _ = ImGUI.inputU32("max_stack_size", &self.upgrades.burn_max_stack_size);
for (1.., &self.upgrades.burn_levels) |i, *level| { for (1.., &self.upgrades.burn_levels) |i, *level| {
@ -1799,7 +1997,8 @@ pub fn frame(self: *App, plt: Platform.Frame) !void {
// Apply burn // Apply burn
if (wood.wood_burning) { if (wood.wood_burning) {
wood.wood_health = @max(wood.wood_health - self.upgrades.burn_speed * dt, 0); const burn_speed: f32 = @floatFromInt(self.upgrades.burn_speed);
wood.wood_health = @max(wood.wood_health - burn_speed * dt, 0);
if (wood.wood_health == 0) { if (wood.wood_health == 0) {
self.heat += self.upgrades.burn_heat_per_wood * self.getBurnMultiplier(); self.heat += self.upgrades.burn_heat_per_wood * self.getBurnMultiplier();
@ -1811,7 +2010,7 @@ pub fn frame(self: *App, plt: Platform.Frame) !void {
// Each wood entity will assign itself to the nearest minion that isn't busy // Each wood entity will assign itself to the nearest minion that isn't busy
if (wood.wood_carried_by == null and wood.targeted_by_entity == null) { if (wood.wood_carried_by == null and wood.targeted_by_entity == null) {
var minion_iter = self.initNearestEntityIter(.minion, wood.pos, plt.arena); var minion_iter = self.initNearestEntityIter(.minion, wood.pos, plt.frame);
while (try minion_iter.next()) |minion_id| { while (try minion_iter.next()) |minion_id| {
const minion = self.entities.getAssumeExists(minion_id); const minion = self.entities.getAssumeExists(minion_id);
if (minion.minion_carried_wood_len == self.upgrades.minion_carry_capacity) { if (minion.minion_carried_wood_len == self.upgrades.minion_carry_capacity) {
@ -1841,7 +2040,7 @@ pub fn frame(self: *App, plt: Platform.Frame) !void {
continue; continue;
} }
var minion_iter = self.initNearestEntityIter(.minion, burn_station.pos, plt.arena); var minion_iter = self.initNearestEntityIter(.minion, burn_station.pos, plt.frame);
while (try minion_iter.next()) |minion_id| { while (try minion_iter.next()) |minion_id| {
const minion = self.entities.getAssumeExists(minion_id); const minion = self.entities.getAssumeExists(minion_id);
const state = minion.minion_state; const state = minion.minion_state;
@ -1858,7 +2057,7 @@ pub fn frame(self: *App, plt: Platform.Frame) !void {
var tree_iter = self.initEntityIteratorByType(.tree); var tree_iter = self.initEntityIteratorByType(.tree);
while (tree_iter.next()) |tree_id| { while (tree_iter.next()) |tree_id| {
const tree = self.entities.getAssumeExists(tree_id); const tree = self.entities.getAssumeExists(tree_id);
var minion_iter = self.initNearestEntityIter(.minion, tree.pos, plt.arena); var minion_iter = self.initNearestEntityIter(.minion, tree.pos, plt.frame);
while (try minion_iter.next()) |minion_id| { while (try minion_iter.next()) |minion_id| {
const minion = self.entities.getAssumeExists(minion_id); const minion = self.entities.getAssumeExists(minion_id);
if (minion.minion_carried_wood_len == self.upgrades.minion_carry_capacity) { if (minion.minion_carried_wood_len == self.upgrades.minion_carry_capacity) {
@ -1901,7 +2100,7 @@ pub fn frame(self: *App, plt: Platform.Frame) !void {
continue; continue;
} }
var minion_iter = self.initNearestEntityIter(.minion, wood_station.pos, plt.arena); var minion_iter = self.initNearestEntityIter(.minion, wood_station.pos, plt.frame);
while (try minion_iter.next()) |minion_id| { while (try minion_iter.next()) |minion_id| {
const minion = self.entities.getAssumeExists(minion_id); const minion = self.entities.getAssumeExists(minion_id);
if (minion.minion_carried_wood_len == self.upgrades.minion_carry_capacity) { if (minion.minion_carried_wood_len == self.upgrades.minion_carry_capacity) {
@ -2087,6 +2286,14 @@ pub fn frame(self: *App, plt: Platform.Frame) !void {
); );
} }
if (self.getBurnLevelIndex() == null) {
eternal_flame.eternal_flame_size = .small;
} else if (self.getBurnLevelIndex() == 0) {
eternal_flame.eternal_flame_size = .medium;
} else {
eternal_flame.eternal_flame_size = .large;
}
switch (eternal_flame.eternal_flame_size) { switch (eternal_flame.eternal_flame_size) {
.small => { .small => {
const flame_size = Vec2.init(16, 32).multiplyScalar(4); const flame_size = Vec2.init(16, 32).multiplyScalar(4);
@ -2118,10 +2325,6 @@ pub fn frame(self: *App, plt: Platform.Frame) !void {
self.drawEntityAnimation(e, plt.dt); self.drawEntityAnimation(e, plt.dt);
} }
if (e.type == .minion and e.minion_state == .burn_wood and e.minion_throw_cooldown > 0) {
Gfx.drawRectangle(e.pos.sub(.init(5, 65)), .init(10, 10), .rgb(200, 20, 20));
}
if (e.type == .burn_station) { if (e.type == .burn_station) {
Gfx.drawSprite( Gfx.drawSprite(
self.terrain_sheet.get(123, 81), self.terrain_sheet.get(123, 81),
@ -2134,31 +2337,13 @@ pub fn frame(self: *App, plt: Platform.Frame) !void {
if (e.type == .minion and self.show_minion_state) { if (e.type == .minion and self.show_minion_state) {
Gfx.drawText(self.font, .{ Gfx.drawText(self.font, .{
.height = 16, .height = 16,
.text = try std.fmt.allocPrint(plt.arena, "{}", .{e.minion_state}), .text = try std.fmt.allocPrint(plt.frame, "{}", .{e.minion_state}),
.pos = e.pos.add(.init(0, 20)), .pos = e.pos.add(.init(0, 20)),
}); });
} }
} }
} }
{ // Draw eternal flame stats
var eternal_flame_iter = self.initEntityIteratorByType(.eternal_flame);
while (eternal_flame_iter.next()) |id| {
const eternal_flame = self.entities.getAssumeExists(id);
Gfx.drawText(self.font, .{
.text = try std.fmt.allocPrint(plt.arena, "Stack: {}", .{self.countEternalFlameStackSize()}),
.pos = eternal_flame.pos.sub(.init(10, 80)),
.height = 24
});
Gfx.drawText(self.font, .{
.text = try std.fmt.allocPrint(plt.arena, "Mult: {}", .{self.getBurnMultiplier()}),
.pos = eternal_flame.pos.sub(.init(10, 110)),
.height = 24
});
}
}
{ // Draw wood { // Draw wood
var wood_iter = self.initEntityIteratorByType(.wood); var wood_iter = self.initEntityIteratorByType(.wood);
while (wood_iter.next()) |id| { while (wood_iter.next()) |id| {
@ -2187,8 +2372,49 @@ pub fn frame(self: *App, plt: Platform.Frame) !void {
} }
} }
const previous_tree_level = self.upgrades.tree_level;
const previous_chop_level = self.upgrades.minion_chop_level;
const previous_walk_level = self.upgrades.minion_walk_level;
const previous_throw_level = self.upgrades.minion_throw_level;
try self.showUI(plt); try self.showUI(plt);
try self.showDebug(plt); try self.showDebug(plt);
if (previous_tree_level != self.upgrades.tree_level) {
if (self.upgrades.tree_level >= Upgrades.tree_levels.len) {
self.upgrades.tree_level = Upgrades.tree_levels.len;
}
const level = Upgrades.tree_levels[self.upgrades.tree_level-1];
self.upgrades.tree_health = level.health;
self.upgrades.tree_respawn_duration = level.respawn_duration;
self.upgrades.tree_wood_amount = level.wood_amount;
self.upgrades.tree_wood_health = level.wood_health;
}
if (previous_chop_level != self.upgrades.minion_chop_level) {
if (self.upgrades.minion_chop_level >= Upgrades.chop_levels.len) {
self.upgrades.minion_chop_level = Upgrades.chop_levels.len;
}
const level = Upgrades.chop_levels[self.upgrades.minion_chop_level-1];
self.upgrades.minion_chop_damage = level.damage;
self.upgrades.minion_chop_rate = level.rate;
}
if (previous_walk_level != self.upgrades.minion_walk_level) {
if (self.upgrades.minion_walk_level >= Upgrades.walk_levels.len) {
self.upgrades.minion_walk_level = Upgrades.walk_levels.len;
}
const level = Upgrades.walk_levels[self.upgrades.minion_walk_level-1];
self.upgrades.minion_walk = level;
}
if (previous_throw_level != self.upgrades.minion_throw_level) {
if (self.upgrades.minion_throw_level >= Upgrades.throw_levels.len) {
self.upgrades.minion_throw_level = Upgrades.throw_levels.len;
}
const level = Upgrades.throw_levels[self.upgrades.minion_throw_level-1];
self.upgrades.minion_throw_cooldown = level.cooldown;
self.upgrades.minion_throw_strength = level.strength;
}
} }
pub fn deinit(self: *App, plt: Platform.Deinit) void { pub fn deinit(self: *App, plt: Platform.Deinit) void {

View File

@ -1818,7 +1818,7 @@ pub const Sprite = struct {
position: ?Vec2, position: ?Vec2,
padding: u32, padding: u32,
const max_sprites = 128; const max_sprites = 256;
const SlotMap = SlotMapType(std.math.IntFittingRange(0, max_sprites-1), u8, Sprite); const SlotMap = SlotMapType(std.math.IntFittingRange(0, max_sprites-1), u8, Sprite);
pub const Id = SlotMap.Id; pub const Id = SlotMap.Id;
}; };