Skip to content

Commit

Permalink
contracts & client config: scale building cost (#1722)
Browse files Browse the repository at this point in the history
* contracts & client config: scale building cost

* contracts: use quadratic formula for scaling building cost

* contract: function rename
  • Loading branch information
credence0x authored Oct 1, 2024
1 parent bc3f0c7 commit f7c36c6
Show file tree
Hide file tree
Showing 10 changed files with 75 additions and 33 deletions.
2 changes: 2 additions & 0 deletions config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
setBattleConfig,
setBuildingCategoryPopConfig,
setBuildingConfig,
setBuildingGeneralConfig,
setCapacityConfig,
setCombatConfig,
setHyperstructureConfig,
Expand Down Expand Up @@ -57,6 +58,7 @@ await setBuildingCategoryPopConfig(account, provider);
await setPopulationConfig(account, provider);
await setBuildingConfig(account, provider);
await setResourceBuildingConfig(account, provider);
await setBuildingGeneralConfig(account, provider);
await setWeightConfig(account, provider);
await setCombatConfig(account, provider);
await setBattleConfig(account, provider);
Expand Down
1 change: 1 addition & 0 deletions contracts/scripts/system_models.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"BankConfig",
"TroopConfig",
"BuildingConfig",
"BuildingGeneralConfig",
"BuildingCategoryPopConfig",
"PopulationConfig",
"HyperstructureResourceConfig",
Expand Down
53 changes: 27 additions & 26 deletions contracts/src/models/buildings.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ use core::poseidon::poseidon_hash_span;
use core::zeroable::Zeroable;
use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait};
use eternum::alias::ID;
use eternum::constants::{ResourceTypes, POPULATION_CONFIG_ID};
use eternum::constants::{ResourceTypes, POPULATION_CONFIG_ID, WORLD_CONFIG_ID};
use eternum::models::config::{
TickConfig, TickImpl, TickTrait, ProductionConfig, BuildingConfig, BuildingConfigCustomImpl,
BuildingCategoryPopConfigCustomTrait, PopulationConfig
BuildingCategoryPopConfigCustomTrait, PopulationConfig, BuildingGeneralConfig
};
use eternum::models::owner::{EntityOwner, EntityOwnerCustomTrait};
use eternum::models::population::{Population, PopulationCustomTrait};
Expand All @@ -15,6 +15,7 @@ use eternum::models::production::{
};
use eternum::models::resources::ResourceCustomTrait;
use eternum::models::resources::{Resource, ResourceCustomImpl, ResourceCost};
use eternum::utils::math::{PercentageImpl, PercentageValueImpl};

//todo we need to define border of innner hexes

Expand Down Expand Up @@ -88,22 +89,6 @@ impl BuildingCategoryIntoFelt252 of Into<BuildingCategory, felt252> {
}


#[generate_trait]
impl BonusPercentageImpl of BonusPercentageTrait {
fn _1() -> u128 {
100
}

fn _10() -> u128 {
1_000
}

fn _100() -> u128 {
10_000
}
}


#[generate_trait]
impl BuildingProductionCustomImpl of BuildingProductionCustomTrait {
fn is_resource_producer(self: Building) -> bool {
Expand Down Expand Up @@ -138,7 +123,7 @@ impl BuildingProductionCustomImpl of BuildingProductionCustomTrait {
BuildingCategory::None => 0,
BuildingCategory::Castle => 0,
BuildingCategory::Resource => 0,
BuildingCategory::Farm => BonusPercentageImpl::_10().try_into().unwrap(), // 10%
BuildingCategory::Farm => PercentageValueImpl::_10().try_into().unwrap(), // 10%
BuildingCategory::FishingVillage => 0,
BuildingCategory::Barracks => 0,
BuildingCategory::Market => 0,
Expand Down Expand Up @@ -293,7 +278,7 @@ impl BuildingProductionCustomImpl of BuildingProductionCustomTrait {
let production_config: ProductionConfig = get!(world, produced_resource_type, ProductionConfig);

let bonus_amount: u128 = (production_config.amount * (*self.bonus_percent).into())
/ BonusPercentageImpl::_100();
/ PercentageValueImpl::_100().into();

production_config.amount + bonus_amount
}
Expand Down Expand Up @@ -428,7 +413,7 @@ impl BuildingCustomImpl of BuildingCustomTrait {
category: BuildingCategory,
produce_resource_type: Option<u8>,
inner_coord: Coord
) -> Building {
) -> (Building, BuildingQuantityv2) {
// check that the entity has a position
let outer_entity_position = get!(world, outer_entity_id, Position);
outer_entity_position.assert_not_zero();
Expand Down Expand Up @@ -488,7 +473,7 @@ impl BuildingCustomImpl of BuildingCustomTrait {
// set population
set!(world, (population));

building
(building, building_quantity)
}

/// Pause building production without removing the building
Expand Down Expand Up @@ -598,17 +583,33 @@ impl BuildingCustomImpl of BuildingCustomTrait {
destroyed_building_category
}

fn make_payment(world: IWorldDispatcher, entity_id: ID, category: BuildingCategory, resource_type: u8) {
let building_config: BuildingConfig = BuildingConfigCustomImpl::get(world, category, resource_type);
fn make_payment(self: Building, building_quantity: BuildingQuantityv2, world: IWorldDispatcher) {
let building_general_config: BuildingGeneralConfig = get!(world, WORLD_CONFIG_ID, BuildingGeneralConfig);
let building_config: BuildingConfig = BuildingConfigCustomImpl::get(
world, self.category, self.produced_resource_type
);
let mut index = 0;
loop {
if index == building_config.resource_cost_count {
break;
}

// calculate cost of building based on the formula:
// Cost = Base + (Base * Rate * (N - 1)²)
// Where:
// Base = The cost of the first building
// Rate = How quickly the cost goes up (a small number like 0.1 or 0.2)
// N = Which number building this is (1st, 2nd, 3rd, etc.)
//
let resource_cost: ResourceCost = get!(world, (building_config.resource_cost_id, index), ResourceCost);
let mut resource = ResourceCustomImpl::get(world, (entity_id, resource_cost.resource_type));
resource.burn(resource_cost.amount);
let mut resource = ResourceCustomImpl::get(world, (self.outer_entity_id, resource_cost.resource_type));
let percentage_additional_cost = PercentageImpl::get(
resource_cost.amount, building_general_config.base_cost_percent_increase.into()
);
let scale_factor = building_quantity.value - 1;
let total_cost = resource_cost.amount
+ (scale_factor.into() * scale_factor.into() * percentage_additional_cost);
resource.burn(total_cost);
resource.save(world);
index += 1;
};
Expand Down
9 changes: 9 additions & 0 deletions contracts/src/models/config.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,15 @@ pub struct BankConfig {
lp_fee_denom: u128,
}

#[derive(Copy, Drop, Serde)]
#[dojo::model]
pub struct BuildingGeneralConfig {
#[key]
config_id: ID,
base_cost_percent_increase: u16,
}


#[derive(Copy, Drop, Serde)]
#[dojo::model]
pub struct BuildingConfig {
Expand Down
8 changes: 3 additions & 5 deletions contracts/src/systems/buildings/contracts.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,12 @@ mod building_systems {
get!(world, entity_id, EntityOwner).assert_caller_owner(world);

// todo: check that entity is a realm
let building: Building = BuildingCustomImpl::create(
let (building, building_quantity) = BuildingCustomImpl::create(
world, entity_id, building_category, produce_resource_type, building_coord
);

// make payment for building
BuildingCustomImpl::make_payment(
world, building.outer_entity_id, building.category, building.produced_resource_type
);
// pay one time cost of the building
building.make_payment(building_quantity, world);
}
fn pause_production(ref world: IWorldDispatcher, entity_id: ID, building_coord: Coord) {
BuildingCustomImpl::pause_production(world, entity_id, building_coord);
Expand Down
9 changes: 8 additions & 1 deletion contracts/src/systems/config/contracts.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ trait ITroopConfig {

#[dojo::interface]
trait IBuildingConfig {
fn set_building_general_config(ref world: IWorldDispatcher, base_cost_percent_increase: u16);
fn set_building_config(
ref world: IWorldDispatcher,
building_category: BuildingCategory,
Expand Down Expand Up @@ -149,7 +150,7 @@ mod config_systems {
CapacityConfig, SpeedConfig, WeightConfig, WorldConfig, LevelingConfig, RealmFreeMintConfig, MapConfig,
TickConfig, ProductionConfig, BankConfig, TroopConfig, BuildingConfig, BuildingCategoryPopConfig,
PopulationConfig, HyperstructureResourceConfig, HyperstructureConfig, StaminaConfig, StaminaRefillConfig,
MercenariesConfig, BattleConfig, TravelStaminaCostConfig
MercenariesConfig, BattleConfig, TravelStaminaCostConfig, BuildingGeneralConfig
};

use eternum::models::position::{Position, PositionCustomTrait, Coord};
Expand Down Expand Up @@ -528,6 +529,12 @@ mod config_systems {

#[abi(embed_v0)]
impl BuildingConfigCustomImpl of super::IBuildingConfig<ContractState> {
fn set_building_general_config(ref world: IWorldDispatcher, base_cost_percent_increase: u16) {
assert_caller_is_admin(world);

set!(world, BuildingGeneralConfig { config_id: WORLD_CONFIG_ID, base_cost_percent_increase });
}

fn set_building_config(
ref world: IWorldDispatcher,
building_category: BuildingCategory,
Expand Down
10 changes: 10 additions & 0 deletions sdk/packages/eternum/src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
ARMY_ENTITY_TYPE,
BASE_POPULATION_CAPACITY,
BUILDING_CAPACITY,
BUILDING_FIXED_COST_SCALE_PERCENT,
BUILDING_POPULATION,
BUILDING_RESOURCE_PRODUCED,
DONKEY_ENTITY_TYPE,
Expand Down Expand Up @@ -72,6 +73,15 @@ export const setBuildingCategoryPopConfig = async (account: Account, provider: E
console.log(`Configuring building category population ${tx.statusReceipt}...`);
};

export const setBuildingGeneralConfig = async (account: Account, provider: EternumProvider) => {
const tx = await provider.set_building_general_config({
signer: account,
base_cost_percent_increase: BUILDING_FIXED_COST_SCALE_PERCENT,
});

console.log(`Configuring building general config ${tx.statusReceipt}...`);
};

export const setPopulationConfig = async (account: Account, provider: EternumProvider) => {
const tx = await provider.set_population_config({
signer: account,
Expand Down
2 changes: 1 addition & 1 deletion sdk/packages/eternum/src/constants/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export const ONE_MONTH = 2628000;

// Buildings
export const BASE_POPULATION_CAPACITY = 5;

export const BUILDING_FIXED_COST_SCALE_PERCENT = 5_000; // 5_000/10_000 = 50%
// Points
export const HYPERSTRUCTURE_POINTS_PER_CYCLE = 10;
export const HYPERSTRUCTURE_POINTS_ON_COMPLETION = 2_000_000; // about the amount of points generated by the structure in 2 days
Expand Down
10 changes: 10 additions & 0 deletions sdk/packages/eternum/src/provider/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,16 @@ export class EternumProvider extends EnhancedDojoProvider {
);
}

public async set_building_general_config(props: SystemProps.SetBuildingGeneralConfigProps) {
const { base_cost_percent_increase, signer } = props;

return await this.executeAndCheckTransaction(signer, {
contractAddress: getContractByName(this.manifest, `${NAMESPACE}-config_systems`),
entrypoint: "set_building_general_config",
calldata: [base_cost_percent_increase],
});
}

public async set_population_config(props: SystemProps.SetPopulationConfigProps) {
const { base_population, signer } = props;

Expand Down
4 changes: 4 additions & 0 deletions sdk/packages/eternum/src/types/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,10 @@ export interface SetBuildingCategoryPopConfigProps extends SystemSigner {
calls: { building_category: BuildingType; population: num.BigNumberish; capacity: num.BigNumberish }[];
}

export interface SetBuildingGeneralConfigProps extends SystemSigner {
base_cost_percent_increase: num.BigNumberish;
}

export interface SetPopulationConfigProps extends SystemSigner {
base_population: num.BigNumberish;
}
Expand Down

0 comments on commit f7c36c6

Please sign in to comment.